"use client";

import { useCallback, useEffect, useRef, useState } from "react";

import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import { alpha, useTheme } from "@mui/material/styles";

import { useAppLanguage } from "@/components/providers/app-language-provider";
import { getMeetingRequestStatusStyle } from "@/components/ui/meeting-request-status-badge";
import {
  MonthCalendar,
  formatCalendarParticipantText,
  formatCalendarTimeRange,
  type CalendarLanguage,
} from "@/components/ui/month-calendar";
import { CdcGpsfMeetingRequestDetailDialog } from "@/features/cdc-gpsf/meeting-requests/components/detail/cdc-gpsf-meeting-request-detail-dialog";
import {
  getMeetingRequestFont,
  type UiLang,
} from "@/features/pswg/meeting-request/meeting-request-i18n";

import {
  getChangedMeetingDate,
  getMeetingCalendarEvents,
  MEETING_CHANGED_EVENT,
  MEETING_CHANGED_STORAGE_KEY,
  type MeetingCalendarEvent,
} from "../../service/meeting-calendar-service";

import { MeetingRequestDetailDialog } from "./meeting-request-detail-dialog";

function MeetingEventCard({
  event,
  language,
  onClick,
}: {
  event: MeetingCalendarEvent;
  language: CalendarLanguage;
  onClick: () => void;
}) {
  const theme = useTheme();
  const statusStyle = getMeetingRequestStatusStyle(
    event.status === "Draft" ? "Drafted" : event.status,
    theme.palette.mode === "dark",
  );

  return (
    <Box
      role="button"
      tabIndex={0}
      onClick={(e) => {
        e.stopPropagation();
        onClick();
      }}
      onKeyDown={(e) => {
        if (e.key === "Enter" || e.key === " ") {
          e.preventDefault();
          e.stopPropagation();
          onClick();
        }
      }}
      sx={{
        mt: 1,
        p: 1.25,
        minWidth: 0,
        maxWidth: 185,
        borderRadius: "4px",
        border: `1px solid ${theme.palette.divider}`,
        bgcolor: theme.palette.background.paper,
        cursor: "pointer",
        transition: "border-color 160ms ease, transform 160ms ease",
        "&:hover": {
          borderColor: theme.palette.primary.main,
          transform: "translateY(-1px)",
        },
      }}
    >
      <Box sx={{ display: "flex", alignItems: "center", gap: 0.75 }}>
        <Box
          aria-hidden
          sx={{
            width: 3,
            height: 14,
            flexShrink: 0,
            borderRadius: 999,
            bgcolor: statusStyle.color,
          }}
        />
        <Typography
          title={event.title}
          noWrap
          sx={{
            minWidth: 0,
            fontFamily: getMeetingRequestFont(
              language === "en" ? "en" : "km",
            ),
            fontSize: 10,
            fontWeight: 500,
            color: theme.palette.text.primary,
          }}
        >
          {event.title}
        </Typography>
      </Box>

      <Typography
        sx={{
          mt: 0.5,
          fontSize: 9,
          color: theme.palette.text.secondary,
        }}
      >
        {formatCalendarTimeRange(event.startTime, event.endTime, language)}
      </Typography>

      <Typography
        sx={{
          mt: 0.25,
          fontSize: 9,
          color: theme.palette.text.secondary,
          fontFamily: getMeetingRequestFont(language === "en" ? "en" : "km"),
        }}
      >
        <Box component="span" sx={{ color: theme.palette.text.primary }}>
          {formatCalendarParticipantText(event.participants, language)}
        </Box>
      </Typography>
    </Box>
  );
}

