import { LeaveType } from "@/app/api/timesheets";
import { LeaveEntry } from "@/app/api/timesheets/actions";
import {
  DAILY_NORMAL_MAX_HOURS,
  TIMESHEET_DAILY_MAX_HOURS,
} from "@/app/api/timesheets/utils";
import { shortDateFormatter } from "@/app/utils/formatUtil";
import { roundToNearestQuarter } from "@/app/utils/manhourUtils";
import { Check, Delete, Close } from "@mui/icons-material";
import {
  Box,
  Button,
  FormControl,
  InputLabel,
  MenuItem,
  Modal,
  ModalProps,
  Paper,
  Select,
  SxProps,
  TextField,
  Typography,
} from "@mui/material";
import React, { useCallback, useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";

export interface Props extends Omit<ModalProps, "children"> {
  onSave: (leaveEntry: LeaveEntry, recordDate?: string) => Promise<void>;
  onDelete?: () => Promise<void>;
  leaveTypes: LeaveType[];
  defaultValues?: Partial<LeaveEntry>;
  modalSx?: SxProps;
  recordDate?: string;
  isHoliday?: boolean;
}

const modalSx: SxProps = {
  position: "absolute",
  top: "50%",
  left: "50%",
  transform: "translate(-50%, -50%)",
  width: "90%",
  maxHeight: "90%",
  padding: 3,
  display: "flex",
  flexDirection: "column",
  gap: 2,
};
const LeaveEditModal: React.FC<Props> = ({
  onSave,
  onDelete,
  open,
  onClose,
  leaveTypes,
  defaultValues,
  recordDate,
  modalSx: mSx,
  isHoliday,
}) => {
  const {
    t,
    i18n: { language },
  } = useTranslation("home");
  const { register, control, reset, getValues, trigger, formState, setError } =
    useForm<LeaveEntry>({
      defaultValues: {
        leaveTypeId: leaveTypes[0].id,
      },
    });

  useEffect(() => {
    reset(defaultValues ?? { leaveTypeId: leaveTypes[0].id, id: Date.now() });
  }, [defaultValues, leaveTypes, reset]);

  const saveHandler = useCallback(async () => {
    const valid = await trigger();
    if (valid) {
      try {
        await onSave(getValues(), recordDate);
        reset({ id: Date.now() });
      } catch (e) {
        setError("root", {
          message: e instanceof Error ? e.message : "Unknown error",
        });
      }
    }
  }, [getValues, onSave, recordDate, reset, setError, trigger]);

  const closeHandler = useCallback<NonNullable<ModalProps["onClose"]>>(
    (...args) => {
      onClose?.(...args);
      reset({ id: Date.now() });
    },
    [onClose, reset],
  );

  return (
    <Modal open={open} onClose={closeHandler}>
      <Paper sx={{ ...modalSx, ...mSx }}>
        {recordDate && (
          <Typography
            variant="h6"
            marginBlockEnd={2}
            color={isHoliday ? "error.main" : undefined}
          >
            {shortDateFormatter(language).format(new Date(recordDate))}
          </Typography>
        )}
        <FormControl fullWidth>
          <InputLabel>{t("Leave Types")}</InputLabel>
          <Controller
            defaultValue={leaveTypes[0].id}
            control={control}
            name="leaveTypeId"
            render={({ field }) => (
              <Select label={t("Leave Types")} {...field}>
                {leaveTypes.map((type, index) => (
                  <MenuItem key={`${type.id}-${index}`} value={type.id}>
                    {t(type.name)}
                  </MenuItem>
                ))}
              </Select>
            )}
          />
        </FormControl>
        <TextField
          type="number"
          label={t("Hours")}
          fullWidth
          {...register("inputHours", {
            setValueAs: (value) => roundToNearestQuarter(parseFloat(value)),
            validate: (value) => {
              if (isHoliday) {
                return t("Cannot input normal hours on holidays");
              }

              return (
                (0 < value && value <= DAILY_NORMAL_MAX_HOURS) ||
                t(
                  "Input hours should be between 0 and {{DAILY_NORMAL_MAX_HOURS}}",
                  { DAILY_NORMAL_MAX_HOURS },
                )
              );
            },
          })}
          error={Boolean(formState.errors.inputHours)}
          helperText={formState.errors.inputHours?.message}
        />
        <TextField
          label={t("Remarks")}
          fullWidth
          multiline
          rows={2}
          {...register("remark")}
        />
        {formState.errors.root?.message && (
          <Typography variant="caption" color="error">
            {t(formState.errors.root.message, {
              DAILY_NORMAL_MAX_HOURS,
              TIMESHEET_DAILY_MAX_HOURS,
            })}
          </Typography>
        )}
        <Box display="flex" justifyContent="flex-end" gap={1}>
          {onDelete && (
            <Button
              variant="outlined"
              startIcon={<Delete />}
              color="error"
              onClick={onDelete}
            >
              {t("Delete")}
            </Button>
          )}
          <Button
            variant="outlined"
            startIcon={<Close />}
            onClick={(event) => closeHandler(event, "backdropClick")}
          >
            {t("Close")}
          </Button>
          <Button
            variant="contained"
            startIcon={<Check />}
            onClick={saveHandler}
          >
            {t("Save")}
          </Button>
        </Box>
      </Paper>
    </Modal>
  );
};

export default LeaveEditModal;
