"use client";

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

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

import { getFormBorderColor } from "@/components/ui/form";
import type { AppSelectOption } from "@/components/ui/select";
import { AdditionalAgencyFields } from "@/features/pswg/working-group-issues/components/create-issuses/additional-agency-fields";
import type {
  AddWorkingGroupIssueDialogProps,
  Agency,
  UploadStatus,
} from "@/features/pswg/working-group-issues/components/create-issuses/add-working-group-issue-dialog-types";
import { DialogFooter } from "@/features/pswg/working-group-issues/components/create-issuses/dialog-footer";
import { IssueAttachmentField } from "@/features/pswg/working-group-issues/components/create-issuses/issue-attachment-field";
import { WorkingGroupIssueMainFields } from "@/features/pswg/working-group-issues/components/create-issuses/working-group-issue-main-fields";
import {
  useWgCategories,
  useWgIssuePrimaryGovernment,
  useWorkingGroupIssueDetail,
  useWorkingGroupIssueForm,
} from "@/features/pswg/working-group-issues/hook/use-working-group-issues";
import type { WorkingGroupIssueAgency } from "@/features/pswg/working-group-issues/service/working-group-issues-service";

const ATTACHMENT_MAX_BYTES = 10 * 1024 * 1024;

function toAgencyOption(
  agency: WorkingGroupIssueAgency,
): AppSelectOption<Agency> {
  return {
    data: {
      id: String(agency.id),
      logo: agency.logo ?? "",
      name: agency.name,
    },
    label: agency.name,
    value: String(agency.id),
  };
}

type IssueFormState = {
  workingGroupName: string | null;
  governmentAgency: string;
  categoryId: string;
  issue: string;
  description: string;
  recommendation: string;
  secondAgency: string;
  thirdAgency: string;
  fourthAgency: string;
  fifthAgency: string;
  currentIssueStatusId: number | null;
  syncedDetailId: number | null;
  lastOpen: boolean;
};

function createEmptyIssueFormState(open: boolean): IssueFormState {
  return {
    workingGroupName: null,
    governmentAgency: "",
    categoryId: "",
    issue: "",
    description: "",
    recommendation: "",
    secondAgency: "",
    thirdAgency: "",
    fourthAgency: "",
    fifthAgency: "",
    currentIssueStatusId: null,
    syncedDetailId: null,
    lastOpen: open,
  };
}

