"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import interactionPlugin from "@fullcalendar/interaction";
import { AppShell } from "@/components/app/AppShell";
import { PageHeader } from "@/components/layout/PageHeader";
import { Alert } from "@/components/ui/Alert";
import { Button } from "@/components/ui/Button";
import { ConfirmDialog } from "@/components/ui/ConfirmDialog";
import { Field, Input, Select, Textarea } from "@/components/ui/Field";
import { PersianDatePicker } from "@/components/ui/PersianDatePicker";
import { ApiError, apiDelete, apiGet, apiPatch, apiPost } from "@/lib/api";
import { addGregorianDays, gregorianIsoFromDate, jalaliDayNumber, jalaliMonth, shiftJalaliMonth } from "@/lib/jalali-month";
import { hasPermission, isHoldingAdmin } from "@/lib/permissions";
import { getActiveBranchId } from "@/lib/session-context";

type EventType = "occasion" | "official_holiday" | "emergency_holiday" | "school_holiday";

type CalendarEventRow = {
  id: number;
  type: EventType;
  title: string;
  description: string | null;
  starts_on: string;
  ends_on: string;
  status: "active" | "cancelled";
  scope: "organization" | "branches";
  is_closing: boolean;
  branches: { id: number; name: string; code: string }[];
};

type Summary = {
  holidays_this_month: number;
  occasions_this_month: number;
  emergency_holidays: number;
  instructional_days: number;
};

type BranchRow = { id: number; name: string; code: string };

const TYPE_META: Record<EventType, { label: string; color: string; dot: string }> = {
  official_holiday: { label: "تعطیلی رسمی", color: "#dc2626", dot: "🔴" },
  emergency_holiday: { label: "تعطیلی اضطراری", color: "#ea580c", dot: "🟠" },
  occasion: { label: "مناسبت", color: "#2563eb", dot: "🔵" },
  school_holiday: { label: "تعطیلی مدرسه", color: "#7c3aed", dot: "🟣" },
};

const emptyForm = {
  type: "occasion" as EventType,
  title: "",
  description: "",
  starts_on: "",
  ends_on: "",
  scope: "organization" as "organization" | "branches",
  branch_ids: [] as number[],
};

