"use client";

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

import Button from "@mui/material/Button";
import CardContent from "@mui/material/CardContent";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import Autocomplete from "@mui/material/Autocomplete";
import CircularProgress from "@mui/material/CircularProgress";

import { Calendar, momentLocalizer, Views } from "react-big-calendar";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { DateTimePicker } from "@mui/x-date-pickers/DateTimePicker";

import dayjs, { Dayjs } from "dayjs";
import moment from "moment";

import "react-big-calendar/lib/css/react-big-calendar.css";
import "./Calendar.css";

import PageContainer from "@/app/components/container/PageContainer";
import BlankCard from "@/app/components/shared/BlankCard";
import { Box, LinearProgress } from "@mui/material";

moment.locale("en-US");
const localizer = momentLocalizer(moment);

// -------------------------
// Types
// -------------------------
export interface CalendarEvent {
  title: string;
  start: Date;
  end: Date;
  color?: string;
  adminId?: number;
}

interface BackendPeriod {
  in: string;
  out: string;
}

interface BackendAdminDay {
  id: number;
  name: string;
  period: BackendPeriod;
}

interface BackendDaysResponse {
  status: string;
  days: {
    [date: string]: BackendAdminDay[];
  };
}

const AdminColorPool = ["green", "default", "red", "azure", "warning"];

// -------------------------
// Event cleaners
// -------------------------
const mergeOverlapping = (events: CalendarEvent[]): CalendarEvent[] => {
  const byAdmin: Record<number, CalendarEvent[]> = {};

  events.forEach((ev) => {
    if (!ev.adminId) return;
    if (!byAdmin[ev.adminId]) byAdmin[ev.adminId] = [];
    byAdmin[ev.adminId].push(ev);
  });

  const merged: CalendarEvent[] = [];

  Object.values(byAdmin).forEach((adminEvents) => {
    const sorted = adminEvents.sort(
      (a, b) => a.start.getTime() - b.start.getTime()
    );

    let current = sorted[0];

    for (let i = 1; i < sorted.length; i++) {
      const next = sorted[i];

      // If overlapping or touching
      if (next.start <= current.end) {
        current = {
          ...current,
          end: new Date(Math.max(current.end.getTime(), next.end.getTime())),
        };
      } else {
        merged.push(current);
        current = next;
      }
    }

    merged.push(current);
  });

  return merged;
};

const removeExactDuplicates = (events: CalendarEvent[]): CalendarEvent[] => {
  const map = new Map<string, CalendarEvent>();

  events.forEach((ev) => {
    if (!ev.adminId) return;
    const key = `${ev.adminId}_${ev.start.toISOString()}_${ev.end.toISOString()}`;
    if (!map.has(key)) map.set(key, ev);
  });

  return Array.from(map.values());
};

const cleanEvents = (events: CalendarEvent[]): CalendarEvent[] => {
  return mergeOverlapping(removeExactDuplicates(events));
};