export default function AddWorkingGroupIssueDialog({
  issueId,
  onCreated,
  onSaved,
  open,
  onClose,
}: AddWorkingGroupIssueDialogProps) {
  const theme = useTheme();
  const isEditMode = issueId !== undefined;
  const {
    agencies,
    createIssue,
    defaultDraftStatusId,
    defaultSavedStatusId,
    error,
    isLoadingOptions,
    isSaving,
    updateIssue,
  } = useWorkingGroupIssueForm();

  const {
    data: primaryGovernment,
    error: primaryGovernmentError,
    isLoading: isLoadingPrimaryGovernment,
  } = useWgIssuePrimaryGovernment(open && !isEditMode);

  const [formState, setFormState] = useState(() =>
    createEmptyIssueFormState(open),
  );
  const [localError, setLocalError] = useState<string | null>(null);
  const {
    workingGroupName,
    governmentAgency,
    categoryId,
    issue,
    description,
    recommendation,
    secondAgency,
    thirdAgency,
    fourthAgency,
    fifthAgency,
  } = formState;

  // Categories are loaded from the same cache the filter bar uses, so opening
  // the dialog after the list has rendered is instant.
  const { data: categories = [], isLoading: isLoadingCategories } =
    useWgCategories();

  const [attachment, setAttachment] = useState<File | null>(null);
  const [uploadStatus, setUploadStatus] = useState<UploadStatus>("idle");

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

  // Only fetch the issue when the dialog is open in edit mode — React Query
  // caches it by id, so reopening the same issue is instant.
  const {
    detail: editingDetail,
    error: editingDetailError,
    isLoading: isLoadingIssue,
  } = useWorkingGroupIssueDetail(
    issueId ?? 0,
    "Unable to load issue.",
    open && isEditMode,
  );

  const agencyOptions = useMemo<AppSelectOption<Agency>[]>(
    () => {
      const options = agencies.map(toAgencyOption);

      if (!primaryGovernment?.governmentAgency) {
        return options;
      }

      const contextOption = toAgencyOption(primaryGovernment.governmentAgency);
      const hasContextAgency = options.some(
        (option) => option.value === contextOption.value,
      );

      return hasContextAgency ? options : [contextOption, ...options];
    },
    [agencies, primaryGovernment],
  );

  const categoryOptions = useMemo<AppSelectOption[]>(
    () =>
      categories.map((category) => ({
        label: category.name,
        value: String(category.id),
      })),
    [categories],
  );

  const primaryGovernmentErrorMessage =
    !isEditMode && primaryGovernmentError
      ? primaryGovernmentError instanceof Error
        ? primaryGovernmentError.message
        : "Unable to load related government agency."
      : null;
  const contextGovernmentAgency = primaryGovernment?.governmentAgency
    ? String(primaryGovernment.governmentAgency.id)
    : "";
  const primaryGovernmentAgency = isEditMode
    ? governmentAgency
    : contextGovernmentAgency;
  const visibleWorkingGroupName =
    workingGroupName ?? primaryGovernment?.workingGroup.name ?? "";
  const additionalAgencyOptions = useMemo(
    () =>
      agencyOptions.filter((option) => option.value !== primaryGovernmentAgency),
    [agencyOptions, primaryGovernmentAgency],
  );

  const isFormFilled =
    visibleWorkingGroupName.trim() !== "" &&
    primaryGovernmentAgency.trim() !== "" &&
    categoryId.trim() !== "" &&
    issue.trim() !== "" &&
    description.trim() !== "" &&
    recommendation.trim() !== "";

  function updateFormField<Key extends keyof IssueFormState>(
    key: Key,
    value: IssueFormState[Key],
  ) {
    setFormState((previousState) => ({
      ...previousState,
      [key]: value,
    }));
  }

  const resetForm = useCallback(() => {
    setFormState((previousState) =>
      createEmptyIssueFormState(previousState.lastOpen),
    );
    setAttachment(null);
    setUploadStatus("idle");
    setLocalError(null);
  }, []);

  if (open !== formState.lastOpen) {
    if (open && !isEditMode) {
      setFormState(createEmptyIssueFormState(open));
    } else {
      setFormState((previousState) => ({
        ...previousState,
        lastOpen: open,
        syncedDetailId: open ? previousState.syncedDetailId : null,
      }));
    }
  } else if (open && isEditMode && editingDetail) {
    if (editingDetail.id !== formState.syncedDetailId) {
      const agencyByOrder = new Map(
        editingDetail.governmentAgencies.map((agency) => [
          agency.agencyOrder,
          String(agency.stakeholderId),
        ]),
      );

      setFormState((previousState) => ({
        ...previousState,
        governmentAgency: agencyByOrder.get(1) ?? "",
        secondAgency: agencyByOrder.get(2) ?? "",
        thirdAgency: agencyByOrder.get(3) ?? "",
        fourthAgency: agencyByOrder.get(4) ?? "",
        fifthAgency: agencyByOrder.get(5) ?? "",
        workingGroupName: editingDetail.workingGroupName,
        issue: editingDetail.title,
        description: editingDetail.description,
        recommendation: editingDetail.recommendation,
        categoryId:
          editingDetail.categoryId !== null
            ? String(editingDetail.categoryId)
            : "",
        currentIssueStatusId: editingDetail.issueStatusId,
        syncedDetailId: editingDetail.id,
        lastOpen: open,
      }));
      setAttachment(null);
      setUploadStatus("idle");
    }
  } else if (!open && formState.syncedDetailId !== null) {
    setFormState((previousState) => ({
      ...previousState,
      syncedDetailId: null,
      lastOpen: open,
    }));
  }

  const displayedError =
    localError ??
    (open && isEditMode ? editingDetailError : null) ??
    error ??
    primaryGovernmentErrorMessage;

  function handleSelectedFile(file: File) {
    if (file.size > ATTACHMENT_MAX_BYTES) {
      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) {
      return;
    }

    handleSelectedFile(file);
    event.target.value = "";
  }

  function handleDrop(event: DragEvent<HTMLDivElement>) {
    event.preventDefault();

    const file = event.dataTransfer.files?.[0];
    if (!file) {
      return;
    }

    handleSelectedFile(file);
  }

  function handleDragOver(event: DragEvent<HTMLDivElement>) {
    event.preventDefault();
  }

  function handleUploadClick() {
    fileInputRef.current?.click();
  }

  function getSelectedGovernmentAgencies() {
    return [
      { agencyId: primaryGovernmentAgency, agencyOrder: 1 },
      { agencyId: secondAgency, agencyOrder: 2 },
      { agencyId: thirdAgency, agencyOrder: 3 },
      { agencyId: fourthAgency, agencyOrder: 4 },
      { agencyId: fifthAgency, agencyOrder: 5 },
    ]
      .filter((agency) => agency.agencyId.trim() !== "")
      .map((agency) => ({
        agencyOrder: agency.agencyOrder,
        stakeholderId: Number(agency.agencyId),
      }))
      .filter((agency) => Number.isFinite(agency.stakeholderId));
  }

  async function submitIssue(issueStatusId: number | null) {
    setLocalError(null);

    if (!issueStatusId) {
      setLocalError("Issue status was not found. Please seed issue statuses.");
      return;
    }

    const governmentAgencies = getSelectedGovernmentAgencies();
    if (governmentAgencies.length === 0) {
      setLocalError("Please select at least one government agency.");
      return;
    }

    const parsedCategoryId = Number(categoryId);
    if (!Number.isFinite(parsedCategoryId) || parsedCategoryId < 1) {
      setLocalError("Please select an issue category.");
      return;
    }

    const payload = {
      attachmentFile: attachment,
      description: description.trim(),
      governmentAgencies,
      categoryId: parsedCategoryId,
      issueStatusId,
      recommendation: recommendation.trim(),
      title: issue.trim(),
    };

    const saved =
      isEditMode && issueId !== undefined
        ? await updateIssue(issueId, payload)
        : await createIssue(payload);

    if (saved) {
      resetForm();
      onCreated?.();
      onSaved?.();
      onClose();
    }
  }

  const isLoadingForm =
    isLoadingOptions ||
    isLoadingCategories ||
    isLoadingIssue ||
    (!isEditMode && isLoadingPrimaryGovernment);

  const isEditingDraft = isEditMode && editingDetail?.status === "Draft";

  function getSaveIssueStatusId() {
    if (isEditingDraft) {
      return defaultSavedStatusId;
    }

    return isEditMode
      ? formState.currentIssueStatusId ?? defaultDraftStatusId
      : defaultSavedStatusId ?? defaultDraftStatusId;
  }

  return (
    <Dialog
      open={open}
      onClose={onClose}
      maxWidth={false}
      scroll="paper"
      sx={{
        "& .MuiDialog-container": {
          justifyContent: "flex-end",
          alignItems: "flex-start",
        },
      }}
      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)}`,
          bgcolor: theme.palette.background.paper,
        }}
      >
        <Typography
          sx={{
            fontSize: 18,
            fontWeight: 700,
            color: theme.palette.text.primary,
          }}
        >
          {isEditMode ? "Edit Issue" : "Add Issue"}
        </Typography>
      </Box>

      <Box
        sx={{
          px: 2,
          py: 1.8,
          overflowY: "auto",
          maxHeight: "calc(100vh - 150px)",
          bgcolor: theme.palette.background.paper,
        }}
      >
        {displayedError ? (
          <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,
            }}
          >
            {displayedError}
          </Typography>
        ) : null}

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

        <WorkingGroupIssueMainFields
          agencyOptions={agencyOptions}
          categoryOptions={categoryOptions}
          isLoadingCategories={isLoadingCategories}
          isLoadingPrimaryGovernment={
            !isEditMode && isLoadingPrimaryGovernment
          }
          workingGroupName={visibleWorkingGroupName}
          onWorkingGroupNameChange={(value) =>
            updateFormField("workingGroupName", value)
          }
          governmentAgency={primaryGovernmentAgency}
          issue={issue}
          onIssueChange={(value) => updateFormField("issue", value)}
          categoryId={categoryId}
          onCategoryIdChange={(value) =>
            updateFormField("categoryId", value)
          }
          description={description}
          onDescriptionChange={(value) => updateFormField("description", value)}
          recommendation={recommendation}
          onRecommendationChange={(value) =>
            updateFormField("recommendation", value)
          }
        />

        <IssueAttachmentField
          attachment={attachment}
          existingAttachmentUrl={editingDetail?.attachment}
          fileInputRef={fileInputRef}
          uploadStatus={uploadStatus}
          onFileChange={handleFileChange}
          onUploadClick={handleUploadClick}
          onDrop={handleDrop}
          onDragOver={handleDragOver}
        />

        <AdditionalAgencyFields
          agencyOptions={additionalAgencyOptions}
          secondAgency={secondAgency}
          onSecondAgencyChange={(value) =>
            updateFormField("secondAgency", value)
          }
          thirdAgency={thirdAgency}
          onThirdAgencyChange={(value) => updateFormField("thirdAgency", value)}
          fourthAgency={fourthAgency}
          onFourthAgencyChange={(value) =>
            updateFormField("fourthAgency", value)
          }
          fifthAgency={fifthAgency}
          onFifthAgencyChange={(value) => updateFormField("fifthAgency", value)}
        />
      </Box>

      <DialogFooter
        isFormFilled={isFormFilled && !isLoadingForm}
        isSaving={isSaving}
        onSaveDraft={() => void submitIssue(defaultDraftStatusId)}
        onSubmitIssue={() => void submitIssue(getSaveIssueStatusId())}
        saveLabel={
          isEditingDraft ? "Save" : isEditMode ? "Save Changes" : "Save"
        }
      />
    </Dialog>
  );
}
