"use client";

import { useEffect, useMemo, useState } from "react";
import {
  FetchError,
  apiGet,
  apiPost,
  type PublicTemplate,
} from "@/lib/client-api";
import type { NavbarSavedEntry } from "@/components/layout/NavbarInteractive";

const WEEKDAY_LABELS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];

function startOfMonth(date: Date) {
  return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1));
}

function addMonths(date: Date, n: number) {
  return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + n, 1));
}

function fmtDate(date: Date) {
  return date.toLocaleDateString("en-US", {
    month: "short",
    day: "numeric",
    year: "numeric",
  });
}

function isoDay(date: Date) {
  return Date.UTC(
    date.getUTCFullYear(),
    date.getUTCMonth(),
    date.getUTCDate(),
  );
}

function buildGrid(viewMonth: Date) {
  const first = startOfMonth(viewMonth);
  const startWeekday = first.getUTCDay();
  const daysInMonth = new Date(
    Date.UTC(first.getUTCFullYear(), first.getUTCMonth() + 1, 0),
  ).getUTCDate();
  const cells: Array<{ date: Date | null; key: string }> = [];
  for (let i = 0; i < startWeekday; i++) {
    cells.push({ date: null, key: `pad-${i}` });
  }
  for (let d = 1; d <= daysInMonth; d++) {
    const date = new Date(
      Date.UTC(first.getUTCFullYear(), first.getUTCMonth(), d),
    );
    cells.push({ date, key: `d-${d}` });
  }
  while (cells.length % 7 !== 0) {
    cells.push({ date: null, key: `tail-${cells.length}` });
  }
  return cells;
}

