"use client";

import { useParams } from "@/lib/route-params";
import { useCallback, useEffect, useMemo, useState } from "react";
import { AppShell } from "@/components/app/AppShell";
import { ListExportActions } from "@/components/export/ListExportActions";
import { SchoolSetupNav } from "@/components/school/SchoolSetupNav";
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 { PageContentSkeleton, Skeleton } from "@/components/ui/Skeleton";
import { ApiError, apiGet, apiPost } from "@/lib/api";
import { classBreadcrumbLabels } from "@/lib/breadcrumbs";
import { padNationalCodeDigits, parsePersonIdentifierToken, toAsciiDigits } from "@school/ui";

interface ClassDetail {
  id: number;
  name: string;
  code?: string | null;
  field?: string | null;
  branch_id: number;
  grade_level_id: number;
  academic_year_id: number;
  grade_level?: { id: number; name: string } | null;
  education_stage?: { id: number; name: string } | null;
  study_field?: { id: number; name: string } | null;
  academic_year?: { id: number; title: string } | null;
  branch?: { id: number; name: string } | null;
}

interface Candidate {
  id: number;
  full_name: string;
  national_code: string;
  is_foreign_national?: boolean;
  grade_level_id?: number | null;
  grade_label?: string | null;
}

interface PlaceItem {
  national_code: string;
  is_foreign_national: boolean;
  name?: string;
}

interface PlaceResult {
  national_code: string;
  is_foreign_national?: boolean;
  name?: string | null;
  status: string;
  message: string;
  full_name?: string;
  student_id?: number;
  conflict_branch_name?: string;
  same_class?: boolean;
  class_room_id?: number;
  class_name?: string | null;
}

function parseLines(raw: string): PlaceItem[] {
  return raw
    .split(/\r?\n/)
    .map((line) => line.trim())
    .filter(Boolean)
    .map((line): PlaceItem | null => {
      const parts = line.split("|").map((p) => p.trim());
      if (parts.length >= 2) {
        const parsed = parsePersonIdentifierToken(parts[parts.length - 1]);
        if (!parsed) {
          return null;
        }
        const name = parts.slice(0, -1).join(" ").trim();
        return { ...parsed, name: name || undefined };
      }

      const trimmed = line.trim();
      if (!/\s/.test(trimmed)) {
        return parsePersonIdentifierToken(trimmed);
      }

      const nationalMatch = line.match(/^(.*?)[\s,،]+(\d{8,10})$/);
      if (nationalMatch) {
        return {
          national_code: padNationalCodeDigits(nationalMatch[2]),
          is_foreign_national: false,
          name: nationalMatch[1].trim() || undefined,
        };
      }

      const foreignMatch = line.match(/^(.*?)[\s,،]+(\S{1,30})$/);
      if (foreignMatch) {
        const parsed = parsePersonIdentifierToken(foreignMatch[2]);
        if (parsed) {
          return { ...parsed, name: foreignMatch[1].trim() || undefined };
        }
      }

      return null;
    })
    .filter((item): item is PlaceItem => item != null);
}

const STATUS_LABEL: Record<string, string> = {
  placed: "آماده / ثبت شد",
  conflict_other_school: "تعارض مدرسه دیگر",
  grade_mismatch: "پایه ناسازگار",
  field_mismatch: "رشته ناسازگار",
  not_found: "یافت نشد",
  name_mismatch: "عدم تطابق نام",
  already_in_class: "قبلاً در کلاس",
};

