import { TimeEntry, RecordTimesheetInput } from "@/app/api/timesheets/actions";
import { shortDateFormatter } from "@/app/utils/formatUtil";
import { Add } from "@mui/icons-material";
import { Box, Button, Stack, Typography } from "@mui/material";
import dayjs from "dayjs";
import React, { useCallback, useMemo, useState } from "react";
import { useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { AssignedProject, ProjectWithTasks } from "@/app/api/projects";
import TimesheetEditModal, {
  Props as TimesheetEditModalProps,
} from "./TimesheetEditModal";
import TimeEntryCard from "./TimeEntryCard";
import { HolidaysResult } from "@/app/api/holidays";
import { getHolidayForDate } from "@/app/utils/holidayUtils";
import FastTimeEntryModal from "./FastTimeEntryModal";

interface Props {
  date: string;
  allProjects: ProjectWithTasks[];
  assignedProjects: AssignedProject[];
  companyHolidays: HolidaysResult[];
  fastEntryEnabled?: boolean;
}

const MobileTimesheetEntry: React.FC<Props> = ({
  date,
  allProjects,
  assignedProjects,
  companyHolidays,
  fastEntryEnabled,
}) => {
  const {
    t,
    i18n: { language },
  } = useTranslation("home");

  const projectMap = useMemo(() => {
    return allProjects.reduce<{
      [id: ProjectWithTasks["id"]]: ProjectWithTasks;
    }>((acc, project) => {
      return { ...acc, [project.id]: project };
    }, {});
  }, [allProjects]);

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

  const { watch, setValue, clearErrors } =
    useFormContext<RecordTimesheetInput>();
  const currentEntries = watch(date);

  // Edit modal
  const [editModalProps, setEditModalProps] = useState<
    Partial<TimesheetEditModalProps>
  >({});
  const [editModalOpen, setEditModalOpen] = useState(false);

  const openEditModal = useCallback(
    (defaultValues?: TimeEntry) => () => {
      setEditModalProps({
        defaultValues,
        onDelete: defaultValues
          ? () => {
              setValue(
                date,
                currentEntries.filter((entry) => entry.id !== defaultValues.id),
              );
              clearErrors(date);
              setEditModalOpen(false);
            }
          : undefined,
      });
      setEditModalOpen(true);
    },
    [clearErrors, currentEntries, date, setValue],
  );

  const closeEditModal = useCallback(() => {
    setEditModalOpen(false);
  }, []);

  const onSaveEntry = useCallback(
    async (entry: TimeEntry) => {
      const existingEntry = currentEntries.find((e) => e.id === entry.id);
      if (existingEntry) {
        setValue(
          date,
          currentEntries.map((e) => ({
            ...(e.id === existingEntry.id ? entry : e),
          })),
        );
        clearErrors(date);
      } else {
        setValue(date, [...currentEntries, entry]);
      }
      setEditModalOpen(false);
    },
    [clearErrors, currentEntries, date, setValue],
  );

  // Fast entry modal
  const [fastEntryModalOpen, setFastEntryModalOpen] = useState(false);
  const closeFastEntryModal = useCallback(() => {
    setFastEntryModalOpen(false);
  }, []);
  const openFastEntryModal = useCallback(() => {
    setFastEntryModalOpen(true);
  }, []);
  const onSaveFastEntry = useCallback(
    async (entries: TimeEntry[]) => {
      setValue(date, [...currentEntries, ...entries]);
      setFastEntryModalOpen(false);
    },
    [currentEntries, date, setValue],
  );

  return (
    <>
      <Typography
        paddingInline={2}
        variant="overline"
        color={isHoliday ? "error.main" : undefined}
      >
        {shortDateFormatter(language).format(dayJsObj.toDate())}
        {holiday && (
          <Typography
            marginInlineStart={1}
            variant="caption"
          >{`(${holiday.title})`}</Typography>
        )}
      </Typography>
      <Box
        paddingInline={2}
        flex={1}
        display="flex"
        flexDirection="column"
        gap={2}
        overflow="scroll"
      >
        {currentEntries.length ? (
          currentEntries.map((entry, index) => {
            const project = entry.projectId
              ? projectMap[entry.projectId]
              : undefined;

            const task = project?.tasks.find((t) => t.id === entry.taskId);

            return (
              <TimeEntryCard
                key={`${entry.id}-${index}`}
                project={project}
                task={task}
                entry={entry}
                onEdit={openEditModal(entry)}
              />
            );
          })
        ) : (
          <Typography variant="body2" display="block">
            {t("Add some time entries!")}
          </Typography>
        )}
        <Stack alignItems={"flex-start"} spacing={1}>
          <Button startIcon={<Add />} onClick={openEditModal()}>
            {t("Record time")}
          </Button>
          {fastEntryEnabled && (
            <Button startIcon={<Add />} onClick={openFastEntryModal}>
              {t("Fast time entry")}
            </Button>
          )}
        </Stack>
        <TimesheetEditModal
          allProjects={allProjects}
          assignedProjects={assignedProjects}
          open={editModalOpen}
          onClose={closeEditModal}
          onSave={onSaveEntry}
          isHoliday={Boolean(isHoliday)}
          fastEntryEnabled={fastEntryEnabled}
          {...editModalProps}
        />
        {fastEntryEnabled && (
          <FastTimeEntryModal
            allProjects={allProjects}
            assignedProjects={assignedProjects}
            open={fastEntryModalOpen}
            isHoliday={Boolean(isHoliday)}
            onClose={closeFastEntryModal}
            onSave={onSaveFastEntry}
          />
        )}
      </Box>
    </>
  );
};

export default MobileTimesheetEntry;
