"use client";

import { useEffect, useMemo, useRef, useState, type ChangeEvent } from "react";
import { useParams, useRouter } from "next/navigation";

import ArrowBackIosNewOutlinedIcon from "@mui/icons-material/ArrowBackIosNewOutlined";
import CalendarMonthOutlinedIcon from "@mui/icons-material/CalendarMonthOutlined";
import CheckOutlinedIcon from "@mui/icons-material/CheckOutlined";
import CloseOutlinedIcon from "@mui/icons-material/CloseOutlined";
import KeyboardArrowDownOutlinedIcon from "@mui/icons-material/KeyboardArrowDownOutlined";
import PersonOutlineOutlinedIcon from "@mui/icons-material/PersonOutlineOutlined";
import PictureAsPdfOutlinedIcon from "@mui/icons-material/PictureAsPdfOutlined";

import Alert from "@mui/material/Alert";
import Autocomplete from "@mui/material/Autocomplete";
import Avatar from "@mui/material/Avatar";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Checkbox from "@mui/material/Checkbox";
import Chip from "@mui/material/Chip";
import CircularProgress from "@mui/material/CircularProgress";
import InputAdornment from "@mui/material/InputAdornment";
import TextField from "@mui/material/TextField";
import Tooltip from "@mui/material/Tooltip";
import Typography from "@mui/material/Typography";
import { alpha, useTheme } from "@mui/material/styles";

import type { PlenaryApiItem, PlenaryMinistryApi } from "../plenary-data";
import {
  getActiveMinistries,
  getPlenaryDetail,
  updatePlenary,
  uploadPlenaryDocument,
} from "../service/plenary-service";

type EditForm = {
  name: string;
  meetingDate: string;
  deadline: string;
};

const API_BASE_URL =
  process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001/api/v1";

const BACKEND_ORIGIN = API_BASE_URL.replace(/\/api\/v1\/?$/, "");

function toDateInputValue(value: string | null | undefined): string {
  if (!value) {
    return "";
  }

  return value.slice(0, 10);
}

function getMinistryLogoUrl(
  logo: string | null | undefined,
): string | undefined {
  if (!logo) {
    return undefined;
  }

  if (logo.startsWith("http://") || logo.startsWith("https://")) {
    return logo;
  }

  return `${BACKEND_ORIGIN}${logo.startsWith("/") ? "" : "/"}${logo}`;
}

function formatFileSize(bytes: number): string {
  if (bytes < 1024) {
    return `${bytes} B`;
  }

  if (bytes < 1024 * 1024) {
    return `${Math.ceil(bytes / 1024)} KB`;
  }

  return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
}

function getDocumentFileName(
  documentReference: string | null | undefined,
): string {
  if (!documentReference) {
    return "Document Reference";
  }

  const referenceWithoutHash = documentReference.split("#")[0];

  const [filePath, queryString = ""] = referenceWithoutHash.split("?");

  const originalName = new URLSearchParams(queryString).get("originalName");

  if (originalName?.trim()) {
    return originalName.trim();
  }

  const fileName = filePath.replace(/\\/g, "/").split("/").pop();

  if (!fileName) {
    return "Document Reference";
  }

  try {
    return decodeURIComponent(fileName);
  } catch {
    return fileName;
  }
}

function getErrorMessage(error: unknown): string {
  if (error instanceof Error && error.message.trim()) {
    return error.message;
  }

  return "Unable to update Plenary.";
}

function FieldLabel({
  children,
  required = false,
}: {
  children: string;
  required?: boolean;
}) {
  return (
    <Typography
      sx={{
        mb: 1.4,
        color: "text.primary",
        fontSize: 15,
        fontWeight: 600,
        lineHeight: 1.25,
      }}
    >
      {children}

      {required ? (
        <Box
          component="span"
          sx={{
            ml: 0.35,
            color: "#EF4444",
          }}
        >
          *
        </Box>
      ) : null}
    </Typography>
  );
}

