import {
  RecordLeaveInput,
  RecordTimesheetInput,
} from "@/app/api/timesheets/actions";
import { manhourFormatter, shortDateFormatter } from "@/app/utils/formatUtil";
import { ArrowBack, Check } from "@mui/icons-material";
import {
  Box,
  Button,
  Card,
  CardActionArea,
  CardContent,
  Stack,
  Typography,
} from "@mui/material";
import dayjs from "dayjs";
import React, { useCallback, useState } from "react";
import { useTranslation } from "react-i18next";
import {
  DAILY_NORMAL_MAX_HOURS,
  TIMESHEET_DAILY_MAX_HOURS,
} from "@/app/api/timesheets/utils";
import { HolidaysResult } from "@/app/api/holidays";
import { getHolidayForDate } from "@/app/utils/holidayUtils";

interface Props<EntryComponentProps = object> {
  days: string[];
  companyHolidays: HolidaysResult[];
  leaveEntries: RecordLeaveInput;
  timesheetEntries: RecordTimesheetInput;
  EntryComponent: React.FunctionComponent<
    EntryComponentProps & { date: string }
  >;
  entryComponentProps: EntryComponentProps;
  errorComponent?: React.ReactNode;
  onSubmit?: () => void;
}

function DateHoursList<EntryTableProps>({
  days,
  leaveEntries,
  timesheetEntries,
  EntryComponent,
  entryComponentProps,
  companyHolidays,
  errorComponent,
  onSubmit,
}: Props<EntryTableProps>) {
  const {
    t,
    i18n: { language },
  } = useTranslation("home");

  const [selectedDate, setSelectedDate] = useState("");
  const isDateSelected = selectedDate !== "";

  const makeSelectDate = useCallback(
    (date: string) => () => {
      setSelectedDate(date);
    },
    [],
  );

  const onDateDone = useCallback<React.MouseEventHandler<HTMLButtonElement>>(
    (e) => {
      setSelectedDate("");
      e.preventDefault();
    },
    [],
  );

  return (
    <>
      {isDateSelected ? (
        <EntryComponent date={selectedDate} {...entryComponentProps} />
      ) : (
        <Box overflow="scroll" flex={1}>
          {days.map((day, index) => {
            const dayJsObj = dayjs(day);

            const holiday = getHolidayForDate(day, companyHolidays);
            const isHoliday =
              holiday || dayJsObj.day() === 0 || dayJsObj.day() === 6;

            const leaves = leaveEntries[day];
            const leaveHours =
              leaves?.reduce((acc, entry) => acc + entry.inputHours, 0) || 0;

            const timesheet = timesheetEntries[day];
            const timesheetNormalHours =
              timesheet?.reduce(
                (acc, entry) => acc + (entry.inputHours || 0),
                0,
              ) || 0;
            const timesheetOtHours =
              timesheet?.reduce(
                (acc, entry) => acc + (entry.otHours || 0),
                0,
              ) || 0;
            const timesheetHours = timesheetNormalHours + timesheetOtHours;

            const dailyTotal = leaveHours + timesheetHours;

            const normalHoursExceeded =
              timesheetNormalHours + leaveHours > DAILY_NORMAL_MAX_HOURS;
            const dailyTotalExceeded = dailyTotal > TIMESHEET_DAILY_MAX_HOURS;

            return (
              <Card
                key={`${day}-${index}`}
                sx={{ marginBlockEnd: 2, marginInline: 2 }}
              >
                <CardActionArea onClick={makeSelectDate(day)}>
                  <CardContent sx={{ padding: 3 }}>
                    <Typography
                      variant="overline"
                      component="div"
                      sx={{
                        color: isHoliday ? "error.main" : undefined,
                      }}
                    >
                      {shortDateFormatter(language).format(dayJsObj.toDate())}
                      {holiday && (
                        <Typography
                          marginInlineStart={1}
                          variant="caption"
                        >{`(${holiday.title})`}</Typography>
                      )}
                    </Typography>
                    <Stack spacing={1}>
                      <Box
                        sx={{
                          display: "flex",
                          justifyContent: "space-between",
                          flexWrap: "wrap",
                          alignItems: "baseline",
                          color: normalHoursExceeded ? "error.main" : undefined,
                        }}
                      >
                        <Typography variant="body2">
                          {t("Timesheet Hours")}
                        </Typography>
                        <Typography>
                          {manhourFormatter.format(timesheetHours)}
                        </Typography>
                        {normalHoursExceeded && (
                          <Typography
                            component="div"
                            width="100%"
                            variant="caption"
                          >
                            {t(
                              "The daily normal hours (timesheet hours + leave hours) cannot be more than {{DAILY_NORMAL_MAX_HOURS}} (timesheet hours: {{timesheetNormalHours}}, leave hours: {{leaveHours}}). Please use other hours for exceeding hours or decrease the leave hours.",
                              {
                                timesheetNormalHours,
                                leaveHours,
                                DAILY_NORMAL_MAX_HOURS,
                              },
                            )}
                          </Typography>
                        )}
                      </Box>
                      <Box
                        sx={{
                          display: "flex",
                          justifyContent: "space-between",
                          flexWrap: "wrap",
                          alignItems: "baseline",
                          color: normalHoursExceeded ? "error.main" : undefined,
                        }}
                      >
                        <Typography variant="body2">
                          {t("Leave Hours")}
                        </Typography>
                        <Typography>
                          {manhourFormatter.format(leaveHours)}
                        </Typography>
                        {normalHoursExceeded && (
                          <Typography
                            component="div"
                            width="100%"
                            variant="caption"
                          >
                            {t(
                              "The daily normal hours (timesheet hours + leave hours) cannot be more than {{DAILY_NORMAL_MAX_HOURS}} (timesheet hours: {{timesheetNormalHours}}, leave hours: {{leaveHours}}). Please use other hours for exceeding hours or decrease the leave hours.",
                              {
                                timesheetNormalHours,
                                leaveHours,
                                DAILY_NORMAL_MAX_HOURS,
                              },
                            )}
                          </Typography>
                        )}
                      </Box>

                      <Box
                        sx={{
                          display: "flex",
                          justifyContent: "space-between",
                          flexWrap: "wrap",
                          alignItems: "baseline",
                          color: dailyTotalExceeded ? "error.main" : undefined,
                        }}
                      >
                        <Typography variant="body2">
                          {t("Daily Total Hours")}
                        </Typography>
                        <Typography>
                          {manhourFormatter.format(timesheetHours + leaveHours)}
                        </Typography>
                        {dailyTotalExceeded && (
                          <Typography
                            component="div"
                            width="100%"
                            variant="caption"
                          >
                            {t(
                              "The daily total hours cannot be more than {{TIMESHEET_DAILY_MAX_HOURS}}",
                              {
                                TIMESHEET_DAILY_MAX_HOURS,
                              },
                            )}
                          </Typography>
                        )}
                      </Box>
                    </Stack>
                  </CardContent>
                </CardActionArea>
              </Card>
            );
          })}
        </Box>
      )}
      {errorComponent}
      <Box padding={2} display="flex" justifyContent="flex-end">
        {isDateSelected ? (
          <Button
            variant="outlined"
            startIcon={<ArrowBack />}
            onClick={onDateDone}
          >
            {t("Done")}
          </Button>
        ) : (
          <Button
            variant="contained"
            startIcon={<Check />}
            type="submit"
            onClick={onSubmit}
          >
            {t("Save")}
          </Button>
        )}
      </Box>
    </>
  );
}

export default DateHoursList;
