import {
  TimeEntry,
  RecordTimeLeaveInput,
  LeaveEntry,
} 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 "../TimesheetTable/TimesheetEditModal";
import LeaveEditModal, {
  Props as LeaveEditModalProps,
} from "../LeaveTable/LeaveEditModal";
import TimeEntryCard from "../TimesheetTable/TimeEntryCard";
import { HolidaysResult } from "@/app/api/holidays";
import { getHolidayForDate } from "@/app/utils/holidayUtils";
import FastTimeEntryModal from "../TimesheetTable/FastTimeEntryModal";
import { LeaveType } from "@/app/api/timesheets";
import LeaveEntryCard from "../LeaveTable/LeaveEntryCard";
import { Task } from "@/app/api/tasks";

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

const TimeLeaveMobileEntry: React.FC<Props> = ({
  date,
  allProjects,
  assignedProjects,
  companyHolidays,
  fastEntryEnabled,
  leaveTypes,
  miscTasks,
}) => {
  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 leaveTypeMap = useMemo<{ [id: LeaveType["id"]]: LeaveType }>(() => {
    return leaveTypes.reduce(
      (acc, leaveType) => ({ ...acc, [leaveType.id]: leaveType }),
      {},
    );
  }, [leaveTypes]);

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

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

  // Time entry edit modal
  const [editTimeModalProps, setEditTimeModalProps] = useState<
    Partial<TimesheetEditModalProps>
  >({});
  const [editTimeModalOpen, setEditTimeModalOpen] = useState(false);

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

  const closeEditTimeModal = useCallback(() => {
    setEditTimeModalOpen(false);
  }, []);

  const onSaveTimeEntry = useCallback(
    async (entry: TimeEntry) => {
      const existingEntry = currentEntries.find(
        (e) => e.type === "timeEntry" && e.id === entry.id,
      );
      const newEntry = { type: "timeEntry" as const, ...entry };
      if (existingEntry) {
        setValue(
          date,
          currentEntries.map((e) => ({
            ...(e === existingEntry ? newEntry : e),
          })),
        );
        clearErrors(date);
      } else {
        setValue(date, [...currentEntries, newEntry]);
      }
      setEditTimeModalOpen(false);
    },
    [clearErrors, currentEntries, date, setValue],
  );

  // Leave entry edit modal
  const [editLeaveModalProps, setEditLeaveModalProps] = useState<
    Partial<LeaveEditModalProps>
  >({});
  const [editLeaveModalOpen, setEditLeaveModalOpen] = useState(false);

  const openEditLeaveModal = useCallback(
    (defaultValues?: LeaveEntry) => () => {
      setEditLeaveModalProps({
        defaultValues: defaultValues ? { ...defaultValues } : undefined,
        onDelete: defaultValues
          ? async () => {
              setValue(
                date,
                currentEntries.filter((entry) => entry.id !== defaultValues.id),
              );
              clearErrors(date);
              setEditLeaveModalOpen(false);
            }
          : undefined,
      });
      setEditLeaveModalOpen(true);
    },
    [clearErrors, currentEntries, date, setValue],
  );

  const closeEditLeaveModal = useCallback(() => {
    setEditLeaveModalOpen(false);
  }, []);

  const onSaveLeaveEntry = useCallback(
    async (entry: LeaveEntry) => {
      const existingEntry = currentEntries.find(
        (e) => e.type === "leaveEntry" && e.id === entry.id,
      );
      const newEntry = { type: "leaveEntry" as const, ...entry };
      if (existingEntry) {
        setValue(
          date,
          currentEntries.map((e) => ({
            ...(e === existingEntry ? newEntry : e),
          })),
        );
        clearErrors(date);
      } else {
        setValue(date, [...currentEntries, newEntry]);
      }
      setEditLeaveModalOpen(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.map((e) => ({ type: "timeEntry" as const, ...e })),
      ]);
      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) => {
            if (entry.type === "timeEntry") {
              const project = entry.projectId
                ? projectMap[entry.projectId]
                : undefined;

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

              return (
                <TimeEntryCard
                  key={`${entry.id}-${index}`}
                  project={project}
                  task={task}
                  entry={entry}
                  onEdit={openEditTimeModal(entry)}
                />
              );
            } else {
              return (
                <LeaveEntryCard
                  key={`${entry.id}-${index}`}
                  entry={entry}
                  onEdit={openEditLeaveModal(entry)}
                  leaveTypeMap={leaveTypeMap}
                />
              );
            }
          })
        ) : (
          <Typography variant="body2" display="block">
            {t("Add some time entries!")}
          </Typography>
        )}
        <Stack alignItems={"flex-start"} spacing={1}>
          <Button startIcon={<Add />} onClick={openEditTimeModal()}>
            {t("Record time")}
          </Button>
          <Button startIcon={<Add />} onClick={openEditLeaveModal()}>
            {t("Record leave")}
          </Button>
          {fastEntryEnabled && (
            <Button startIcon={<Add />} onClick={openFastEntryModal}>
              {t("Fast time entry")}
            </Button>
          )}
        </Stack>
        <TimesheetEditModal
          recordDate={date}
          allProjects={allProjects}
          assignedProjects={assignedProjects}
          open={editTimeModalOpen}
          onClose={closeEditTimeModal}
          onSave={onSaveTimeEntry}
          isHoliday={Boolean(isHoliday)}
          miscTasks={miscTasks}
          {...editTimeModalProps}
        />
        <LeaveEditModal
          recordDate={date}
          leaveTypes={leaveTypes}
          open={editLeaveModalOpen}
          onClose={closeEditLeaveModal}
          onSave={onSaveLeaveEntry}
          isHoliday={Boolean(isHoliday)}
          {...editLeaveModalProps}
        />
        {fastEntryEnabled && (
          <FastTimeEntryModal
            recordDate={date}
            allProjects={allProjects}
            assignedProjects={assignedProjects}
            open={fastEntryModalOpen}
            isHoliday={Boolean(isHoliday)}
            onClose={closeFastEntryModal}
            onSave={onSaveFastEntry}
          />
        )}
      </Box>
    </>
  );
};

export default TimeLeaveMobileEntry;
