"use client";

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

import Alert from "@mui/material/Alert";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import CircularProgress from "@mui/material/CircularProgress";
import Divider from "@mui/material/Divider";
import Drawer from "@mui/material/Drawer";
import IconButton from "@mui/material/IconButton";
import Snackbar from "@mui/material/Snackbar";
import Typography from "@mui/material/Typography";
import {
  alpha,
  useTheme,
} from "@mui/material/styles";

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

import { CefpAddIssueAgenciesSection } from "./cefp-add-issue-agencies-section";

import {
  CefpAddIssueAttachmentSection,
  validateCefpAttachment,
} from "./cefp-add-issue-attachment-section";

import { CefpAddIssueInformationSection } from "./cefp-add-issue-information-section";

import {
  EMPTY_CEFP_ADD_ISSUE_FORM_VALUE,
  type CefpAddIssueFieldErrors,
  type CefpAddIssueFormValue,
  type CefpAddIssueOption,
} from "./cefp-add-issue-types";

type AlertSeverity =
  | "success"
  | "error";

type AlertState = {
  open: boolean;
  message: string;
  severity: AlertSeverity;
};

type CefpAddIssueDrawerProps = {
  open: boolean;

  mode?: "create" | "edit";

  initialValue?: CefpAddIssueFormValue | null;

  existingAttachmentName?: string | null;
  existingAttachmentUrl?: string | null;

  workingGroups?: CefpAddIssueOption[];

  governmentAgencies?: CefpAddIssueOption[];

  categories?: CefpAddIssueOption[];

  submitting?: boolean;

  onClose: () => void;

  onSubmit?: (
    value: CefpAddIssueFormValue,
  ) => Promise<unknown> | unknown;

  onSaveDraft?: (
    value: CefpAddIssueFormValue,
  ) => Promise<unknown> | unknown;
};

type CefpAddIssueFormContentProps = {
  mode: "create" | "edit";

  initialValue?: CefpAddIssueFormValue | null;

  existingAttachmentName?: string | null;
  existingAttachmentUrl?: string | null;

  workingGroups: CefpAddIssueOption[];

  governmentAgencies: CefpAddIssueOption[];

  categories: CefpAddIssueOption[];

  submitting: boolean;

  onClose: () => void;

  onSubmit?: (
    value: CefpAddIssueFormValue,
  ) => Promise<unknown> | unknown;

  onSaveDraft?: (
    value: CefpAddIssueFormValue,
  ) => Promise<unknown> | unknown;
};

const DEFAULT_WORKING_GROUPS: CefpAddIssueOption[] =
  [];

const DEFAULT_GOVERNMENT_AGENCIES: CefpAddIssueOption[] =
  [];

const DEFAULT_CATEGORIES: CefpAddIssueOption[] =
  [];

function CloseIcon() {
  return (
    <Box
      component="svg"
      viewBox="0 0 24 24"
      aria-hidden="true"
      sx={{
        width: 20,
        height: 20,
        display: "block",
      }}
    >
      <path
        d="M6 6L18 18M18 6L6 18"
        fill="none"
        stroke="currentColor"
        strokeLinecap="round"
        strokeWidth="1.8"
      />
    </Box>
  );
}

