"use client";

import Link from "next/link";
import { useCallback, useEffect, useMemo, useState } from "react";
import { AppShell } from "@/components/app/AppShell";
import { DataTable, DataTableEmpty } from "@/components/layout/DataTable";
import {
  GRADE_RULE_STEPS,
  GradeRulesWizard,
} from "@/components/pre-registration/GradeRulesWizard";
import { Alert } from "@/components/ui/Alert";
import { Button } from "@/components/ui/Button";
import { Field, Select } from "@/components/ui/Field";
import { PageContentSkeleton } from "@/components/ui/Skeleton";
import {
  AcademicYear,
  AdminUser,
  ApiError,
  EducationStage,
  GradeLevel,
  RuleSetItem,
  apiGet,
  apiPatch,
  apiPost,
  getStoredUser,
} from "@/lib/api";
import { validateGradeRulesStep, firstGradeRulesError } from "@/lib/grade-rules-validation";
import { FormErrorSummary } from "@/components/forms/FormErrorSummary";
import { HoldingCatalogPanel } from "@/components/pre-registration/HoldingCatalogPanel";
import type { DocumentCatalogItem, FormFieldCatalogItem } from "@/components/pre-registration/CatalogPickers";
import {
  GradeRulesDraft,
  draftToRules,
  emptyRulesTemplate,
  rulesToDraft,
} from "@/lib/rule-set";
import { getActiveRole } from "@/lib/session-context";

type OverviewRow = {
  grade: GradeLevel;
  stageName: string;
  orgRule?: RuleSetItem;
};

function hasStoredRules(rules: unknown): boolean {
  return (
    !!rules &&
    typeof rules === "object" &&
    !Array.isArray(rules) &&
    Object.keys(rules as Record<string, unknown>).length > 0
  );
}

function Badge({ ok, label }: { ok: boolean; label: string }) {
  return (
    <span
      className={`rounded-full px-2 py-0.5 text-[11px] font-semibold ${
        ok ? "bg-green-100 text-green-800" : "bg-slate-100 text-slate-600"
      }`}
    >
      {label}
    </span>
  );
}