export function CalendarPanel({
  entries,
  favoriteIds,
  onAdd,
  onRemove,
  onClose,
}: {
  entries: NavbarSavedEntry[];
  favoriteIds: string[];
  onAdd: (entry: NavbarSavedEntry) => void;
  onRemove: (id: string) => void;
  onClose: () => void;
}) {
  const today = useMemo(() => {
    const now = new Date();
    return new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()));
  }, []);
  const [viewMonth, setViewMonth] = useState(today);
  const [selected, setSelected] = useState(today);
  const [templates, setTemplates] = useState<PublicTemplate[]>([]);
  const [pickerTemplateId, setPickerTemplateId] = useState("");
  const [note, setNote] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    apiGet<{ items: PublicTemplate[] }>("/api/templates")
      .then((res) => setTemplates(res.items ?? []))
      .catch(() => setTemplates([]));
  }, []);

  const entriesByDay = useMemo(() => {
    const map = new Map<number, NavbarSavedEntry[]>();
    for (const e of entries) {
      const d = new Date(e.scheduledFor);
      const key = isoDay(d);
      const arr = map.get(key) ?? [];
      arr.push(e);
      map.set(key, arr);
    }
    return map;
  }, [entries]);

  const selectedEntries = entriesByDay.get(isoDay(selected)) ?? [];

  const cells = useMemo(() => buildGrid(viewMonth), [viewMonth]);

  const monthLabel = viewMonth.toLocaleDateString("en-US", {
    month: "long",
    year: "numeric",
  });

  const addEntry = async () => {
    if (!pickerTemplateId) {
      setError("Pick a template to schedule.");
      return;
    }
    setError(null);
    setSubmitting(true);
    try {
      const tpl = templates.find((t) => t.id === pickerTemplateId);
      const res = await apiPost<{
        id: string;
        templateId: string;
        scheduledFor: string;
        note: string;
      }>("/api/calendar/saved-templates", {
        templateId: pickerTemplateId,
        scheduledFor: selected.toISOString(),
        note,
      });
      onAdd({
        id: res.id,
        templateId: res.templateId,
        templateName: tpl?.name ?? "",
        templateCategory: tpl?.category ?? "",
        templateIcon: tpl?.icon ?? "",
        scheduledFor: res.scheduledFor,
        note: res.note,
      });
      setPickerTemplateId("");
      setNote("");
    } catch (err) {
      setError(err instanceof FetchError ? err.message : "Failed to schedule.");
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div className="p-4">
      <div className="mb-3 flex items-center justify-between">
        <h3 className="text-sm font-semibold text-foreground">Your calendar</h3>
        <button
          type="button"
          onClick={onClose}
          aria-label="Close calendar"
          className="rounded p-1 text-muted hover:bg-rose-50 hover:text-rose-700"
        >
          ✕
        </button>
      </div>

      <div className="mb-3 flex items-center justify-between">
        <button
          type="button"
          onClick={() => setViewMonth(addMonths(viewMonth, -1))}
          aria-label="Previous month"
          className="grid h-7 w-7 place-items-center rounded-full text-rose-500 hover:bg-rose-50"
        >
          ‹
        </button>
        <span className="text-sm font-semibold text-foreground">{monthLabel}</span>
        <button
          type="button"
          onClick={() => setViewMonth(addMonths(viewMonth, 1))}
          aria-label="Next month"
          className="grid h-7 w-7 place-items-center rounded-full text-rose-500 hover:bg-rose-50"
        >
          ›
        </button>
      </div>

      <div className="grid grid-cols-7 gap-1 text-center text-[10px] font-semibold text-muted">
        {WEEKDAY_LABELS.map((d) => (
          <span key={d}>{d}</span>
        ))}
      </div>
      <div className="mt-1 grid grid-cols-7 gap-1">
        {cells.map((cell) => {
          if (!cell.date) {
            return <div key={cell.key} className="h-9" />;
          }
          const isSelected = isoDay(cell.date) === isoDay(selected);
          const isToday = isoDay(cell.date) === isoDay(today);
          const hasEntries = entriesByDay.has(isoDay(cell.date));
          return (
            <button
              key={cell.key}
              type="button"
              onClick={() => setSelected(cell.date as Date)}
              className={`relative grid h-9 place-items-center rounded-lg text-xs transition-colors ${
                isSelected
                  ? "bg-rose-500 font-semibold text-white"
                  : isToday
                    ? "bg-rose-100 font-semibold text-rose-700"
                    : "hover:bg-rose-50 text-foreground"
              }`}
            >
              {cell.date.getUTCDate()}
              {hasEntries ? (
                <span
                  className={`absolute bottom-1 h-1 w-1 rounded-full ${
                    isSelected ? "bg-white" : "bg-rose-500"
                  }`}
                />
              ) : null}
            </button>
          );
        })}
      </div>

      <div className="mt-4 rounded-xl border border-rose-100 bg-rose-50/40 p-3">
        <div className="mb-2 flex items-center justify-between">
          <span className="text-xs font-semibold text-foreground">
            {fmtDate(selected)}
          </span>
          <span className="text-[10px] uppercase tracking-wide text-muted">
            {selectedEntries.length} planned
          </span>
        </div>

        {selectedEntries.length > 0 ? (
          <ul className="mb-3 space-y-1.5">
            {selectedEntries.map((e) => (
              <li
                key={e.id}
                className="flex items-center justify-between rounded-lg bg-white px-2.5 py-1.5 text-xs"
              >
                <span className="truncate font-medium text-foreground">
                  {e.templateName || "Template"}
                </span>
                <button
                  type="button"
                  onClick={() => onRemove(e.id)}
                  className="ml-2 text-rose-400 hover:text-rose-600"
                  aria-label="Remove entry"
                >
                  ✕
                </button>
              </li>
            ))}
          </ul>
        ) : null}

        <div className="space-y-2">
          <select
            value={pickerTemplateId}
            onChange={(e) => setPickerTemplateId(e.target.value)}
            className="w-full rounded-lg border border-rose-200 bg-white px-2.5 py-1.5 text-xs text-foreground focus:border-rose-500 focus:outline-none"
          >
            <option value="">Choose a template…</option>
            {templates.map((t) => {
              const isFav = favoriteIds.includes(t.id);
              return (
                <option key={t.id} value={t.id}>
                  {isFav ? "♥ " : ""}
                  {t.name}
                  {" · "}
                  {t.category}
                </option>
              );
            })}
          </select>
          <input
            type="text"
            value={note}
            onChange={(e) => setNote(e.target.value)}
            placeholder="Note (optional)"
            className="w-full rounded-lg border border-rose-200 bg-white px-2.5 py-1.5 text-xs text-foreground placeholder:text-muted focus:border-rose-500 focus:outline-none"
          />
          {error ? <p className="text-[11px] text-rose-600">{error}</p> : null}
          <button
            type="button"
            onClick={addEntry}
            disabled={submitting}
            className="w-full rounded-lg bg-gradient-to-r from-rose-500 to-pink-600 px-3 py-1.5 text-xs font-semibold text-white shadow disabled:opacity-60"
          >
            {submitting ? "Scheduling…" : "Schedule for this day"}
          </button>
        </div>
      </div>
    </div>
  );
}
