"use client";

import { useRouter } from "next/navigation";

import {
  useCallback,
  useEffect,
  useMemo,
  useState,
} from "react";

import Alert from "@mui/material/Alert";
import Box from "@mui/material/Box";
import Snackbar from "@mui/material/Snackbar";
import { useTheme } from "@mui/material/styles";

import { useAppLanguage } from "@/components/providers/app-language-provider";

import {
  CdcIssueMatrixFilters,
  defaultCdcIssueMatrixFilters,
  type CdcIssueMatrixFilterOptions,
  type CdcIssueMatrixFilterState,
} from "@/features/cdc/cdc-issue-matrix/components/cdc-issue-matrix-filters";

import { CdcIssueMatrixHeader } from "@/features/cdc/cdc-issue-matrix/components/cdc-issue-matrix-header";
import { normalizeCdcIssueMatrixLanguage } from "@/features/cdc/cdc-issue-matrix/components/cdc-issue-matrix-i18n";
import { CdcIssueMatrixStatusCards } from "@/features/cdc/cdc-issue-matrix/components/cdc-issue-matrix-status-cards";

import type { CdcIssueMatrixView } from "@/features/cdc/cdc-issue-matrix/components/cdc-issue-matrix-view-toggle";

import {
  useCefpGovernmentAgencies,
  useCefpIssueCategories,
  useDeleteCefpIssue,
  useCefpIssueMatrixList,
  useCefpIssueMatrixSummary,
  useCefpWorkingGroups,
  useCreateCefpIssue,
  useUpdateCefpIssue,
  useUpdateCefpIssueEscalation,
  useUpdateCefpIssueStatus,
} from "../hook/use-cefp-issue-matrix";

import { CefpAddIssueDrawer } from "./cefp-add-issue-drawer";
import { CefpDeleteIssueDialog } from "./cefp-delete-issue-dialog";
import { CefpIssueMatrixGrid } from "./cefp-issue-matrix-grid";

import type { CefpIssueMatrixRow } from "./cefp-issue-matrix-data";

import {
  CefpIssueMatrixTable,
  type CefpPlenaryEscalationControl,
  type CefpStatusEditControl,
  type CefpStatusOption,
} from "./cefp-issue-matrix-table";

import type { CefpAddIssueFormValue } from "./cefp-add-issue-types";

import {
  getCefpIssueEditInfo,
  type CefpIssueEditInfo,
} from "../service/cefp-issue-matrix-service";

const SAVED_STATUS_ID = Number(
  process.env.NEXT_PUBLIC_CEFP_SAVED_STATUS_ID ??
  process.env.NEXT_PUBLIC_CEFP_NEW_SUBMISSION_STATUS_ID ??
  3,
);

const DRAFT_STATUS_ID = Number(
  process.env.NEXT_PUBLIC_CEFP_DRAFT_STATUS_ID ?? 1,
);

/**
 * Backend status mapping.
 *
 * កុំប្ដូរទៅទាញពី rows ព្រោះអាចធ្វើឱ្យ ID ច្រឡំ។
 *
 * 4 = In Progress
 * 2 = Not Addressed
 * 5 = Solved
 */
const IN_PROGRESS_STATUS_ID = 4;
const NOT_ADDRESSED_STATUS_ID = 2;
const SOLVED_STATUS_ID = 5;

function parsePositiveInteger(
  value: string,
): number | null {
  const parsedValue = Number(value);

  if (
    !Number.isInteger(parsedValue) ||
    parsedValue <= 0
  ) {
    return null;
  }

  return parsedValue;
}

function buildGovernmentAgencies(
  formValue: CefpAddIssueFormValue,
) {
  const selectedIds = [
    parsePositiveInteger(
      formValue.governmentAgencyId,
    ),
    parsePositiveInteger(
      formValue.secondAgencyId,
    ),
    parsePositiveInteger(
      formValue.thirdAgencyId,
    ),
    parsePositiveInteger(
      formValue.fourthAgencyId,
    ),
    parsePositiveInteger(
      formValue.fifthAgencyId,
    ),
  ].filter(
    (id): id is number => id !== null,
  );

  const uniqueIds = selectedIds.filter(
    (id, index, allIds) =>
      allIds.indexOf(id) === index,
  );

  return uniqueIds.map(
    (stakeholderId, index) => ({
      stakeholderId,
      agencyOrder: index + 1,
    }),
  );
}