// -------------------------
// Component
// -------------------------
const BigCalendar: React.FC<{ sessionData?: any }> = ({ sessionData }) => {
  const [admins, setAdmins] = useState<{ id: number; username: string }[]>([]);
  const [selectedEmployee, setSelectedEmployee] = useState<number | "all">(
    "all"
  );
  const [inputValue, setInputValue] = useState("");
  const [isLoadingAdmins, setIsLoadingAdmins] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [calevents, setCalEvents] = useState<CalendarEvent[]>([]);

  const [open, setOpen] = useState<boolean>(false);
  const [title, setTitle] = useState<string>("");
  const [start, setStart] = useState<Dayjs | null>(dayjs());
  const [end, setEnd] = useState<Dayjs | null>(dayjs());
  const [color, setColor] = useState<string>("default"); // mainly for dialog display
  const [timezones, setTimezones] = useState<any>(['MST', 'IST']);
  const [selectedTimezone, setSelectedTimezone] = useState<any | null>('IST');
  const [updateEventObj, setUpdateEventObj] =
    useState<CalendarEvent | null>(null);

  const [currentMonth, setCurrentMonth] = useState<string>(
    moment().format("YYYY-MM")
  );

  // Persistent admin-color mapping
  const adminColorRef = useRef<Record<number, string>>({});

  const getAdminColor = (adminId: number) => {
    if (adminColorRef.current[adminId]) {
      return adminColorRef.current[adminId];
    }

    const used = new Set(Object.values(adminColorRef.current));
    const available = AdminColorPool.filter((c) => !used.has(c));

    const assigned =
      available[0] ||
      AdminColorPool[adminId % AdminColorPool.length]; // fallback pattern

    adminColorRef.current[adminId] = assigned;
    return assigned;
  };

  // -------------------------
  // Fetch admins (for dropdown)
  // -------------------------
  const fetchAdmins = async () => {
    try {
      setIsLoadingAdmins(true);
      setIsLoading(true);
      const token = sessionData?.token ?? "";
      const res = await axios.post("/api/getAdmins", { token });
      const list = res.data.admins || [];

      const formatted = list.map((a: any) => ({
        id: a.id,
        username: a.username || `${a.first ?? ""} ${a.last ?? ""}`.trim() || "Unknown",
      }));

      setAdmins(formatted);
    } catch (err) {
      console.error("Admin fetch error:", err);
    } finally {
      setIsLoadingAdmins(false);
      setIsLoading(false);

    }
  };

  useEffect(() => {
    fetchAdmins();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // -------------------------
  // Fetch month data (shifts)
  // -------------------------
  const fetchMonthData = useCallback(
    async (monthString: string, adminValue: number | "all", timezone: string) => {
      setIsLoading(true);

      try {
        const res = await axios.post<BackendDaysResponse>(
          `/api/getAdminsWorkDays`,
          {
            month: monthString,
            admin: adminValue === "all" ? null : adminValue,
            timezone: timezone,
          }
        );

        const data = res.data;

        if (!data.days) {


          setCalEvents([]);
          return;
        }

        const events: CalendarEvent[] = [];

        Object.entries(data.days).forEach(([_, adminList]) => {
          adminList.forEach((admin: BackendAdminDay) => {
            events.push({
              title: admin.name,
              start: new Date(admin.period.in),
              end: new Date(admin.period.out),
              color: getAdminColor(admin.id),
              adminId: admin.id,
            });
          });
        });

        setCalEvents(cleanEvents(events));
      } catch (err) {
        console.error("Calendar month fetch error:", err);
      } finally {
        setIsLoading(false);

      }
    },
    []
  );

  // Load data when month or selected employee changes
  useEffect(() => {
    fetchMonthData(currentMonth, selectedEmployee, selectedTimezone);
  }, [currentMonth, selectedEmployee, fetchMonthData, selectedTimezone]);

  // -------------------------
  // Calendar navigation
  // -------------------------
  const handleNavigate = (date: Date) => {
    const newMonth = moment(date).format("YYYY-MM");
    if (newMonth !== currentMonth) {
      setCurrentMonth(newMonth);
    }
  };

  // -------------------------
  // Event click -> view dialog
  // -------------------------
  const editEvent = (event: CalendarEvent) => {
    setTitle(event.title);
    setStart(dayjs(event.start));
    setEnd(dayjs(event.end));
    setColor(event.color || "default");
    setUpdateEventObj(event);
    setOpen(true);
  };

  const handleClose = () => {
    setOpen(false);
    setTitle("");
    setStart(dayjs());
    setEnd(dayjs());
    setColor("default");
    setUpdateEventObj(null);
  };

  const eventColors = (event: CalendarEvent) => ({
    className: `event-${event.color ?? "default"}`,
  });


  // -------------------------
  // Render
  // -------------------------
  return (
    <PageContainer title="Calendar" description="Shift Calendar">
      {isLoading && <><LinearProgress /><br /></>}

      <BlankCard>

        <CardContent>

          {/* Employee filter */}
          <Box
            sx={{
              width: "100%",
              mb: 2,
            }}
          >
            <Box
              sx={{
                display: "grid",
                gap: 2,
                width: "100%",
                gridTemplateColumns: {
                  xs: "1fr",        // mobile → full width
                  md: "1fr 1fr",    // desktop → half + half
                },
              }}
            >
              <Autocomplete
                fullWidth
                options={[{ id: "all", username: "All Employees" }, ...admins]}
                getOptionLabel={(option: any) => option.username}
                isOptionEqualToValue={(option: any, value: any) =>
                  option.id === value.id
                }
                value={
                  selectedEmployee === "all"
                    ? { id: "all", username: "All Employees" }
                    : admins.find((a) => a.id === selectedEmployee) || null
                }
                onChange={(event, newValue) => {
                  const id = newValue?.id;
                  setSelectedEmployee(id === "all" ? "all" : Number(id));
                }}
                inputValue={inputValue}
                onInputChange={(event, newInputValue) =>
                  setInputValue(newInputValue)
                }
                loading={isLoadingAdmins}
                renderInput={(params) => (
                  <TextField
                    {...params}
                    label="Employee"
                    placeholder="Select an Employee"
                    size="small"
                    InputProps={{
                      ...params.InputProps,
                      endAdornment: (
                        <>
                          {isLoadingAdmins && (
                            <CircularProgress color="inherit" size={20} />
                          )}
                          {params.InputProps.endAdornment}
                        </>
                      ),
                    }}
                  />
                )}
              />

              <Autocomplete
                fullWidth
                options={timezones}
                getOptionLabel={(option: any) => option}
                isOptionEqualToValue={(option: any, value: any) =>
                  option === value
                }
                value={selectedTimezone}
                onChange={(event, newValue) => {
                  console.log("Timezone changed to:", newValue);
                  setSelectedTimezone(newValue);
                }}
                renderInput={(params) => (
                  <TextField
                    {...params}
                    label="Timezone"
                    placeholder="Select a Timezone"
                    size="small"
                  />
                )}
              />

            </Box>
          </Box>

          {/* Calendar */}
          <Calendar
            selectable
            events={calevents}
            localizer={localizer}
            defaultView={Views.MONTH}
            style={{ height: "calc(100vh - 350px)" }}
            onSelectEvent={editEvent}
            eventPropGetter={eventColors}
            onNavigate={handleNavigate}
          />
        </CardContent>
      </BlankCard>

      {/* Event view dialog */}
      <Dialog open={open} onClose={handleClose} fullWidth maxWidth="xs">
        <DialogContent>
          <Typography variant="h4" sx={{ mb: 2 }}>
            Shift Details
          </Typography>

          <TextField
            fullWidth
            label="Employee"
            value={title}
            onChange={(e) => setTitle(e.target.value)}
            sx={{ mb: 3 }}
          />

          <LocalizationProvider dateAdapter={AdapterDayjs}>
            <DateTimePicker
              label="Start Date & Time"
              value={start}
              onChange={(v) => setStart(v)}
              slotProps={{
                textField: { fullWidth: true, sx: { mb: 3 } },
              }}
            />

            <DateTimePicker
              label="End Date & Time"
              value={end}
              onChange={(v) => setEnd(v)}
              slotProps={{
                textField: {
                  fullWidth: true,
                  sx: { mb: 3 },
                  error: Boolean(start && end && start > end),
                  helperText:
                    start && end && start > end
                      ? "End date/time must be later than start"
                      : "",
                },
              }}
            />
          </LocalizationProvider>
        </DialogContent>

        <DialogActions sx={{ p: 3 }}>
          <Button onClick={handleClose}>Close</Button>
        </DialogActions>
      </Dialog>
    </PageContainer>
  );
};

export default BigCalendar;
