"use client";

import { useCallback, useEffect, useState } from "react";
import { createClient, getBrowserUserId } from "@/lib/supabase/client";
import { getNextReminderOccurrence } from "@/lib/reminders";
import { useWorkspaceStore } from "@/stores/workspace-store";
import type {
  Reminder,
  ReminderRecurrenceRule,
  ReminderSourceType,
  ReminderStatus,
} from "@/types";

export interface ReminderUpsertInput {
  body?: string | null;
  recurrence_days?: number[];
  recurrence_rule?: ReminderRecurrenceRule;
  remind_at: string;
  source_id?: string | null;
  source_title?: string | null;
  source_type?: ReminderSourceType;
  source_url?: string | null;
  status?: ReminderStatus;
  title: string;
}

const DEFAULT_WEEKDAY_RECURRENCE = [1, 2, 3, 4, 5];

function normalizeRecurrenceDays(rule: ReminderRecurrenceRule | undefined, days: number[] | undefined) {
  if (rule !== "weekdays") return [];

  const normalized = Array.from(
    new Set((days || []).filter((day) => Number.isInteger(day) && day >= 0 && day <= 6)),
  ).sort((left, right) => {
    const leftOrder = left === 0 ? 7 : left;
    const rightOrder = right === 0 ? 7 : right;
    return leftOrder - rightOrder;
  });

  return normalized.length > 0 ? normalized : DEFAULT_WEEKDAY_RECURRENCE;
}

export function useReminders() {
  const [reminders, setReminders] = useState<Reminder[]>([]);
  const [loading, setLoading] = useState(true);
  const [userId, setUserId] = useState<string | null>(null);
  const supabase = createClient();
  const activeTeamId = useWorkspaceStore((state) => state.activeTeamId);
  const initialized = useWorkspaceStore((state) => state.initialized);

  useEffect(() => {
    void getBrowserUserId().then(setUserId).catch(() => setUserId(null));
  }, []);

  const requireCurrentUserId = useCallback(async () => {
    const currentUserId = userId || (await getBrowserUserId());
    if (currentUserId && currentUserId !== userId) {
      setUserId(currentUserId);
    }
    return currentUserId;
  }, [userId]);

  const fetchReminders = useCallback(async () => {
    if (!initialized) return;

    setLoading(true);
    const currentUserId = await requireCurrentUserId();
    if (!currentUserId) {
      setReminders([]);
      setLoading(false);
      return;
    }

    let query = supabase
      .from("reminders")
      .select("*")
      .eq("user_id", currentUserId)
      .order("remind_at", { ascending: true })
      .order("created_at", { ascending: false });

    query = activeTeamId ? query.eq("team_id", activeTeamId) : query.is("team_id", null);

    const { data, error } = await query;
    if (error) {
      console.warn("Could not load reminders", error);
      setReminders([]);
      setLoading(false);
      return;
    }

    setReminders((data || []) as Reminder[]);
    setLoading(false);
  }, [activeTeamId, initialized, requireCurrentUserId, supabase]);

  useEffect(() => {
    if (!initialized) return;
    const timer = window.setTimeout(() => {
      void fetchReminders();
    }, 0);

    return () => window.clearTimeout(timer);
  }, [fetchReminders, initialized]);

  const createReminder = useCallback(
    async (input: ReminderUpsertInput) => {
      const currentUserId = await requireCurrentUserId();
      if (!currentUserId) throw new Error("Not authenticated");

      const { data, error } = await supabase
        .from("reminders")
        .insert({
          body: input.body?.trim() || null,
          recurrence_days: normalizeRecurrenceDays(input.recurrence_rule, input.recurrence_days),
          recurrence_rule: input.recurrence_rule || "none",
          remind_at: input.remind_at,
          source_id: input.source_id || null,
          source_title: input.source_title?.trim() || null,
          source_type: input.source_type || "manual",
          source_url: input.source_url || null,
          status: input.status || "scheduled",
          team_id: activeTeamId,
          title: input.title.trim(),
          user_id: currentUserId,
        })
        .select()
        .single();

      if (error) throw error;

      await fetchReminders();
      return data as Reminder;
    },
    [activeTeamId, fetchReminders, requireCurrentUserId, supabase],
  );

  const updateReminder = useCallback(
    async (reminderId: string, input: ReminderUpsertInput) => {
      const { error } = await supabase
        .from("reminders")
        .update({
          body: input.body?.trim() || null,
          completed_at: input.status === "done" ? new Date().toISOString() : null,
          delivered_at: null,
          recurrence_days: normalizeRecurrenceDays(input.recurrence_rule, input.recurrence_days),
          recurrence_rule: input.recurrence_rule || "none",
          remind_at: input.remind_at,
          snoozed_until: null,
          source_id: input.source_id || null,
          source_title: input.source_title?.trim() || null,
          source_type: input.source_type || "manual",
          source_url: input.source_url || null,
          status: input.status || "scheduled",
          title: input.title.trim(),
        })
        .eq("id", reminderId);

      if (error) throw error;

      await fetchReminders();
    },
    [fetchReminders, supabase],
  );

  const completeReminder = useCallback(
    async (reminderId: string) => {
      const reminder = reminders.find((item) => item.id === reminderId);
      if (!reminder) return;

      const nextOccurrence = getNextReminderOccurrence(reminder);
      const payload = nextOccurrence
        ? {
            completed_at: null,
            delivered_at: null,
            remind_at: nextOccurrence,
            snoozed_until: null,
            status: "scheduled" as ReminderStatus,
          }
        : {
            completed_at: new Date().toISOString(),
            status: "done" as ReminderStatus,
          };

      const { error } = await supabase.from("reminders").update(payload).eq("id", reminderId);
      if (error) throw error;

      await fetchReminders();
    },
    [fetchReminders, reminders, supabase],
  );

  const snoozeReminder = useCallback(
    async (reminderId: string, minutes: number) => {
      const snoozedUntil = new Date(Date.now() + minutes * 60_000).toISOString();
      const { error } = await supabase
        .from("reminders")
        .update({
          delivered_at: null,
          snoozed_until: snoozedUntil,
          status: "snoozed",
        })
        .eq("id", reminderId);

      if (error) throw error;

      await fetchReminders();
    },
    [fetchReminders, supabase],
  );

  const cancelReminder = useCallback(
    async (reminderId: string) => {
      const { error } = await supabase
        .from("reminders")
        .update({ status: "cancelled" })
        .eq("id", reminderId);

      if (error) throw error;

      await fetchReminders();
    },
    [fetchReminders, supabase],
  );

  const deleteReminder = useCallback(
    async (reminderId: string) => {
      const { error } = await supabase.from("reminders").delete().eq("id", reminderId);
      if (error) throw error;

      setReminders((current) => current.filter((reminder) => reminder.id !== reminderId));
    },
    [supabase],
  );

  return {
    cancelReminder,
    completeReminder,
    createReminder,
    deleteReminder,
    loading,
    refetch: fetchReminders,
    reminders,
    snoozeReminder,
    updateReminder,
  };
}
