"use client";

import { useMemo, useRef, useState } from "react";
import type { ChangeEvent, DragEvent } from "react";

import Box from "@mui/material/Box";
import Checkbox from "@mui/material/Checkbox";
import Dialog from "@mui/material/Dialog";
import Typography from "@mui/material/Typography";
import { alpha, useTheme } from "@mui/material/styles";

import { AppButton, AppSecondaryButton } from "@/components/ui/button";
import {
  AppFormField,
  AppFormGrid,
  AppFormTextField,
  getFormBorderColor,
} from "@/components/ui/form";
import { AppSelect } from "@/components/ui/select";
import { AppTextEditor } from "@/components/ui/text-editor";
import { useCdcIssueForm } from "../hook/use-cdc-issue-form";
import type {
  CdcIssueMatrixFormAgency,
  CdcIssueMatrixFormWorkingGroup,
} from "../service/cdc-issue-matrix-service";
import { AgencyDisplay } from "@/features/pswg/plenary/components/add-issue-dialog/agency-display";
import { IssueAttachmentField } from "@/features/pswg/plenary/components/add-issue-dialog/issue-attachment-field";
import type { Agency, UploadStatus } from "@/features/pswg/plenary/components/add-issue-dialog/add-issue-dialog-types";

type CdcAddIssueDialogProps = {
  open: boolean;
  onClose: () => void;
  onCreated?: () => void;
};

function toAgency(value: CdcIssueMatrixFormAgency): Agency {
  return {
    id: String(value.id),
    logo: value.logo ?? "",
    name: value.name,
  };
}

function toWorkingGroupOption(value: CdcIssueMatrixFormWorkingGroup) {
  return {
    label: value.name,
    value: String(value.id),
  };
}

function toSelectedAgencyIds(values: string[]) {
  return values
    .filter((value) => value.trim() !== "")
    .map((value, index) => ({
      agencyOrder: index + 1,
      stakeholderId: Number(value),
    }))
    .filter((value) => Number.isFinite(value.stakeholderId));
}

