"use client";

import { useMemo, useState } from "react";
import { useLang } from "@/context/LanguageContext";
import {
  Alert,
  Button,
  Card,
  EmptyState,
  PageHeader,
  Select,
  StatCard,
  StatusBadge,
} from "@/components/ui";
import { api, useApi } from "@/lib/client";
import { formatDate } from "@/lib/utils";
import { REPORT_PRESETS } from "@/lib/report-html";
import { buildCampusMarksheetHtml, buildCampusTabulationHtml, buildCampusTranscriptHtml } from "@/lib/campus-reports";
import { CU_GRADE_SCALES, cuGradeRange } from "@/lib/campus-grades";
import { toBnDigits } from "@/lib/constants";
import { IconAward, IconCheck, IconFile, IconTrend, IconUsers } from "@/components/icons";
import { emsConfirm } from "@/components/ConfirmDialog";

interface Program { id: number; name: string; nameBn: string | null; code: string; gradeScale: string }
interface ExamMini {
  id: number;
  name: string;
  examType: string;
  sessionYear: string | null;
  resultPublished: boolean;
  program: { id: number; name: string; nameBn: string | null };
  term: { id: number; name: string; nameBn: string | null } | null;
}
interface ResultRow {
  student: { id: number; studentIdNo: string; name: string; nameBn: string | null; sessionYear: string; boardRollNo: string | null; registrationNo: string | null };
  courses: {
    scheduleId: number; courseCode: string; courseName: string; courseNameBn: string | null;
    credits: number; fullMarks: number; passMarks: number; marks: number | null; absent: boolean;
    entered: boolean; percent: number | null; grade: string | null; point: number | null; failed: boolean;
  }[];
  creditsAttempted: number;
  creditsEarned: number;
  totalMarks: number;
  fullMarksTotal: number;
  gpa: number | null;
  status: string;
}
interface SemesterResult {
  exam: {
    id: number; name: string; examType: string; sessionYear: string | null;
    startDate: string | null; endDate: string | null; resultPublished: boolean;
    program: { id: number; name: string; nameBn: string | null; gradeScale: string; faculty: string | null; department: string | null; totalCredits: number };
    term: { id: number; name: string; nameBn: string | null } | null;
  };
  rows: ResultRow[];
  stats: { students: number; passed: number; failed: number; incomplete: number; highestGpa: number | null; lowestGpa: number | null };
}
interface StudentMini { id: number; studentIdNo: string; name: string; nameBn: string | null; sessionYear: string; program: { id: number; name: string; nameBn: string | null } }
interface TranscriptData {
  student: {
    id: number; studentIdNo: string; name: string; nameBn: string | null; sessionYear: string;
    boardRollNo: string | null; registrationNo: string | null;
    program: { id: number; name: string; nameBn: string | null; gradeScale: string; faculty: string | null; department: string | null; totalCredits: number };
  };
  terms: {
    examId: number; examName: string; termName: string; termNameBn: string | null;
    courses: { code: string; name: string; nameBn: string | null; credits: number; marks: number | null; fullMarks: number; grade: string; point: number }[];
    credits: number;
    gpa: number;
  }[];
  cgpa: number | null;
  totalCredits: number;
  programCredits: number;
}
interface Me { user: { institution: { id: number; name: string; logo?: string | null } | null } | null }

function openPrint(html: string) {
  const w = window.open("", "_blank", "width=1020,height=760");
  if (!w) return;
  w.document.write(html);
  w.document.close();
  w.focus();
  setTimeout(() => w.print(), 350);
}

/** College & University results: semester GPA result sheets (marksheet +
    tabulation) on the program's grade scale, and CGPA transcripts. */