export function MeetingRequestsCalendar({
  initialMeetingId,
}: {
  initialMeetingId?: number;
}) {
  const theme = useTheme();
  const isDark = theme.palette.mode === "dark";
  const { language: appLanguage } = useAppLanguage();
  const language: UiLang = appLanguage === "en" ? "en" : "km";

  const [displayDate, setDisplayDate] = useState(() => {
    const now = new Date();
    return new Date(now.getFullYear(), now.getMonth(), 1);
  });
  const [selectedEvent, setSelectedEvent] =
    useState<MeetingCalendarEvent | null>(null);
  const [detailMeetingRequestId, setDetailMeetingRequestId] = useState<
    number | null
  >(null);
  const [meetingEvents, setMeetingEvents] = useState<MeetingCalendarEvent[]>(
    [],
  );
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const initialMeetingOpenedRef = useRef(false);

  function openEventDetail(event: MeetingCalendarEvent) {
    if (event.meetingRequestId) {
      setSelectedEvent(null);
      setDetailMeetingRequestId(event.meetingRequestId);
      return;
    }

    setDetailMeetingRequestId(null);
    setSelectedEvent(event);
  }

  function closeEventDetail() {
    setSelectedEvent(null);
    setDetailMeetingRequestId(null);
  }

  const loadMeetings = useCallback(
    async (signal?: AbortSignal) => {
      try {
        setLoading(true);
        setError("");

        const events = await getMeetingCalendarEvents(signal);
        setMeetingEvents(events);

        if (initialMeetingId && !initialMeetingOpenedRef.current) {
          const initialEvent = events.find(
            (event) => Number(event.id) === initialMeetingId,
          );

          if (initialEvent) {
            const eventDate = new Date(`${initialEvent.date}T00:00:00`);

            initialMeetingOpenedRef.current = true;
            openEventDetail(initialEvent);
            setDisplayDate(
              new Date(eventDate.getFullYear(), eventDate.getMonth(), 1),
            );
          }
        }
      } catch (requestError) {
        if (signal?.aborted) return;

        console.error(
          "Unable to load Ministry meetings for PSWG calendar",
          requestError,
        );
        setError(
          requestError instanceof Error
            ? requestError.message
            : "Unable to load meetings.",
        );
      } finally {
        if (!signal?.aborted) setLoading(false);
      }
    },
    [initialMeetingId],
  );

  useEffect(() => {
    const controller = new AbortController();
    // eslint-disable-next-line react-hooks/set-state-in-effect -- initial data fetch with abort handling
    void loadMeetings(controller.signal);

    return () => controller.abort();
  }, [loadMeetings]);

  useEffect(() => {
    const refresh = () => void loadMeetings();

    const handleMeetingChanged = (event: Event) => {
      const customEvent = event as CustomEvent<{ meetingDate?: string }>;
      const date = customEvent.detail?.meetingDate;

      if (date) {
        const nextDate = new Date(`${date}T00:00:00`);
        setDisplayDate(
          new Date(nextDate.getFullYear(), nextDate.getMonth(), 1),
        );
      }

      refresh();
    };

    const handleStorage = (event: StorageEvent) => {
      if (event.key !== MEETING_CHANGED_STORAGE_KEY) return;

      const date = getChangedMeetingDate(event.newValue);
      if (date) {
        const nextDate = new Date(`${date}T00:00:00`);
        setDisplayDate(
          new Date(nextDate.getFullYear(), nextDate.getMonth(), 1),
        );
      }

      refresh();
    };

    window.addEventListener(MEETING_CHANGED_EVENT, handleMeetingChanged);
    window.addEventListener("storage", handleStorage);
    window.addEventListener("focus", refresh);

    return () => {
      window.removeEventListener(MEETING_CHANGED_EVENT, handleMeetingChanged);
      window.removeEventListener("storage", handleStorage);
      window.removeEventListener("focus", refresh);
    };
  }, [loadMeetings]);

  return (
    <>
      {(loading || error) && (
        <Box
          sx={{
            px: 2.5,
            py: 1,
            mb: 1,
            borderRadius: "8px",
            borderBottom: `1px solid ${
              isDark ? alpha("#ffffff", 0.08) : "#f5f5f5"
            }`,
          }}
        >
          <Typography
            sx={{
              color: error
                ? "#f04438"
                : isDark
                  ? alpha("#ffffff", 0.68)
                  : "#667085",
              fontSize: 13,
              fontWeight: 500,
            }}
          >
            {error || "Loading Ministry meetings..."}
          </Typography>
        </Box>
      )}

      <MonthCalendar
        items={meetingEvents}
        getItemId={(event) => event.id}
        getItemDateKey={(event) => event.date}
        month={{
          year: displayDate.getFullYear(),
          monthIndex: displayDate.getMonth(),
        }}
        onMonthChange={({ year, monthIndex }) => {
          setDisplayDate(new Date(year, monthIndex, 1));
        }}
        weekStartsOn={1}
        headerLayout="centered-year"
        renderItem={(event) => (
          <MeetingEventCard
            event={event}
            language={language}
            onClick={() => openEventDetail(event)}
          />
        )}
      />

      <CdcGpsfMeetingRequestDetailDialog
        open={detailMeetingRequestId != null}
        meetingRequestId={detailMeetingRequestId}
        onClose={closeEventDetail}
      />

      <MeetingRequestDetailDialog
        key={selectedEvent?.id ?? "empty-meeting-request-dialog"}
        open={Boolean(selectedEvent)}
        event={selectedEvent}
        language={language}
        onClose={closeEventDetail}
      />
    </>
  );
}