export default function OrgDefaultsPage() {
  const user = useMemo(() => getStoredUser<AdminUser>(), []);
  const role = getActiveRole();
  const isSuperAdmin = role === "super_admin" || role === "developer" || Boolean(user?.roles.includes("super_admin") || user?.roles.includes("developer"));

  const [mode, setMode] = useState<"overview" | "edit">("overview");
  const [step, setStep] = useState(1);
  const [stages, setStages] = useState<EducationStage[]>([]);
  const [grades, setGrades] = useState<GradeLevel[]>([]);
  const [years, setYears] = useState<AcademicYear[]>([]);
  const [ruleSets, setRuleSets] = useState<RuleSetItem[]>([]);
  const [gradeId, setGradeId] = useState(0);
  const [selectedRuleSet, setSelectedRuleSet] = useState<RuleSetItem | null>(null);
  const [draft, setDraft] = useState<GradeRulesDraft | null>(null);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({});
  const [documentCatalog, setDocumentCatalog] = useState<DocumentCatalogItem[]>([]);
  const [formFieldCatalog, setFormFieldCatalog] = useState<FormFieldCatalogItem[]>([]);
  const [message, setMessage] = useState<string | null>(null);

  const currentYear = years.find((y) => y.is_current) ?? years[0];
  const selectedGrade = grades.find((g) => g.id === gradeId);

  const orgRulesByGrade = useMemo(() => {
    const map = new Map<number, RuleSetItem>();
    if (!currentYear) return map;

    for (const rule of ruleSets) {
      if (
        rule.branch_id == null &&
        rule.target_type === "grade_level" &&
        rule.academic_year_id === currentYear.id
      ) {
        map.set(rule.target_id, rule);
      }
    }

    return map;
  }, [ruleSets, currentYear]);

  const stageNameById = useMemo(() => {
    const map = new Map<number, string>();
    for (const stage of stages) {
      map.set(stage.id, stage.name);
    }
    return map;
  }, [stages]);

  const overviewRows = useMemo<OverviewRow[]>(() => {
    return grades.map((grade) => ({
      grade,
      stageName:
        grade.education_stage_id != null
          ? (stageNameById.get(grade.education_stage_id) ?? "—")
          : "—",
      orgRule: orgRulesByGrade.get(grade.id),
    }));
  }, [grades, stageNameById, orgRulesByGrade]);

  const load = useCallback(async () => {
    if (!user || !isSuperAdmin) {
      setLoading(false);
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const [yearList, stageList, gradeList, rules, docs, formFields] = await Promise.all([
        apiGet<AcademicYear[]>("/academic-years?active_only=1"),
        apiGet<EducationStage[]>("/education-stages"),
        apiGet<GradeLevel[]>("/grade-levels"),
        apiGet<RuleSetItem[]>(`/pre-registration-rule-sets?organization_id=${user.organization_id}`),
        apiGet<DocumentCatalogItem[]>(
          `/pre-registration-document-catalog?organization_id=${user.organization_id}`,
        ).catch(() => []),
        apiGet<FormFieldCatalogItem[]>(
          `/pre-registration-form-field-catalog?organization_id=${user.organization_id}`,
        ).catch(() => []),
      ]);

      setYears(yearList);
      setStages(stageList);
      setGrades(gradeList.sort((a, b) => (a.order ?? a.id) - (b.order ?? b.id)));
      setRuleSets(rules);
      setDocumentCatalog(docs);
      setFormFieldCatalog(formFields);
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در بارگذاری");
    } finally {
      setLoading(false);
    }
  }, [user, isSuperAdmin]);

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

  const openEdit = (targetGradeId: number) => {
    const rule = orgRulesByGrade.get(targetGradeId) ?? null;
    const base = (rule?.rules as Record<string, unknown> | undefined) ?? emptyRulesTemplate();

    setGradeId(targetGradeId);
    setSelectedRuleSet(rule);
    setDraft(rulesToDraft(base));
    setStep(1);
    setMode("edit");
    setError(null);
    setMessage(null);
  };

  const saveRulesForGrade = async (
    targetGradeId: number,
    existing: RuleSetItem | null,
    rules: Record<string, unknown>,
    isActive: boolean,
  ): Promise<RuleSetItem> => {
    if (!user || !currentYear) {
      throw new Error("سال تحصیلی یا کاربر مشخص نیست.");
    }

    if (existing) {
      return apiPatch<RuleSetItem>(`/pre-registration-rule-sets/${existing.id}`, {
        is_active: isActive,
        rules,
      });
    }

    return apiPost<RuleSetItem>("/pre-registration-rule-sets", {
      organization_id: user.organization_id,
      branch_id: null,
      target_type: "grade_level",
      target_id: targetGradeId,
      academic_year_id: currentYear.id,
      is_active: isActive,
      rules,
    });
  };

  const resolveTargets = (scope: "grade" | "all_grades") => {
    if (scope === "all_grades") {
      return grades.map((g) => ({ grade: g, rule: orgRulesByGrade.get(g.id) ?? null }));
    }
    return [{ grade: selectedGrade!, rule: selectedRuleSet }];
  };

  const validateForApply = (): string | null => {
    for (const s of GRADE_RULE_STEPS) {
      const err = firstGradeRulesError(validateGradeRulesStep(s.id, draft));
      if (err) return `مرحله «${s.label}»: ${err}`;
    }
    return null;
  };

  const applyRules = async (scope: "grade" | "all_grades") => {
    if (!user || !draft || !currentYear || !gradeId) return;

    const validationError = validateForApply();
    if (validationError) {
      setError(validationError);
      setFieldErrors(validateGradeRulesStep(step, draft));
      return;
    }
    setFieldErrors({});

    setSaving(true);
    setError(null);
    setMessage(null);

    try {
      const targets = resolveTargets(scope);
      if (targets.length === 0 || !targets[0]?.grade) {
        setError("پایه‌ای برای اعمال یافت نشد.");
        return;
      }

      let updated = 0;

      for (const { grade, rule } of targets) {
        if (!grade) continue;
        const base = (rule?.rules as Record<string, unknown> | undefined) ?? emptyRulesTemplate();
        const rules = draftToRules(draft, base);

        const saved = await saveRulesForGrade(grade.id, rule, rules, draft.enabled);
        updated++;

        setRuleSets((prev) => {
          const without = prev.filter((item) => item.id !== saved.id);
          return [...without, saved];
        });

        if (grade.id === gradeId) {
          setSelectedRuleSet(saved);
        }
      }

      await load();

      const scopeLabel =
        scope === "all_grades"
          ? `همه پایه‌ها (${updated})`
          : (selectedGrade?.name ?? "این پایه");

      setMessage(`تنظیمات برای ${scopeLabel} اعمال شد.`);
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در ذخیره");
    } finally {
      setSaving(false);
    }
  };

  const summarize = (row: OverviewRow) => {
    const rules = (row.orgRule?.rules ?? {}) as Record<string, unknown>;
    const enabled = rules.enabled !== false && row.orgRule?.is_active !== false;

    return {
      enabled,
      hasRule: Boolean(row.orgRule && hasStoredRules(row.orgRule.rules)),
    };
  };

  if (!isSuperAdmin) {
    return (
      <AppShell title="اعمال گروهی تنظیمات" subtitle="پیش‌ثبت‌نام">
        <Alert tone="error">این صفحه فقط برای مدیر کل در دسترس است.</Alert>
        <Link href="/pre-registration/settings" className="mt-4 inline-block">
          <Button variant="secondary">بازگشت به تنظیمات</Button>
        </Link>
      </AppShell>
    );
  }

  if (loading) {
    return (
      <AppShell title="اعمال گروهی تنظیمات" subtitle="پیش‌ثبت‌نام — بارگذاری…">
        <PageContentSkeleton />
      </AppShell>
    );
  }

  return (
    <AppShell
      title="اعمال گروهی تنظیمات"
      subtitle={`پیش‌ثبت‌نام · سال ${currentYear?.title ?? "—"}`}
    >
      <div className="space-y-4">
        {error ? <Alert tone="error">{error}</Alert> : null}
        {message ? <Alert tone="success">{message}</Alert> : null}

        <Alert tone="info">
          هر پایه را جداگانه ویرایش کنید. پس از تکمیل wizard، با «اعمال» ذخیره کنید. اعمال تنظیمات،
          قوانین اختصاصی مدارس برای پایه‌های هدف را حذف می‌کند.{" "}
          <Link href="/pre-registration/settings" className="font-semibold underline">
            تنظیمات پیش‌ثبت‌نام
          </Link>
        </Alert>

        {mode === "overview" ? (
          <>
            {user ? (
              <HoldingCatalogPanel
                organizationId={user.organization_id}
                documents={documentCatalog}
                fields={formFieldCatalog}
                onDocumentsChange={setDocumentCatalog}
                onFieldsChange={setFormFieldCatalog}
              />
            ) : null}
          <div className="rounded-2xl border border-[var(--border)] bg-white shadow-card">
            <DataTable
              columns={[
                { key: "grade", label: "پایه" },
                { key: "stage", label: "مقطع" },
                { key: "status", label: "وضعیت" },
                { key: "actions", label: "" },
              ]}
            >
              {overviewRows.length === 0 ? (
                <DataTableEmpty colSpan={4}>پایه‌ای تعریف نشده است.</DataTableEmpty>
              ) : (
                overviewRows.map((row) => {
                  const info = summarize(row);
                  return (
                    <tr key={row.grade.id} className="border-t border-[var(--border)]">
                      <td className="px-4 py-3 font-semibold">{row.grade.name}</td>
                      <td className="px-4 py-3 text-sm text-[var(--muted)]">{row.stageName}</td>
                      <td className="px-4 py-3">
                        {info.hasRule ? (
                          <Badge ok={info.enabled} label={info.enabled ? "فعال" : "غیرفعال"} />
                        ) : (
                          <Badge ok={false} label="تعریف نشده" />
                        )}
                      </td>
                      <td className="px-4 py-3">
                        <Button size="sm" onClick={() => openEdit(row.grade.id)}>
                          {info.hasRule ? "ویرایش" : "تعریف"}
                        </Button>
                      </td>
                    </tr>
                  );
                })
              )}
            </DataTable>
          </div>
          </>
        ) : (
          draft && (
            <div className="space-y-4">
              <div className="rounded-2xl border border-[var(--border)] bg-white p-4 shadow-card">
                <Field label="پایه">
                  <Select
                    value={gradeId}
                    onChange={(e) => openEdit(Number(e.target.value))}
                    disabled={saving}
                  >
                    {grades.map((g) => (
                      <option key={g.id} value={g.id}>
                        {g.name}
                      </option>
                    ))}
                  </Select>
                </Field>
                <p className="mt-2 text-xs text-[var(--muted)]">
                  بین مراحل از تب بالا جابه‌جا شوید. پس از تکمیل wizard، «اعمال» را بزنید.
                </p>
              </div>

              <div className="flex gap-1 overflow-x-auto pb-1">
                {GRADE_RULE_STEPS.map((s) => (
                  <button
                    key={s.id}
                    type="button"
                    disabled={saving}
                    onClick={() => setStep(s.id)}
                    className={`shrink-0 rounded-full px-3 py-1.5 text-xs font-semibold disabled:opacity-60 ${
                      step === s.id ? "bg-primary text-white" : "bg-white ring-1 ring-[var(--border)]"
                    }`}
                  >
                    {s.id}. {s.label}
                  </button>
                ))}
              </div>

              <div className="rounded-2xl border border-[var(--border)] bg-white p-4 shadow-card">
                <GradeRulesWizard
                  step={step}
                  draft={draft}
                  onDraftChange={(updater) =>
                    setDraft((prev) => (prev ? updater(prev) : prev))
                  }
                  selectedGradeName={selectedGrade?.name}
                  academicYearTitle={currentYear?.title ?? null}
                  documentCatalog={documentCatalog}
                  formFieldCatalog={formFieldCatalog}
                  fieldErrors={fieldErrors}
                />

                <div className="mt-6 space-y-3 border-t border-[var(--border)] pt-4">
                  <FormErrorSummary errors={fieldErrors} general={error} />
                  <div className="flex flex-wrap gap-2">
                    <Button loading={saving} onClick={() => void applyRules("grade")}>
                      اعمال · همین پایه
                    </Button>
                    <Button
                      variant="secondary"
                      loading={saving}
                      onClick={() => void applyRules("all_grades")}
                    >
                      اعمال · همه پایه‌ها
                    </Button>
                    <Button
                      type="button"
                      variant="secondary"
                      disabled={saving}
                      onClick={() => setMode("overview")}
                    >
                      بازگشت
                    </Button>
                  </div>
                </div>
              </div>
            </div>
          )
        )}
      </div>
    </AppShell>
  );
}
