"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { Alert } from "@/components/ui/Alert";
import { Button } from "@/components/ui/Button";
import { PageContentSkeleton } from "@/components/ui/Skeleton";
import { TeacherPanel } from "@/components/teacher/ui/TeacherPanel";
import { ApiError, apiGet, apiPost } from "@/lib/api";

export interface MatrixStudent {
  enrollment_id: number;
  student_profile_id?: number | null;
  first_name?: string | null;
  last_name?: string | null;
  student_code?: string | null;
}

export interface MatrixAssessment {
  id: number;
  title: string;
  assessment_date?: string | null;
  max_score: number | string;
  scope: string;
}

export interface MatrixPayload {
  students: MatrixStudent[];
  assessments: MatrixAssessment[];
  scores: Record<string, { score: number | string; note?: string | null }>;
}

function cellKey(assessmentId: number, enrollmentId: number) {
  return `${assessmentId}_${enrollmentId}`;
}

function studentName(row: MatrixStudent) {
  const parts = [row.first_name, row.last_name].filter(Boolean);
  return parts.length ? parts.join(" ") : row.student_code ?? `#${row.enrollment_id}`;
}

function formatFaDate(value?: string | null) {
  if (!value) return "—";
  try {
    return new Date(value + "T12:00:00").toLocaleDateString("fa-IR", {
      year: "numeric",
      month: "2-digit",
      day: "2-digit",
    });
  } catch {
    return value;
  }
}

function VerticalHeader({
  title,
  date,
  maxScore,
}: {
  title: string;
  date?: string | null;
  maxScore: number | string;
}) {
  return (
    <div className="flex h-[120px] w-full flex-col items-center justify-end gap-1 px-1">
      <span
        className="text-[11px] font-semibold leading-tight text-slate-700"
        style={{ writingMode: "vertical-rl", transform: "rotate(180deg)" }}
        title={title}
      >
        {title}
      </span>
      <span
        className="text-[10px] text-slate-500"
        style={{ writingMode: "vertical-rl", transform: "rotate(180deg)" }}
      >
        {formatFaDate(date)}
      </span>
      <span className="text-[9px] text-slate-400">/{maxScore}</span>
    </div>
  );
}