export function PlenaryEditScreen() {
  const router = useRouter();
  const params = useParams();
  const theme = useTheme();

  const plenaryId = Number(params?.id);

  const isValidPlenaryId = Number.isInteger(plenaryId) && plenaryId > 0;

  const fileInputRef = useRef<HTMLInputElement | null>(null);

  const [plenary, setPlenary] = useState<PlenaryApiItem | null>(null);

  const [ministries, setMinistries] = useState<PlenaryMinistryApi[]>([]);

  const [selectedMinistries, setSelectedMinistries] = useState<
    PlenaryMinistryApi[]
  >([]);

  const [selectedDocument, setSelectedDocument] = useState<File | null>(null);

  const [form, setForm] = useState<EditForm>({
    name: "",
    meetingDate: "",
    deadline: "",
  });

  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState("");

  const selectedMinistryIds = useMemo(
    () => selectedMinistries.map((item) => item.id),
    [selectedMinistries],
  );

  useEffect(() => {
    if (!isValidPlenaryId) {
      return;
    }

    let cancelled = false;

    async function loadEditData() {
      try {
        const [detail, ministryOptions] = await Promise.all([
          getPlenaryDetail(plenaryId),
          getActiveMinistries(),
        ]);

        if (cancelled) {
          return;
        }

        const currentMinistries = detail.ministries ?? [];

        const ministryMap = new Map<number, PlenaryMinistryApi>();

        ministryOptions.forEach((ministry) => {
          ministryMap.set(ministry.id, ministry);
        });

        currentMinistries.forEach((ministry) => {
          if (!ministryMap.has(ministry.id)) {
            ministryMap.set(ministry.id, ministry);
          }
        });

        const mergedMinistries = [...ministryMap.values()];

        const selected = currentMinistries
          .map(
            (ministry) =>
              mergedMinistries.find((item) => item.id === ministry.id) ??
              ministry,
          )
          .filter((item): item is PlenaryMinistryApi => Boolean(item));

        setPlenary(detail);
        setMinistries(mergedMinistries);
        setSelectedMinistries(selected);

        setForm({
          name: detail.name ?? "",
          meetingDate: toDateInputValue(detail.meetingDate),
          deadline: toDateInputValue(detail.deadline),
        });

        setSelectedDocument(null);
        setError("");
      } catch (loadError: unknown) {
        if (!cancelled) {
          setError(getErrorMessage(loadError));
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    }

    void loadEditData();

    return () => {
      cancelled = true;
    };
  }, [isValidPlenaryId, plenaryId]);

  function updateForm<K extends keyof EditForm>(field: K, value: EditForm[K]) {
    setForm((current) => ({
      ...current,
      [field]: value,
    }));
  }

  function openDocumentPicker() {
    if (!fileInputRef.current) {
      return;
    }

    fileInputRef.current.value = "";
    fileInputRef.current.click();
  }

  function handleDocumentChange(event: ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0];

    if (!file) {
      return;
    }

    const isPdf =
      file.type === "application/pdf" ||
      file.name.toLowerCase().endsWith(".pdf");

    if (!isPdf) {
      setError("Only PDF documents are allowed.");
      event.target.value = "";
      return;
    }

    if (file.size > 10 * 1024 * 1024) {
      setError("Document file size must not exceed 10 MB.");
      event.target.value = "";
      return;
    }

    setSelectedDocument(file);
    setError("");
  }

  function validateForm(): string | null {
    if (!form.name.trim()) {
      return "Plenary Name is required.";
    }

    if (!form.meetingDate) {
      return "Meeting Date is required.";
    }

    if (!form.deadline) {
      return "Deadline is required.";
    }

    if (form.deadline < form.meetingDate) {
      return "Deadline must be equal to or later than Meeting Date.";
    }

    if (selectedMinistryIds.length === 0) {
      return "Please select at least one Ministry.";
    }

    return null;
  }

  async function handleSave() {
    if (!plenary) {
      return;
    }

    const validationError = validateForm();

    if (validationError) {
      setError(validationError);
      return;
    }

    try {
      setSaving(true);
      setError("");

      await updatePlenary(plenary.id, {
        name: form.name.trim(),
        meetingDate: form.meetingDate,
        deadline: form.deadline,
        ministryIds: selectedMinistryIds,
      });

      if (selectedDocument) {
        await uploadPlenaryDocument(plenary.id, selectedDocument);
      }

      router.push(`/cdc-gpsf/plenary/plenaries/${plenary.id}`);

      router.refresh();
    } catch (saveError: unknown) {
      setError(getErrorMessage(saveError));
    } finally {
      setSaving(false);
    }
  }

  const fieldSx = {
    "& .MuiOutlinedInput-root": {
      minHeight: 48,
      borderRadius: "7px",
      bgcolor: alpha(theme.palette.text.primary, 0.018),

      "& fieldset": {
        borderColor: alpha(theme.palette.text.primary, 0.1),
      },

      "&:hover fieldset": {
        borderColor: alpha(theme.palette.primary.main, 0.42),
      },

      "&.Mui-focused fieldset": {
        borderColor: theme.palette.primary.main,
        borderWidth: 1,
      },
    },

    "& .MuiInputBase-input": {
      py: "10px",
      fontSize: 14,
      fontWeight: 500,
    },

    "& .MuiInputBase-input[type='date']": {
      py: "10px",
    },

    "& .MuiAutocomplete-inputRoot": {
      minHeight: 48,
      py: "0 !important",
      px: "12px !important",
      alignItems: "center",
    },

    "& .MuiAutocomplete-input": {
      py: "0 !important",
      minWidth: "16px !important",
    },

    "& .MuiAutocomplete-endAdornment": {
      right: "12px !important",
    },
  };

  const iconSx = {
    color: "text.secondary",
    fontSize: 20,
  };

  if (!isValidPlenaryId) {
    return (
      <Box sx={{ p: 4 }}>
        <Alert severity="error">Invalid Plenary ID.</Alert>
      </Box>
    );
  }

  if (loading) {
    return (
      <Box
        sx={{
          minHeight: "65vh",
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
        }}
      >
        <CircularProgress size={30} />
      </Box>
    );
  }

  if (!plenary) {
    return (
      <Box sx={{ p: 4 }}>
        <Alert severity="error">{error || "Plenary was not found."}</Alert>
      </Box>
    );
  }

  const isSent = plenary.statusCode === "SENT";

  const documentTitle = selectedDocument
    ? selectedDocument.name
    : getDocumentFileName(plenary.documentReference);

  const documentSize = selectedDocument
    ? `${formatFileSize(selectedDocument.size)} · Ready to upload`
    : "200 KB";

  return (
    <Box
      sx={{
        width: "100%",
        minHeight: "100%",
        pl: {
          xs: 2,
          sm: 4,
          md: 8,
        },
        pr: {
          xs: 2,
          sm: 4,
          md: 4,
        },
        py: {
          xs: 3,
          md: 4.5,
        },
        bgcolor: "background.default",
      }}
    >
      <Box
        sx={{
          width: "100%",
          maxWidth: "none",
          mx: 0,
        }}
      >
        <Box
          sx={{
            mb: 4,
            display: "grid",
            gridTemplateColumns: {
              xs: "1fr",
              md: "130px minmax(0, 1fr) auto",
            },
            alignItems: {
              xs: "flex-start",
              md: "center",
            },
            gap: {
              xs: 2,
              md: 2.5,
            },
          }}
        >
          <Button
            onClick={() => router.back()}
            startIcon={
              <ArrowBackIosNewOutlinedIcon
                sx={{
                  fontSize: 15,
                }}
              />
            }
            sx={{
              width: "fit-content",
              minWidth: "auto",
              px: 0,
              py: 0.25,
              color: "text.secondary",
              textTransform: "none",
              fontSize: 14,
              fontWeight: 500,

              "&:hover": {
                bgcolor: "transparent",
                color: "text.primary",
              },
            }}
          >
            Back
          </Button>

          <Box>
            <Typography
              sx={{
                color: "text.primary",
                fontSize: 22,
                fontWeight: 700,
                lineHeight: 1.2,
              }}
            >
              Edit Plenary
            </Typography>

            <Typography
              sx={{
                mt: 0.7,
                color: "text.secondary",
                fontSize: 14,
              }}
            >
              Update Plenary Information
            </Typography>
          </Box>

          <Box
            sx={{
              display: "flex",
              alignItems: "center",
              gap: 2,
              justifyContent: {
                xs: "flex-start",
                md: "flex-end",
              },
            }}
          >
            <Button
              variant="outlined"
              disabled={saving}
              startIcon={<CloseOutlinedIcon sx={{ fontSize: 21 }} />}
              onClick={() => router.back()}
              sx={{
                minWidth: 130,
                height: 48,
                borderRadius: "7px",
                borderColor: alpha(theme.palette.text.primary, 0.42),
                color: "text.secondary",
                textTransform: "none",
                fontSize: 14,
                fontWeight: 600,
              }}
            >
              Cancel
            </Button>

            <Button
              variant="outlined"
              disabled={saving}
              startIcon={
                saving ? (
                  <CircularProgress size={18} color="inherit" />
                ) : (
                  <CheckOutlinedIcon sx={{ fontSize: 21 }} />
                )
              }
              onClick={() => void handleSave()}
              sx={{
                minWidth: 156,
                height: 48,
                borderRadius: "7px",
                borderColor: alpha(theme.palette.text.primary, 0.42),
                color: "text.secondary",
                textTransform: "none",
                fontSize: 14,
                fontWeight: 600,
              }}
            >
              {saving ? "Saving..." : "Save Change"}
            </Button>
          </Box>
        </Box>

        {error ? (
          <Alert
            severity="error"
            onClose={() => setError("")}
            sx={{
              mb: 3,
            }}
          >
            {error}
          </Alert>
        ) : null}

        <Box
          sx={{
            display: "grid",
            gridTemplateColumns: "1fr",
            gap: 4,
          }}
        >
          <Box>
            <FieldLabel required>Plenary Name</FieldLabel>

            <TextField
              fullWidth
              value={form.name}
              placeholder="Input plenary name"
              onChange={(event) => updateForm("name", event.target.value)}
              slotProps={{
                input: {
                  startAdornment: (
                    <InputAdornment position="start">
                      <PersonOutlineOutlinedIcon sx={iconSx} />
                    </InputAdornment>
                  ),
                },
              }}
              sx={fieldSx}
            />
          </Box>

          <Box>
            <FieldLabel required>Ministry</FieldLabel>

            <Autocomplete
              multiple
              disableCloseOnSelect
              disableClearable
              options={ministries}
              value={selectedMinistries}
              onChange={(_event, nextValue) => {
                setSelectedMinistries(nextValue);
              }}
              getOptionLabel={(option) => option.name}
              isOptionEqualToValue={(option, selected) =>
                option.id === selected.id
              }
              popupIcon={<KeyboardArrowDownOutlinedIcon />}
              renderOption={(optionProps, option, state) => (
                <Box
                  component="li"
                  {...optionProps}
                  sx={{
                    minHeight: 50,
                    gap: 1.25,
                  }}
                >
                  <Checkbox
                    checked={state.selected}
                    sx={{
                      p: 0,
                      mr: 0.5,
                    }}
                  />

                  <Avatar
                    src={getMinistryLogoUrl(option.logo)}
                    alt={option.name}
                    sx={{
                      width: 28,
                      height: 28,
                      fontSize: 12,
                      fontWeight: 800,
                      bgcolor: alpha(theme.palette.primary.main, 0.12),
                      color: "primary.main",
                    }}
                  >
                    {option.name.charAt(0).toUpperCase()}
                  </Avatar>

                  <Typography
                    sx={{
                      fontSize: 14,
                      fontWeight: 600,
                    }}
                  >
                    {option.name}
                  </Typography>
                </Box>
              )}
              renderValue={(value) => {
                const selected = Array.from(value);

                if (selected.length === 0) {
                  return null;
                }

                return (
                  <Box
                    sx={{
                      minWidth: 0,
                      display: "flex",
                      alignItems: "center",
                      gap: 1.1,
                      overflow: "hidden",
                    }}
                  >
                    <PersonOutlineOutlinedIcon
                      sx={{
                        flexShrink: 0,
                        color: "text.secondary",
                        fontSize: 21,
                      }}
                    />

                    <Box
                      sx={{
                        display: "flex",
                        alignItems: "center",
                        flexShrink: 0,

                        "& .MuiAvatar-root:not(:first-of-type)": {
                          ml: -0.8,
                        },
                      }}
                    >
                      {selected.slice(0, 3).map((item) => (
                        <Avatar
                          key={item.id}
                          src={getMinistryLogoUrl(item.logo)}
                          alt={item.name}
                          sx={{
                            width: 28,
                            height: 28,
                            fontSize: 11,
                            fontWeight: 800,
                            border: `2px solid ${theme.palette.background.paper}`,
                            bgcolor: alpha(theme.palette.primary.main, 0.12),
                            color: "primary.main",
                          }}
                        >
                          {item.name.charAt(0).toUpperCase()}
                        </Avatar>
                      ))}
                    </Box>

                    <Typography
                      sx={{
                        minWidth: 0,
                        overflow: "hidden",
                        textOverflow: "ellipsis",
                        whiteSpace: "nowrap",
                        fontSize: 14,
                        fontWeight: 600,
                      }}
                    >
                      {selected.map((item) => item.name).join(", ")}
                    </Typography>
                  </Box>
                );
              }}
              renderInput={(params) => (
                <TextField
                  {...params}
                  placeholder={
                    selectedMinistries.length === 0 ? "Select Ministry" : ""
                  }
                  sx={fieldSx}
                />
              )}
            />
          </Box>

          <Box
            sx={{
              display: "grid",
              gridTemplateColumns: {
                xs: "1fr",
                md: "1fr 1fr",
              },
              columnGap: {
                md: 5,
              },
              rowGap: 4,
            }}
          >
            <Box>
              <FieldLabel required>Meeting Date</FieldLabel>

              <TextField
                fullWidth
                type="date"
                value={form.meetingDate}
                onChange={(event) =>
                  updateForm("meetingDate", event.target.value)
                }
                slotProps={{
                  input: {
                    startAdornment: (
                      <InputAdornment position="start">
                        <CalendarMonthOutlinedIcon sx={iconSx} />
                      </InputAdornment>
                    ),
                  },
                }}
                sx={fieldSx}
              />
            </Box>

            <Box>
              <FieldLabel required>Deadline</FieldLabel>

              <TextField
                fullWidth
                type="date"
                value={form.deadline}
                onChange={(event) => updateForm("deadline", event.target.value)}
                slotProps={{
                  input: {
                    startAdornment: (
                      <InputAdornment position="start">
                        <CalendarMonthOutlinedIcon sx={iconSx} />
                      </InputAdornment>
                    ),
                  },
                }}
                sx={fieldSx}
              />
            </Box>

            <Box>
              <FieldLabel required>Status</FieldLabel>

              <Box
                sx={{
                  minHeight: 48,
                  px: 2,
                  display: "flex",
                  alignItems: "center",
                  border: "1px solid",
                  borderColor: alpha(theme.palette.text.primary, 0.1),
                  borderRadius: "7px",
                  bgcolor: alpha(theme.palette.text.primary, 0.018),
                }}
              >
                <Chip
                  label={plenary.status}
                  size="small"
                  sx={{
                    minWidth: 112,
                    height: 22,
                    borderRadius: "20px",
                    fontSize: 12,
                    fontWeight: 600,
                    color: isSent ? "#16A34A" : "#D97706",
                    bgcolor: alpha(isSent ? "#22C55E" : "#F59E0B", 0.08),
                    border: `1px solid ${alpha(
                      isSent ? "#22C55E" : "#F59E0B",
                      0.25,
                    )}`,
                  }}
                />
              </Box>
            </Box>

            <Box>
              <FieldLabel required>Attachment</FieldLabel>

              <input
                ref={fileInputRef}
                hidden
                type="file"
                accept="application/pdf,.pdf"
                onChange={handleDocumentChange}
              />

              <Box
                role="button"
                tabIndex={0}
                onClick={openDocumentPicker}
                onKeyDown={(event) => {
                  if (event.key === "Enter" || event.key === " ") {
                    event.preventDefault();
                    openDocumentPicker();
                  }
                }}
                sx={{
                  width: 262,
                  maxWidth: "100%",
                  minHeight: 48,
                  px: 1.25,
                  py: 0.65,
                  display: "flex",
                  alignItems: "center",
                  gap: 1.1,
                  cursor: "pointer",
                  borderRadius: "7px",
                  border: "1px solid",
                  borderColor: alpha(theme.palette.text.primary, 0.04),
                  bgcolor: alpha(theme.palette.text.primary, 0.025),

                  "&:hover": {
                    bgcolor: alpha(theme.palette.primary.main, 0.045),
                    borderColor: alpha(theme.palette.primary.main, 0.2),
                  },
                }}
              >
                <PictureAsPdfOutlinedIcon
                  sx={{
                    flexShrink: 0,
                    color: "#EF4444",
                    fontSize: 21,
                  }}
                />

                <Tooltip title={documentTitle} arrow>
                  <Box
                    sx={{
                      minWidth: 0,
                      flex: 1,
                    }}
                  >
                    <Typography
                      sx={{
                        maxWidth: 190,
                        overflow: "hidden",
                        textOverflow: "ellipsis",
                        whiteSpace: "nowrap",
                        color: "text.primary",
                        fontSize: 13,
                        fontWeight: 600,
                        lineHeight: 1.15,
                      }}
                    >
                      {documentTitle}
                    </Typography>

                    <Typography
                      sx={{
                        mt: 0.25,
                        color: selectedDocument
                          ? "primary.main"
                          : "text.secondary",
                        fontSize: 10,
                        lineHeight: 1.1,
                      }}
                    >
                      {documentSize}
                    </Typography>
                  </Box>
                </Tooltip>
              </Box>
            </Box>
          </Box>
        </Box>
      </Box>
    </Box>
  );
}
