import React, { useCallback, useMemo } from "react";
import {
  Box,
  Button,
  Card,
  CardActions,
  CardContent,
  Modal,
  ModalProps,
  SxProps,
  Typography,
} from "@mui/material";
import { useTranslation } from "react-i18next";
import { Check, Close } from "@mui/icons-material";
import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
import {
  RecordLeaveInput,
  RecordTimesheetInput,
  saveLeave,
} from "@/app/api/timesheets/actions";
import dayjs from "dayjs";
import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
import LeaveTable from "../LeaveTable";
import { LeaveType } from "@/app/api/timesheets";
import FullscreenModal from "../FullscreenModal";
import MobileLeaveTable from "../LeaveTable/MobileLeaveTable";
import useIsMobile from "@/app/utils/useIsMobile";
import { HolidaysResult } from "@/app/api/holidays";
import {
  DAILY_NORMAL_MAX_HOURS,
  TIMESHEET_DAILY_MAX_HOURS,
  validateLeaveRecord,
} from "@/app/api/timesheets/utils";
import ErrorAlert from "../ErrorAlert";

interface Props {
  isOpen: boolean;
  onClose: () => void;
  username: string;
  defaultLeaveRecords?: RecordLeaveInput;
  leaveTypes: LeaveType[];
  timesheetRecords: RecordTimesheetInput;
  companyHolidays: HolidaysResult[];
}

const modalSx: SxProps = {
  position: "absolute",
  top: "50%",
  left: "50%",
  transform: "translate(-50%, -50%)",
  width: { xs: "calc(100% - 2rem)", sm: "90%" },
  maxHeight: "90%",
  maxWidth: 1400,
};

const LeaveModal: React.FC<Props> = ({
  isOpen,
  onClose,
  username,
  defaultLeaveRecords,
  timesheetRecords,
  leaveTypes,
  companyHolidays,
}) => {
  const { t } = useTranslation("home");

  const defaultValues = useMemo(() => {
    const today = dayjs();
    return Array(7)
      .fill(undefined)
      .reduce<RecordLeaveInput>((acc, _, index) => {
        const date = today.subtract(index, "day").format(INPUT_DATE_FORMAT);
        return {
          ...acc,
          [date]: defaultLeaveRecords?.[date] ?? [],
        };
      }, {});
  }, [defaultLeaveRecords]);

  const formProps = useForm<RecordLeaveInput>({ defaultValues });

  const onSubmit = useCallback<SubmitHandler<RecordLeaveInput>>(
    async (data) => {
      const errors = validateLeaveRecord(data, timesheetRecords);
      if (errors) {
        Object.keys(errors).forEach((date) =>
          formProps.setError(date, {
            message: errors[date],
          }),
        );
        return;
      }
      const savedRecords = await saveLeave(data, username);

      const today = dayjs();
      const newFormValues = Array(7)
        .fill(undefined)
        .reduce<RecordLeaveInput>((acc, _, index) => {
          const date = today.subtract(index, "day").format(INPUT_DATE_FORMAT);
          return {
            ...acc,
            [date]: savedRecords[date] ?? [],
          };
        }, {});

      formProps.reset(newFormValues);
      onClose();
    },
    [formProps, onClose, timesheetRecords, username],
  );

  const onCancel = useCallback(() => {
    formProps.reset(defaultValues);
    onClose();
  }, [defaultValues, formProps, onClose]);

  const onModalClose = useCallback<NonNullable<ModalProps["onClose"]>>(
    (_, reason) => {
      if (reason !== "backdropClick") {
        onCancel();
      }
    },
    [onCancel],
  );

  const errorComponent = (
    <ErrorAlert
      errors={Object.keys(formProps.formState.errors).map((date) => {
        const error = formProps.formState.errors[date]?.message;
        return error
          ? `${date}: ${t(error, {
              TIMESHEET_DAILY_MAX_HOURS,
              DAILY_NORMAL_MAX_HOURS,
            })}`
          : undefined;
      })}
    />
  );

  const matches = useIsMobile();

  return (
    <FormProvider {...formProps}>
      {!matches ? (
        // Desktop version
        <Modal open={isOpen} onClose={onModalClose}>
          <Card sx={modalSx}>
            <CardContent
              component="form"
              onSubmit={formProps.handleSubmit(onSubmit)}
            >
              <Typography variant="overline" display="block" marginBlockEnd={1}>
                {t("Record Leave")}
              </Typography>
              <Box
                sx={{
                  marginInline: -3,
                  marginBlock: 4,
                }}
              >
                <LeaveTable
                  companyHolidays={companyHolidays}
                  leaveTypes={leaveTypes}
                  timesheetRecords={timesheetRecords}
                />
              </Box>
              {errorComponent}
              <CardActions sx={{ justifyContent: "flex-end" }}>
                <Button
                  variant="outlined"
                  startIcon={<Close />}
                  onClick={onCancel}
                >
                  {t("Cancel")}
                </Button>
                <Button variant="contained" startIcon={<Check />} type="submit">
                  {t("Save")}
                </Button>
              </CardActions>
            </CardContent>
          </Card>
        </Modal>
      ) : (
        // Mobile version
        <FullscreenModal
          open={isOpen}
          onClose={onModalClose}
          closeModal={onCancel}
        >
          <Box
            display="flex"
            flexDirection="column"
            gap={2}
            height="100%"
            component="form"
            onSubmit={formProps.handleSubmit(onSubmit)}
          >
            <Typography variant="h6" padding={2} flex="none">
              {t("Record Leave")}
            </Typography>
            <MobileLeaveTable
              companyHolidays={companyHolidays}
              leaveTypes={leaveTypes}
              timesheetRecords={timesheetRecords}
              errorComponent={errorComponent}
            />
          </Box>
        </FullscreenModal>
      )}
    </FormProvider>
  );
};

export default LeaveModal;
