"use client";

import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { useCallback, useEffect, useMemo, useRef, 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 { ListExportActions } from "@/components/export/ListExportActions";
import { Alert } from "@/components/ui/Alert";
import { Button } from "@/components/ui/Button";
import { Field, Select } from "@/components/ui/Field";
import {
  AcademicYear,
  AdminUser,
  ApiError,
  BranchItem,
  EducationStage,
  GradeLevel,
  RuleSetItem,
  SeatQuotaItem,
  apiGet,
  apiPatch,
  apiPost,
  apiPut,
  getStoredUser,
} from "@/lib/api";
import {
  GradeRulesDraft,
  draftToRules,
  emptyRulesTemplate,
  rulesToDraft,
} from "@/lib/rule-set";
import { validateGradeRulesStep } from "@/lib/grade-rules-validation";
import { FormErrorSummary } from "@/components/forms/FormErrorSummary";
import type { DocumentCatalogItem, FormFieldCatalogItem } from "@/components/pre-registration/CatalogPickers";
import { resolveBranchId } from "@/lib/resolve-branch";
import { getActiveRole } from "@/lib/session-context";

function asObject(value: unknown): Record<string, unknown> {
  return value && typeof value === "object" && !Array.isArray(value)
    ? (value as Record<string, unknown>)
    : {};
}

interface SchoolDetail {
  id: number;
  name: string;
  code: string;
  school_type?: "boys" | "girls" | null;
  grade_level_ids?: number[];
}

type OverviewRow = {
  grade: GradeLevel;
  stageName: string;
  branchRule?: RuleSetItem;
  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>
  );
}

function InlineToggle({
  gradeId,
  enabled,
  disabled,
  onChange,
}: {
  gradeId: number;
  enabled: boolean;
  disabled: boolean;
  onChange: (enabled: boolean) => void;
}) {
  return (
    <div className="flex flex-wrap items-center gap-3">
      <label className="inline-flex cursor-pointer items-center gap-1.5 text-xs">
        <input
          type="radio"
          name={`grade-registration-${gradeId}`}
          checked={enabled}
          disabled={disabled}
          onChange={() => onChange(true)}
          className="shrink-0"
        />
        <span>فعال</span>
      </label>
      <label className="inline-flex cursor-pointer items-center gap-1.5 text-xs">
        <input
          type="radio"
          name={`grade-registration-${gradeId}`}
          checked={!enabled}
          disabled={disabled}
          onChange={() => onChange(false)}
          className="shrink-0"
        />
        <span>غیرفعال</span>
      </label>
    </div>
  );
}