export default function CalendarPage() {
  const isSuperAdmin = isHoldingAdmin();
  const canManage = hasPermission("calendar.event.manage");
  const canImport = hasPermission("calendar.event.import");

  const [range, setRange] = useState(() => jalaliMonth());
  const [events, setEvents] = useState<CalendarEventRow[]>([]);
  const [summary, setSummary] = useState<Summary | null>(null);
  const [branches, setBranches] = useState<BranchRow[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [message, setMessage] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [showForm, setShowForm] = useState(false);
  const [editId, setEditId] = useState<number | null>(null);
  const [form, setForm] = useState(emptyForm);
  const [detail, setDetail] = useState<CalendarEventRow | null>(null);
  const [confirm, setConfirm] = useState<{ kind: "cancel" | "delete"; event: CalendarEventRow } | null>(null);
  const [busy, setBusy] = useState(false);
  const [history, setHistory] = useState<{ id: number; description: string; causer_name: string | null; created_at: string | null }[] | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const qs = `from=${range.from}&to=${range.to}`;
      const [rows, stats] = await Promise.all([
        apiGet<CalendarEventRow[]>(`/calendar/events?${qs}`),
        apiGet<Summary>(`/calendar/summary?${qs}`),
      ]);
      setEvents(rows);
      setSummary(stats);
      setError(null);
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطای سرور. لطفاً دوباره تلاش کنید.");
    } finally {
      setLoading(false);
    }
  }, [range.from, range.to]);

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

  useEffect(() => {
    if (!isSuperAdmin) return;
    apiGet<BranchRow[]>("/branches")
      .then(setBranches)
      .catch(() => setBranches([]));
  }, [isSuperAdmin]);

  const goToday = () => setRange(jalaliMonth());
  const goPrev = () => setRange(shiftJalaliMonth(range, -1));
  const goNext = () => setRange(shiftJalaliMonth(range, 1));

  const fcEvents = useMemo(
    () =>
      events
        .filter((e) => e.status === "active")
        .map((e) => ({
          id: String(e.id),
          title: e.title,
          start: e.starts_on,
          end: addGregorianDays(e.ends_on, 1),
          allDay: true,
          backgroundColor: TYPE_META[e.type].color,
          borderColor: TYPE_META[e.type].color,
        })),
    [events],
  );

  const countsByDay = useMemo(() => {
    const map: Record<string, number> = {};
    for (const e of events.filter((row) => row.status === "active")) {
      let cursor = e.starts_on;
      while (cursor <= e.ends_on) {
        map[cursor] = (map[cursor] ?? 0) + 1;
        cursor = addGregorianDays(cursor, 1);
      }
    }
    return map;
  }, [events]);

  const openCreate = (date?: string) => {
    const type = isSuperAdmin ? "occasion" : "school_holiday";
    setEditId(null);
    setForm({
      ...emptyForm,
      type,
      starts_on: date ?? "",
      ends_on: date ?? "",
      scope: isSuperAdmin ? "organization" : "branches",
      branch_ids: isSuperAdmin ? [] : getActiveBranchId() ? [getActiveBranchId() as number] : [],
    });
    setShowForm(true);
    setDetail(null);
  };

  const openEdit = (row: CalendarEventRow) => {
    setEditId(row.id);
    setForm({
      type: row.type,
      title: row.title,
      description: row.description ?? "",
      starts_on: row.starts_on,
      ends_on: row.ends_on,
      scope: row.scope,
      branch_ids: row.branches.map((b) => b.id),
    });
    setShowForm(true);
    setDetail(null);
  };

  const canMutate = (row: CalendarEventRow) => {
    if (!canManage || row.status !== "active") return false;
    if (isSuperAdmin) return true;
    const mine = getActiveBranchId();
    return (
      row.type === "school_holiday" &&
      row.branches.length === 1 &&
      mine !== null &&
      row.branches[0].id === mine
    );
  };

  const submit = async () => {
    setBusy(true);
    setError(null);
    setMessage(null);
    try {
      const payload = {
        type: form.type,
        title: form.title,
        description: form.description || null,
        starts_on: form.starts_on,
        ends_on: form.ends_on || form.starts_on,
        scope: isSuperAdmin ? form.scope : "branches",
        branch_ids: isSuperAdmin && form.scope === "organization" ? [] : form.branch_ids,
      };
      if (editId) {
        await apiPatch(`/calendar/events/${editId}`, payload);
        setMessage("رویداد به‌روزرسانی شد.");
      } else {
        await apiPost("/calendar/events", payload);
        setMessage("رویداد ثبت شد.");
      }
      setShowForm(false);
      await load();
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "امکان ثبت رویداد وجود ندارد.");
    } finally {
      setBusy(false);
    }
  };

  const runConfirm = async () => {
    if (!confirm) return;
    setBusy(true);
    try {
      if (confirm.kind === "cancel") {
        await apiPost(`/calendar/events/${confirm.event.id}/cancel`, {});
        setMessage("رویداد لغو شد.");
      } else {
        await apiDelete(`/calendar/events/${confirm.event.id}`);
        setMessage("رویداد حذف شد.");
      }
      setConfirm(null);
      setDetail(null);
      await load();
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "عملیات انجام نشد.");
    } finally {
      setBusy(false);
    }
  };

  const openHistory = async (row: CalendarEventRow) => {
    try {
      const rows = await apiGet<typeof history>(`/calendar/events/${row.id}/activities`);
      setHistory(rows ?? []);
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "تاریخچه در دسترس نیست.");
    }
  };

  const typeOptions = isSuperAdmin
    ? (Object.keys(TYPE_META) as EventType[])
    : (["school_holiday"] as EventType[]);

  return (
    <AppShell title="تقویم و تعطیلات" subtitle="مناسبت‌ها و تعطیلی‌های شمسی سازمان و شعب">
      <PageHeader
        title="تقویم و تعطیلات"
        subtitle={range.title}
        actions={
          <div className="flex flex-wrap gap-2">
            {canImport ? (
              <Link href="/calendar/import">
                <Button variant="secondary">ورود گروهی از اکسل</Button>
              </Link>
            ) : null}
            {canManage ? <Button onClick={() => openCreate()}>رویداد جدید</Button> : null}
          </div>
        }
      />

      {error ? <Alert tone="error">{error}</Alert> : null}
      {message ? <Alert tone="success">{message}</Alert> : null}

      <div className="mb-4 grid grid-cols-2 gap-2.5 sm:grid-cols-4 sm:gap-3">
        <StatCard title="تعطیلات این ماه" value={summary?.holidays_this_month} />
        <StatCard title="مناسبت‌های این ماه" value={summary?.occasions_this_month} />
        <StatCard title="تعطیلات اضطراری" value={summary?.emergency_holidays} />
        <StatCard title="روزهای آموزشی" value={summary?.instructional_days} />
      </div>

      <div className="mb-3 flex flex-wrap items-center justify-between gap-2">
        <div className="flex gap-2">
          <Button variant="secondary" onClick={goPrev}>ماه قبل</Button>
          <Button variant="secondary" onClick={goToday}>امروز</Button>
          <Button variant="secondary" onClick={goNext}>ماه بعد</Button>
        </div>
        <div className="flex flex-wrap gap-3 text-xs text-[var(--muted)]">
          {(Object.keys(TYPE_META) as EventType[]).map((key) => (
            <span key={key}>{TYPE_META[key].dot} {TYPE_META[key].label}</span>
          ))}
        </div>
      </div>

      <div className="calendar-fc overflow-hidden rounded-2xl border border-[var(--border)] bg-white p-2 shadow-card sm:p-4">
        {loading ? (
          <p className="p-8 text-center text-sm text-[var(--muted)]">در حال بارگذاری تقویم…</p>
        ) : (
          <FullCalendar
            key={`${range.from}-${range.to}`}
            plugins={[dayGridPlugin, interactionPlugin]}
            initialView="dayGridMonth"
            locale="fa"
            direction="rtl"
            headerToolbar={false}
            height="auto"
            firstDay={6}
            fixedWeekCount={false}
            showNonCurrentDates={false}
            visibleRange={{ start: range.from, end: addGregorianDays(range.to, 1) }}
            events={fcEvents}
            dateClick={(info) => {
              if (canManage) openCreate(info.dateStr || gregorianIsoFromDate(info.date));
            }}
            eventClick={(info) => {
              const found = events.find((e) => String(e.id) === info.event.id);
              if (found) setDetail(found);
            }}
            dayCellContent={(arg) => {
              const iso = arg.dateStr || gregorianIsoFromDate(arg.date);
              const count = countsByDay[iso] ?? 0;
              return (
                <div className="flex w-full items-start justify-between gap-1">
                  <span>{jalaliDayNumber(iso)}</span>
                  {count > 0 ? (
                    <span className="rounded-full bg-slate-100 px-1.5 text-[10px] font-bold text-slate-600">{count}</span>
                  ) : null}
                </div>
              );
            }}
          />
        )}
        {!loading && events.filter((e) => e.status === "active").length === 0 ? (
          <p className="px-4 pb-4 text-center text-sm text-[var(--muted)]">
            در این ماه رویدادی ثبت نشده است.
          </p>
        ) : null}
      </div>

      {showForm ? (
        <Modal title={editId ? "ویرایش رویداد" : "ایجاد رویداد"} onClose={() => setShowForm(false)}>
          <div className="grid gap-3">
            <Field label="نوع رویداد">
              <Select
                value={form.type}
                onChange={(e) => setForm({ ...form, type: e.target.value as EventType })}
                disabled={!isSuperAdmin}
              >
                {typeOptions.map((key) => (
                  <option key={key} value={key}>{TYPE_META[key].label}</option>
                ))}
              </Select>
            </Field>
            <Field label="عنوان">
              <Input value={form.title} onChange={(e) => setForm({ ...form, title: e.target.value })} placeholder="مثلاً تعطیلی به علت آلودگی هوا" />
            </Field>
            <div className="grid gap-3 sm:grid-cols-2">
              <Field label="از تاریخ">
                <PersianDatePicker value={form.starts_on} onChange={(v) => setForm({ ...form, starts_on: v, ends_on: form.ends_on || v })} />
              </Field>
              <Field label="تا تاریخ">
                <PersianDatePicker value={form.ends_on} onChange={(v) => setForm({ ...form, ends_on: v })} />
              </Field>
            </div>
            <Field label="توضیحات">
              <Textarea value={form.description} onChange={(e) => setForm({ ...form, description: e.target.value })} rows={3} />
            </Field>
            {isSuperAdmin ? (
              <Field label="محدوده">
                <Select
                  value={form.scope}
                  onChange={(e) => setForm({ ...form, scope: e.target.value as "organization" | "branches" })}
                >
                  <option value="organization">کل سامانه</option>
                  <option value="branches">شعب منتخب</option>
                </Select>
              </Field>
            ) : (
              <p className="text-sm text-[var(--muted)]">محدوده: مدرسه من</p>
            )}
            {isSuperAdmin && form.scope === "branches" ? (
              <div className="max-h-40 space-y-1 overflow-auto rounded-xl border border-[var(--border)] p-2">
                {branches.map((b) => (
                  <label key={b.id} className="flex items-center gap-2 text-sm">
                    <input
                      type="checkbox"
                      checked={form.branch_ids.includes(b.id)}
                      onChange={(e) => {
                        setForm({
                          ...form,
                          branch_ids: e.target.checked
                            ? [...form.branch_ids, b.id]
                            : form.branch_ids.filter((id) => id !== b.id),
                        });
                      }}
                    />
                    {b.name}
                  </label>
                ))}
              </div>
            ) : null}
            <div className="mt-2 flex justify-end gap-2">
              <Button variant="secondary" onClick={() => setShowForm(false)}>انصراف</Button>
              <Button onClick={submit} loading={busy} disabled={!form.title || !form.starts_on}>ثبت</Button>
            </div>
          </div>
        </Modal>
      ) : null}

      {detail ? (
        <Modal title="جزئیات رویداد" onClose={() => { setDetail(null); setHistory(null); }}>
          <dl className="space-y-2 text-sm">
            <div><span className="text-[var(--muted)]">نوع: </span>{TYPE_META[detail.type].dot} {TYPE_META[detail.type].label}</div>
            <div><span className="text-[var(--muted)]">عنوان: </span>{detail.title}</div>
            <div><span className="text-[var(--muted)]">بازه: </span>{detail.starts_on} تا {detail.ends_on}</div>
            <div><span className="text-[var(--muted)]">محدوده: </span>{detail.scope === "organization" ? "کل سامانه" : detail.branches.map((b) => b.name).join("، ") || "—"}</div>
            {detail.description ? <div><span className="text-[var(--muted)]">توضیحات: </span>{detail.description}</div> : null}
            {detail.status === "cancelled" ? <div className="text-amber-700">این رویداد لغو شده است.</div> : null}
          </dl>
          <div className="mt-4 flex flex-wrap gap-2">
            {canMutate(detail) ? (
              <>
                <Button variant="secondary" onClick={() => openEdit(detail)}>ویرایش</Button>
                <Button variant="secondary" onClick={() => setConfirm({ kind: "cancel", event: detail })}>لغو</Button>
                <Button variant="danger" onClick={() => setConfirm({ kind: "delete", event: detail })}>حذف</Button>
              </>
            ) : null}
            {isSuperAdmin ? <Button variant="ghost" onClick={() => openHistory(detail)}>تاریخچه تغییرات</Button> : null}
          </div>
          {history ? (
            <ul className="mt-4 max-h-40 space-y-2 overflow-auto text-xs text-[var(--muted)]">
              {history.length === 0 ? <li>تاریخچه‌ای ثبت نشده است.</li> : history.map((h) => (
                <li key={h.id}>{h.description} — {h.causer_name ?? "سامانه"}</li>
              ))}
            </ul>
          ) : null}
        </Modal>
      ) : null}

      <ConfirmDialog
        open={!!confirm}
        title={confirm?.kind === "delete" ? "حذف رویداد" : "لغو رویداد"}
        message={confirm?.kind === "delete"
          ? "آیا از حذف این رویداد مطمئن هستید؟ این کار قابل بازگشت نیست."
          : "با لغو، این رویداد دیگر به‌عنوان تعطیل یا مناسبت فعال محسوب نمی‌شود."}
        confirmLabel={confirm?.kind === "delete" ? "حذف" : "لغو رویداد"}
        loading={busy}
        onConfirm={runConfirm}
        onCancel={() => setConfirm(null)}
      />
    </AppShell>
  );
}

function StatCard({ title, value }: { title: string; value?: number }) {
  return (
    <div className="rounded-xl border border-[var(--border)] bg-white p-3 shadow-card sm:rounded-2xl sm:p-4">
      <p className="text-xs text-[var(--muted)] sm:text-sm">{title}</p>
      <p className="mt-0.5 text-xl font-bold sm:mt-1 sm:text-2xl">{value ?? "—"}</p>
    </div>
  );
}

function Modal({ title, onClose, children }: { title: string; onClose: () => void; children: React.ReactNode }) {
  return (
    <div className="fixed inset-0 z-50 flex items-end justify-center bg-black/40 p-0 sm:items-center sm:p-4">
      <div className="max-h-[92vh] w-full max-w-lg overflow-auto rounded-t-2xl border border-[var(--border)] bg-white p-5 shadow-xl sm:rounded-2xl">
        <div className="mb-4 flex items-center justify-between">
          <h3 className="text-base font-bold">{title}</h3>
          <button type="button" className="text-sm text-[var(--muted)]" onClick={onClose}>بستن</button>
        </div>
        {children}
      </div>
    </div>
  );
}