export function ClassGradesMatrix({
  classRoomId,
  subjectId,
  refreshKey = 0,
  onStudentClick,
}: {
  classRoomId: number;
  subjectId: number;
  refreshKey?: number;
  onStudentClick?: (studentProfileId: number) => void;
}) {
  const [data, setData] = useState<MatrixPayload | null>(null);
  const [localScores, setLocalScores] = useState<Record<string, string>>({});
  const [baseline, setBaseline] = useState<Record<string, string>>({});
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [flash, setFlash] = useState<string | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const payload = await apiGet<MatrixPayload>(
        `/teacher/classes/${classRoomId}/grades-matrix?subject_id=${subjectId}`,
      );
      setData(payload);

      const initial: Record<string, string> = {};
      for (const student of payload.students) {
        for (const assessment of payload.assessments) {
          const key = cellKey(assessment.id, student.enrollment_id);
          const score = payload.scores[key]?.score;
          if (score != null) initial[key] = String(score);
        }
      }
      setLocalScores(initial);
      setBaseline(initial);
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در بارگذاری ماتریس");
    } finally {
      setLoading(false);
    }
  }, [classRoomId, subjectId]);

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

  const dirtyKeys = useMemo(() => {
    const keys = new Set<string>();
    const allKeys = new Set([...Object.keys(localScores), ...Object.keys(baseline)]);
    for (const key of allKeys) {
      if ((localScores[key] ?? "") !== (baseline[key] ?? "")) keys.add(key);
    }
    return keys;
  }, [localScores, baseline]);

  const save = async () => {
    if (!data || dirtyKeys.size === 0) return;
    setSaving(true);
    setError(null);
    setFlash(null);
    try {
      const entries = [...dirtyKeys].map((key) => {
        const [assessmentId, enrollmentId] = key.split("_").map(Number);
        const raw = localScores[key];
        return {
          assessment_id: assessmentId,
          enrollment_id: enrollmentId,
          score: raw === "" || raw == null ? null : Number(raw),
        };
      });

      await apiPost(`/teacher/classes/${classRoomId}/grades-matrix/save`, { entries });
      setBaseline({ ...localScores });
      setFlash(`${entries.length} نمره ذخیره شد.`);
      await load();
    } catch (err) {
      setError(err instanceof ApiError ? err.message : "خطا در ذخیره");
    } finally {
      setSaving(false);
    }
  };

  if (loading) {
    return <PageContentSkeleton rows={6} />;
  }

  if (!data) {
    return error ? <Alert tone="error">{error}</Alert> : null;
  }

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

      <div className="flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between">
        <p className="text-xs text-slate-500">
          {data.students.length} دانش‌آموز · {data.assessments.length} ارزیابی
          {dirtyKeys.size > 0 ? (
            <span className="mr-2 text-amber-700"> · {dirtyKeys.size} سلول ذخیره نشده</span>
          ) : null}
        </p>
        <Button className="h-10 w-full rounded-xl sm:w-auto" onClick={save} loading={saving} disabled={dirtyKeys.size === 0}>
          ذخیره تغییرات
        </Button>
      </div>

      {dirtyKeys.size > 0 ? (
        <p className="text-xs text-amber-700">سلول‌های زرد = تغییر ذخیره نشده</p>
      ) : null}

      {data.assessments.length === 0 ? (
        <Alert tone="info">هنوز ارزیابی ثبت نشده. با «+ ارزیابی جدید» یک ستون اضافه کنید.</Alert>
      ) : (
        <>
          <div className="space-y-3 md:hidden">
            {data.students.map((student) => (
              <div key={student.enrollment_id} className="rounded-2xl border border-slate-200 bg-white p-3 shadow-sm">
                <button
                  type="button"
                  disabled={!student.student_profile_id}
                  onClick={() => {
                    if (student.student_profile_id) onStudentClick?.(student.student_profile_id);
                  }}
                  className="mb-2 text-right text-sm font-bold text-slate-900 hover:text-primary disabled:cursor-default"
                >
                  {studentName(student)}
                </button>
                <div className="-mx-1 flex gap-2 overflow-x-auto px-1 pb-1">
                  {data.assessments.map((assessment) => {
                    const key = cellKey(assessment.id, student.enrollment_id);
                    const max = Number(assessment.max_score);
                    const dirty = dirtyKeys.has(key);
                    return (
                      <label key={key} className="w-[4.75rem] shrink-0">
                        <span className="mb-1 block h-8 overflow-hidden text-[10px] font-medium leading-tight text-slate-500">
                          {assessment.title}
                        </span>
                        <input
                          type="number"
                          min={0}
                          max={max}
                          step="0.25"
                          inputMode="decimal"
                          placeholder="—"
                          className={`no-spinner h-11 w-full rounded-xl border text-center text-sm outline-none focus:ring-2 focus:ring-primary/30 ${
                            dirty ? "border-amber-300 bg-amber-50" : "border-slate-200 bg-white"
                          }`}
                          value={localScores[key] ?? ""}
                          onChange={(e) =>
                            setLocalScores((prev) => ({ ...prev, [key]: e.target.value }))
                          }
                        />
                      </label>
                    );
                  })}
                </div>
              </div>
            ))}
          </div>

          <div className="hidden md:block">
            <TeacherPanel padded={false}>
              <div className="max-h-[min(70vh,640px)] overflow-auto">
                <table className="min-w-full border-collapse text-sm">
                  <thead className="sticky top-0 z-20 bg-slate-50 shadow-sm">
                    <tr>
                      <th className="sticky right-0 z-30 min-w-[140px] border-b border-l border-slate-200 bg-slate-50 px-3 py-2 text-right font-semibold text-slate-600">
                        دانش‌آموز
                      </th>
                      {data.assessments.map((assessment) => (
                        <th
                          key={assessment.id}
                          className="min-w-[72px] border-b border-slate-200 px-1 py-2 text-center align-bottom"
                        >
                          <VerticalHeader
                            title={assessment.title}
                            date={assessment.assessment_date}
                            maxScore={assessment.max_score}
                          />
                        </th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {data.students.map((student) => (
                      <tr key={student.enrollment_id} className="border-t border-slate-100">
                        <td className="sticky right-0 z-10 border-l border-slate-200 bg-white px-3 py-1.5 font-medium text-slate-800">
                          <button
                            type="button"
                            disabled={!student.student_profile_id}
                            onClick={() => {
                              if (student.student_profile_id) onStudentClick?.(student.student_profile_id);
                            }}
                            className="text-right hover:text-primary disabled:cursor-default"
                          >
                            {studentName(student)}
                          </button>
                        </td>
                        {data.assessments.map((assessment) => {
                          const key = cellKey(assessment.id, student.enrollment_id);
                          const max = Number(assessment.max_score);
                          const dirty = dirtyKeys.has(key);
                          return (
                            <td
                              key={key}
                              className={`px-1 py-1 text-center ${dirty ? "bg-amber-50" : ""}`}
                            >
                              <input
                                type="number"
                                min={0}
                                max={max}
                                step="0.25"
                                inputMode="decimal"
                                placeholder="—"
                                className={`no-spinner h-10 w-14 rounded-xl border px-1 text-center text-sm outline-none focus:ring-2 focus:ring-primary/30 ${
                                  dirty ? "border-amber-300 bg-amber-50" : "border-slate-200 bg-white"
                                }`}
                                value={localScores[key] ?? ""}
                                onChange={(e) =>
                                  setLocalScores((prev) => ({ ...prev, [key]: e.target.value }))
                                }
                              />
                            </td>
                          );
                        })}
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </TeacherPanel>
          </div>
        </>
      )}
    </div>
  );
}
