"use client";

import { useEffect, useState } from "react";
import { PeriodDateTimeField } from "@/components/academic/PeriodDateTimeField";
import { Alert } from "@/components/ui/Alert";
import { Button } from "@/components/ui/Button";
import { Field, Input } from "@/components/ui/Field";
import { ApiError, apiDelete, apiGet, apiPatch, apiPost, apiPut } from "@/lib/api";
import {
  GradeEntryAccessGrant,
  ReportCardItem,
  ReportCardPeriodRow,
} from "@/lib/report-cards";

interface TeacherOption {
  id: number;
  name: string;
  national_code?: string | null;
}

function sameInstant(a?: string | null, b?: string | null): boolean {
  if (!a && !b) return true;
  if (!a || !b) return false;
  const left = new Date(a).getTime();
  const right = new Date(b).getTime();
  if (Number.isNaN(left) || Number.isNaN(right)) return a === b;
  return left === right;
}

function formatFaDateTime(iso?: string | null): string {
  if (!iso) return "—";
  const parsed = new Date(iso);
  if (Number.isNaN(parsed.getTime())) return "—";
  return parsed.toLocaleString("fa-IR", { dateStyle: "short", timeStyle: "short" });
}

function grantStatusLabel(grant: GradeEntryAccessGrant): string {
  const now = Date.now();
  const start = grant.starts_at ? new Date(grant.starts_at).getTime() : 0;
  const end = new Date(grant.ends_at).getTime();
  if (!Number.isNaN(start) && start > now) return "هنوز شروع نشده";
  if (!Number.isNaN(end) && end >= now) return "فعال";
  return "منقضی";
}

function visibilityError(period: ReportCardPeriodRow): string | null {
  if (!period.visible_to_students_at) return null;
  const visible = new Date(period.visible_to_students_at).getTime();
  if (Number.isNaN(visible)) return null;
  const end = period.grade_entry_ends_at ? new Date(period.grade_entry_ends_at).getTime() : NaN;
  const start = period.grade_entry_starts_at ? new Date(period.grade_entry_starts_at).getTime() : NaN;
  const afterEntry = Number.isNaN(end) ? start : end;
  if (Number.isNaN(afterEntry)) return "ابتدا زمان ثبت نمره را مشخص کنید.";
  if (visible <= afterEntry) return "زمان نمایش به دانش‌آموز باید بعد از پایان ثبت نمره باشد.";
  return null;
}

function periodDirty(period: ReportCardPeriodRow, saved?: ReportCardPeriodRow): boolean {
  if (!saved) return true;
  return (
    !sameInstant(period.grade_entry_starts_at, saved.grade_entry_starts_at) ||
    !sameInstant(period.grade_entry_ends_at, saved.grade_entry_ends_at) ||
    !sameInstant(period.visible_to_students_at, saved.visible_to_students_at)
  );
}

