"use client";

import { useEffect, useState } from "react";
import { useLang } from "@/context/LanguageContext";
import { EmptyState, PageHeader, LoadingArea, Button } from "@/components/ui";
import { api, useApi } from "@/lib/client";
import { formatDate, formatNumber, type Locale } from "@/lib/utils";
import { toBnDigits } from "@/lib/constants";
import { IconAward, IconFile } from "@/components/icons";
import { DEFAULT_ACCENT, DEFAULT_PRIMARY } from "@/lib/print";
import QRCodeStyling from "qr-code-styling";
import ExamSheetCard, {
  DEFAULT_MKS_FIELDS,
  mksThemeVars,
  sessionLabelText,
  type ExamSheetLabels,
} from "@/components/ExamSheetCard";
import type { SheetRow } from "@/lib/result-sheet";

interface SubjectRow {
  scheduleId: number;
  subject: string | null;
  subjectBn: string | null;
  date: string;
  fullMarks: number;
  passMarks: number | null;
  cq: number | null;
  mcq: number | null;
  applied: number | null;
  total: number | null;
  note: string | null;
  grade: string | null;
  point: number | null;
  failed: boolean;
}

interface ExamResult {
  id: number;
  name: string;
  nameBn: string | null;
  className: string | null;
  classNameBn: string | null;
  status: string;
  startDate: string;
  endDate: string | null;
  resultPublishedAt: string | null;
  subjects: SubjectRow[];
  marksEntered: number;
  totalSubjects: number;
  obtained: number;
  fullTotal: number;
  percent: number | null;
  grade: string | null;
  gpa: number | null;
  result: "PASSED" | "FAILED" | "INCOMPLETE";
}

/** the portal-grade marksheet payload (same row the institution prints) */
interface MksData {
  exam: {
    id: number;
    name: string;
    nameBn: string | null;
    className: string | null;
    classNameBn: string | null;
    startDate: string;
    endDate: string | null;
  };
  row: SheetRow;
  institution: { name: string; address: string; phone: string; logo: string | null } | null;
  principalSignature: string | null;
  principalName: string | null;
}

/** Student/parent: published exam results with grades, GPA, pass/fail and a
    printable marksheet in the institution's EXACT official design (the same
    component the office prints from). Running/unpublished exams never appear. */