function CefpAddIssueFormContent({
  mode,
  initialValue,
  existingAttachmentName,
  existingAttachmentUrl,
  workingGroups,
  governmentAgencies,
  categories,
  submitting,
  onClose,
  onSubmit,
  onSaveDraft,
}: CefpAddIssueFormContentProps) {
  const theme =
    useTheme();

  const { language } =
    useAppLanguage();

  const isKhmer =
    language === "kh";

  const text = isKhmer
    ? {
        title:
          mode === "edit"
            ? "កែប្រែបញ្ហា"
            : "បន្ថែមបញ្ហា",

        draft:
          "រក្សាទុកព្រាង",

        save:
          mode === "edit"
            ? "រក្សាទុកការកែប្រែ"
            : "រក្សាទុក",

        draftSuccess:
          "បានរក្សាទុកព្រាងដោយជោគជ័យ។",

        saveSuccess:
          mode === "edit"
            ? "បានកែប្រែបញ្ហាដោយជោគជ័យ។"
            : "បានរក្សាទុកបញ្ហាដោយជោគជ័យ។",

        draftError:
          "មិនអាចរក្សាទុកព្រាងបានទេ។",

        saveError:
          "មិនអាចរក្សាទុកបញ្ហាបានទេ។",

        workingGroupRequired:
          "សូមជ្រើសរើសក្រុមការងារ។",

        governmentAgencyRequired:
          "សូមជ្រើសរើសក្រសួង ឬស្ថាប័នរដ្ឋ។",

        issueRequired:
          "សូមបញ្ចូលចំណងជើងបញ្ហា។",

        categoryRequired:
          "សូមជ្រើសរើសប្រភេទបញ្ហា។",

        descriptionRequired:
          "សូមបញ្ចូលការពិពណ៌នាអំពីបញ្ហា។",

        recommendationRequired:
          "សូមបញ្ចូលអនុសាសន៍។",

        close:
          "បិទ",
      }
    : {
        title:
          mode === "edit"
            ? "Edit Issue"
            : "Add Issue",

        draft:
          "Draft",

        save:
          mode === "edit"
            ? "Save Changes"
            : "Save",

        draftSuccess:
          "Draft saved successfully.",

        saveSuccess:
          mode === "edit"
            ? "Issue updated successfully."
            : "Issue saved successfully.",

        draftError:
          "Unable to save draft.",

        saveError:
          "Unable to save issue.",

        workingGroupRequired:
          "Please select a working group.",

        governmentAgencyRequired:
          "Please select a government agency.",

        issueRequired:
          "Issue title is required.",

        categoryRequired:
          "Please select a category of issue.",

        descriptionRequired:
          "Issue description is required.",

        recommendationRequired:
          "Recommendation is required.",

        close:
          "Close",
      };

  const fontFamily = isKhmer
    ? '"Battambang", "Kantumruy Pro", sans-serif'
    : '"Inter", "Segoe UI", Arial, sans-serif';

  const [
    value,
    setValue,
  ] =
    useState<CefpAddIssueFormValue>(
      () => ({
        ...EMPTY_CEFP_ADD_ISSUE_FORM_VALUE,
        ...(initialValue ?? {}),
      }),
    );

  const [
    errors,
    setErrors,
  ] =
    useState<CefpAddIssueFieldErrors>(
      {},
    );

  const [
    actionType,
    setActionType,
  ] = useState<
    "draft" | "save" | null
  >(null);

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

  const isSubmitting =
    submitting ||
    actionType !== null;

  const hasChanges =
    useMemo(() => {
      return (
        value.workingGroupId.trim() !==
          "" ||
        value.governmentAgencyId.trim() !==
          "" ||
        value.issue.trim() !==
          "" ||
        value.categoryId.trim() !==
          "" ||
        value.description.trim() !==
          "" ||
        value.recommendation.trim() !==
          "" ||
        value.attachment !==
          null ||
        value.secondAgencyId.trim() !==
          "" ||
        value.thirdAgencyId.trim() !==
          "" ||
        value.fourthAgencyId.trim() !==
          "" ||
        value.fifthAgencyId.trim() !==
          ""
      );
    }, [value]);

  const updateField = <
    K extends keyof CefpAddIssueFormValue,
  >(
    key: K,
    nextValue:
      CefpAddIssueFormValue[K],
  ) => {
    setValue(
      (previousValue) => ({
        ...previousValue,
        [key]: nextValue,
      }),
    );

    setErrors(
      (previousErrors) => {
        if (
          !previousErrors[key]
        ) {
          return previousErrors;
        }

        const nextErrors = {
          ...previousErrors,
        };

        delete nextErrors[key];

        return nextErrors;
      },
    );
  };

  const showAlert = (
    message: string,
    severity: AlertSeverity,
  ) => {
    setAlert({
      open: true,
      message,
      severity,
    });
  };

  const closeAlert =
    () => {
      setAlert(
        (previousAlert) => ({
          ...previousAlert,
          open: false,
        }),
      );
    };

  const resetForm =
    () => {
      setValue({
        ...EMPTY_CEFP_ADD_ISSUE_FORM_VALUE,
        ...(mode === "edit"
          ? initialValue ?? {}
          : {}),
      });

      setErrors({});
    };

  const validateSaveForm =
    (): CefpAddIssueFieldErrors => {
      const nextErrors: CefpAddIssueFieldErrors =
        {};

      if (
        !value.workingGroupId.trim()
      ) {
        nextErrors.workingGroupId =
          text.workingGroupRequired;
      }

      if (
        !value.governmentAgencyId.trim()
      ) {
        nextErrors.governmentAgencyId =
          text.governmentAgencyRequired;
      }

      if (!value.issue.trim()) {
        nextErrors.issue =
          text.issueRequired;
      }

      if (
        !value.categoryId.trim()
      ) {
        nextErrors.categoryId =
          text.categoryRequired;
      }

      if (
        !value.description.trim()
      ) {
        nextErrors.description =
          text.descriptionRequired;
      }

      if (
        !value.recommendation.trim()
      ) {
        nextErrors.recommendation =
          text.recommendationRequired;
      }

      const attachmentError =
        validateCefpAttachment(
          value.attachment,
          language,
        );

      if (attachmentError) {
        nextErrors.attachment =
          attachmentError;
      }

      return nextErrors;
    };

  const validateDraftForm =
    (): CefpAddIssueFieldErrors => {
      const nextErrors: CefpAddIssueFieldErrors =
        {};

      const attachmentError =
        validateCefpAttachment(
          value.attachment,
          language,
        );

      if (attachmentError) {
        nextErrors.attachment =
          attachmentError;
      }

      return nextErrors;
    };

  const handleSave =
    async () => {
      if (isSubmitting) {
        return;
      }

      const nextErrors =
        validateSaveForm();

      if (
        Object.keys(
          nextErrors,
        ).length > 0
      ) {
        setErrors(
          nextErrors,
        );

        return;
      }

      setActionType(
        "save",
      );

      try {
        await onSubmit?.(
          value,
        );

        resetForm();

        showAlert(
          text.saveSuccess,
          "success",
        );

        window.setTimeout(
          () => {
            onClose();
          },
          900,
        );
      } catch (
        requestError
      ) {
        showAlert(
          requestError instanceof Error
            ? requestError.message
            : text.saveError,
          "error",
        );
      } finally {
        setActionType(
          null,
        );
      }
    };

  const handleDraft =
    async () => {
      if (
        isSubmitting ||
        !hasChanges
      ) {
        return;
      }

      const nextErrors =
        validateDraftForm();

      if (
        Object.keys(
          nextErrors,
        ).length > 0
      ) {
        setErrors(
          nextErrors,
        );

        return;
      }

      setActionType(
        "draft",
      );

      try {
        await onSaveDraft?.(
          value,
        );

        resetForm();

        showAlert(
          text.draftSuccess,
          "success",
        );

        window.setTimeout(
          () => {
            onClose();
          },
          900,
        );
      } catch (
        requestError
      ) {
        showAlert(
          requestError instanceof Error
            ? requestError.message
            : text.draftError,
          "error",
        );
      } finally {
        setActionType(
          null,
        );
      }
    };

  const handleClose =
    () => {
      if (isSubmitting) {
        return;
      }

      resetForm();
      onClose();
    };

  return (
    <>
      <Box
        sx={{
          height:
            "100%",

          minHeight:
            0,

          display:
            "flex",

          flexDirection:
            "column",

          bgcolor:
            "background.paper",

          color:
            "text.primary",

          fontFamily,
        }}
      >
        <Box
          sx={{
            minHeight:
              72,

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

            display:
              "flex",

            alignItems:
              "center",

            justifyContent:
              "space-between",

            flexShrink:
              0,

            bgcolor:
              "background.paper",
          }}
        >
          <Typography
            component="h2"
            sx={{
              color:
                "text.primary",

              fontFamily,

              fontSize: {
                xs:
                  isKhmer
                    ? 22
                    : 24,

                sm:
                  isKhmer
                    ? 24
                    : 26,
              },

              fontWeight:
                600,

              lineHeight:
                1.3,
            }}
          >
            {text.title}
          </Typography>

          <IconButton
            type="button"
            aria-label={
              text.close
            }
            title={
              text.close
            }
            disabled={
              isSubmitting
            }
            onClick={
              handleClose
            }
            sx={{
              display: {
                xs:
                  "inline-flex",

                md:
                  "none",
              },

              color:
                "text.secondary",
            }}
          >
            <CloseIcon />
          </IconButton>
        </Box>

        <Divider />

        <Box
          component="form"
          noValidate
          onSubmit={(
            event,
          ) => {
            event.preventDefault();

            void handleSave();
          }}
          sx={{
            flex: 1,
            minHeight: 0,

            display:
              "flex",

            flexDirection:
              "column",

            bgcolor:
              "background.paper",
          }}
        >
          <Box
            sx={{
              flex: 1,
              minHeight: 0,

              overflowX:
                "hidden",

              overflowY:
                "auto",

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

              pt: 3,
              pb: 4,

              bgcolor:
                "background.paper",

              "&::-webkit-scrollbar":
                {
                  width: 8,
                },

              "&::-webkit-scrollbar-track":
                {
                  bgcolor:
                    "action.hover",
                },

              "&::-webkit-scrollbar-thumb":
                {
                  bgcolor:
                    alpha(
                      theme
                        .palette
                        .text
                        .secondary,
                      0.42,
                    ),

                  borderRadius:
                    999,
                },
            }}
          >
            <CefpAddIssueInformationSection
              value={value}
              errors={errors}
              workingGroups={
                workingGroups
              }
              governmentAgencies={
                governmentAgencies
              }
              categories={
                categories
              }
              onChange={
                updateField
              }
            />

            <Box
              sx={{
                mt: 3,
              }}
            >
              <CefpAddIssueAttachmentSection
                file={
                  value.attachment
                }
                existingFileName={
                  mode === "edit"
                    ? existingAttachmentName
                    : null
                }
                existingFileUrl={
                  mode === "edit"
                    ? existingAttachmentUrl
                    : null
                }
                error={
                  errors.attachment
                }
                onChange={(file) => {
                  updateField(
                    "attachment",
                    file,
                  );
                }}
              />
            </Box>

            <Box
              sx={{
                mt: 3,
              }}
            >
              <CefpAddIssueAgenciesSection
                value={value}
                governmentAgencies={
                  governmentAgencies
                }
                onChange={
                  updateField
                }
              />
            </Box>
          </Box>

          <Box
            sx={{
              flexShrink:
                0,

              minHeight: {
                xs: 68,
                sm: 72,
              },

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

              py: {
                xs: 1.25,
                sm: 1.5,
              },

              display:
                "flex",

              alignItems:
                "center",

              justifyContent:
                "flex-end",

              gap: {
                xs: 1.25,
                sm: 2,
              },

              bgcolor:
                "background.paper",

              borderTop:
                "1px solid",

              borderColor:
                "divider",

              position:
                "relative",

              zIndex:
                2,
            }}
          >
            {mode === "create" ? (
            <Button
              type="button"
              variant="contained"
              disabled={
                isSubmitting ||
                !hasChanges
              }
              onClick={() => {
                void handleDraft();
              }}
              sx={{
                width: {
                  xs: 125,
                  sm: 150,
                },

                height:
                  42,

                borderRadius:
                  1.5,

                bgcolor:
                  "#98A2B3",

                color:
                  "#FFFFFF",

                boxShadow:
                  "none",

                textTransform:
                  "none",

                fontFamily,

                fontSize:
                  13,

                fontWeight:
                  600,

                "&:hover": {
                  bgcolor:
                    "#667085",

                  boxShadow:
                    "none",
                },

                "&.Mui-disabled":
                  {
                    bgcolor:
                      "#D0D5DD",

                    color:
                      "#FFFFFF",
                  },
              }}
            >
              {actionType ===
              "draft" ? (
                <CircularProgress
                  size={18}
                  color="inherit"
                />
              ) : (
                text.draft
              )}
            </Button>
            ) : null}

            <Button
              type="submit"
              variant="contained"
              disabled={
                isSubmitting ||
                !hasChanges
              }
              sx={{
                width: {
                  xs: 125,
                  sm: 150,
                },

                height:
                  42,

                borderRadius:
                  1.5,

                bgcolor:
                  "primary.main",

                color:
                  "primary.contrastText",

                boxShadow:
                  "none",

                textTransform:
                  "none",

                fontFamily,

                fontSize:
                  13,

                fontWeight:
                  600,

                "&:hover": {
                  bgcolor:
                    "primary.dark",

                  boxShadow:
                    "none",
                },

                "&.Mui-disabled":
                  {
                    bgcolor:
                      "action.disabledBackground",

                    color:
                      "text.disabled",
                  },
              }}
            >
              {actionType ===
              "save" ? (
                <CircularProgress
                  size={18}
                  color="inherit"
                />
              ) : (
                text.save
              )}
            </Button>
          </Box>
        </Box>
      </Box>

      <Snackbar
        open={
          alert.open
        }
        autoHideDuration={
          3500
        }
        anchorOrigin={{
          vertical:
            "bottom",

          horizontal:
            "right",
        }}
        onClose={(
          _event,
          reason,
        ) => {
          if (
            reason ===
            "clickaway"
          ) {
            return;
          }

          closeAlert();
        }}
        sx={{
          zIndex:
            1500,

          mb: 1,
          mr: 1,
        }}
      >
        <Alert
          severity={
            alert.severity
          }
          variant="filled"
          onClose={
            closeAlert
          }
          sx={{
            minWidth: {
              xs: 280,
              sm: 420,
            },

            alignItems:
              "center",

            borderRadius:
              1,

            fontFamily,

            fontSize:
              14,

            fontWeight:
              500,
          }}
        >
          {alert.message}
        </Alert>
      </Snackbar>
    </>
  );
}