export default function ClassPlacementPage() {
  const { id, classId } = useParams<{ id: string; classId: string }>();
  const branchId = Number(id);
  const roomId = Number(classId);

  const [room, setRoom] = useState<ClassDetail | null>(null);
  const [candidates, setCandidates] = useState<Candidate[]>([]);
  const [text, setText] = useState("");
  const [results, setResults] = useState<PlaceResult[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [resolvingCode, setResolvingCode] = useState<string | null>(null);
  const [releaseTarget, setReleaseTarget] = useState<PlaceResult | null>(null);
  const [releasing, setReleasing] = useState(false);
  const [gradeFilter, setGradeFilter] = useState<"all" | "class" | "none">("all");
  const [candidateQuery, setCandidateQuery] = useState("");

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const [classDetail, pool] = await Promise.all([
        apiGet<ClassDetail>(`/class-rooms/${roomId}`),
        apiGet<Candidate[]>(`/class-rooms/${roomId}/placement-candidates`),
      ]);
      setRoom(classDetail);
      setCandidates(pool);
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در بارگذاری");
    } finally {
      setLoading(false);
    }
  }, [roomId]);

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

  const items = useMemo(() => parseLines(text), [text]);

  const listedCodes = useMemo(
    () => new Set(items.map((item) => item.national_code)),
    [items],
  );

  const filteredCandidates = useMemo(() => {
    const classGradeId = room?.grade_level_id ?? null;
    const q = toAsciiDigits(candidateQuery).trim().toLowerCase();
    const digits = q.replace(/\D/g, "");
    const padded = padNationalCodeDigits(digits);

    return candidates.filter((candidate) => {
      if (gradeFilter === "class") {
        if (!classGradeId || candidate.grade_level_id !== classGradeId) return false;
      } else if (gradeFilter === "none") {
        if (candidate.grade_level_id != null) return false;
      }

      if (!q) return true;
      const name = candidate.full_name.toLowerCase();
      const code = (candidate.national_code || "").toLowerCase();
      const codeDigits = code.replace(/\D/g, "");
      return (
        name.includes(q) ||
        code.includes(q) ||
        (digits.length > 0 && (codeDigits.includes(digits) || codeDigits === padded || codeDigits.endsWith(digits)))
      );
    });
  }, [candidates, candidateQuery, gradeFilter, room?.grade_level_id]);

  const addCandidateToList = (candidate: Candidate) => {
    const parsed = parsePersonIdentifierToken(candidate.national_code);
    const code = parsed?.national_code ?? candidate.national_code.trim();
    if (!code || listedCodes.has(code)) return;
    const line = `${candidate.full_name} | ${code}`;
    setText((prev) => (prev.trim() ? `${prev.trimEnd()}\n${line}` : line));
    setError(null);
  };

  const run = async (dryRun: boolean) => {
    if (!items.length) {
      setError("حداقل یک کد ملی یا شناسه اتباع معتبر وارد کنید.");
      return;
    }
    setBusy(true);
    setError(null);
    setSuccess(null);
    try {
      const data = await apiPost<{
        results: PlaceResult[];
        placed_count: number;
        dry_run: boolean;
      }>(`/class-rooms/${roomId}/place-students`, {
        items,
        dry_run: dryRun,
      });
      setResults(data.results);
      if (!dryRun) {
        setSuccess(`${data.placed_count} دانش‌آموز کلاس‌بندی شد.`);
        setText("");
        await load();
      }
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در کلاس‌بندی");
    } finally {
      setBusy(false);
    }
  };

  const resolveConflict = async (result: PlaceResult) => {
    setResolvingCode(result.national_code);
    setError(null);
    setSuccess(null);
    try {
      const data = await apiPost<{
        results: PlaceResult[];
        placed_count: number;
        dry_run: boolean;
      }>(`/class-rooms/${roomId}/place-students`, {
        items: [{
          national_code: result.national_code,
          is_foreign_national: result.is_foreign_national,
          resolve_conflict: true,
        }],
        dry_run: false,
      });
      const next = data.results[0];
      if (next) {
        setResults((prev) =>
          prev.map((row) => (row.national_code === result.national_code ? next : row)),
        );
      }
      if (next?.status === "placed") {
        setSuccess("مغایرت اصلاح و دانش‌آموز کلاس‌بندی شد.");
        await load();
      } else if (next) {
        setError(next.message);
      }
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در اصلاح مغایرت");
    } finally {
      setResolvingCode(null);
    }
  };

  const confirmReleaseFromClass = async () => {
    if (!releaseTarget?.student_id) return;
    setReleasing(true);
    setError(null);
    setSuccess(null);
    try {
      await apiPost(`/students/${releaseTarget.student_id}/release-placement`, {
        mode: "unassign_class",
      });
      const data = await apiPost<{
        results: PlaceResult[];
        placed_count: number;
        dry_run: boolean;
      }>(`/class-rooms/${roomId}/place-students`, {
        items: [{
          national_code: releaseTarget.national_code,
          is_foreign_national: releaseTarget.is_foreign_national,
          name: releaseTarget.name ?? undefined,
        }],
        dry_run: true,
      });
      const next = data.results[0];
      if (next) {
        setResults((prev) =>
          prev.map((row) => (row.national_code === releaseTarget.national_code ? next : row)),
        );
      }
      setSuccess("دانش‌آموز از کلاس خارج شد و آماده کلاس‌بندی در این کلاس است.");
      setReleaseTarget(null);
      await load();
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در حذف از کلاس");
    } finally {
      setReleasing(false);
    }
  };

  return (
    <AppShell
      title="کلاس‌بندی"
      breadcrumbLabels={classBreadcrumbLabels(room)}
    >
      <div className="mb-4 flex flex-wrap items-center justify-between gap-2">
        <SchoolSetupNav branchId={branchId} classId={roomId} current="placement" />
        <ListExportActions
          exportPath={`/class-rooms/${classId}/placement-candidates/export`}
          filters={{}}
          filenameBase="placement-candidates-export"
          onError={setError}
        />
      </div>

      {error ? <Alert tone="error">{error}</Alert> : null}
      {success ? <div className="mb-3"><Alert tone="success">{success}</Alert></div> : null}

      {loading && !room ? <PageContentSkeleton rows={5} /> : null}

      <div className={`grid gap-4 lg:grid-cols-2 ${loading && !room ? "hidden" : ""}`}>
        <div className="rounded-2xl border border-[var(--border)] bg-white p-4 shadow-card">
          <h3 className="mb-2 text-sm font-bold">ورود لیست دانش‌آموزان</h3>
          <p className="mb-3 text-xs leading-6 text-[var(--muted)]">
            هر خط یک نفر: کد ملی ۱۰ رقمی یا شناسه اتباع، یا{" "}
            <span className="font-mono">نام | شناسه</span>
            {" "}(برای جلوگیری از هم‌نامی، نام را همراه شناسه بنویسید).
            اگر کد ملی بدون صفر اول (۸ یا ۹ رقم) وارد شود، سیستم با صفر اول هم جستجو می‌کند.
          </p>
          <Field label="لیست">
            <Textarea
              rows={12}
              value={text}
              onChange={(e) => setText(e.target.value)}
              placeholder={"0012345678\nعلی رضایی | 0012345679\nسارا محمدی | AB1234567"}
              dir="rtl"
            />
          </Field>
          <p className="mt-2 text-xs text-[var(--muted)]">
            {items.length} مورد معتبر برای ارسال
          </p>
          <div className="mt-4 flex flex-wrap gap-2">
            <Button variant="secondary" loading={busy} disabled={loading} onClick={() => run(true)}>
              پیش‌نمایش تطبیق
            </Button>
            <Button loading={busy} disabled={loading} onClick={() => run(false)}>
              تأیید و کلاس‌بندی
            </Button>
          </div>
        </div>

        <div className="space-y-4">
          <div className="rounded-2xl border border-[var(--border)] bg-white p-4 shadow-card">
            <h3 className="mb-2 text-sm font-bold">
              بدون کلاس در این مدرسه
              {room?.grade_level?.name ? ` (پایه ${room.grade_level.name} یا بدون پایه)` : ""}
            </h3>
            <div className="mb-3 grid gap-2 sm:grid-cols-2">
              <Field label="فیلتر پایه">
                <Select
                  value={gradeFilter}
                  onChange={(e) => setGradeFilter(e.target.value as "all" | "class" | "none")}
                >
                  <option value="all">
                    {room?.grade_level?.name
                      ? `پایه ${room.grade_level.name} یا بدون پایه`
                      : "همه"}
                  </option>
                  {room?.grade_level?.name ? (
                    <option value="class">فقط پایه {room.grade_level.name}</option>
                  ) : null}
                  <option value="none">فقط بدون پایه</option>
                </Select>
              </Field>
              <Field label="جستجوی نام یا کد ملی">
                <Input
                  value={candidateQuery}
                  onChange={(e) => setCandidateQuery(e.target.value)}
                  placeholder="نام یا کد ملی (۹ رقمی هم جستجو می‌شود)"
                />
              </Field>
            </div>
            {loading ? (
              <div className="space-y-2">
                {Array.from({ length: 5 }).map((_, i) => (
                  <Skeleton key={i} className="h-8 w-full" />
                ))}
              </div>
            ) : candidates.length === 0 ? (
              <p className="text-sm text-[var(--muted)]">دانش‌آموز بدون کلاس برای این پایه یا بدون پایه نیست.</p>
            ) : filteredCandidates.length === 0 ? (
              <p className="text-sm text-[var(--muted)]">موردی با این فیلتر یا کد ملی یافت نشد.</p>
            ) : (
              <ul className="max-h-72 space-y-2 overflow-y-auto text-sm">
                {filteredCandidates.map((c) => {
                  const parsed = parsePersonIdentifierToken(c.national_code);
                  const code = parsed?.national_code ?? c.national_code.trim();
                  const alreadyListed = listedCodes.has(code);
                  const idLabel = c.is_foreign_national || parsed?.is_foreign_national
                    ? "شناسه اتباع"
                    : "کد ملی";
                  return (
                    <li
                      key={c.id}
                      className="flex flex-wrap items-center justify-between gap-2 border-b border-[var(--border)] pb-2"
                    >
                      <div className="min-w-0">
                        <div className="font-medium">{c.full_name}</div>
                        <div className="font-mono text-xs text-[var(--muted)]">
                          {idLabel}: {c.national_code || "—"}
                          {c.grade_label ? ` · پایه ${c.grade_label}` : " · بدون پایه"}
                        </div>
                      </div>
                      <Button
                        variant="secondary"
                        disabled={alreadyListed}
                        onClick={() => addCandidateToList(c)}
                      >
                        {alreadyListed ? "در لیست هست" : "افزودن به لیست"}
                      </Button>
                    </li>
                  );
                })}
              </ul>
            )}
          </div>

          <div className="rounded-2xl border border-[var(--border)] bg-white p-4 shadow-card">
            <h3 className="mb-2 text-sm font-bold">نتایج</h3>
            {results.length === 0 ? (
              <p className="text-sm text-[var(--muted)]">هنوز پیش‌نمایش یا ثبتی انجام نشده.</p>
            ) : (
              <ul className="max-h-80 space-y-3 overflow-y-auto text-sm">
                {results.map((r, i) => (
                  <li
                    key={`${r.national_code}-${i}`}
                    className={`rounded-xl border px-3 py-2 ${
                      r.status === "placed"
                        ? "border-green-200 bg-green-50"
                        : r.status === "conflict_other_school"
                          ? "border-amber-200 bg-amber-50"
                          : "border-red-200 bg-red-50"
                    }`}
                  >
                    <div className="flex flex-wrap items-center justify-between gap-2">
                      <span className="font-medium">
                        {r.full_name || r.name || "—"} ·{" "}
                        <span className="font-mono text-xs">{r.national_code}</span>
                      </span>
                      <span className="text-xs font-semibold">
                        {STATUS_LABEL[r.status] ?? r.status}
                      </span>
                    </div>
                    <p className="mt-1 text-xs leading-6 text-[var(--muted)]">{r.message}</p>
                    {r.status === "grade_mismatch" || r.status === "field_mismatch" ? (
                      <div className="mt-2">
                        <Button
                          variant="secondary"
                          loading={resolvingCode === r.national_code}
                          disabled={busy || resolvingCode !== null || releasing}
                          onClick={() => resolveConflict(r)}
                        >
                          اصلاح مغایرت و کلاس‌بندی
                        </Button>
                      </div>
                    ) : null}
                    {r.status === "already_in_class" && r.student_id && r.same_class === false ? (
                      <div className="mt-2">
                        <Button
                          variant="danger"
                          disabled={busy || resolvingCode !== null || releasing}
                          onClick={() => setReleaseTarget(r)}
                        >
                          حذف از کلاس
                        </Button>
                      </div>
                    ) : null}
                  </li>
                ))}
              </ul>
            )}
          </div>
        </div>
      </div>

      <ConfirmDialog
        open={releaseTarget != null}
        title="حذف از کلاس"
        message={
          releaseTarget
            ? `آیا «${releaseTarget.full_name || releaseTarget.name || releaseTarget.national_code}» از کلاس «${releaseTarget.class_name ?? "فعلی"}» خارج شود؟ سپس می‌توانید او را در این کلاس کلاس‌بندی کنید.`
            : ""
        }
        confirmLabel="حذف از کلاس"
        loading={releasing}
        onCancel={() => setReleaseTarget(null)}
        onConfirm={confirmReleaseFromClass}
      />
    </AppShell>
  );
}