export default function MeResultsPage() {
  const { t, locale } = useLang();
  const { data, loading } = useApi<{ exams: ExamResult[] }>("/api/me/results");
  const [openExam, setOpenExam] = useState<number | null>(null);
  const [printingExam, setPrintingExam] = useState<number | null>(null);

  // pending marksheet: fetched → hidden-rendered → QR generated → printed
  const [mks, setMks] = useState<MksData | null>(null);
  const [mksQr, setMksQr] = useState<string | null>(null);

  const num = (v: string | number) => (locale === "bn" ? toBnDigits(v) : String(v));

  const sheetLabels: ExamSheetLabels = {
    fatherLabel: t.portal.resultsPage.fatherLabel,
    motherLabel: t.portal.resultsPage.motherLabel,
    roll: t.portal.admissionsPage.roll,
    classLabel: t.portal.studentsPage.classLabel,
    fieldNameSection: t.portal.resultsPage.fieldNames.section,
    fieldNameShift: t.portal.resultsPage.fieldNames.shift,
    sessionLabel: t.portal.resultsPage.sessionLabel,
    scanToVerify: t.portal.resultsPage.scanToVerify,
    subject: t.categories.SUBJECT,
    examColLabel: t.portal.resultsPage.examLabel,
    periodicalExamColLabel: t.portal.resultsPage.periodicalExam,
    marksCol: t.portal.resultsPage.marksCol,
    highestCol: t.portal.resultsPage.highestCol,
    statusCol: t.portal.resultsPage.statusCol,
    failed: t.portal.resultsPage.failed,
    passed: t.portal.resultsPage.passed,
    total: t.portal.resultsPage.total,
    meritPos: t.portal.resultsPage.meritPos,
    academicDay: t.portal.resultsPage.academicDay,
    present: t.portal.resultsPage.present,
    absent: t.portal.resultsPage.absent,
    progress: t.portal.resultsPage.progress,
    good: t.portal.resultsPage.good,
    needImprovement: t.portal.resultsPage.needImprovement,
    bad: t.portal.resultsPage.bad,
    signTeacher: t.portal.resultsPage.signTeacher,
    signGuardian: t.portal.resultsPage.signGuardian,
    signPrincipal: t.portal.resultsPage.signPrincipal,
    authorization: t.portal.resultsPage.authorization,
    activities: t.portal.resultsPage.activities,
    developedBy: t.portal.resultsPage.developedBy,
  };

  async function printMarksheet(examId: number) {
    setPrintingExam(examId);
    try {
      const res = await api<MksData>(`/api/me/results?examId=${examId}`);
      setMksQr(null);
      setMks(res);
    } catch {
      /* marksheet unavailable */
    } finally {
      setPrintingExam(null);
    }
  }

  // verification QR for the pending sheet — same rendering as the portal
  useEffect(() => {
    if (!mks) return;
    let cancelled = false;
    (async () => {
      const qrText = mks.row.verifyCode ?? null;
      if (!qrText) {
        setMksQr(null);
        return;
      }
      try {
        const qr = new QRCodeStyling({
          width: 240,
          height: 240,
          margin: 10,
          data: qrText,
          backgroundOptions: { color: "#ffffff" },
          dotsOptions: { type: "rounded", color: "#14514a" },
          cornersSquareOptions: { type: "extra-rounded", color: "#14514a" },
          cornersDotOptions: { type: "dot", color: DEFAULT_ACCENT },
        });
        const blob = (await qr.getRawData("png")) as Blob | null;
        if (!cancelled && blob) setMksQr(URL.createObjectURL(blob));
      } catch {
        if (!cancelled) setMksQr(null);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [mks]);

  // once the hidden card + QR are ready, print via the same iframe approach
  useEffect(() => {
    if (!mks || (mks.row.verifyCode && !mksQr)) return;
    (async () => {
      const root = document.getElementById("meMksRoot");
      if (root && root.childElementCount > 0) {
        const cssUrls = ["/assets/css/bootstrap.css", "/assets/css/style.css", "/assets/css/increlog.css"];
        const cssTexts = await Promise.all(cssUrls.map((u) => fetch(u).then((r) => r.text()).catch(() => "")));
        const fontLinks = Array.from(document.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"]'))
          .filter((l) => l.href.includes("fonts.googleapis"))
          .map((l) => l.outerHTML)
          .join("\n");
        const iframe = document.createElement("iframe");
        iframe.style.cssText = "position:fixed;right:0;bottom:0;width:0;height:0;border:0;visibility:hidden;";
        document.body.appendChild(iframe);
        const doc = iframe.contentDocument;
        if (doc) {
          doc.open();
          doc.write(
            `<!DOCTYPE html><html lang="${document.documentElement.lang}"><head><meta charset="utf-8">${fontLinks}<style>${cssTexts.join("\n")}</style><style>
              body { margin: 0; padding: 10px; background: #fff; }
              .card { box-shadow: none !important; border: 1px solid #dee2e6 !important;
                      break-inside: avoid; page-break-after: always; margin: 0 0 10px; }
              .card:last-child { page-break-after: auto; }
              @page { size: A4; margin: 8mm; }
            </style></head><body>${root.innerHTML}</body></html>`
          );
          doc.close();
          await new Promise<void>((resolve) => {
            iframe.onload = () => resolve();
            setTimeout(() => resolve(), 1500);
          });
          const idoc = iframe.contentDocument;
          if (idoc) {
            await Promise.all(
              Array.from(idoc.images).map((img) =>
                img.complete ? Promise.resolve() : new Promise<void>((res) => { img.onload = () => res(); img.onerror = () => res(); })
              )
            );
            try { await idoc.fonts?.ready; } catch { /* older browsers */ }
          }
          await new Promise((r) => setTimeout(r, 150));
          iframe.contentWindow?.focus();
          iframe.contentWindow?.print();
          setTimeout(() => iframe.remove(), 60_000);
        }
      }
      if (mksQr) URL.revokeObjectURL(mksQr);
      setMks(null);
      setMksQr(null);
    })();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [mks, mksQr]);

  if (loading) {
    return (
      <div>
        <PageHeader title={t.me.resultsTitle} subtitle={t.me.resultsSubtitle} />
        <LoadingArea label={t.common.loading} />
      </div>
    );
  }

  const exams = data?.exams ?? [];
  const resultBadge = (r: string) =>
    r === "PASSED" ? "badge-success" : r === "FAILED" ? "badge-danger" : "badge-warning";
  const resultLabel = (r: string) =>
    r === "PASSED" ? t.me.resultPassed : r === "FAILED" ? t.me.resultFailed : t.me.resultIncomplete;

  return (
    <div>
      <PageHeader title={t.me.resultsTitle} subtitle={t.me.resultsSubtitle} />

      {exams.length === 0 ? (
        <div className="card">
          <EmptyState icon={<IconAward />} title={t.me.noResultsDetail} />
        </div>
      ) : (
        exams.map((e) => {
          const open = openExam === e.id;
          return (
            <div className="card mb-3 ems-fade-in" key={e.id}>
              <div
                className="card-header d-flex flex-wrap align-items-center justify-content-between gap-2 ems-clickable"
                onClick={() => setOpenExam(open ? null : e.id)}
                role="button"
                tabIndex={0}
                onKeyDown={(ev) => ev.key === "Enter" && setOpenExam(open ? null : e.id)}
              >
                <div>
                  <h6 className="mb-0 f-w-700">
                    {locale === "bn" && e.nameBn ? e.nameBn : e.name}
                    {e.className && (
                      <span className="text-muted f-w-500 ms-2 ems-fs-13">
                        {locale === "bn" && e.classNameBn ? e.classNameBn : e.className}
                      </span>
                    )}
                  </h6>
                  <p className="mb-0 ems-fs-12 text-muted">
                    {formatDate(e.startDate, locale)}
                    {e.endDate ? ` → ${formatDate(e.endDate, locale)}` : ""}
                    {e.resultPublishedAt ? ` · ${t.me.publishedOn} ${formatDate(e.resultPublishedAt, locale)}` : ""}
                  </p>
                </div>
                <div className="d-flex flex-wrap align-items-center gap-2">
                  {e.result && (
                    <span className={`badge ${resultBadge(e.result)}`}>{resultLabel(e.result)}</span>
                  )}
                  {e.grade && (
                    <span className="badge badge-soft-teal" title={t.me.gradeCol}>
                      {e.grade}
                      {e.gpa != null ? ` · GPA ${formatNumber(e.gpa, locale)}` : ""}
                    </span>
                  )}
                  {e.percent != null && (
                    <span
                      className={`f-w-800 ${
                        e.percent >= 60 ? "text-success" : e.percent >= 33 ? "text-warning" : "text-danger"
                      }`}
                    >
                      {formatNumber(e.percent, locale)}%
                    </span>
                  )}
                </div>
              </div>
              {open && (
                <div className="card-body pt-2">
                  <div className="d-flex justify-content-end mb-2">
                    <Button size="sm" variant="secondary" loading={printingExam === e.id} onClick={() => printMarksheet(e.id)}>
                      <IconFile className="svg-14" />
                      <span className="ms-1">{t.me.marksheetBtn}</span>
                    </Button>
                  </div>
                  <div className="table-responsive">
                    <table className="table table-hover align-middle mb-0">
                      <thead className="ems-table-head">
                        <tr>
                          <th>{t.me.subjectCol}</th>
                          <th className="text-center">CQ</th>
                          <th className="text-center">MCQ</th>
                          <th className="text-center">{t.me.appliedCol}</th>
                          <th className="text-center">{t.me.totalCol}</th>
                          <th className="text-center">{t.me.fullMarksCol}</th>
                          <th className="text-center">{t.me.gradeCol}</th>
                        </tr>
                      </thead>
                      <tbody>
                        {e.subjects.map((s) => (
                          <tr key={s.scheduleId}>
                            <td className="f-w-600 ems-fs-13">
                              {locale === "bn" && s.subjectBn ? s.subjectBn : s.subject ?? "—"}
                              {s.failed && <span className="badge badge-danger ms-1">{t.me.failedShort}</span>}
                            </td>
                            <td className="text-center ems-fs-13">{s.cq ?? "—"}</td>
                            <td className="text-center ems-fs-13">{s.mcq ?? "—"}</td>
                            <td className="text-center ems-fs-13">{s.applied ?? "—"}</td>
                            <td className={`text-center f-w-700 ${s.failed ? "text-danger" : ""}`}>{s.total ?? "—"}</td>
                            <td className="text-center text-muted ems-fs-12">{s.fullMarks}</td>
                            <td className="text-center">
                              {s.grade ? (
                                <span className={`badge ${s.failed ? "badge-danger" : "badge-soft-teal"}`}>{s.grade}</span>
                              ) : (
                                "—"
                              )}
                            </td>
                          </tr>
                        ))}
                        <tr className="ems-table-head">
                          <td className="f-w-700">{t.me.grandTotal}</td>
                          <td className="text-center">—</td>
                          <td className="text-center">—</td>
                          <td className="text-center">—</td>
                          <td className="text-center f-w-800 text-success">{e.obtained}</td>
                          <td className="text-center f-w-700">{e.fullTotal}</td>
                          <td className="text-center f-w-700">
                            {e.percent != null ? `${formatNumber(e.percent, locale)}%` : "—"}
                          </td>
                        </tr>
                      </tbody>
                    </table>
                  </div>
                </div>
              )}
            </div>
          );
        })
      )}

      {/* hidden print root — the official marksheet card, cloned into the print iframe */}
      <div id="meMksRoot" style={{ position: "fixed", right: 0, bottom: 0, width: 0, height: 0, overflow: "hidden" }} aria-hidden>
        {mks && (
          <ExamSheetCard
            row={mks.row}
            inst={mks.institution}
            exam={mks.exam}
            classText={
              mks.exam
                ? locale === "bn" && mks.exam.classNameBn
                  ? mks.exam.classNameBn
                  : mks.exam.className ?? "—"
                : "—"
            }
            qr={mksQr}
            visibleFields={DEFAULT_MKS_FIELDS}
            principalSig={mks.principalSignature}
            principalName={mks.principalName}
            sessionText={sessionLabelText(mks.exam?.startDate)}
            labels={sheetLabels}
            locale={locale as Locale}
            num={num}
            themeVars={mksThemeVars(DEFAULT_PRIMARY, DEFAULT_ACCENT)}
          />
        )}
      </div>
    </div>
  );
}