export default function GradeRulesPage() {
  const searchParams = useSearchParams();
  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 queryBranchId = Number(searchParams.get("branchId") || 0) || null;
  const fallbackBranch =
    user?.branches.find((b) => b.is_primary)?.id ?? user?.branches[0]?.id ?? null;

  const [selectedBranchId, setSelectedBranchId] = useState<number | null>(() =>
    resolveBranchId(queryBranchId, fallbackBranch),
  );
  const [branches, setBranches] = useState<BranchItem[]>([]);
  const [step, setStep] = useState(1);
  const [mode, setMode] = useState<"overview" | "edit">("overview");
  const [school, setSchool] = useState<SchoolDetail | null>(null);
  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 [savingGradeId, setSavingGradeId] = useState<number | null>(null);
  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 editPanelRef = useRef<HTMLDivElement>(null);

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

  useEffect(() => {
    if (mode !== "edit") return;
    editPanelRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
    window.scrollTo({ top: 0, behavior: "smooth" });
  }, [step, mode]);

  useEffect(() => {
    setSelectedBranchId(resolveBranchId(queryBranchId, fallbackBranch));
  }, [queryBranchId, fallbackBranch]);

  const loadMeta = useCallback(async () => {
    if (!user) return;
    setLoading(true);
    setError(null);
    try {
      const requests: Promise<unknown>[] = [
        apiGet<AcademicYear[]>("/academic-years?active_only=1"),
        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(() => []),
      ];

      if (isSuperAdmin) {
        requests.push(apiGet<BranchItem[]>("/branches"));
      }

      const results = await Promise.all(requests);
      const yearList = results[0] as AcademicYear[];
      const rules = results[1] as RuleSetItem[];
      setYears(yearList);
      setRuleSets(rules);
      setDocumentCatalog(results[2] as DocumentCatalogItem[]);
      setFormFieldCatalog(results[3] as FormFieldCatalogItem[]);

      if (isSuperAdmin) {
        const branchList = results[4] as BranchItem[];
        setBranches(branchList);
        if (!branchId && branchList[0]?.id) {
          setSelectedBranchId(branchList[0].id);
          setLoading(false);
          return;
        }
      }

      if (!branchId) {
        setSchool(null);
        setStages([]);
        setGrades([]);
        setLoading(false);
        return;
      }

      const [stageList, gradeList, detail] = await Promise.all([
        apiGet<EducationStage[]>(`/education-stages?branch_id=${branchId}`),
        apiGet<GradeLevel[]>(`/grade-levels?branch_id=${branchId}`),
        apiGet<SchoolDetail>(`/branches/${branchId}/directory`).catch(() =>
          apiGet<SchoolDetail>(`/branches/${branchId}`).catch(() => null),
        ),
      ]);

      setStages(stageList);
      setSchool(detail);
      setGrades(gradeList);
      if (gradeList.length && !gradeList.some((g) => g.id === gradeId)) {
        setGradeId(gradeList[0].id);
      }
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در بارگذاری");
    } finally {
      setLoading(false);
    }
  }, [branchId, gradeId, isSuperAdmin, user]);

  useEffect(() => {
    void loadMeta();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [branchId, user?.organization_id]);

  const hydrateDraftFromRules = useCallback(() => {
    if (!gradeId || !currentYear) return;
    const branchRule = branchId
      ? ruleSets.find(
          (r) =>
            r.target_type === "grade_level" &&
            r.target_id === gradeId &&
            r.academic_year_id === currentYear.id &&
            r.branch_id === branchId,
        )
      : undefined;
    const orgRule = ruleSets.find(
      (r) =>
        r.target_type === "grade_level" &&
        r.target_id === gradeId &&
        r.academic_year_id === currentYear.id &&
        r.branch_id == null,
    );

    setSelectedRuleSet(branchRule ?? null);

    const branchHasRules = Boolean(branchRule && hasStoredRules(branchRule.rules));
    const rulesSource = branchHasRules
      ? branchRule?.rules
      : orgRule?.rules ?? emptyRulesTemplate();
    const next = rulesToDraft((rulesSource as Record<string, unknown>) ?? emptyRulesTemplate());
    const activeRule = branchHasRules ? branchRule : orgRule;
    next.is_active = activeRule?.is_active ?? true;
    if (activeRule) {
      next.enabled =
        (activeRule.rules as { enabled?: boolean })?.enabled !== false &&
        activeRule.is_active !== false;
    }
    setDraft(next);
  }, [gradeId, branchId, ruleSets, currentYear]);

  // فقط وقتی وارد ویرایش می‌شویم یا پایه/مدرسه عوض می‌شود — نه با هر رفرش ruleSets
  useEffect(() => {
    if (mode !== "edit") return;
    hydrateDraftFromRules();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [mode, gradeId, branchId, currentYear?.id]);

  useEffect(() => {
    if (mode === "edit") return;
    if (!gradeId || !currentYear) return;
    hydrateDraftFromRules();
  }, [mode, gradeId, branchId, currentYear, hydrateDraftFromRules]);

  useEffect(() => {
    if (!user || !branchId || !gradeId || !currentYear || mode !== "edit") return;
    let cancelled = false;

    const loadExtras = async () => {
      try {
        const [quotas, location, schedules] = await Promise.all([
          apiGet<SeatQuotaItem[]>(`/pre-registration-seat-quotas?branch_id=${branchId}`),
          apiGet<{ value: unknown }>(
            `/settings/resolve?key=registration.exam_location&organization_id=${user.organization_id}&branch_id=${branchId}`,
          ),
          apiGet<{ value: unknown }>(
            `/settings/resolve?key=registration.exam_schedules&organization_id=${user.organization_id}&branch_id=${branchId}`,
          ),
        ]);
        if (cancelled) return;

        const quota = quotas.find(
          (q) =>
            q.target_type === "grade_level" &&
            q.target_id === gradeId &&
            q.academic_year_id === currentYear.id,
        );
        const loc = asObject(location.value);
        const map = asObject(loc.map);
        const list = Array.isArray(schedules.value) ? schedules.value : [];
        const mine = list.find(
          (s) => asObject(s).grade_level_id != null && Number(asObject(s).grade_level_id) === gradeId,
        );
        const row = asObject(mine);
        const branchRule = ruleSets.find(
          (r) =>
            r.target_type === "grade_level" &&
            r.target_id === gradeId &&
            r.academic_year_id === currentYear.id &&
            r.branch_id === branchId,
        );
        const hasFollowupKey =
          !!branchRule?.rules &&
          typeof branchRule.rules === "object" &&
          Object.prototype.hasOwnProperty.call(branchRule.rules, "followup");

        setDraft((prev) => {
          if (!prev) return prev;
          const legacyExam =
            !hasFollowupKey &&
            Boolean(
              String(loc.title ?? "") ||
                String(row.starts_at ?? "") ||
                String(row.title ?? ""),
            );

          return {
            ...prev,
            seat_quota: quota ? String(quota.max_seats) : prev.seat_quota,
            waitlist_max: quota?.waitlist_max != null ? String(quota.waitlist_max) : prev.waitlist_max,
            ...(legacyExam
              ? {
                  followupMode: "exam" as const,
                  examTitle: String(loc.title ?? prev.examTitle),
                  examAddress: String(loc.address ?? prev.examAddress),
                  examNotes: String(loc.notes ?? prev.examNotes),
                  examLat: map.lat != null ? String(map.lat) : prev.examLat,
                  examLng: map.lng != null ? String(map.lng) : prev.examLng,
                  examScheduleTitle: String(row.title ?? prev.examScheduleTitle),
                  examStartsAt: String(row.starts_at ?? "").slice(0, 10) || prev.examStartsAt,
                  examEndsAt: String(row.ends_at ?? "").slice(0, 10) || prev.examEndsAt,
                }
              : {}),
          };
        });
      } catch {
        /* optional extras — draft rules still usable */
      }
    };

    void loadExtras();
    return () => {
      cancelled = true;
    };
  }, [user, branchId, gradeId, currentYear, mode, ruleSets]);

  const overviewRows: OverviewRow[] = useMemo(() => {
    if (!currentYear) return [];
    return grades.map((grade) => {
      const stageName =
        stages.find((s) => s.id === grade.education_stage_id)?.name ?? "—";
      return {
        grade,
        stageName,
        branchRule: branchId
          ? ruleSets.find(
              (r) =>
                r.target_type === "grade_level" &&
                r.target_id === grade.id &&
                r.academic_year_id === currentYear.id &&
                r.branch_id === branchId,
            )
          : undefined,
        orgRule: ruleSets.find(
          (r) =>
            r.target_type === "grade_level" &&
            r.target_id === grade.id &&
            r.academic_year_id === currentYear.id &&
            r.branch_id == null,
        ),
      };
    });
  }, [grades, stages, ruleSets, currentYear, branchId]);

  const openEdit = (id: number) => {
    setGradeId(id);
    setStep(1);
    setMode("edit");
    setMessage(null);
    setError(null);
  };

  const genderLabel = (genders: string[]) => {
    if (genders.includes("male") && genders.includes("female")) return "پسر/دختر";
    if (genders.includes("male")) return "پسر";
    if (genders.includes("female")) return "دختر";
    return "—";
  };

  const canAllowBoys = school?.school_type !== "girls";
  const canAllowGirls = school?.school_type !== "boys";

  // نوع مدرسه انتخاب‌های غیرمجاز را از پیش‌نویس حذف می‌کند
  useEffect(() => {
    if (mode !== "edit") return;
    setDraft((prev) => {
      if (!prev) return prev;
      const allowBoys = canAllowBoys ? prev.allowBoys : false;
      const allowGirls = canAllowGirls ? prev.allowGirls : false;
      const nextBoys = canAllowBoys && !canAllowGirls ? true : allowBoys;
      const nextGirls = canAllowGirls && !canAllowBoys ? true : allowGirls;
      if (prev.allowBoys === nextBoys && prev.allowGirls === nextGirls) return prev;
      return { ...prev, allowBoys: nextBoys, allowGirls: nextGirls };
    });
  }, [mode, canAllowBoys, canAllowGirls, gradeId]);

  const validateStep = (stepId: number): Record<string, string> =>
    validateGradeRulesStep(stepId, draft, { canAllowBoys, canAllowGirls });

  const resolveSavedRuleSet = async (
    saved: RuleSetItem | null | undefined,
    rules: Record<string, unknown>,
  ): Promise<RuleSetItem | null> => {
    if (saved?.id) return saved;

    // اگر پاسخ API خالی بود، از فهرست قوانین همان پایه را پیدا کن
    const list = await apiGet<RuleSetItem[]>(
      `/pre-registration-rule-sets?organization_id=${user!.organization_id}`,
    );
    const found =
      list.find(
        (r) =>
          r.target_type === "grade_level" &&
          r.target_id === gradeId &&
          r.academic_year_id === currentYear!.id &&
          r.branch_id === branchId,
      ) ?? null;

    if (found) return { ...found, rules, is_active: draft!.enabled };

    if (selectedRuleSet?.id) {
      return {
        ...selectedRuleSet,
        rules,
        is_active: draft!.enabled,
      };
    }

    return null;
  };

  /** ذخیره اطلاعات تا همین مرحله — بدون خروج از حالت ویرایش */
  const persistStep = async (stepId: number): Promise<boolean> => {
    if (!user || !draft || !currentYear || !gradeId) return false;
    if (branchId == null) {
      setError("برای ویرایش قوانین، ابتدا مدرسه فعال را انتخاب کنید.");
      return false;
    }

    const validationErrors = validateStep(stepId);
    if (Object.keys(validationErrors).length) {
      setFieldErrors(validationErrors);
      setError(null);
      return false;
    }
    setFieldErrors({});

    setSaving(true);
    setError(null);
    try {
      const clampedDraft: GradeRulesDraft = {
        ...draft,
        allowBoys: canAllowBoys ? draft.allowBoys : false,
        allowGirls: canAllowGirls ? draft.allowGirls : false,
      };
      if (canAllowBoys && !canAllowGirls) clampedDraft.allowBoys = true;
      if (canAllowGirls && !canAllowBoys) clampedDraft.allowGirls = true;

      const orgRule = ruleSets.find(
        (r) =>
          r.target_type === "grade_level" &&
          r.target_id === gradeId &&
          r.academic_year_id === currentYear.id &&
          r.branch_id == null,
      );
      const existingBranchRule = ruleSets.find(
        (r) =>
          r.target_type === "grade_level" &&
          r.target_id === gradeId &&
          r.academic_year_id === currentYear.id &&
          r.branch_id === branchId,
      );
      const base = (selectedRuleSet?.rules ??
        existingBranchRule?.rules ??
        orgRule?.rules ??
        emptyRulesTemplate()) as Record<string, unknown>;
      const rules = draftToRules(clampedDraft, base);
      let response: RuleSetItem | null | undefined;
      const ruleId = selectedRuleSet?.id ?? existingBranchRule?.id;
      if (ruleId && (selectedRuleSet?.branch_id ?? existingBranchRule?.branch_id) === branchId) {
        response = await apiPatch<RuleSetItem>(
          `/pre-registration-rule-sets/${ruleId}`,
          {
            is_active: draft.enabled,
            rules,
          },
        );
      } else {
        response = await apiPost<RuleSetItem>("/pre-registration-rule-sets", {
          organization_id: user.organization_id,
          branch_id: branchId,
          target_type: "grade_level",
          target_id: gradeId,
          academic_year_id: currentYear.id,
          is_active: draft.enabled,
          rules,
        });
      }

      const saved = await resolveSavedRuleSet(response, rules);
      if (!saved?.id) {
        setError("ذخیره انجام شد اما پاسخ سرور ناقص بود. لطفاً صفحه را تازه کنید.");
        return false;
      }

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

      if (stepId >= 7 && draft.seat_quota) {
        await apiPost("/pre-registration-seat-quotas", {
          branch_id: branchId,
          target_type: "grade_level",
          target_id: gradeId,
          academic_year_id: currentYear.id,
          max_seats: Number(draft.seat_quota) || 0,
          waitlist_max: draft.waitlist_max !== "" ? Number(draft.waitlist_max) : null,
        });
      }

      if (stepId >= 8 && draft.followupMode === "exam") {
        const lat = draft.examLat !== "" ? Number(draft.examLat) : null;
        const lng = draft.examLng !== "" ? Number(draft.examLng) : null;
        await apiPut(`/branches/${branchId}/settings`, {
          key: "registration.exam_location",
          value: {
            title: draft.examTitle,
            address: draft.examAddress,
            notes: draft.examNotes,
            map: lat != null && lng != null && !Number.isNaN(lat) && !Number.isNaN(lng)
              ? { lat, lng }
              : null,
          },
          inherits: false,
        });

        const schedulesRes = await apiGet<{ value: unknown }>(
          `/settings/resolve?key=registration.exam_schedules&organization_id=${user.organization_id}&branch_id=${branchId}`,
        );
        const existing = Array.isArray(schedulesRes.value)
          ? (schedulesRes.value as Array<Record<string, unknown>>)
          : [];
        const others = existing.filter((s) => Number(s.grade_level_id) !== gradeId);
        await apiPut(`/branches/${branchId}/settings`, {
          key: "registration.exam_schedules",
          value: [
            ...others,
            {
              grade_level_id: gradeId,
              title: draft.examScheduleTitle || selectedGrade?.name || "",
              starts_at: draft.examStartsAt || null,
              ends_at: draft.examEndsAt || null,
            },
          ],
          inherits: false,
        });
      }

      if (stepId >= 8 && draft.followupMode === "contact_later") {
        // زمان‌بندی این پایه را از لیست آزمون مدرسه بردار (اگر قبلاً آزمون بوده)
        const schedulesRes = await apiGet<{ value: unknown }>(
          `/settings/resolve?key=registration.exam_schedules&organization_id=${user.organization_id}&branch_id=${branchId}`,
        );
        const existing = Array.isArray(schedulesRes.value)
          ? (schedulesRes.value as Array<Record<string, unknown>>)
          : [];
        const others = existing.filter((s) => Number(s.grade_level_id) !== gradeId);
        if (others.length !== existing.length) {
          await apiPut(`/branches/${branchId}/settings`, {
            key: "registration.exam_schedules",
            value: others,
            inherits: false,
          });
        }
      }

      return true;
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در ذخیره");
      return false;
    } finally {
      setSaving(false);
    }
  };

  const goToStep = async (nextStep: number) => {
    if (nextStep === step) return;
    const ok = await persistStep(step);
    if (!ok) return;
    setMessage(null);
    setStep(nextStep);
  };

  const goNext = async () => {
    const ok = await persistStep(step);
    if (!ok) return;
    setMessage(null);
    setStep(step + 1);
  };

  const saveFinal = async () => {
    const ok = await persistStep(GRADE_RULE_STEPS.length);
    if (!ok) return;
    setMessage("تنظیمات پایه ذخیره شد.");
    await loadMeta();
    setMode("overview");
  };

  const exportFilters = {
    organization_id: user?.organization_id,
    branch_id: branchId,
  };

  const updateGradeEnabled = async (row: OverviewRow, enabled: boolean) => {
    if (!user || !branchId || !currentYear) return;

    const targetGradeId = row.grade.id;
    const branchHasRules = Boolean(row.branchRule && hasStoredRules(row.branchRule.rules));
    const baseRules = (branchHasRules
      ? row.branchRule?.rules
      : row.orgRule?.rules ?? emptyRulesTemplate()) as Record<string, unknown>;
    const currentEnabled =
      baseRules.enabled !== false &&
      (branchHasRules ? row.branchRule?.is_active : row.orgRule?.is_active) !== false;

    if (currentEnabled === enabled) return;

    setSavingGradeId(targetGradeId);
    setError(null);

    const rules = { ...baseRules, enabled };

    try {
      let saved: RuleSetItem;
      if (row.branchRule && row.branchRule.branch_id === branchId) {
        saved = await apiPatch<RuleSetItem>(`/pre-registration-rule-sets/${row.branchRule.id}`, {
          is_active: enabled,
          rules,
        });
      } else {
        saved = await apiPost<RuleSetItem>("/pre-registration-rule-sets", {
          organization_id: user.organization_id,
          branch_id: branchId,
          target_type: "grade_level",
          target_id: targetGradeId,
          academic_year_id: currentYear.id,
          is_active: enabled,
          rules,
        });
      }

      setRuleSets((prev) => {
        const without = prev.filter((item) => item.id !== saved.id);
        return [...without, saved];
      });
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در ذخیره");
    } finally {
      setSavingGradeId(null);
    }
  };

  const summarize = (row: OverviewRow) => {
    const branchHasRules = Boolean(row.branchRule && hasStoredRules(row.branchRule.rules));
    const rules = (branchHasRules
      ? row.branchRule?.rules
      : row.orgRule?.rules ?? {}) as Record<string, unknown>;
    const activeRule = branchHasRules ? row.branchRule : row.orgRule;
    const enabled = rules.enabled !== false && activeRule?.is_active !== false;
    const docs = Array.isArray(rules.required_documents) ? rules.required_documents.length : 0;
    const rawGenders = rules.allowed_genders;
    const genders = Array.isArray(rawGenders)
      ? rawGenders.map(String)
      : typeof rawGenders === "string"
        ? [rawGenders]
        : rawGenders && typeof rawGenders === "object"
          ? Object.values(rawGenders as Record<string, unknown>).map(String)
          : [];
    const fee = (rules.admission_fee as { free?: boolean; amount?: number }) ?? {};
    const followup = (rules.followup as { mode?: string } | undefined)?.mode;
    const followupLabel =
      followup === "exam" ? "آزمون" : followup === "contact_later" ? "تماس بعدی" : "—";
    const schoolType = school?.school_type;
    const portalGenders =
      schoolType === "boys"
        ? genders.filter((g) => g === "male")
        : schoolType === "girls"
          ? genders.filter((g) => g === "female")
          : genders;
    return {
      enabled,
      docs,
      genders,
      portalGenders,
      schoolType: schoolType ?? null,
      fee,
      followupLabel,
      hasRule: Boolean(activeRule || row.orgRule),
    };
  };

  return (
    <AppShell
      title="قوانین و شرایط هر پایه"
      subtitle={
        school
          ? `${school.name} · سال ${currentYear?.title ?? "—"}`
          : "مدیریت قوانین پیش‌ثبت‌نام پایه‌های مدرسه"
      }
    >
      <div className="space-y-4">
        {error && mode !== "edit" ? <Alert tone="error">{error}</Alert> : null}
        {message ? <Alert tone="success">{message}</Alert> : null}

        <Link
          href="/pre-registration"
          className="inline-flex rounded-xl bg-slate-100 px-3 py-2 text-xs font-semibold text-slate-700"
        >
          ← بازگشت به پیش‌ثبت‌نام
        </Link>

        {branchId && school ? (
          <Alert tone="info">
            مدیریت قوانین و شرایط پیش‌ثبت‌نام برای پایه‌های مدرسه{" "}
            <span className="font-bold">{school.name}</span>
            {school.code ? (
              <>
                {" "}
                <span className="text-[var(--muted)]">({school.code})</span>
              </>
            ) : null}
            . از این صفحه فعال/غیرفعال بودن هر پایه، مدارک، ظرفیت و سایر شرایط ثبت‌نام را
            تنظیم کنید.
          </Alert>
        ) : null}

        {isSuperAdmin && branches.length > 0 ? (
          <div className="rounded-2xl border border-[var(--border)] bg-white p-4 shadow-card">
            <Field label="مدرسه">
              <Select
                value={branchId ?? ""}
                onChange={(e) => {
                  setMode("overview");
                  setSelectedBranchId(Number(e.target.value) || null);
                }}
              >
                {branches.map((b) => (
                  <option key={b.id} value={b.id}>
                    {b.name}
                  </option>
                ))}
              </Select>
            </Field>
          </div>
        ) : null}

        {!branchId ? (
          <Alert tone="warning">
            مدرسه فعال مشخص نیست. از صفحه{" "}
            <Link href="/select-context" className="font-semibold underline">
              انتخاب زمینه
            </Link>{" "}
            نقش مدیر مدرسه و شعبه را انتخاب کنید.
          </Alert>
        ) : null}

        {branchId && grades.length === 0 && !loading ? (
          <Alert tone="error">
            برای این مدرسه هیچ پایه‌ای ثبت نشده. ابتدا از{" "}
            <Link href={`/schools/${branchId}/edit`} className="underline">
              ویرایش مدرسه
            </Link>{" "}
            مقاطع و پایه‌ها را انتخاب کنید.
          </Alert>
        ) : null}

        {mode === "overview" && branchId ? (
          <>
            <div className="flex flex-wrap items-center justify-between gap-2">
              <p className="text-sm text-[var(--muted)]">
                وضعیت پیش‌ثبت‌نام هر پایه را مستقیماً تغییر دهید یا با دکمه ویرایش، قوانین کامل را
                تنظیم کنید.
              </p>
              <div className="flex flex-wrap items-center gap-2">
                <ListExportActions
                  exportPath="/pre-registration-rule-sets/export"
                  filters={exportFilters}
                  contextKeys={["organization_id", "branch_id"]}
                  filenameBase="pre-registration-rule-sets-export"
                  onError={setError}
                />
                <Link href={`/pre-registration/settings?branchId=${branchId}`}>
                  <Button variant="secondary">تنظیمات پیش‌ثبت‌نام</Button>
                </Link>
                <Link href={`/pre-registration/payment?branchId=${branchId}`}>
                  <Button variant="secondary">پرداخت و درگاه</Button>
                </Link>
              </div>
            </div>

            <DataTable
              loading={loading}
              columns={[
                { key: "idx", label: "#" },
                { key: "stage", label: "مقطع" },
                { key: "grade", label: "پایه" },
                { key: "status", label: "وضعیت" },
                { key: "toggle", label: "فعال‌سازی" },
                { key: "docs", label: "مدارک" },
                { key: "gender", label: "جنسیت" },
                { key: "fee", label: "هزینه قانون پایه" },
                { key: "followup", label: "مرحله بعد" },
                { key: "ops", label: "عملیات" },
              ]}
            >
              {overviewRows.length === 0 ? (
                <DataTableEmpty colSpan={10} message="پایه‌ای یافت نشد." />
              ) : (
                overviewRows.map((row, i) => {
                  const s = summarize(row);
                  return (
                    <tr key={row.grade.id} className="hover:bg-slate-50">
                      <td className="px-3 py-3">{i + 1}</td>
                      <td className="px-3 py-3 text-xs text-[var(--muted)]">{row.stageName}</td>
                      <td className="px-3 py-3 font-medium">{row.grade.name}</td>
                      <td className="px-3 py-3">
                        <Badge
                          ok={s.hasRule && s.enabled}
                          label={!s.hasRule ? "بدون قانون" : s.enabled ? "فعال" : "غیرفعال"}
                        />
                      </td>
                      <td className="px-3 py-3">
                        <InlineToggle
                          gradeId={row.grade.id}
                          enabled={s.enabled}
                          disabled={savingGradeId === row.grade.id}
                          onChange={(enabled) => void updateGradeEnabled(row, enabled)}
                        />
                      </td>
                      <td className="px-3 py-3 text-xs">{s.docs ? `${s.docs} مدرک` : "—"}</td>
                      <td className="px-3 py-3 text-xs">
                        {!s.hasRule
                          ? "—"
                          : genderLabel(s.portalGenders.length ? s.portalGenders : s.genders)}
                      </td>
                      <td className="px-3 py-3 text-xs">
                        {s.fee.free || !s.fee.amount
                          ? "رایگان / از مدرسه"
                          : `${Number(s.fee.amount).toLocaleString("fa-IR")} ریال`}
                      </td>
                      <td className="px-3 py-3 text-xs">{s.followupLabel}</td>
                      <td className="px-3 py-3">
                        <Button
                          variant="secondary"
                          className="!px-3 !py-1.5 text-xs"
                          onClick={() => openEdit(row.grade.id)}
                        >
                          ویرایش
                        </Button>
                      </td>
                    </tr>
                  );
                })
              )}
            </DataTable>
          </>
        ) : null}

        {mode === "edit" && draft && branchId ? (
          <div ref={editPanelRef} className="space-y-4">
            <div className="flex flex-wrap items-center justify-between gap-2">
              <div>
                <h2 className="font-bold">ویرایش پایه: {selectedGrade?.name}</h2>
                <p className="text-xs text-[var(--muted)]">
                  سال {currentYear?.title} · قوانین مخصوص این مدرسه
                </p>
              </div>
              <Button variant="secondary" onClick={() => setMode("overview")}>
                بازگشت به نمای کلی
              </Button>
            </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={() => void goToStep(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))}
                branchId={branchId}
                schoolType={school?.school_type ?? null}
                selectedGradeName={selectedGrade?.name}
                academicYearTitle={currentYear?.title}
                showBranchPaymentLink
                showBranchExamMap
                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">
                  {step > 1 ? (
                    <Button
                      type="button"
                      variant="secondary"
                      disabled={saving}
                      onClick={() => void goToStep(step - 1)}
                    >
                      مرحله قبل
                    </Button>
                  ) : null}
                  {GRADE_RULE_STEPS.length > step ? (
                    <Button type="button" loading={saving} onClick={() => void goNext()}>
                      مرحله بعد
                    </Button>
                  ) : (
                    <Button loading={saving} onClick={() => void saveFinal()}>
                      ذخیره نهایی
                    </Button>
                  )}
                  <Button type="button" variant="secondary" disabled={saving} onClick={() => setMode("overview")}>
                    بازگشت
                  </Button>
                </div>
              </div>
            </div>
          </div>
        ) : null}
      </div>
    </AppShell>
  );
}