export default function CampusResultsPage() {
  const { t, locale } = useLang();
  const L = t.portal.campusResultsPage;

  const [tab, setTab] = useState<"semester" | "transcript">("semester");
  const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null);

  const programsData = useApi<{ programs: Program[] }>("/api/portal/campus/programs");
  const examsData = useApi<{ exams: ExamMini[] }>("/api/portal/campus/exams");
  const me = useApi<Me>("/api/auth/me");
  const programs = programsData.data?.programs ?? [];
  const exams = examsData.data?.exams ?? [];

  // semester tab
  const [examId, setExamId] = useState("");
  const resultsUrl = examId ? `/api/portal/campus/results?examId=${examId}` : null;
  const resultsData = useApi<SemesterResult>(resultsUrl);
  const result = resultsData.data ?? null;

  // transcript tab
  const [trProgramId, setTrProgramId] = useState("");
  const [trStudentId, setTrStudentId] = useState("");
  const studentsUrl = trProgramId ? `/api/portal/campus/students?programId=${trProgramId}` : null;
  const trStudentsData = useApi<{ students: StudentMini[] }>(studentsUrl);
  const transcriptUrl = trStudentId ? `/api/portal/campus/results?studentId=${trStudentId}` : null;
  const transcriptData = useApi<TranscriptData>(transcriptUrl);

  const nm = (en: string | null | undefined, bn: string | null | undefined) =>
    locale === "bn" && bn ? bn : en ?? "—";

  const preset = REPORT_PRESETS[0];
  const inst = me.data?.user?.institution ?? null;
  const instMini = inst ? { name: inst.name, logo: inst.logo ?? null } : null;

  async function publishResult(val: boolean) {
    if (!result) return;
    const ok = await emsConfirm({ message: val ? L.publishResultConfirm : L.unpublishResultConfirm, danger: false });
    if (!ok) return;
    try {
      await api(`/api/portal/campus/exams/${result.exam.id}`, {
        method: "PATCH",
        body: JSON.stringify({ resultPublished: val }),
      });
      setMessage({ type: "success", text: val ? L.resultPublishedMsg : L.resultUnpublishedMsg });
      examsData.reload();
      resultsData.reload();
    } catch {
      setMessage({ type: "error", text: t.common.tryAgain });
    }
  }

  function printMarksheet(row: ResultRow) {
    if (!result) return;
    const html = buildCampusMarksheetHtml({
      inst: instMini,
      locale,
      student: {
        studentIdNo: row.student.studentIdNo, name: row.student.name, nameBn: row.student.nameBn,
        sessionYear: row.student.sessionYear, boardRollNo: row.student.boardRollNo, registrationNo: row.student.registrationNo,
      },
      examName: result.exam.name,
      programName: nm(result.exam.program.name, result.exam.program.nameBn),
      programScale: result.exam.program.gradeScale,
      termName: result.exam.term ? nm(result.exam.term.name, result.exam.term.nameBn) : null,
      sessionYear: result.exam.sessionYear,
      courses: row.courses,
      creditsAttempted: row.creditsAttempted,
      totalMarks: row.totalMarks,
      fullMarksTotal: row.fullMarksTotal,
      gpa: row.gpa,
      status: row.status,
      labels: {
        marksheetTitle: L.marksheetTitle,
        studentId: L.studentIdLabel,
        name: L.nameLabel,
        program: L.programLabel,
        term: L.termLabel,
        session: L.sessionLabel,
        exam: L.examLabel,
        course: L.courseLabel,
        credits: L.creditsLabel,
        fullMarks: L.fullMarksLabel,
        passMarks: L.passMarksLabel,
        obtained: L.obtainedLabel,
        percent: L.percentLabel,
        grade: L.gradeLabel,
        point: L.pointLabel,
        totals: L.totalsLabel,
        gpa: L.gpaLabel,
        result: L.resultLabel,
        scale: L.scaleLabel,
        preparedBy: L.preparedByLabel,
        examController: L.controllerLabel,
        passed: L.res_PASSED,
        failed: L.res_FAILED,
        incomplete: L.res_INCOMPLETE,
        absentShort: L.absentShort,
        notEntered: L.notEntered,
      },
      primary: preset.primary,
      accent: preset.accent,
      poweredBy: t.landing.poweredBy,
      scanLabel: t.portal.resultsPage.scanToVerify,
    });
    openPrint(html);
  }

  function printTabulation() {
    if (!result) return;
    const courseCodes = result.rows[0]?.courses.map((c) => c.courseCode) ?? [];
    const hasCourse = new Map(result.rows[0]?.courses.map((c) => [c.scheduleId, c.courseCode]) ?? []);
    const html = buildCampusTabulationHtml({
      inst: instMini,
      locale,
      examName: result.exam.name,
      programName: nm(result.exam.program.name, result.exam.program.nameBn),
      termName: result.exam.term ? nm(result.exam.term.name, result.exam.term.nameBn) : null,
      sessionYear: result.exam.sessionYear,
      courseCodes,
      rows: result.rows.map((r) => ({
        studentIdNo: r.student.studentIdNo,
        name: r.student.name,
        nameBn: r.student.nameBn,
        cells: r.courses.map((c) => (c.entered ? `${c.grade ?? "—"} (${c.marks ?? 0})` : null)),
        gpa: r.gpa,
        status: r.status,
      })),
      labels: {
        tabulationTitle: L.tabulationTitle,
        student: L.thStudent,
        gpa: L.thGpa,
        result: L.thResult,
        passed: L.res_PASSED,
        failed: L.res_FAILED,
        incomplete: L.res_INCOMPLETE,
      },
      primary: preset.primary,
      accent: preset.accent,
      poweredBy: t.landing.poweredBy,
      scanLabel: t.portal.resultsPage.scanToVerify,
    });
    void hasCourse;
    void courseCodes;
    openPrint(html);
  }

  function printTranscript() {
    const data = transcriptData.data;
    if (!data) return;
    const html = buildCampusTranscriptHtml({
      inst: instMini,
      locale,
      student: {
        studentIdNo: data.student.studentIdNo, name: data.student.name, nameBn: data.student.nameBn,
        sessionYear: data.student.sessionYear, boardRollNo: data.student.boardRollNo, registrationNo: data.student.registrationNo,
      },
      programName: nm(data.student.program.name, data.student.program.nameBn),
      faculty: data.student.program.faculty,
      department: data.student.program.department,
      programScale: data.student.program.gradeScale,
      terms: data.terms,
      cgpa: data.cgpa,
      totalCredits: data.totalCredits,
      programCredits: data.programCredits,
      labels: {
        transcriptTitle: L.transcriptTitle,
        name: L.nameLabel,
        studentId: L.studentIdLabel,
        program: L.programLabel,
        faculty: L.facultyLabel,
        department: L.departmentLabel,
        session: L.sessionLabel,
        boardRoll: L.boardRollLabel,
        registration: L.registrationLabel,
        course: L.courseLabel,
        credits: L.creditsLabel,
        obtained: L.obtainedLabel,
        grade: L.gradeLabel,
        point: L.pointLabel,
        gpa: L.gpaLabel,
        creditsCompleted: L.creditsCompletedLabel,
        cgpa: L.cgpaLabel,
        scale: L.scaleLabel,
        examController: L.controllerLabel,
        registrar: L.registrarLabel,
      },
      primary: preset.primary,
      accent: preset.accent,
      poweredBy: t.landing.poweredBy,
      scanLabel: t.portal.resultsPage.scanToVerify,
    });
    openPrint(html);
  }

  const scaleSteps = useMemo(() => {
    const scale = result?.exam.program.gradeScale ?? "GPA4";
    return { key: scale, steps: CU_GRADE_SCALES[scale] ?? CU_GRADE_SCALES.GPA4 };
  }, [result]);

  const tabs: { id: typeof tab; label: string }[] = [
    { id: "semester", label: L.tabSemester },
    { id: "transcript", label: L.tabTranscript },
  ];

  return (
    <div>
      <PageHeader title={L.title} subtitle={L.subtitle} />

      {message && (
        <div className="mb-4">
          <Alert type={message.type} onClose={() => setMessage(null)}>{message.text}</Alert>
        </div>
      )}

      <ul className="nav nav-tabs mb-4">
        {tabs.map((x) => (
          <li className="nav-item" key={x.id}>
            <button className={`nav-link f-w-600 ${tab === x.id ? "active" : ""}`} type="button" onClick={() => setTab(x.id)}>
              {x.label}
            </button>
          </li>
        ))}
      </ul>

      {/* ---------------------- Semester results ---------------------- */}
      {tab === "semester" && (
        <div className="card">
          <div className="card-header">
            <div className="row g-2 align-items-end">
              <div className="col-md-5">
                <Select label={L.pickExam} wrapperClassName="form-group mb-0" value={examId} onChange={(e) => setExamId(e.target.value)}>
                  <option value="">—</option>
                  {exams.map((e) => (
                    <option key={e.id} value={e.id}>
                      {e.name} · {nm(e.program.name, e.program.nameBn)}{e.resultPublished ? " ✔" : ""}
                    </option>
                  ))}
                </Select>
              </div>
              {result && (
                <div className="col-md-7 d-flex justify-content-md-end gap-2 flex-wrap">
                  <Button variant="secondary" onClick={printTabulation} disabled={result.rows.length === 0}>{L.printTabulation}</Button>
                  <Button variant={result.exam.resultPublished ? "secondary" : "primary"} onClick={() => publishResult(!result.exam.resultPublished)}>
                    {result.exam.resultPublished ? L.unpublishResult : L.publishResult}
                  </Button>
                </div>
              )}
            </div>
          </div>
          {!examId ? (
            <div className="card-body"><EmptyState title={L.noExamSelected} /></div>
          ) : resultsData.loading && !resultsData.data ? (
            <div className="card-body text-center py-4"><span className="spinner-border text-primary" role="status" /></div>
          ) : !result || result.rows.length === 0 ? (
            <div className="card-body"><EmptyState icon={<IconFile />} title={t.portal.campusExamsPage.noEligible} /></div>
          ) : (
            <>
              <div className="card-body border-bottom">
                <div className="row g-3">
                  <div className="col-6 col-md-4 col-xl-2"><StatCard label={L.statStudents} value={String(result.stats.students)} icon={<IconUsers className="svg-16" />} /></div>
                  <div className="col-6 col-md-4 col-xl-2"><StatCard label={L.statPassed} value={String(result.stats.passed)} icon={<IconCheck className="svg-16" />} accent="blue" /></div>
                  <div className="col-6 col-md-4 col-xl-2"><StatCard label={L.statFailed} value={String(result.stats.failed)} icon={<IconFile className="svg-16" />} accent="red" /></div>
                  <div className="col-6 col-md-4 col-xl-2"><StatCard label={L.statIncomplete} value={String(result.stats.incomplete)} icon={<IconFile className="svg-16" />} accent="orange" /></div>
                  <div className="col-6 col-md-4 col-xl-2"><StatCard label={L.statHighestGpa} value={result.stats.highestGpa?.toFixed(2) ?? "—"} icon={<IconAward className="svg-16" />} accent="purple" /></div>
                  <div className="col-6 col-md-4 col-xl-2"><StatCard label={L.statLowestGpa} value={result.stats.lowestGpa?.toFixed(2) ?? "—"} icon={<IconTrend className="svg-16" />} accent="sky" /></div>
                </div>
                <div className="mt-3 d-flex flex-wrap gap-2 align-items-center">
                  <span className="badge badge-secondary">
                    {result.exam.program.gradeScale === "GPA5" ? t.portal.campusAcademicPage.scaleGpa5 : t.portal.campusAcademicPage.scaleGpa4}
                  </span>
                  {scaleSteps.steps.map((s, i) => (
                    <span key={s.grade} className="badge badge-light" style={{ border: "1px solid #e3e8ef" }}>
                      {s.grade} · {locale === "bn" ? toBnDigits(cuGradeRange(scaleSteps.steps, i)) : cuGradeRange(scaleSteps.steps, i)} · {s.point.toFixed(2)}
                    </span>
                  ))}
                </div>
              </div>
              <div className="table-responsive">
                <table className="table table-hover align-middle mb-0">
                  <thead className="ems-table-head">
                    <tr>
                      <th>{L.thStudent}</th>
                      <th>{L.programLabel}</th>
                      <th className="text-center">{L.thTotal}</th>
                      <th className="text-center">{L.thCredits}</th>
                      <th className="text-center">{L.thGpa}</th>
                      <th>{L.thResult}</th>
                      <th className="text-end">{L.thActions}</th>
                    </tr>
                  </thead>
                  <tbody>
                    {result.rows.map((r) => (
                      <tr key={r.student.id}>
                        <td>
                          <p className="mb-0 f-w-700">{nm(r.student.name, r.student.nameBn)}</p>
                          <p className="mb-0 ems-fs-11 text-muted">{r.student.studentIdNo}</p>
                        </td>
                        <td className="ems-fs-12">
                          {nm(result.exam.program.name, result.exam.program.nameBn)}
                          {result.exam.term ? <p className="mb-0 text-muted">{nm(result.exam.term.name, result.exam.term.nameBn)}</p> : null}
                        </td>
                        <td className="text-center ems-fs-12">{r.totalMarks} / {r.fullMarksTotal}</td>
                        <td className="text-center">{r.creditsEarned}{r.creditsEarned !== r.creditsAttempted ? <span className="text-danger"> / {r.creditsAttempted}</span> : null}</td>
                        <td className="text-center f-w-700">{r.gpa?.toFixed(2) ?? "—"}</td>
                        <td>
                          <StatusBadge
                            status={r.status === "PASSED" ? "ACTIVE" : r.status === "FAILED" ? "SUSPENDED" : "PENDING"}
                            label={L[`res_${r.status}` as keyof typeof L] ?? r.status}
                          />
                        </td>
                        <td className="text-end">
                          <Button variant="secondary" onClick={() => printMarksheet(r)}>{L.viewMarksheet}</Button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </>
          )}
        </div>
      )}

      {/* ------------------------- Transcript ------------------------- */}
      {tab === "transcript" && (
        <div className="row g-4">
          <div className="col-lg-4">
            <Card>
              <div className="row g-2">
                <div className="col-12">
                  <Select label={L.pickProgram} required value={trProgramId} onChange={(e) => { setTrProgramId(e.target.value); setTrStudentId(""); }}>
                    <option value="">—</option>
                    {programs.map((p) => <option key={p.id} value={p.id}>{nm(p.name, p.nameBn)}</option>)}
                  </Select>
                </div>
                <div className="col-12">
                  <Select label={L.pickStudent} value={trStudentId} onChange={(e) => setTrStudentId(e.target.value)} disabled={!trProgramId}>
                    <option value="">—</option>
                    {(trStudentsData.data?.students ?? []).map((s) => (
                      <option key={s.id} value={s.id}>{s.studentIdNo} — {nm(s.name, s.nameBn)}</option>
                    ))}
                  </Select>
                </div>
                {trStudentId && (
                  <div className="col-12">
                    <Button className="w-100" onClick={printTranscript} disabled={!transcriptData.data || (transcriptData.data?.terms.length ?? 0) === 0}>
                      <IconAward className="svg-16" />
                      <span className="ms-1">{L.printTranscript}</span>
                    </Button>
                  </div>
                )}
              </div>
            </Card>
            {!trProgramId ? (
              <p className="text-muted mt-3">{L.hintPickStudent}</p>
            ) : null}
          </div>
          <div className="col-lg-8">
            {!trStudentId ? (
              <Card><EmptyState title={L.hintPickStudent} /></Card>
            ) : transcriptData.loading && !transcriptData.data ? (
              <Card><div className="text-center py-4"><span className="spinner-border text-primary" role="status" /></div></Card>
            ) : !transcriptData.data || transcriptData.data.terms.length === 0 ? (
              <Card><EmptyState title={L.noPublishedResults} /></Card>
            ) : (
              <Card>
                <div className="d-flex justify-content-between align-items-center mb-3">
                  <div>
                    <p className="mb-0 f-w-700">{nm(transcriptData.data.student.name, transcriptData.data.student.nameBn)}</p>
                    <p className="mb-0 ems-fs-12 text-muted">
                      {transcriptData.data.student.studentIdNo} · {nm(transcriptData.data.student.program.name, transcriptData.data.student.program.nameBn)} · {transcriptData.data.student.sessionYear}
                    </p>
                  </div>
                  <div className="text-end">
                    <p className="mb-0 ems-fs-11 text-muted">{L.cgpaLabel}</p>
                    <p className="mb-0 f-w-700" style={{ fontSize: 22, color: "#24695c" }}>
                      {transcriptData.data.cgpa?.toFixed(2) ?? "—"}
                    </p>
                    <p className="mb-0 ems-fs-11 text-muted">
                      {L.creditsCompletedLabel}: {transcriptData.data.totalCredits}
                      {transcriptData.data.programCredits > 0 ? ` / ${transcriptData.data.programCredits}` : ""}
                    </p>
                  </div>
                </div>
                {transcriptData.data.terms.map((term) => (
                  <div key={term.examId} className="mb-3">
                    <div className="d-flex justify-content-between align-items-center">
                      <p className="mb-1 f-w-700 ems-fs-13">{nm(term.termName, term.termNameBn)} — {term.examName}</p>
                      <span className="badge badge-success">{L.gpaLabel}: {term.gpa.toFixed(2)}</span>
                    </div>
                    <div className="table-responsive">
                      <table className="table table-sm table-hover align-middle mb-0">
                        <thead className="ems-table-head">
                          <tr>
                            <th>{L.courseLabel}</th>
                            <th className="text-center">{L.creditsLabel}</th>
                            <th className="text-center">{L.obtainedLabel}</th>
                            <th className="text-center">{L.gradeLabel}</th>
                            <th className="text-center">{L.pointLabel}</th>
                          </tr>
                        </thead>
                        <tbody>
                          {term.courses.map((c) => (
                            <tr key={`${term.examId}-${c.code}`}>
                              <td className="ems-fs-12"><b>{c.code}</b> — {nm(c.name, c.nameBn)}</td>
                              <td className="text-center">{c.credits}</td>
                              <td className="text-center">{c.marks ?? "—"} / {c.fullMarks}</td>
                              <td className="text-center f-w-700">{c.grade}</td>
                              <td className="text-center">{c.point.toFixed(2)}</td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  </div>
                ))}
              </Card>
            )}
          </div>
        </div>
      )}
    </div>
  );
}
