"use client";

import { useState, useEffect, useCallback } from "react";
import type {
  CalendarInfo,
  CalendarEvent,
  CalendarHealth,
  GoogleCachedEvent,
  PersonFilter,
} from "@/lib/types";

export interface UseCalendarReturn {
  calendars: CalendarInfo[];
  events: CalendarEvent[];
  googleEvents: GoogleCachedEvent[];
  health: CalendarHealth | null;
  loading: boolean;
  error: string | null;
  currentMonth: Date;
  selectedDate: Date | null;
  activeCalendarIds: Set<string>;
  activePersonFilters: Set<PersonFilter>;
  goToNextMonth: () => void;
  goToPrevMonth: () => void;
  goToToday: () => void;
  selectDate: (date: Date | null) => void;
  toggleCalendar: (calendarId: string) => void;
  togglePersonFilter: (person: PersonFilter) => void;
  createEvent: (event: {
    calendar_id: string;
    title: string;
    description?: string;
    notes?: string;
    start_time: string;
    end_time: string;
    all_day?: boolean;
    location?: string;
    recurrence_rule?: string;
    created_by: string;
    people?: { person_name: string; invite_preference: string }[];
    reminders?: { person_name: string; remind_at: string }[];
  }) => Promise<CalendarEvent | null>;
  updateEvent: (
    id: string,
    updates: {
      title?: string;
      description?: string;
      notes?: string;
      start_time?: string;
      end_time?: string;
      all_day?: boolean;
      location?: string;
      recurrence_rule?: string;
      people?: { person_name: string; invite_preference: string }[];
    }
  ) => Promise<CalendarEvent | null>;
  deleteEvent: (id: string) => Promise<boolean>;
  createReminder: (eventId: string, personName: string, remindAt: string) => Promise<boolean>;
  deleteReminder: (id: string) => Promise<boolean>;
  refresh: () => void;
}