export default function CdcAddIssueDialog({
  open,
  onClose,
  onCreated,
}: CdcAddIssueDialogProps) {
  const theme = useTheme();
  const {
    agencies,
    error: formError,
    isLoading,
    isSaving,
    draftIssueStatusId,
    issueStatusId,
    save,
    workingGroups,
  } = useCdcIssueForm(open);

  const [workingGroupId, setWorkingGroupId] = useState("");
  const [governmentAgency, setGovernmentAgency] = useState("");
  const [issue, setIssue] = useState("");
  const [description, setDescription] = useState("");
  const [recommendation, setRecommendation] = useState("");
  const [additionalAgencies, setAdditionalAgencies] = useState([
    "",
    "",
    "",
    "",
  ]);
  const [attachment, setAttachment] = useState<File | null>(null);
  const [uploadStatus, setUploadStatus] = useState<UploadStatus>("idle");
  const [localError, setLocalError] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement | null>(null);

  const agencyOptions = useMemo(
    () => agencies.map(toAgency),
    [agencies],
  );
  const selectedGovernmentAgencyId =
    governmentAgency || agencyOptions[0]?.id || "";
  const workingGroupOptions = useMemo(
    () => workingGroups.map(toWorkingGroupOption),
    [workingGroups],
  );
  const selectedWorkingGroup = workingGroupOptions.find(
    (option) => option.value === workingGroupId,
  );

  const isFormFilled =
    workingGroupId !== "" &&
    selectedGovernmentAgencyId !== "" &&
    issue.trim() !== "" &&
    description.trim() !== "" &&
    recommendation.trim() !== "" &&
    issueStatusId > 0;

  function handleAdditionalAgencyChange(index: number, value: string) {
    setAdditionalAgencies((current) =>
      current.map((agency, agencyIndex) =>
        agencyIndex === index ? value : agency,
      ),
    );
  }

  function handleSelectedFile(file: File) {
    if (file.size > 10 * 1024 * 1024) {
      setLocalError("Attachment file size must not exceed 10 MB.");
      return;
    }

    setLocalError(null);
    setAttachment(file);
    setUploadStatus("uploading");
    window.setTimeout(() => setUploadStatus("completed"), 800);
  }

  function handleFileChange(event: ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0];
    if (file) handleSelectedFile(file);
    event.target.value = "";
  }

  function handleDrop(event: DragEvent<HTMLDivElement>) {
    event.preventDefault();
    const file = event.dataTransfer.files?.[0];
    if (file) handleSelectedFile(file);
  }

  async function handleSave(statusId: number) {
    setLocalError(null);

    if (!isFormFilled || statusId <= 0) {
      setLocalError("Please complete all required fields.");
      return;
    }

    try {
      await save({
        attachmentFile: attachment,
        description: description.trim(),
        governmentAgencies: toSelectedAgencyIds([
          selectedGovernmentAgencyId,
          ...additionalAgencies,
        ]),
        issueStatusId: statusId,
        recommendation: recommendation.trim(),
        workingGroupId: Number(workingGroupId),
        title: issue.trim(),
      });
      onCreated?.();
      onClose();
    } catch {
      // The hook exposes the server error below; keep the drawer open so the
      // user can correct the form without losing the entered values.
    }
  }

  return (
    <Dialog
      open={open}
      onClose={onClose}
      maxWidth={false}
      scroll="paper"
      sx={{
        "& .MuiDialog-container": {
          alignItems: "flex-start",
          justifyContent: "flex-end",
        },
      }}
      slotProps={{
        paper: {
          sx: {
            mt: 0,
            mr: 0,
            width: 700,
            maxWidth: "95vw",
            maxHeight: "calc(100vh - 16px)",
            borderRadius: "10px",
            overflow: "hidden",
            bgcolor: theme.palette.background.paper,
            color: theme.palette.text.primary,
          },
        },
      }}
    >
      <Box
        sx={{
          px: 2,
          py: 1.6,
          borderBottom: `1px solid ${getFormBorderColor(theme)}`,
        }}
      >
        <Typography sx={{ fontSize: 18, fontWeight: 700 }}>
          Add Issue
        </Typography>
      </Box>

      <Box
        sx={{
          px: 2,
          py: 1.8,
          overflowY: "auto",
          maxHeight: "calc(100vh - 150px)",
        }}
      >
        {localError || formError ? (
          <Typography
            sx={{
              mb: 1.4,
              px: 1.2,
              py: 1,
              borderRadius: "6px",
              bgcolor: theme.palette.mode === "dark" ? "rgba(239,68,68,0.14)" : "#FEF2F2",
              color: "#DC2626",
              fontSize: 12,
              fontWeight: 600,
            }}
          >
            {localError ?? formError}
          </Typography>
        ) : null}

        {isLoading ? (
          <Typography sx={{ mb: 1.4, color: theme.palette.text.secondary, fontSize: 12 }}>
            Loading form options...
          </Typography>
        ) : null}

        <AppFormGrid sx={{ mb: 1.6 }}>
          <AppFormField label="Working Group Name" required>
            <AppSelect
              value={workingGroupId}
              options={workingGroupOptions}
              placeholder="Select working group name"
              onChange={setWorkingGroupId}
              renderSelectedValue={() => (
                <Typography sx={{ fontSize: 12, fontWeight: 600 }}>
                  {selectedWorkingGroup?.label ?? "Select working group name"}
                </Typography>
              )}
              renderOption={(option) => (
                <Box sx={{ display: "flex", alignItems: "center", gap: 0.5 }}>
                  <Checkbox
                    checked={option.value === workingGroupId}
                    size="small"
                    sx={{ p: 0.5, color: theme.palette.primary.main }}
                  />
                  <Typography sx={{ fontSize: 12 }}>{option.label}</Typography>
                </Box>
              )}
              MenuProps={{
                slotProps: {
                  paper: {
                    sx: {
                      maxHeight: 240,
                      "& .MuiMenuItem-root": { minHeight: 52 },
                    },
                  },
                },
              }}
            />
          </AppFormField>

          <AppFormField label="Government Agency" required>
            <AppSelect
              value={selectedGovernmentAgencyId}
              options={agencyOptions.map((agency) => ({
                data: agency,
                label: agency.name,
                value: agency.id,
              }))}
              placeholder="Select Agency"
              onChange={setGovernmentAgency}
              renderSelectedValue={(option) => (
                <AgencyDisplay agency={option?.data} />
              )}
              renderOption={(option) => <AgencyDisplay agency={option.data} />}
            />
          </AppFormField>
        </AppFormGrid>

        <Box sx={{ mb: 1.6 }}>
          <AppFormField label="Issue" required>
            <AppFormTextField
              value={issue}
              onChange={(event) => setIssue(event.target.value)}
              placeholder="Write Issue title"
            />
          </AppFormField>
        </Box>

        <Box sx={{ mb: 1.6 }}>
          <AppFormField label="Description of the Issue" required>
            <AppTextEditor
              value={description}
              onChange={setDescription}
              placeholder="Write description ........"
            />
          </AppFormField>
        </Box>

        <Box sx={{ mb: 1.6 }}>
          <AppFormField label="Recommendation" required>
            <AppTextEditor
              value={recommendation}
              onChange={setRecommendation}
              placeholder="Write Recommendation.........."
            />
          </AppFormField>
        </Box>

        <IssueAttachmentField
          attachment={attachment}
          fileInputRef={fileInputRef}
          uploadStatus={uploadStatus}
          onFileChange={handleFileChange}
          onUploadClick={() => fileInputRef.current?.click()}
          onDrop={handleDrop}
          onDragOver={(event) => event.preventDefault()}
        />

        <AppFormGrid>
          {additionalAgencies.map((value, index) => (
            <AppFormField key={index} label={`${index + 2}${index === 0 ? "nd" : index === 1 ? "rd" : index === 2 ? "th" : "th"} Agency`}>
              <AppSelect
                value={value}
                options={agencyOptions
                  .filter(
                    (agency) =>
                      agency.id !== selectedGovernmentAgencyId &&
                      additionalAgencies.every(
                        (selectedAgencyId, selectedIndex) =>
                          selectedIndex === index ||
                          selectedAgencyId !== agency.id,
                      ),
                  )
                  .map((agency) => ({
                    data: agency,
                    label: agency.name,
                    value: agency.id,
                  }))}
                placeholder="Select Agency"
                onChange={(nextValue) => handleAdditionalAgencyChange(index, nextValue)}
                renderSelectedValue={(option) => <AgencyDisplay agency={option?.data} />}
                renderOption={(option) => <AgencyDisplay agency={option.data} />}
              />
            </AppFormField>
          ))}
        </AppFormGrid>
      </Box>

      <Box
        sx={{
          px: 2,
          py: 1.5,
          borderTop: `1px solid ${getFormBorderColor(theme)}`,
          display: "flex",
          justifyContent: "flex-end",
          gap: 2,
        }}
      >
        <AppSecondaryButton
          onClick={() => void handleSave(draftIssueStatusId)}
          disabled={isSaving || !isFormFilled}
          sx={{
            width: 125,
            minWidth: 125,
            height: 36,
            color: isFormFilled ? theme.palette.primary.main : theme.palette.text.primary,
            borderColor: isFormFilled ? theme.palette.primary.main : getFormBorderColor(theme),
            fontWeight: 700,
            fontSize: 12,
            "&:hover": {
              borderColor: theme.palette.primary.main,
              bgcolor: alpha(theme.palette.primary.main, 0.08),
            },
          }}
        >
          Draft
        </AppSecondaryButton>
        <AppButton
          onClick={() => void handleSave(issueStatusId)}
          disabled={isSaving || !isFormFilled}
          sx={{
            width: 125,
            minWidth: 125,
            height: 36,
            bgcolor: isFormFilled ? theme.palette.primary.main : "#7B828D",
            fontWeight: 700,
            fontSize: 12,
          }}
        >
          {isSaving ? "Saving..." : "Save"}
        </AppButton>
      </Box>
    </Dialog>
  );
}
