"use client";

import { useCallback, useState } from "react";

import type { CalendarView } from "../types";
import { navigateDate } from "../lib/date-utils";

export interface UseCalendarOptions {
  view?: CalendarView;
  onViewChange?: (view: CalendarView) => void;
  defaultView?: CalendarView;

  date?: Date;
  onDateChange?: (date: Date) => void;
  defaultDate?: Date;
}

export interface UseCalendarResult {
  view: CalendarView;
  date: Date;
  setView: (view: CalendarView) => void;
  setDate: (date: Date) => void;
  goToday: () => void;
  goPrev: () => void;
  goNext: () => void;
}

/**
 * Headless calendar state: owns the current view + focused date and the
 * navigation actions, supporting both controlled and uncontrolled usage.
 * Rendering-free on purpose so the logic is testable and reusable apart from
 * the visual `Calendar`.
 */
export function useCalendar({
  view: viewProp,
  onViewChange,
  defaultView = "month",
  date: dateProp,
  onDateChange,
  defaultDate,
}: UseCalendarOptions): UseCalendarResult {
  const [viewState, setViewState] = useState<CalendarView>(defaultView);
  const [dateState, setDateState] = useState<Date>(
    () => defaultDate ?? new Date(),
  );

  const view = viewProp ?? viewState;
  const date = dateProp ?? dateState;

  const isViewControlled = viewProp !== undefined;
  const isDateControlled = dateProp !== undefined;

  const setView = useCallback(
    (next: CalendarView) => {
      if (!isViewControlled) setViewState(next);
      onViewChange?.(next);
    },
    [isViewControlled, onViewChange],
  );

  const setDate = useCallback(
    (next: Date) => {
      if (!isDateControlled) setDateState(next);
      onDateChange?.(next);
    },
    [isDateControlled, onDateChange],
  );

  const goToday = useCallback(() => setDate(new Date()), [setDate]);
  const goPrev = useCallback(
    () => setDate(navigateDate(date, view, -1)),
    [date, view, setDate],
  );
  const goNext = useCallback(
    () => setDate(navigateDate(date, view, 1)),
    [date, view, setDate],
  );

  return { view, date, setView, setDate, goToday, goPrev, goNext };
}