export function CefpAddIssueDrawer({
  open,

  mode = "create",

  initialValue = null,

  existingAttachmentName = null,
  existingAttachmentUrl = null,

  workingGroups =
    DEFAULT_WORKING_GROUPS,

  governmentAgencies =
    DEFAULT_GOVERNMENT_AGENCIES,

  categories =
    DEFAULT_CATEGORIES,

  submitting = false,

  onClose,
  onSubmit,
  onSaveDraft,
}: CefpAddIssueDrawerProps) {
  const theme =
    useTheme();

  const handleClose =
    () => {
      if (submitting) {
        return;
      }

      onClose();
    };

  const formContentKey = [
    mode,
    initialValue?.workingGroupId ?? "",
    initialValue?.governmentAgencyId ?? "",
    initialValue?.issue ?? "",
    initialValue?.categoryId ?? "",
    initialValue?.secondAgencyId ?? "",
    initialValue?.thirdAgencyId ?? "",
    initialValue?.fourthAgencyId ?? "",
    initialValue?.fifthAgencyId ?? "",
    existingAttachmentName ?? "",
  ].join("|");

  return (
    <Drawer
      anchor="right"
      open={open}
      onClose={
        handleClose
      }
      slotProps={{
        backdrop: {
          sx: {
            bgcolor:
              theme.palette
                .mode ===
              "dark"
                ? "rgba(0, 0, 0, 0.72)"
                : "rgba(16, 24, 40, 0.52)",
          },
        },

        paper: {
          sx: {
            top: 0,
            right: 0,

            bottom: {
              xs: 0,
              md: "12px",
            },

            width: {
              xs: "100%",
              sm: "88%",
              md: "760px",
              lg: "800px",
            },

            maxWidth:
              "100%",

            height: {
              xs:
                "100dvh",

              md:
                "calc(100dvh - 12px)",
            },

            borderRadius: {
              xs: 0,

              md:
                "10px 0 0 10px",
            },

            overflow:
              "hidden",

            bgcolor:
              "background.paper",

            backgroundImage:
              "none",

            color:
              "text.primary",

            borderLeft:
              "1px solid",

            borderColor:
              "divider",

            boxShadow:
              theme.palette
                .mode ===
              "dark"
                ? "-12px 0 40px rgba(0, 0, 0, 0.55)"
                : "-12px 0 40px rgba(16, 24, 40, 0.18)",
          },
        },
      }}
    >
      {open ? (
        <CefpAddIssueFormContent
          key={formContentKey}
          mode={mode}
          initialValue={initialValue}
          existingAttachmentName={
            existingAttachmentName
          }
          existingAttachmentUrl={
            existingAttachmentUrl
          }
          workingGroups={
            workingGroups
          }
          governmentAgencies={
            governmentAgencies
          }
          categories={
            categories
          }
          submitting={
            submitting
          }
          onClose={
            handleClose
          }
          onSubmit={
            onSubmit
          }
          onSaveDraft={
            onSaveDraft
          }
        />
      ) : null}
    </Drawer>
  );
}