export function CefpIssueMatrixScreen() {
  const router = useRouter();
  const theme = useTheme();

  const { language } =
    useAppLanguage();

  const isKhmer =
    language === "kh";

  const matrixLanguage =
    normalizeCdcIssueMatrixLanguage(
      language,
    );

  const {
    rows,
    isLoading: isLoadingRows,
    isFetching: isFetchingRows,
    error: rowsError,
  } = useCefpIssueMatrixList();

  const {
    summary,
    isLoading: isLoadingSummary,
    isFetching: isFetchingSummary,
    error: summaryError,
  } = useCefpIssueMatrixSummary();

  const {
    workingGroups,
    isLoadingWorkingGroups,
    isFetchingWorkingGroups,
  } = useCefpWorkingGroups();

  const {
    governmentAgencies,
    isLoadingGovernmentAgencies,
    isFetchingGovernmentAgencies,
  } = useCefpGovernmentAgencies();

  const {
    categories,
    isLoadingCategories,
    isFetchingCategories,
  } = useCefpIssueCategories();

  const {
    createIssue,
    isCreating,
  } = useCreateCefpIssue();

  const {
    updateIssue,
    isUpdatingIssue,
  } = useUpdateCefpIssue();

  const {
    deleteIssue,
    isDeletingIssue,
  } = useDeleteCefpIssue();

  const {
    updateEscalation,
    isUpdatingEscalation,
    updatingEscalationIssueId,
  } =
    useUpdateCefpIssueEscalation();

  const {
    updateStatus,
    isUpdatingStatus,
    updatingStatusIssueId,
  } =
    useUpdateCefpIssueStatus();

  const [search, setSearch] =
    useState("");

  const [view, setView] =
    useState<CdcIssueMatrixView>(
      "list",
    );

  const [
    addIssueOpen,
    setAddIssueOpen,
  ] = useState(false);


  const [
    editRow,
    setEditRow,
  ] = useState<CefpIssueMatrixRow | null>(null);

  const [
    editIssueInfo,
    setEditIssueInfo,
  ] =
    useState<CefpIssueEditInfo | null>(
      null,
    );

  const [
    isLoadingEditAttachment,
    setIsLoadingEditAttachment,
  ] =
    useState(false);


  const [
    deleteRow,
    setDeleteRow,
  ] = useState<CefpIssueMatrixRow | null>(null);

  const [filters, setFilters] =
    useState<CdcIssueMatrixFilterState>({
      ...defaultCdcIssueMatrixFilters,
    });

  const [alert, setAlert] = useState<{
    open: boolean;
    severity: "success" | "error";
    message: string;
  }>({
    open: false,
    severity: "success",
    message: "",
  });

  const filterOptions =
    useMemo<CdcIssueMatrixFilterOptions>(
      () => {
        function getUniqueOptions(
          values: string[],
          sortDescending = false,
        ) {
          const options = Array.from(
            new Set(
              values.filter(
                (value) =>
                  value &&
                  value !== "-",
              ),
            ),
          );

          options.sort(
            (
              firstValue,
              secondValue,
            ) =>
              sortDescending
                ? Number(secondValue) -
                Number(firstValue)
                : firstValue.localeCompare(
                  secondValue,
                ),
          );

          return options;
        }

        return {
          category: getUniqueOptions(
            rows.map(
              (row) => row.category,
            ),
          ),

          status: getUniqueOptions(
            rows.map(
              (row) => row.status,
            ),
          ),

          workingGroup:
            getUniqueOptions(
              rows.map(
                (row) =>
                  row.workingGroup,
              ),
            ),

          year: getUniqueOptions(
            rows.map(
              (row) => row.year,
            ),
            true,
          ),

          plenaryEscalation: [
            "Yes",
            "No",
          ],
        };
      },
      [rows],
    );

  const handleFilterChange = (
    key: keyof CdcIssueMatrixFilterState,
    value: string[],
  ) => {
    setFilters(
      (previousFilters) => ({
        ...previousFilters,
        [key]: value,
      }),
    );
  };

  const prepareAfterCreate = () => {
    setSearch("");

    setFilters({
      ...defaultCdcIssueMatrixFilters,
    });

    setView("list");
  };

  const createFromForm = async (
    formValue: CefpAddIssueFormValue,
    issueStatusId: number,
  ) => {
    const workingGroupId =
      parsePositiveInteger(
        formValue.workingGroupId,
      );

    if (!workingGroupId) {
      throw new Error(
        isKhmer
          ? "សូមជ្រើសរើសក្រុមការងារ។"
          : "Please select a working group.",
      );
    }

    const categoryId =
      parsePositiveInteger(
        formValue.categoryId,
      );

    if (!categoryId) {
      throw new Error(
        isKhmer
          ? "សូមជ្រើសរើសប្រភេទបញ្ហា។"
          : "Please select a category of issue.",
      );
    }

    const selectedGovernmentAgencies =
      buildGovernmentAgencies(
        formValue,
      );

    if (
      selectedGovernmentAgencies.length ===
      0
    ) {
      throw new Error(
        isKhmer
          ? "សូមជ្រើសរើសយ៉ាងហោចណាស់មួយក្រសួង ឬស្ថាប័ន។"
          : "Please select at least one government agency.",
      );
    }

    const response =
      await createIssue({
        workingGroupId,

        title:
          formValue.issue.trim(),

        description:
          formValue.description.trim(),

        recommendation:
          formValue.recommendation.trim(),

        issueStatusId,

        categoryId,

        governmentAgencies:
          selectedGovernmentAgencies,

        attachmentFile:
          formValue.attachment ??
          undefined,
      });

    prepareAfterCreate();

    return response;
  };

  const handleSaveIssue = (
    formValue: CefpAddIssueFormValue,
  ) =>
    createFromForm(
      formValue,
      SAVED_STATUS_ID,
    );

  const handleSaveDraft = (
    formValue: CefpAddIssueFormValue,
  ) =>
    createFromForm(
      formValue,
      DRAFT_STATUS_ID,
    );

  const handleEscalationChange =
    useCallback(
      async (
        issueId: number,
        checked: boolean,
      ) => {
        try {
          await updateEscalation({
            issueId,
            escalation: checked,
          });

          setAlert({
            open: true,
            severity: "success",
            message: isKhmer
              ? "បានកែប្រែការបញ្ជូនបញ្ហាដោយជោគជ័យ។"
              : "Plenary escalation updated successfully.",
          });
        } catch (error) {
          setAlert({
            open: true,
            severity: "error",
            message:
              error instanceof Error
                ? error.message
                : isKhmer
                  ? "មិនអាចកែប្រែការបញ្ជូនបញ្ហាបានទេ។"
                  : "Unable to update plenary escalation.",
          });
        }
      },
      [
        isKhmer,
        updateEscalation,
      ],
    );

  const handleStatusChange =
    useCallback(
      async (
        issueId: number,
        option: CefpStatusOption,
      ) => {
        try {
          await updateStatus({
            issueId,

            issueStatusId:
              option.id,

            statusName:
              option.name,
          });

          setAlert({
            open: true,
            severity: "success",
            message: isKhmer
              ? "បានកែប្រែស្ថានភាពបញ្ហាដោយជោគជ័យ។"
              : `Issue status updated to ${option.name}.`,
          });
        } catch (error) {
          setAlert({
            open: true,
            severity: "error",
            message:
              error instanceof Error
                ? error.message
                : isKhmer
                  ? "មិនអាចកែប្រែស្ថានភាពបញ្ហាបានទេ។"
                  : "Unable to update issue status.",
          });
        }
      },
      [
        isKhmer,
        updateStatus,
      ],
    );

  const plenaryEscalationControl =
    useMemo<CefpPlenaryEscalationControl>(
      () => ({
        updatingIssueId:
          isUpdatingEscalation
            ? updatingEscalationIssueId
            : null,

        onChange:
          handleEscalationChange,
      }),
      [
        handleEscalationChange,
        isUpdatingEscalation,
        updatingEscalationIssueId,
      ],
    );

  const statusEditControl =
    useMemo<CefpStatusEditControl>(
      () => ({
        updatingIssueId:
          isUpdatingStatus
            ? updatingStatusIssueId
            : null,

        options: [
          {
            id:
              IN_PROGRESS_STATUS_ID,
            name:
              "In Progress",
          },
          {
            id:
              SOLVED_STATUS_ID,
            name:
              "Solved",
          },
          {
            id:
              NOT_ADDRESSED_STATUS_ID,
            name:
              "Not Addressed",
          },
        ],

        onChange:
          handleStatusChange,
      }),
      [
        handleStatusChange,
        isUpdatingStatus,
        updatingStatusIssueId,
      ],
    );

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

    let cancelled = false;

    void getCefpIssueEditInfo(
      editRow.issueId,
    )
      .then((issueInfo) => {
        if (cancelled) {
          return;
        }

        setEditIssueInfo(
          issueInfo,
        );
      })
      .catch(() => {
        if (cancelled) {
          return;
        }

        setEditIssueInfo(
          null,
        );
      })
      .finally(() => {
        if (cancelled) {
          return;
        }

        setIsLoadingEditAttachment(
          false,
        );
      });

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

  const handleOpenEdit = useCallback(
    (row: CefpIssueMatrixRow) => {
      setEditIssueInfo(null);
      setIsLoadingEditAttachment(true);
      setEditRow(row);
    },
    [],
  );

  const handleCloseEdit = useCallback(() => {
    if (isUpdatingIssue) {
      return;
    }

    setEditRow(null);
    setEditIssueInfo(null);
    setIsLoadingEditAttachment(false);
  }, [isUpdatingIssue]);

  const editInitialValue =
    useMemo<CefpAddIssueFormValue | null>(() => {
      if (!editRow) {
        return null;
      }

      const selectedCategory =
        categories.find(
          (category) =>
            category.name.trim() ===
            editRow.category.trim(),
        );

      const primaryAgencyOption =
        governmentAgencies.find(
          (agency) =>
            agency.name.trim() ===
            editRow.primaryAgency.trim(),
        );

      const detailAgencies =
        editIssueInfo
          ?.governmentAgencies ??
        [];

      const getAgencyByOrder = (
        order: number,
      ): string => {
        const agency =
          detailAgencies.find(
            (item) =>
              item.agencyOrder ===
              order,
          );

        return agency
          ? String(
            agency.stakeholderId,
          )
          : "";
      };

      /*
       * Old-list fallback only.
       * GET /issues/:id is the main source after Save,
       * so reopening Edit always restores the saved agencies.
       */
      const fallbackRelatedIds =
        editRow.agencies
          .filter(
            (agency) =>
              !primaryAgencyOption ||
              agency.id !==
              primaryAgencyOption.id,
          )
          .map((agency) =>
            String(agency.id),
          );

      const fallbackPrimaryId =
        primaryAgencyOption
          ? String(
            primaryAgencyOption.id,
          )
          : "";

      return {
        workingGroupId:
          String(
            editRow.workingGroupId,
          ),

        governmentAgencyId:
          getAgencyByOrder(1) ||
          fallbackPrimaryId,

        issue:
          editRow.issue === "-"
            ? ""
            : editRow.issue,

        categoryId:
          selectedCategory
            ? String(
              selectedCategory.id,
            )
            : "",

        description:
          editRow.issueDescription === "-"
            ? ""
            : editRow.issueDescription,

        recommendation:
          editRow.recommendation === "-"
            ? ""
            : editRow.recommendation,

        attachment: null,

        secondAgencyId:
          getAgencyByOrder(2) ||
          fallbackRelatedIds[0] ||
          "",

        thirdAgencyId:
          getAgencyByOrder(3) ||
          fallbackRelatedIds[1] ||
          "",

        fourthAgencyId:
          getAgencyByOrder(4) ||
          fallbackRelatedIds[2] ||
          "",

        fifthAgencyId:
          getAgencyByOrder(5) ||
          fallbackRelatedIds[3] ||
          "",
      };
    }, [
      categories,
      editIssueInfo,
      editRow,
      governmentAgencies,
    ]);

  const handleUpdateIssue = async (
    formValue: CefpAddIssueFormValue,
  ) => {
    if (!editRow) {
      return;
    }

    const categoryId =
      parsePositiveInteger(formValue.categoryId);

    if (!categoryId) {
      throw new Error(
        isKhmer
          ? "សូមជ្រើសរើសប្រភេទបញ្ហា។"
          : "Please select a category of issue.",
      );
    }

    const selectedGovernmentAgencies =
      buildGovernmentAgencies(formValue);

    if (selectedGovernmentAgencies.length === 0) {
      throw new Error(
        isKhmer
          ? "សូមជ្រើសរើសយ៉ាងហោចណាស់មួយក្រសួង ឬស្ថាប័ន។"
          : "Please select at least one government agency.",
      );
    }

    await updateIssue({
      issueId: editRow.issueId,
      payload: {
        title: formValue.issue.trim(),
        description: formValue.description.trim(),
        recommendation: formValue.recommendation.trim(),
        issueStatusId: editRow.statusId,
        categoryId,
        governmentAgencies: selectedGovernmentAgencies,
        attachmentFile: formValue.attachment ?? undefined,
      },
    });

    setEditRow(null);
    setEditIssueInfo(null);
    setIsLoadingEditAttachment(false);

    setAlert({
      open: true,
      severity: "success",
      message: isKhmer
        ? "បានកែប្រែបញ្ហាដោយជោគជ័យ។"
        : "Issue updated successfully.",
    });
  };

  const handleDeleteIssue = async () => {
    if (!deleteRow) {
      return;
    }

    try {
      await deleteIssue(deleteRow.issueId);

      setDeleteRow(null);

      setAlert({
        open: true,
        severity: "success",
        message: isKhmer
          ? "បានលុបបញ្ហាដោយជោគជ័យ។"
          : "Issue removed successfully.",
      });
    } catch (error) {
      setAlert({
        open: true,
        severity: "error",
        message:
          error instanceof Error
            ? error.message
            : isKhmer
              ? "មិនអាចលុបបញ្ហាបានទេ។"
              : "Unable to remove issue.",
      });
    }
  };

  const filteredRows =
    useMemo(() => {
      const normalizedSearch =
        search
          .trim()
          .toLowerCase();

      return rows.filter(
        (row) => {
          const matchesSearch =
            normalizedSearch === "" ||
            [
              row.issue,
              row.category,
              row.issueDescription,
              row.recommendation,
              row.governmentDecision,
              row.primaryAgency,
              row.workingGroup,
              row.status,
              row.year,
            ]
              .join(" ")
              .toLowerCase()
              .includes(
                normalizedSearch,
              );

          const matchesCategory =
            filters.category.length ===
            0 ||
            filters.category.includes(
              row.category,
            );

          const matchesStatus =
            filters.status.length ===
            0 ||
            filters.status.includes(
              row.status,
            );

          const matchesWorkingGroup =
            filters.workingGroup
              .length === 0 ||
            filters.workingGroup.includes(
              row.workingGroup,
            );

          const matchesYear =
            filters.year.length === 0 ||
            filters.year.includes(
              row.year,
            );

          const matchesPlenary =
            filters.plenaryEscalation
              .length === 0 ||
            (filters.plenaryEscalation.includes(
              "Yes",
            ) &&
              row.plenaryEscalation) ||
            (filters.plenaryEscalation.includes(
              "No",
            ) &&
              !row.plenaryEscalation);

          return (
            matchesSearch &&
            matchesCategory &&
            matchesStatus &&
            matchesWorkingGroup &&
            matchesYear &&
            matchesPlenary
          );
        },
      );
    }, [
      filters,
      rows,
      search,
    ]);

  const tableLoading =
    isLoadingRows ||
    isFetchingRows ||
    isLoadingSummary ||
    isFetchingSummary;

  const selectOptionsLoading =
    isLoadingWorkingGroups ||
    isFetchingWorkingGroups ||
    isLoadingGovernmentAgencies ||
    isFetchingGovernmentAgencies ||
    isLoadingCategories ||
    isFetchingCategories;

  const pageError =
    rowsError ||
    summaryError;

  return (
    <>
      <Box
        sx={{
          minHeight:
            "calc(100dvh - 64px)",

          width: "100%",

          display: "flex",
          flexDirection: "column",

          bgcolor:
            theme.palette.background.default,

          color:
            theme.palette.text.primary,

          px: {
            xs: 2,
            md: 3,
          },

          py: {
            xs: 2,
            md: 3,
          },
        }}
      >
        <Box
          sx={{
            flex: 1,
            minHeight: 0,
            width: "100%",

            display: "flex",
            flexDirection: "column",
          }}
        >
          <CdcIssueMatrixHeader
            search={search}
            language={
              matrixLanguage
            }
            exportDisabled
            onSearchChange={
              setSearch
            }
            onNewIssue={() => {
              setAddIssueOpen(true);
            }}
          />

          <CdcIssueMatrixFilters
            filters={filters}
            language={
              matrixLanguage
            }
            options={
              filterOptions
            }
            view={view}
            onChange={
              handleFilterChange
            }
            onViewChange={
              setView
            }
          />

          <Box
            sx={{
              mb: 3,
            }}
          >
            <CdcIssueMatrixStatusCards
              language={
                matrixLanguage
              }
              summary={summary}
            />
          </Box>

          {view === "grid" ? (
            <CefpIssueMatrixGrid
              rows={filteredRows}
              language={
                matrixLanguage
              }
              loading={
                tableLoading
              }
              error={pageError}
              showRemark
              plenaryEscalationControl={
                plenaryEscalationControl
              }
              statusEditControl={
                statusEditControl
              }
              onView={(row) => {
                router.push(
                  `/cefp/cefp-issue-matrix/${row.issueId}`,
                );
              }}
              onEdit={handleOpenEdit}
              onRemove={(row) => setDeleteRow(row)}
            />
          ) : (
            <CefpIssueMatrixTable
              rows={filteredRows}
              language={
                matrixLanguage
              }
              loading={
                tableLoading
              }
              error={pageError}
              showRemark
              plenaryEscalationControl={
                plenaryEscalationControl
              }
              statusEditControl={
                statusEditControl
              }
              onView={(row) => {
                router.push(
                  `/cefp/cefp-issue-matrix/${row.issueId}`,
                );
              }}
              onEdit={handleOpenEdit}
              onRemove={(row) => setDeleteRow(row)}
            />
          )}
        </Box>
      </Box>

      <CefpAddIssueDrawer
        open={addIssueOpen}
        workingGroups={
          workingGroups
        }
        governmentAgencies={
          governmentAgencies
        }
        categories={
          categories
        }
        submitting={
          isCreating ||
          selectOptionsLoading
        }
        onClose={() => {
          if (!isCreating) {
            setAddIssueOpen(false);
          }
        }}
        onSaveDraft={
          handleSaveDraft
        }
        onSubmit={
          handleSaveIssue
        }
      />


      <CefpAddIssueDrawer
        open={Boolean(editRow)}
        mode="edit"
        initialValue={editInitialValue}
        existingAttachmentName={
          editIssueInfo?.attachment.fileName ??
          null
        }
        existingAttachmentUrl={
          editIssueInfo?.attachment.attachmentUrl ??
          null
        }
        workingGroups={workingGroups}
        governmentAgencies={governmentAgencies}
        categories={categories}
        submitting={
          isUpdatingIssue ||
          selectOptionsLoading ||
          isLoadingEditAttachment
        }
        onClose={handleCloseEdit}
        onSubmit={handleUpdateIssue}
      />

      <CefpDeleteIssueDialog
        open={Boolean(deleteRow)}
        row={deleteRow}
        language={matrixLanguage}
        deleting={isDeletingIssue}
        onClose={() => {
          if (!isDeletingIssue) {
            setDeleteRow(null);
          }
        }}
        onConfirm={() => {
          void handleDeleteIssue();
        }}
      />

      <Snackbar
        open={alert.open}
        autoHideDuration={3500}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "right",
        }}
        onClose={(
          _event,
          reason,
        ) => {
          if (
            reason === "clickaway"
          ) {
            return;
          }

          setAlert(
            (previousAlert) => ({
              ...previousAlert,
              open: false,
            }),
          );
        }}
      >
        <Alert
          severity={
            alert.severity
          }
          variant="filled"
          onClose={() => {
            setAlert(
              (previousAlert) => ({
                ...previousAlert,
                open: false,
              }),
            );
          }}
        >
          {alert.message}
        </Alert>
      </Snackbar>
    </>
  );
}