export function ReportCardGradeWindowsPanel({ cardId }: { cardId: number }) {
  const [card, setCard] = useState<ReportCardItem | null>(null);
  const [periods, setPeriods] = useState<ReportCardPeriodRow[]>([]);
  const [grants, setGrants] = useState<GradeEntryAccessGrant[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [savingId, setSavingId] = useState<number | null>(null);
  const [togglingId, setTogglingId] = useState<number | null>(null);
  const [granting, setGranting] = useState(false);
  const [grantPeriod, setGrantPeriod] = useState<ReportCardPeriodRow | null>(null);

  const [grantStartsAt, setGrantStartsAt] = useState<string | null>(new Date().toISOString());
  const [grantEndsAt, setGrantEndsAt] = useState<string | null>(null);
  const [grantNote, setGrantNote] = useState("");
  const [teacherQuery, setTeacherQuery] = useState("");
  const [teacherOptions, setTeacherOptions] = useState<TeacherOption[]>([]);
  const [selectedTeacher, setSelectedTeacher] = useState<TeacherOption | null>(null);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      setLoading(true);
      setError(null);
      try {
        const [detail, grantList] = await Promise.all([
          apiGet<ReportCardItem>(`/report-cards/${cardId}`),
          apiGet<GradeEntryAccessGrant[]>(`/report-cards/${cardId}/grade-entry-access`),
        ]);
        if (cancelled) return;
        setCard(detail);
        setPeriods(detail.periods ?? []);
        setGrants(grantList);
      } catch (err) {
        if (!cancelled) {
          setError(err instanceof ApiError ? err.message : "خطا در بارگذاری بازه ثبت نمرات");
        }
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [cardId]);

  useEffect(() => {
    const q = teacherQuery.trim();
    if (q.length < 2 || selectedTeacher) {
      setTeacherOptions([]);
      return;
    }
    const handle = window.setTimeout(async () => {
      try {
        setTeacherOptions(await apiGet<TeacherOption[]>(`/users/search?q=${encodeURIComponent(q)}`));
      } catch {
        setTeacherOptions([]);
      }
    }, 250);
    return () => window.clearTimeout(handle);
  }, [teacherQuery, selectedTeacher]);

  const patchPeriod = (periodId: number, patch: Partial<ReportCardPeriodRow>) => {
    setPeriods((prev) => prev.map((period) => (period.id === periodId ? { ...period, ...patch } : period)));
    setSuccess(null);
  };

  const mergeSavedPeriod = (updated: ReportCardItem, periodId: number) => {
    const next = updated.periods?.find((item) => item.id === periodId);
    setCard(updated);
    if (!next) {
      setPeriods(updated.periods ?? []);
      return;
    }
    setPeriods((prev) => prev.map((period) => (period.id === periodId ? { ...period, ...next } : period)));
  };

  const savePeriod = async (period: ReportCardPeriodRow) => {
    const visError = visibilityError(period);
    if (visError) {
      setError(visError);
      return;
    }
    setSavingId(period.id);
    setError(null);
    setSuccess(null);
    try {
      const updated = await apiPut<ReportCardItem>(`/report-cards/${cardId}/windows`, {
        periods: [{
          id: period.id,
          grade_entry_starts_at: period.grade_entry_starts_at ?? null,
          grade_entry_ends_at: period.grade_entry_ends_at ?? null,
          visible_to_students_at: period.visible_to_students_at ?? null,
          is_active: period.is_active,
        }],
      });
      mergeSavedPeriod(updated, period.id);
      setSuccess(`بازه «${period.name}» ذخیره شد.`);
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در ذخیره بازه مرحله");
    } finally {
      setSavingId(null);
    }
  };

  const togglePeriodActive = async (period: ReportCardPeriodRow) => {
    const nextActive = !period.is_active;
    setTogglingId(period.id);
    setError(null);
    setSuccess(null);
    try {
      await apiPatch(`/report-card-periods/${period.id}`, { is_active: nextActive });
      const apply = (item: ReportCardPeriodRow) =>
        item.id === period.id ? { ...item, is_active: nextActive } : item;
      setPeriods((prev) => prev.map(apply));
      setCard((prev) => (prev ? { ...prev, periods: (prev.periods ?? []).map(apply) } : prev));
      setSuccess(nextActive ? `مرحله «${period.name}» فعال شد.` : `مرحله «${period.name}» غیرفعال شد.`);
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در تغییر وضعیت مرحله");
    } finally {
      setTogglingId(null);
    }
  };

  const openGrantModal = (period: ReportCardPeriodRow) => {
    setGrantPeriod(period);
    setSelectedTeacher(null);
    setTeacherQuery("");
    setTeacherOptions([]);
    setGrantStartsAt(new Date().toISOString());
    setGrantEndsAt(null);
    setGrantNote("");
    setError(null);
  };

  const closeGrantModal = () => {
    setGrantPeriod(null);
    setSelectedTeacher(null);
    setTeacherQuery("");
    setTeacherOptions([]);
  };

  const createGrant = async () => {
    if (!grantPeriod) return;
    if (!selectedTeacher) {
      setError("معلم را جستجو و انتخاب کنید.");
      return;
    }
    if (!grantEndsAt) {
      setError("پایان دسترسی موقت الزامی است.");
      return;
    }
    setGranting(true);
    setError(null);
    setSuccess(null);
    try {
      const created = await apiPost<GradeEntryAccessGrant>(`/report-cards/${cardId}/grade-entry-access`, {
        report_card_period_id: grantPeriod.id,
        teacher_user_id: selectedTeacher.id,
        starts_at: grantStartsAt,
        ends_at: grantEndsAt,
        note: grantNote.trim() || null,
      });
      setGrants((prev) => [created, ...prev]);
      setSelectedTeacher(null);
      setTeacherQuery("");
      setTeacherOptions([]);
      setGrantStartsAt(new Date().toISOString());
      setGrantEndsAt(null);
      setGrantNote("");
      setSuccess("دسترسی موقت برای معلم ثبت شد.");
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در ثبت دسترسی موقت");
    } finally {
      setGranting(false);
    }
  };

  const revokeGrant = async (grant: GradeEntryAccessGrant) => {
    if (!window.confirm(`دسترسی موقت «${grant.teacher_name ?? "معلم"}» حذف شود؟`)) return;
    setError(null);
    setSuccess(null);
    try {
      await apiDelete(`/report-cards/${cardId}/grade-entry-access/${grant.id}`);
      setGrants((prev) => prev.filter((item) => item.id !== grant.id));
      setSuccess("دسترسی موقت حذف شد.");
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در حذف دسترسی موقت");
    }
  };

  if (loading) {
    return <p className="text-sm text-[var(--muted)]">در حال بارگذاری...</p>;
  }

  const modalGrants = grantPeriod
    ? grants.filter((grant) => grant.report_card_period_id === grantPeriod.id)
    : [];

  return (
    <div className="space-y-4">
      {error ? <Alert tone="error">{error}</Alert> : null}
      {success ? <Alert tone="success">{success}</Alert> : null}

      <p className="text-xs text-[var(--muted)]">
        برای هر مرحله زمان‌ها را تنظیم کنید و همان مرحله را ذخیره کنید.
        اگر مرحله را غیرفعال کنید، برای معلمان مثل این است که بازه ثبت هنوز نرسیده است.
        {card?.kind === "official"
          ? " در کارنامه رسمی تا وقتی شروع و پایان ثبت نمره ذخیره شود، معلمان نمی‌توانند نمره وارد کنند."
          : ""}
      </p>

      {periods.length === 0 ? (
        <Alert tone="info">برای این کارنامه مرحله‌ای تعریف نشده است.</Alert>
      ) : (
        <div className="space-y-3">
          {periods.map((period) => {
            const saved = card?.periods?.find((item) => item.id === period.id);
            const dirty = periodDirty(period, saved);
            const visError = visibilityError(period);
            const grantCount = grants.filter((grant) => grant.report_card_period_id === period.id).length;
            return (
              <div
                key={period.id}
                className={`rounded-2xl border bg-white p-4 ${
                  period.is_active ? "border-[var(--border)]" : "border-amber-200"
                }`}
              >
                <div className="mb-3 flex flex-wrap items-start justify-between gap-2">
                  <div>
                    <div className="flex flex-wrap items-center gap-2">
                      <h2 className="font-semibold">{period.name}</h2>
                      <span className={`rounded-full px-2 py-0.5 text-[11px] ${
                        period.is_active ? "bg-emerald-50 text-emerald-700" : "bg-amber-50 text-amber-800"
                      }`}>
                        {period.is_active ? "فعال" : "غیرفعال"}
                      </span>
                    </div>
                    {!period.is_active ? (
                      <p className="mt-1 text-xs text-amber-800">
                        این مرحله غیرفعال است؛ معلمان نمی‌توانند نمره ثبت کنند.
                      </p>
                    ) : null}
                  </div>
                  <div className="flex flex-wrap gap-2">
                    <Button
                      variant="secondary"
                      className="!px-3 !py-1.5 text-xs"
                      onClick={() => openGrantModal(period)}
                    >
                      دسترسی موقت{grantCount ? ` (${grantCount.toLocaleString("fa-IR")})` : ""}
                    </Button>
                    <Button
                      variant={period.is_active ? "danger" : "secondary"}
                      className="!px-3 !py-1.5 text-xs"
                      onClick={() => togglePeriodActive(period)}
                      disabled={togglingId === period.id}
                    >
                      {togglingId === period.id
                        ? "..."
                        : period.is_active
                          ? "غیرفعال کردن"
                          : "فعال کردن"}
                    </Button>
                    <Button
                      className="!px-3 !py-1.5 text-xs"
                      onClick={() => savePeriod(period)}
                      disabled={!dirty || Boolean(visError) || savingId === period.id}
                    >
                      {savingId === period.id ? "در حال ذخیره..." : "ذخیره"}
                    </Button>
                  </div>
                </div>
                <div className="grid gap-2 md:grid-cols-3">
                  <Field label="شروع ثبت نمره">
                    <PeriodDateTimeField
                      value={period.grade_entry_starts_at}
                      onChange={(iso) => patchPeriod(period.id, { grade_entry_starts_at: iso })}
                    />
                  </Field>
                  <Field label="پایان ثبت نمره">
                    <PeriodDateTimeField
                      value={period.grade_entry_ends_at}
                      onChange={(iso) => patchPeriod(period.id, { grade_entry_ends_at: iso })}
                    />
                  </Field>
                  <Field
                    label="نمایش به دانش‌آموز"
                    hint="باید بعد از پایان ثبت نمره باشد."
                    error={visError ?? undefined}
                  >
                    <PeriodDateTimeField
                      value={period.visible_to_students_at}
                      onChange={(iso) => patchPeriod(period.id, { visible_to_students_at: iso })}
                    />
                  </Field>
                </div>
                {dirty && !visError ? (
                  <p className="mt-2 text-xs text-amber-700">تغییرات این مرحله ذخیره نشده است.</p>
                ) : null}
              </div>
            );
          })}
        </div>
      )}

      {grantPeriod ? (
        <div
          className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4"
          onClick={closeGrantModal}
        >
          <div
            role="dialog"
            aria-modal="true"
            className="max-h-[90vh] w-full max-w-2xl overflow-y-auto rounded-2xl border border-[var(--border)] bg-white p-5 shadow-xl"
            onClick={(e) => e.stopPropagation()}
          >
            <div className="mb-4 flex items-start justify-between gap-3">
              <div>
                <h3 className="font-bold text-primary">دسترسی موقت معلمان</h3>
                <p className="mt-1 text-xs text-[var(--muted)]">{grantPeriod.name}</p>
              </div>
              <Button variant="secondary" onClick={closeGrantModal}>بستن</Button>
            </div>

            <p className="mb-4 text-xs text-[var(--muted)]">
              اگر بازه این مرحله بسته یا هنوز نرسیده است، می‌توانید برای معلم مشخص تا تاریخ معین دسترسی بدهید.
            </p>

            <div className="grid gap-2 md:grid-cols-2">
              <Field label="معلم">
                {selectedTeacher ? (
                  <div className="flex items-center justify-between rounded-xl border border-[var(--border)] px-3 py-2 text-sm">
                    <span>
                      {selectedTeacher.name}
                      {selectedTeacher.national_code ? ` · ${selectedTeacher.national_code}` : ""}
                    </span>
                    <button
                      type="button"
                      className="text-xs text-[var(--muted)] hover:text-primary"
                      onClick={() => {
                        setSelectedTeacher(null);
                        setTeacherQuery("");
                      }}
                    >
                      تغییر
                    </button>
                  </div>
                ) : (
                  <div className="relative">
                    <Input
                      value={teacherQuery}
                      onChange={(e) => setTeacherQuery(e.target.value)}
                      placeholder="نام یا کد ملی معلم"
                    />
                    {teacherOptions.length > 0 ? (
                      <div className="absolute z-20 mt-1 max-h-48 w-full overflow-y-auto rounded-xl border border-[var(--border)] bg-white shadow-lg">
                        {teacherOptions.map((option) => (
                          <button
                            key={option.id}
                            type="button"
                            className="block w-full px-3 py-2 text-right text-sm hover:bg-slate-50"
                            onClick={() => {
                              setSelectedTeacher(option);
                              setTeacherQuery(option.name);
                              setTeacherOptions([]);
                            }}
                          >
                            {option.name}
                            {option.national_code ? ` · ${option.national_code}` : ""}
                          </button>
                        ))}
                      </div>
                    ) : null}
                  </div>
                )}
              </Field>
              <Field label="یادداشت (اختیاری)">
                <Input
                  value={grantNote}
                  onChange={(e) => setGrantNote(e.target.value)}
                />
              </Field>
              <Field label="شروع دسترسی">
                <PeriodDateTimeField value={grantStartsAt} onChange={setGrantStartsAt} />
              </Field>
              <Field label="پایان دسترسی">
                <PeriodDateTimeField value={grantEndsAt} onChange={setGrantEndsAt} />
              </Field>
            </div>
            <div className="mt-3">
              <Button onClick={createGrant} disabled={granting}>
                {granting ? "در حال ثبت..." : "اعطای دسترسی موقت"}
              </Button>
            </div>

            <div className="mt-5">
              {modalGrants.length === 0 ? (
                <p className="text-sm text-[var(--muted)]">برای این مرحله دسترسی موقتی ثبت نشده است.</p>
              ) : (
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b border-[var(--border)] text-right text-[var(--muted)]">
                      <th className="py-2 font-medium">معلم</th>
                      <th className="py-2 font-medium">از</th>
                      <th className="py-2 font-medium">تا</th>
                      <th className="py-2 font-medium">وضعیت</th>
                      <th className="py-2 font-medium" />
                    </tr>
                  </thead>
                  <tbody>
                    {modalGrants.map((grant) => (
                      <tr key={grant.id} className="border-b border-[var(--border)]">
                        <td className="py-2">
                          <div>{grant.teacher_name ?? "—"}</div>
                          {grant.note ? (
                            <div className="text-xs text-[var(--muted)]">{grant.note}</div>
                          ) : null}
                        </td>
                        <td className="py-2">{formatFaDateTime(grant.starts_at)}</td>
                        <td className="py-2">{formatFaDateTime(grant.ends_at)}</td>
                        <td className="py-2">{grantStatusLabel(grant)}</td>
                        <td className="py-2 text-left">
                          <Button
                            variant="danger"
                            className="!px-3 !py-1 text-xs"
                            onClick={() => revokeGrant(grant)}
                          >
                            حذف
                          </Button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              )}
            </div>
          </div>
        </div>
      ) : null}
    </div>
  );
}