export function useCalendar(): UseCalendarReturn {
  const [calendars, setCalendars] = useState<CalendarInfo[]>([]);
  const [events, setEvents] = useState<CalendarEvent[]>([]);
  const [googleEvents, setGoogleEvents] = useState<GoogleCachedEvent[]>([]);
  const [health, setHealth] = useState<CalendarHealth | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [currentMonth, setCurrentMonth] = useState(() => {
    const now = new Date();
    return new Date(now.getFullYear(), now.getMonth(), 1);
  });
  const [selectedDate, setSelectedDate] = useState<Date | null>(null);
  const [activeCalendarIds, setActiveCalendarIds] = useState<Set<string>>(new Set());
  const [activePersonFilters, setActivePersonFilters] = useState<Set<PersonFilter>>(
    new Set<PersonFilter>()
  );

  const [refreshKey, setRefreshKey] = useState(0);

  const getDateRange = useCallback(() => {
    const year = currentMonth.getFullYear();
    const month = currentMonth.getMonth();
    const firstDay = new Date(year, month, 1);
    const lastDay = new Date(year, month + 1, 0);

    const start = new Date(firstDay);
    start.setDate(start.getDate() - start.getDay());
    const end = new Date(lastDay);
    end.setDate(end.getDate() + (6 - end.getDay()));
    end.setHours(23, 59, 59, 999);

    return { start: start.toISOString(), end: end.toISOString() };
  }, [currentMonth]);

  const fetchData = useCallback(async () => {
    try {
      setLoading(true);
      setError(null);

      const { start, end } = getDateRange();

      const [healthRes, calsRes, eventsRes, googleRes] = await Promise.all([
        fetch("/api/calendar/health"),
        fetch("/api/calendar/calendars"),
        fetch(`/api/calendar/events?start=${encodeURIComponent(start)}&end=${encodeURIComponent(end)}`),
        fetch(`/api/calendar/google/cached-events?start=${encodeURIComponent(start)}&end=${encodeURIComponent(end)}`),
      ]);

      if (healthRes.ok) setHealth(await healthRes.json());
      if (calsRes.ok) {
        const cals: CalendarInfo[] = await calsRes.json();
        setCalendars(cals);
        if (activeCalendarIds.size === 0) {
          setActiveCalendarIds(new Set(cals.map((c) => c.id)));
        }
      }
      if (eventsRes.ok) setEvents(await eventsRes.json());
      if (googleRes.ok) setGoogleEvents(await googleRes.json());
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setLoading(false);
    }
  }, [getDateRange, refreshKey]);

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

  const goToNextMonth = useCallback(() => {
    setCurrentMonth((prev) => new Date(prev.getFullYear(), prev.getMonth() + 1, 1));
  }, []);

  const goToPrevMonth = useCallback(() => {
    setCurrentMonth((prev) => new Date(prev.getFullYear(), prev.getMonth() - 1, 1));
  }, []);

  const goToToday = useCallback(() => {
    const now = new Date();
    setCurrentMonth(new Date(now.getFullYear(), now.getMonth(), 1));
    setSelectedDate(now);
  }, []);

  const selectDate = useCallback((date: Date | null) => {
    setSelectedDate(date);
  }, []);

  const toggleCalendar = useCallback((calendarId: string) => {
    setActiveCalendarIds((prev) => {
      const next = new Set(prev);
      if (next.has(calendarId)) next.delete(calendarId);
      else next.add(calendarId);
      return next;
    });
  }, []);

  const togglePersonFilter = useCallback((person: PersonFilter) => {
    setActivePersonFilters((prev) => {
      const next = new Set(prev);
      if (next.has(person)) next.delete(person);
      else next.add(person);
      return next;
    });
  }, []);

  const createEventFn = useCallback(async (event: Parameters<UseCalendarReturn["createEvent"]>[0]) => {
    try {
      const res = await fetch("/api/calendar/events", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(event),
      });
      if (!res.ok) throw new Error((await res.json()).error);
      const created: CalendarEvent = await res.json();
      setRefreshKey((k) => k + 1);
      return created;
    } catch (e) {
      setError((e as Error).message);
      return null;
    }
  }, []);

  const updateEventFn = useCallback(async (id: string, updates: Parameters<UseCalendarReturn["updateEvent"]>[1]) => {
    try {
      const res = await fetch(`/api/calendar/events/${encodeURIComponent(id)}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(updates),
      });
      if (!res.ok) throw new Error((await res.json()).error);
      const updated: CalendarEvent = await res.json();
      setRefreshKey((k) => k + 1);
      return updated;
    } catch (e) {
      setError((e as Error).message);
      return null;
    }
  }, []);

  const deleteEventFn = useCallback(async (id: string) => {
    try {
      const res = await fetch(`/api/calendar/events/${encodeURIComponent(id)}`, {
        method: "DELETE",
      });
      if (!res.ok) throw new Error((await res.json()).error);
      setRefreshKey((k) => k + 1);
      return true;
    } catch (e) {
      setError((e as Error).message);
      return false;
    }
  }, []);

  const createReminderFn = useCallback(async (eventId: string, personName: string, remindAt: string) => {
    try {
      const res = await fetch("/api/calendar/reminders", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ event_id: eventId, person_name: personName, remind_at: remindAt }),
      });
      if (!res.ok) throw new Error((await res.json()).error);
      setRefreshKey((k) => k + 1);
      return true;
    } catch (e) {
      setError((e as Error).message);
      return false;
    }
  }, []);

  const deleteReminderFn = useCallback(async (id: string) => {
    try {
      const res = await fetch(`/api/calendar/reminders/${encodeURIComponent(id)}`, {
        method: "DELETE",
      });
      if (!res.ok) throw new Error((await res.json()).error);
      setRefreshKey((k) => k + 1);
      return true;
    } catch (e) {
      setError((e as Error).message);
      return false;
    }
  }, []);

  const refresh = useCallback(() => {
    setRefreshKey((k) => k + 1);
  }, []);

  return {
    calendars, events, googleEvents, health, loading, error,
    currentMonth, selectedDate, activeCalendarIds, activePersonFilters,
    goToNextMonth, goToPrevMonth, goToToday, selectDate,
    toggleCalendar, togglePersonFilter,
    createEvent: createEventFn, updateEvent: updateEventFn, deleteEvent: deleteEventFn,
    createReminder: createReminderFn, deleteReminder: deleteReminderFn,
    refresh,
  };
}
