import { FC, useEffect, useMemo, useState } from 'react';
import {
  Attendance,
  Holiday,
  Leave,
  soriAPIClient,
  Staff,
} from '../../lib/sori';

export const AttendanceScene: FC = () => {
  const [staffs, setStaffs] = useState<Staff[]>([]);
  const [attendances, setAttendances] = useState<Attendance[]>([]);
  const [holidays, setHolidays] = useState<Holiday[]>([]);
  const [leaves, setLeaves] = useState<Leave[]>([]);
  const loadData = async () => {
    const staffsResult = await soriAPIClient.staffs.actions.getStaffs();
    const attendancesResult =
      await soriAPIClient.attendances.actions.getAttendance();
    const holidaysResult = await soriAPIClient.holidays.actions.getHolidays();
    const leavesResult = await soriAPIClient.leaves.actions.getLeaves();

    setStaffs(staffsResult.unwrap());
    setAttendances(attendancesResult.unwrap());
    setHolidays(holidaysResult.unwrap());
    setLeaves(leavesResult.unwrap());
  };

  useEffect(() => {
    loadData();
  }, []);

  const dateArray = useMemo(() => {
    const dayInMs = 1000 * 60 * 60 * 24;
    const fromDate = new Date().getTime();
    const toDate = new Date('Jan 1 2025').getTime();

    const dates: Date[] = [];
    for (let d = fromDate; d >= toDate; d -= dayInMs) {
      dates.push(new Date(d));
    }
    return dates;
  }, []);

  return (
    <>
      <h1 className="m-2 text-xl">Attendance</h1>
      <div className="m-3 w-[900px] overflow-x-auto border">
        <table className="min-w-max border-collapse border">
          <thead>
            <tr className="">
              <th className="sticky left-0 z-20 border bg-neutral-4 p-2">
                Staff
              </th>
              {dateArray.map((d) => (
                <th className="w-[100px] p-2">
                  {d.toLocaleDateString('en-US', {
                    month: 'short',
                    day: 'numeric',
                  })}
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {staffs.map((staff) => (
              <AttendanceTr
                staff={staff}
                attendances={attendances}
                dateArray={dateArray}
                holidays={holidays}
                leaves={leaves}
              />
            ))}
          </tbody>
        </table>
      </div>
    </>
  );
};

const AttendanceTr: FC<{
  staff: Staff;
  attendances: Attendance[];
  dateArray: Date[];
  holidays: Holiday[];
  leaves: Leave[];
}> = ({ staff, attendances, dateArray, holidays, leaves }) => {
  const staffAttendance = useMemo(() => {
    const map = new Set(
      attendances
        .filter((a) => a.staff.toString() === staff._id.toString())
        .map((a) => new Date(a.workDay.date).toDateString()),
    );
    return map;
  }, [attendances, staff._id]);

  const holidayList = useMemo(() => {
    const map = new Set(
      holidays.map((h) => new Date(h.startdate).toDateString()),
    );
    return map;
  }, [holidays]);

  const leaveList = useMemo(() => {
    const map = new Map<string, { type: string; workDayType: string }>();

    leaves
      .filter(
        (l) =>
          l.staff.toString() === staff._id.toString() &&
          l.status === 'approved',
      )
      .map((l) => {
        const date = new Date(l.workDay.date).toDateString();
        map.set(date, { type: l.type, workDayType: l.workDay.type });
      });

    return map;
  }, [leaves, staff._id]);

  const renderCell = (d: Date) => {
    const leave = leaveList.get(d.toDateString());
    if (leave)
      return {
        text: `${leave.type} (${leave.workDayType})`,
        className: 'bg-orange-3',
      };
    if (holidayList.has(d.toDateString())) {
      return { text: '🎉', className: 'bg-red-3' };
    }

    if (staffAttendance.has(d.toDateString())) {
      return { text: '✅', className: 'bg-green-3' };
    }
    if (d.getDay() === 0 || d.getDay() === 6)
      return { text: '', className: 'bg-green-1' };
    return { text: '❌', className: 'bg-red-1' };
  };
  return (
    <tr>
      <td className="sticky left-0 z-10 border bg-neutral-4 p-2 text-center">
        {staff.nameEN}
      </td>
      {dateArray.map((d) => {
        const { text, className } = renderCell(d);
        return (
          <td className={`z-5 p-2 text-center border ${className}`}>{text}</td>
        );
      })}
    </tr>
  );
};
