"use client";

import { Fragment, useEffect, useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { useLang } from "@/context/LanguageContext";
import {
  Alert,
  Button,
  Card,
  EmptyState,
  PageHeader,
  PageLoader,
  Select,
  StatusBadge,
} from "@/components/ui";
import { api, useApi } from "@/lib/client";
import { PRIMARY_GRADE_SCALE, RESULT_OPERATIONAL_TYPES, RESULT_SYSTEM_TYPES, gradeFromPercent, gradeScaleRange, toBnDigits } from "@/lib/constants";
import { formatDate, smoothScrollToSection } from "@/lib/utils";
import type { Locale } from "@/lib/utils";
import QRCodeStyling from "qr-code-styling";
import { IconAward, IconCheck, IconFile, IconInfo, IconLayers, IconPrinter, IconTrend, IconUsers } from "@/components/icons";
import { emsConfirm } from "@/components/ConfirmDialog";
import ExamSheetCard, { type ExamSheetLabels } from "@/components/ExamSheetCard";

type Format = "SINGLE" | "PERIODICAL" | "FINAL" | "COMBINED" | "HIGHSCHOOL";

interface Overview {
  institution: { type: string; name: string };
  exams: {
    id: number;
    name: string;
    nameBn: string | null;
    format: string;
    classItemId: number | null;
    className: string | null;
    classNameBn: string | null;
    startDate: string;
    status: string;
    resultPublished: boolean;
    subjects: number;
    marksEntered: number;
  }[];
  classes: { id: number; name: string; nameBn: string | null; hasPeriodical: boolean }[];
  sectionItems?: { id: number; name: string; nameBn: string | null }[];
  shiftItems?: { id: number; name: string; nameBn: string | null }[];
  /** the principal's uploaded signature (HR) — printed on the sheets */
  principalSignature?: string | null;
  principalName?: string | null;
  teacherSignature?: string | null;
  teacherName?: string | null;
}

/** Final Result (3 exam sets) — API shape for agg=COMBINED */
interface CombinedSet {
  label: string;
  weight: number;
  tutorial: { id: number; name: string; nameBn: string | null } | null;
  semester: { id: number; name: string; nameBn: string | null } | null;
  window: { start: string; end: string } | null;
}
interface CombinedSubject {
  key: string;
  subject: string;
  subjectBn: string | null;
  sets: { tutorial: number | null; semester: number | null; marks: number | null; full: number; highest: number | null }[];
  final: { c: number[]; total: number; totalFull: number; passed: boolean | null };
}
interface CombinedRow {
  studentId: number;
  roll: string;
  name: string;
  nameBn: string | null;
  sectionName: string | null;
  sectionNameBn: string | null;
  shiftName: string | null;
  shiftNameBn: string | null;
  guardianName?: string;
  guardianNameBn?: string | null;
  motherName?: string | null;
  motherNameBn?: string | null;
  photoUrl?: string | null;
  subjects: CombinedSubject[];
  perSetTotals: (number | null)[];
  total: number;
  totalFull: number;
  failedSubjects: number;
  result: "PASSED" | "FAILED" | "INCOMPLETE";
  position: number | null;
  attendance: { academicDay: number; present: number; absent: number }[];
  verifyCode?: string; // EMS-XXXX-XXXX — the QR text
}

interface SubjectCell {
  scheduleId: number;
  subject: string;
  subjectBn: string | null;
  subjectItemId?: number | null;
  full: number;
  mcqFull?: number | null;
  cqFull?: number | null;
  appliedFull?: number | null;
  mcqPass?: number | null;
  cqPass?: number | null;
  appliedPass?: number | null;
  totalPass?: number | null;
  obtained: number | null;
  cq: number | null;
  mcq: number | null;
  applied: number | null;
  percent: number | null;
  grade: string | null;
  failed: boolean;
  perExam?: (number | null)[];
  perExamFull?: number[];
  highest?: number | null;
}

interface Sheet {
  institution: {
    name: string;
    type: string;
    address?: string;
    phone?: string;
    logo?: string | null;
    code?: string | null;
  };
  teacherSignature?: string | null;
  teacherName?: string | null;
  aggregate?: Format | null;
  combined?: {
    classItem: { name: string; nameBn: string | null } | null;
    weights: number[];
    passPercent: number;
    sets: CombinedSet[];
  } | null;
  examNames?: { name: string; nameBn: string | null; format: string }[];
  classItem?: { name: string; nameBn: string | null } | null;
  period?: { start: string; end: string | null } | null;
  exam: {
    id: number;
    name: string;
    nameBn: string | null;
    format: string;
    className: string | null;
    classNameBn: string | null;
    sectionName: string | null;
    sectionNameBn?: string | null;
    shiftName?: string | null;
    shiftNameBn?: string | null;
    startDate: string;
    endDate?: string | null;
    resultPublished: boolean;
  } | null;
  rows: {
    studentId: number;
    roll: string;
    name: string;
    nameBn: string | null;
    sectionName?: string | null;
    sectionNameBn?: string | null;
    shiftName?: string | null;
    shiftNameBn?: string | null;
    groupName?: string | null;
    dob?: string | null;
    subjects: SubjectCell[];
    totalFull: number;
    totalObtained: number;
    percent: number;
    grade: string;
    point: number;
    failedSubjects: number;
    missingSubjects: number;
    result: "PASSED" | "FAILED" | "INCOMPLETE";
    position: number | null;
    activities: string[];
    guardianName?: string;
    guardianNameBn?: string | null;
    motherName?: string | null;
    motherNameBn?: string | null;
    photoUrl?: string | null;
    attendance?: { academicDay: number; present: number; absent: number };
    verifyToken?: string;
    verifyCode?: string; // EMS-XXXX-XXXX — the QR text
  }[];
}


function hexToRgb(hex: string): [number, number, number] {
  const h = hex.replace("#", "");
  const v = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
  return [parseInt(v.slice(0, 2), 16), parseInt(v.slice(2, 4), 16), parseInt(v.slice(4, 6), 16)];
}

/** blend color `a` toward `b`; amount is the portion of `b` (0-1) */
function mix(a: string, b: string, amount: number): string {
  const [r1, g1, b1] = hexToRgb(a);
  const [r2, g2, b2] = hexToRgb(b);
  const f = (x: number, y: number) => Math.max(0, Math.min(255, Math.round(x + (y - x) * amount)));
  return "#" + [f(r1, r2), f(g1, g2), f(b1, b2)].map((x) => x.toString(16).padStart(2, "0")).join("");
}

/** marksheet color presets — same palette family as the certificates module */
const MKS_PRESETS = [
  { primary: "#24695c", accent: "#c9a227" }, // teal & gold
  { primary: "#1e5a8a", accent: "#e39a1e" }, // blue & amber
  { primary: "#7a1f2b", accent: "#c9a227" }, // maroon & gold
  { primary: "#2e6b3e", accent: "#b87333" }, // green & copper
  { primary: "#3f3d8a", accent: "#b0446e" }, // indigo & rose
];

type MksFieldKey = "photo" | "father" | "mother" | "roll" | "className" | "section" | "shift" | "session" | "attendance" | "progress";

function sessionLabel(data: Sheet | null, now: Date): string {
  const iso = data?.exam?.startDate;
  const y = iso ? new Date(iso).getFullYear() : now.getFullYear();
  return `${y}-${String(y + 1).slice(2)}`;
}

/** Grade range on a ratio (percentage-of-full-marks) basis, built from the
    scale steps: A+ ≥80% · A 70%–79% · … · D 33%–39% · F <33% */
function gradeRangeLabel(i: number): string {
  const g = PRIMARY_GRADE_SCALE[i];
  const prev = i > 0 ? PRIMARY_GRADE_SCALE[i - 1] : null;
  if (!prev) return `≥${g.min}%`;
  if (g.min === 0) return `<${prev.min}%`;
  return `${g.min}%–${prev.min - 1}%`;
}

/** localized exam period for the header band: "05 Aug, 2026 – 12 Aug, 2026"
    (a single date when start and end are the same day) */
function examPeriodLabel(data: Sheet | null, locale: Locale): string {
  const startIso = data?.exam ? data.exam.startDate : data?.period?.start ?? null;
  const endIso = data?.exam ? data.exam.endDate ?? null : data?.period?.end ?? null;
  if (!startIso) return "";
  const s = formatDate(startIso, locale);
  if (!endIso || new Date(endIso).toDateString() === new Date(startIso).toDateString()) return s;
  return `${s} – ${formatDate(endIso, locale)}`;
}
export default function PortalResultsPage() {
  const { t, locale } = useLang();
  const overview = useApi<Overview>("/api/portal/results");
  // principal's signature image for the sheets' signature sections
  const principalSig = overview.data?.principalSignature ?? null;

  const [format, setFormat] = useState<Format>("SINGLE");
  // formula/logic info badge (content follows the selected format)
  const [formulaOpen, setFormulaOpen] = useState(false);
  /** High School sheet type: with / without the optional (4th) subject */
  const [hsOptional, setHsOptional] = useState(false);
  // paired-paper pass rule: COMBINED (Bangladesh — e.g. 66/200 passes
  // English) or EACH (every paper needs its own 33%)
  const [hsPassRule, setHsPassRule] = useState<"COMBINED" | "EACH">("COMBINED");
  // High School print pattern: the Increlog marksheet or the board transcript
  const [hsPattern, setHsPattern] = useState<"INCRELOG" | "BOARD">("INCRELOG");
  const [examId, setExamId] = useState<string>("");
  const [classId, setClassId] = useState<string>("");
  const [selectedExamIds, setSelectedExamIds] = useState<number[]>([]);

  // ---- Final Result (3 exam sets) query form ----
  const [cClassId, setCClassId] = useState("");
  const [cSectionId, setCSectionId] = useState("");
  const [cShiftId, setCShiftId] = useState("");
  const [cSession, setCSession] = useState("");
  const [cPass, setCPass] = useState("0");
  const [cWeights, setCWeights] = useState<string[]>(["20", "20", "60"]);
  const [cSets, setCSets] = useState<{ tut: string; sem: string }[]>([
    { tut: "", sem: "" },
    { tut: "", sem: "" },
    { tut: "", sem: "" },
  ]);
  /** applied COMBINED query — the sheet only loads after "Student List" */
  const [combinedQuery, setCombinedQuery] = useState<string | null>(null);
  const [combinedError, setCombinedError] = useState<string | null>(null);
  const [showParts, setShowParts] = useState(false);
  const [mksPrimary, setMksPrimary] = useState("#24695c");
  const [mksAccent, setMksAccent] = useState("#c9a227");
  const [visibleFields, setVisibleFields] = useState<Record<MksFieldKey, boolean>>({
    photo: true, father: true, mother: true, roll: true, className: true,
    section: true, shift: true, session: true, attendance: true, progress: true,
  });
  function toggleField(k: MksFieldKey) {
    setVisibleFields((prev) => ({ ...prev, [k]: !prev[k] }));
  }
  /** Print exactly the marksheet cards (the red area): clone #emsPrintRoot
      into a hidden iframe with the app stylesheets and call print() on it —
      the browser preview then contains only the sheets, one per page. */
  /** Print exactly the marksheet cards (the red area): clone #emsPrintRoot
      into a hidden iframe with inlined app CSS, wait for images + fonts to
      be ready, then print() — the preview always contains the sheets.
      The Final Result (3 sets) sheet prints in A4 landscape. */
  async function handlePrint() {
    const landscape = isCombined;
    const root = document.getElementById("emsPrintRoot");
    if (!root || root.childElementCount === 0) return;

    // inline same-origin stylesheets as <style> (no async <link> race)
    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(() => ""))
    );
    // keep the Google-fonts <link>s (asynchronous but non-blocking for layout)
    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) return;
    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; }
        .ems-print-root { display: block !important; }
        @page { size: A4 ${landscape ? "landscape" : ""}; margin: ${landscape ? "6mm" : format === "HIGHSCHOOL" ? "4mm" : "8mm"}; }
      </style></head><body>${root.innerHTML}</body></html>`
    );
    doc.close();

    // wait for the iframe document + its images (QR object URLs) + fonts
    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);
  }

  const mksThemeVars = {
    "--ems-primary": mksPrimary,
    "--ems-accent": mksAccent,
    "--ems-tint": mix(mksPrimary, "#ffffff", 0.88),
    "--ems-tint-soft": mix(mksPrimary, "#ffffff", 0.94),
    "--ems-dark": mix(mksPrimary, "#000000", 0.34),
    "--ems-primary-25": mix(mksPrimary, "#ffffff", 0.75),
    "--ems-primary-33": mix(mksPrimary, "#ffffff", 0.67),
    "--ems-primary-55": mix(mksPrimary, "#ffffff", 0.45),
    "--ems-present-tint": mix(mksPrimary, "#ffffff", 0.88),
    "--ems-present-text": mix(mksPrimary, "#000000", 0.42),
    "--ems-present-border": mix(mksPrimary, "#ffffff", 0.68),
    "--ems-absent-tint": mix(mksAccent, "#ffffff", 0.86),
    "--ems-absent-text": mix(mksAccent, "#000000", 0.52),
    "--ems-absent-border": mix(mksAccent, "#ffffff", 0.62),
  } as React.CSSProperties;
  const [busy, setBusy] = useState(false);
  const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null);

  /** sheet endpoint for the current pick — shared by the memo and the format
      pills (the pills need to know whether switching actually reloads) */
  function buildSheetUrl(fmt: Format, exam: string, cls: string, ids: number[]): string | null {
    if (fmt === "SINGLE" || fmt === "HIGHSCHOOL") return exam ? `/api/portal/results?examId=${exam}` : null;
    if (fmt === "COMBINED") return null; // armed only via the Student List button
    if (!cls) return null;
    const q = ids.length ? `&examIds=${ids.join(",")}` : "";
    return `/api/portal/results?agg=${fmt}&classItemId=${cls}${q}`;
  }

  /** Exam ids already picked in OTHER set slots (an exam can belong to only
      one slot). Every dropdown still lists ALL class exam names — taken ones
      render disabled instead of being hidden, so the full list stays visible. */
  function takenElsewhere(idx: number, kind: "tut" | "sem") {
    const taken = new Set<string>();
    cSets.forEach((s, i) => {
      const vals = i === idx ? (kind === "tut" ? [s.sem] : [s.tut]) : [s.tut, s.sem];
      for (const v of vals) if (v) taken.add(v);
    });
    return taken;
  }

  /** Final Result: validate the 3-set query, then arm the sheet fetch */
  function applyCombined() {
    setCombinedError(null);
    if (!cClassId) {
      setCombinedError(t.portal.resultsPage.selectClass);
      return;
    }
    const hasExam = cSets.some((s) => s.tut || s.sem);
    if (!hasExam) {
      setCombinedError(t.portal.resultsPage.finalEmpty);
      return;
    }
    const w = cWeights.map((x) => Number(x) || 0);
    const params = new URLSearchParams();
    params.set("agg", "COMBINED");
    params.set("classItemId", cClassId);
    if (cSectionId) params.set("sectionItemId", cSectionId);
    if (cShiftId) params.set("shiftItemId", cShiftId);
    cSets.forEach((s, i) => params.set(`set${i + 1}`, `${s.tut || ""},${s.sem || ""}`));
    w.forEach((x, i) => params.set(`w${i + 1}`, String(x)));
    params.set("pass", String(Number(cPass) || 0));
    setCombinedQuery(`/api/portal/results?${params.toString()}`);
  }

  const sheetUrl = useMemo(
    () => (format === "COMBINED" ? combinedQuery : buildSheetUrl(format, examId, classId, selectedExamIds)),
    [format, examId, classId, selectedExamIds, combinedQuery]
  );

  function toggleExamPick(id: number) {
    skipNextAutoScroll.current = true; // stay on the settings card while composing
    setSelectedExamIds((prev) =>
      prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]
    );
  }

  const classExams = useMemo(() => {
    const list = overview.data?.exams ?? [];
    const scopeId = format === "COMBINED" ? cClassId : classId;
    if (format === "PERIODICAL") return list.filter((e) => e.format === "PERIODICAL" && String(e.classItemId) === scopeId);
    if (format === "FINAL" || format === "COMBINED") return list.filter((e) => String(e.classItemId) === scopeId);
    return [];
  }, [overview.data, format, classId, cClassId]);
  const sheet = useApi<Sheet>(sheetUrl);
  // class-teacher signature — printed only once the result set is published
  const teacherSig =
    sheet.data?.exam?.resultPublished
      ? sheet.data.teacherSignature || overview.data?.teacherSignature || null
      : null;

  // The sheet card renders below the tall settings card, so after picking an
  // exam it sits below the fold and the page looks unchanged. Scroll the
  // loading state / freshly loaded sheet into view so the result is visible.
  // Only *primary* selections scroll (exam / class). Refining the view —
  // publish/unpublish, format pills, adding/removing combined exams — arms
  // skipNextAutoScroll so the user isn't yanked away mid-configuration.
  const resultsAnchor = useRef<HTMLDivElement | null>(null);
  const skipNextAutoScroll = useRef(false);
  const wasSheetLoading = useRef(false);
  useEffect(() => {
    if (!sheetUrl) {
      wasSheetLoading.current = sheet.loading;
      skipNextAutoScroll.current = false; // nothing to reload — don't eat the next selection's scroll
      return;
    }
    // a fetch armed with skip has settled (loading true → false)
    const settled = wasSheetLoading.current && !sheet.loading;
    if (skipNextAutoScroll.current) {
      if (settled) skipNextAutoScroll.current = false;
    } else {
      // smooth glide to the results section — the JS tween in
      // smoothScrollToSection survives the re-render/layout-shift storm that
      // cancels native smooth scrolls (105px clears the fixed header)
      if (resultsAnchor.current) smoothScrollToSection(resultsAnchor.current, 105);
    }
    wasSheetLoading.current = sheet.loading;
  }, [sheetUrl, sheet.loading, sheet.data]);

  // verification QR per student (signed token → /verify/result)
  const [qrMap, setQrMap] = useState<Record<number, string>>({});
  useEffect(() => {
    const rows = sheet.data?.rows ?? [];
    if (rows.length === 0) {
      setQrMap({});
      return;
    }
    let cancelled = false;
    (async () => {
      const origin = typeof window !== "undefined" ? window.location.origin : "";
      const next: Record<number, string> = {};
      for (const r of rows) {
        // QR text is the SHORT verification code (highly readable even at
        // 80x80); rows without one (legacy caches) fall back to the URL token
        const qrText = r.verifyCode
          ?? (r.verifyToken ? `${origin}/verify/result?t=${encodeURIComponent(r.verifyToken)}` : null);
        if (!qrText) continue;
        try {
          // scanner-first QR: solid high-contrast dark modules on white,
          // quiet zone margin, rounded shapes for the modern look
          const qr = new QRCodeStyling({
            width: 240,
            height: 240,
            margin: 10, // quiet zone — required for reliable scanning
            data: qrText,
            backgroundOptions: { color: "#ffffff" },
            dotsOptions: {
              type: "rounded",
              color: mix(mksPrimary, "#000000", 0.55), // dark enough for any scanner
            },
            cornersSquareOptions: { type: "extra-rounded", color: mix(mksPrimary, "#000000", 0.55) },
            cornersDotOptions: { type: "dot", color: mksAccent },
          });
          const blob = (await qr.getRawData("png")) as Blob | null;
          if (blob) next[r.studentId] = URL.createObjectURL(blob);
        } catch {
          /* skip on failure */
        }
      }
      if (!cancelled) setQrMap(next);
    })();
    return () => {
      cancelled = true;
    };
    // regenerate when the theme palette changes so the QR re-tints
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sheet.data, mksPrimary, mksAccent]);


  const instType = overview.data?.institution.type ?? "";
  const operational = RESULT_OPERATIONAL_TYPES.includes(instType);

  async function togglePublish(publish: boolean) {
    if (!examId) return;
    const confirmText = publish ? t.portal.resultsPage.publishConfirm : t.portal.resultsPage.unpublishConfirm;
    if (!(await emsConfirm({ message: confirmText, danger: false }))) return;
    setBusy(true);
    setMessage(null);
    try {
      await api("/api/portal/results", {
        method: "POST",
        body: JSON.stringify({ examId: Number(examId), publish }),
      });
      setMessage({
        type: "success",
        text: publish ? t.portal.resultsPage.published : t.portal.resultsPage.unpublished,
      });
      skipNextAutoScroll.current = true;
      sheet.reload();
      overview.reload();
    } catch {
      setMessage({ type: "error", text: t.common.tryAgain });
    } finally {
      setBusy(false);
    }
  }

  const exam = sheet.data?.exam;
  const rows = useMemo(() => sheet.data?.rows ?? [], [sheet.data]);
  const isCombined = sheet.data?.aggregate === "COMBINED" && !!sheet.data?.combined;
  /** locale-aware digits — Bangla numerals (০-৯) when the UI is Bangla */
  const num = (v: string | number) => (locale === "bn" ? toBnDigits(v) : String(v));
  const combinedRows = useMemo(
    () => (isCombined ? ((sheet.data as unknown as { rows: CombinedRow[] }).rows ?? []) : []),
    [sheet.data, isCombined]
  );
  const merit = useMemo(() => rows.filter((r) => r.position !== null), [rows]);
  const hasAnyPart = rows.some((r) => r.subjects.some((s) => (s.cq ?? 0) + (s.mcq ?? 0) + (s.applied ?? 0) > 0));
  // aggregate formats: per-exam side-by-side columns (Exam 1 | Exam 2 | …)
  const isAggregate = format === "PERIODICAL" || format === "FINAL";
  const examCount = isAggregate ? sheet.data?.examNames?.length ?? 0 : 0;
  const subjSpan = isAggregate
    ? examCount + (showParts && hasAnyPart ? 4 : 1) + 1 // per-exam + combined(parts?) + grade
    : showParts && hasAnyPart
      ? 5
      : 2;

  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,
  };

  const sheetsBlock = (
    <div className="d-flex flex-column gap-4">
      {rows.map((r) => (
        <ExamSheetCard
          key={r.studentId}
          row={r}
          inst={sheet.data?.institution ?? null}
          exam={sheet.data?.exam ?? null}
          classText={
            sheet.data?.exam
              ? locale === "bn" && sheet.data.exam.classNameBn
                ? sheet.data.exam.classNameBn
                : sheet.data.exam.className ?? "—"
              : sheet.data?.classItem
                ? locale === "bn" && sheet.data.classItem.nameBn
                  ? sheet.data.classItem.nameBn
                  : sheet.data.classItem.name
                : "—"
          }
          aggregateExamNames={isAggregate ? sheet.data?.examNames ?? null : null}
          partsColumns={showParts && hasAnyPart}
          qr={qrMap[r.studentId] ?? null}
          visibleFields={visibleFields}
          principalSig={principalSig}
          teacherSig={teacherSig}
          principalName={overview.data?.principalName ?? null}
          sessionText={sessionLabel(sheet.data, new Date())}
          labels={sheetLabels}
          locale={locale}
          num={num}
          themeVars={mksThemeVars}
        />
      ))}
    </div>
  );

  /** Merit list with failure detail — rendered on screen AND in the print
      root (final printed page). Themed via the same CSS vars as the sheets. */
  const meritListTable = (
    <table className="ems-merit-table">
      <thead>
        <tr>
          <th className="pos-col">{t.portal.resultsPage.meritPos}</th>
          <th>{t.common.name}</th>
          <th className="num-col">{t.portal.resultsPage.total}</th>
          <th className="num-col">{t.portal.resultsPage.failed}</th>
          <th>{t.portal.resultsPage.failedSubjects}</th>
          <th className="num-col">{t.portal.resultsPage.grade}</th>
        </tr>
      </thead>
      <tbody>
        {merit.map((r) => {
          const failedSubs = r.subjects.filter((s) => s.failed);
          return (
            <tr key={r.studentId}>
              <td className="pos">{r.position === null ? "—" : num(r.position)}</td>
              <td className="f-w-700 ems-fs-13">
                <span className="ems-roll-badge me-2">{num(r.roll)}</span>
                {locale === "bn" && r.nameBn ? r.nameBn : r.name}
              </td>
              <td className="num f-w-700">{num(r.totalObtained)}/{num(r.totalFull)}</td>
              <td className={`num ${failedSubs.length ? "fail-n" : "pass-n"}`}>
                {failedSubs.length ? num(failedSubs.length) : "—"}
              </td>
              <td className="subj">
                {failedSubs.length
                  ? failedSubs
                      .map((s) => (locale === "bn" && s.subjectBn ? s.subjectBn : s.subject))
                      .join(", ")
                  : "—"}
              </td>
              <td className="num">
                <span className={`badge ${r.grade === "F" ? "badge-danger" : r.point >= 4 ? "badge-success" : "badge-warning"}`}>
                  {r.grade}
                </span>
              </td>
            </tr>
          );
        })}
      </tbody>
    </table>
  );

  /** header line for the printed merit page — carries the class/format/date
      identity that aggregate marksheets deliberately omit */
  const meritPeriod = examPeriodLabel(sheet.data, locale);
  const meritContext = sheet.data?.exam
    ? `${locale === "bn" && sheet.data.exam.nameBn ? sheet.data.exam.nameBn : sheet.data.exam.name}${meritPeriod ? ` · ${meritPeriod}` : ""}`
    : sheet.data?.classItem
      ? `${locale === "bn" && sheet.data.classItem.nameBn ? sheet.data.classItem.nameBn : sheet.data.classItem.name}${
          sheet.data.aggregate ? ` — ${t.portal.resultsPage.formats[sheet.data.aggregate]}` : ""
        }${meritPeriod ? ` · ${meritPeriod}` : ""}`
      : "";

  /** identity header for the merit list sheet — same design language as the
      marksheet header (logo | institution | context). Shared by the on-screen
      merit card and the printed merit page. */
  const meritHeadBlock = (
    <div className="ems-mks-header ems-merit-head">
      {sheet.data?.institution.logo ? (
        <img src={sheet.data.institution.logo} className="ems-mks-logo" alt="" />
      ) : (
        <img src="/assets/images/increlog-logo.png" alt="Increlog" width="52" height="52" draggable="false" style={{ height: 52, width: "auto" }} />
      )}
      <div className="ems-mks-school">
        <h5>{sheet.data?.institution.name}</h5>
        {sheet.data?.institution.address && (
          <p className="addr">{sheet.data.institution.address}</p>
        )}
        {sheet.data?.institution.phone && (
          <p className="contact">{sheet.data.institution.phone}</p>
        )}
      </div>
      <div className="ems-merit-head-meta">
        <span className="title">{t.portal.resultsPage.meritList}</span>
        <span className="ctx">{meritContext}</span>
      </div>
    </div>
  );

  const meritPrintPage = (
    <div className="ems-merit-print" style={mksThemeVars}>
      {meritHeadBlock}
      {meritListTable}
      <div className="ems-sheet-footer">
        <img src="/assets/images/increlog-logo.png" alt="Increlog" width="16" height="16" draggable="false" style={{ height: 16, width: "auto", verticalAlign: -3 }} />
        <span>{t.portal.resultsPage.developedBy}</span>
      </div>
    </div>
  );

  /* ---------- Final Result sheets (3 exam sets, weighted) ----------
     Landscape sheet per student: header | title band | details | marks
     table (3 sets × Tutorial/Semester/Marks/Highest + weighted Final block)
     | per-set attendance summary + Merit | progress | signatures. */
  const combinedMeta = sheet.data?.combined ?? null;
  const setShortLabels = [
    t.portal.resultsPage.setShort1,
    t.portal.resultsPage.setShort2,
    t.portal.resultsPage.setShort3,
  ];
  const fmt2 = (v: number | null | undefined) =>
    v === null || v === undefined ? "—" : num(Number(v).toFixed(2));
  /** session base year for the sheet heading — "2026-27" → "2026" */
  const sessionBaseYear = (() => {
    const s = cSession || sessionLabel(sheet.data, new Date());
    return (s.match(/\d{4}/) ?? [s])[0];
  })();
  /** letter grade (A+ … F) from the primary scale for a weighted ratio */
  const letterFor = (obtained: number, full: number) =>
    full > 0 ? gradeFromPercent((obtained / full) * 100).grade : "—";

  /** session base year for the HS sheet heading */
  const sessionBaseYear2 = (() => {
    const sv = sessionLabel(sheet.data, new Date());
    return (sv.match(/\d{4}/) ?? [sv])[0];
  })();


  /* ---------- High School result sheets ----------
     One portrait sheet per student: CQ / MCQ / Applied parts with in/out
     badges, paired 1st/2nd-paper grades (rowspan), totals + GPA, merit with
     failed-subject detail, attendance, progress and signature block.
     Two sheet types: without / with the optional (4th) subject. */
  const hsOptionalIds = new Set<number>(
    (sheet.data as { optionalSubjectIds?: number[] } | null)?.optionalSubjectIds ?? []
  );

  /** Bangladesh education board tabulation serial — subjects render in this
      order on official primary & high school documents; unknown names follow
      after, keeping their schedule order */
  const HS_BOARD_ORDER = [
    "Bangla", "Bangla 1st Paper", "Bangla 2nd Paper",
    "English", "English 1st Paper", "English 2nd Paper",
    "Mathematics", "Higher Mathematics",
    "Religion & Moral Education",
    "Science", "Physics", "Chemistry", "Biology",
    "Agriculture Studies", "Home Science",
    "Bangladesh & Global Studies", "Geography & Environment",
    "History & World Civilization", "Civics & Good Governance", "Economics",
    "Business Entrepreneurship", "Accounting", "Finance & Banking",
    "ICT", "Physical Education",
  ];
  function hsBoardIndex(name: string): number {
    const idx = HS_BOARD_ORDER.indexOf(name);
    return idx === -1 ? HS_BOARD_ORDER.length : idx;
  }

  /** strip the paper suffix — "Bangla 1st Paper" → "Bangla" */
  function hsBase(name: string): string {
    return name
      .replace(/[-–]?\s*(1st|2nd|first|second)\s*paper/gi, "")
      .replace(/[-–]?\s*(১ম|২য়)\s*পত্র/g, "")
      .trim();
  }
  function hsPaperNo(name: string): 0 | 1 | 2 {
    if (/(1st|first)\s*paper|১ম\s*পত্র/i.test(name)) return 1;
    if (/(2nd|second)\s*paper|২য়\s*পত্র/i.test(name)) return 2;
    return 0;
  }

  interface HsUnit {
    papers: typeof rows[number]["subjects"];
    base: string;
    optional: boolean;
    obtained: number;
    full: number;
    highest: number;
    failed: boolean;
    point: number;
    grade: string;
    hasMarks: boolean;
  }

  /** group a student's subject rows into graded units — user-selected
      combines first, then automatic 1st+2nd paper pairs, else single */
  function hsUnits(subjectsIn: typeof rows[number]["subjects"], combineIds: Set<number>): HsUnit[] {
    // board serial first, 1st paper before 2nd within a base subject
    const subjects = [...subjectsIn].sort((a, b) => {
      const d = hsBoardIndex(a.subject) - hsBoardIndex(b.subject);
      if (d !== 0) return d;
      return hsPaperNo(a.subject) - hsPaperNo(b.subject);
    });
    const units: HsUnit[] = [];
    // user-picked combine group (schedule ids) becomes one graded unit,
    // rendered at its schedule position
    const group = subjects.filter((x) => combineIds.has(x.scheduleId));
    const inGroup = new Set(group.map((g) => g.scheduleId));
    let groupDone = group.length < 2;
    let i = 0;
    while (i < subjects.length) {
      const cur = subjects[i];
      if (inGroup.has(cur.scheduleId)) {
        if (!groupDone) {
          units.push(hsMakeUnit(group));
          groupDone = true;
        }
        i++;
        continue;
      }
      const curNo = hsPaperNo(cur.subject);
      const nxt = subjects[i + 1] && !inGroup.has(subjects[i + 1].scheduleId) ? subjects[i + 1] : null;
      const pair =
        curNo === 1 &&
        nxt &&
        hsPaperNo(nxt.subject) === 2 &&
        hsBase(nxt.subject) === hsBase(cur.subject)
          ? nxt
          : null;
      const papers = pair ? [cur, pair] : [cur];
      units.push(hsMakeUnit(papers));
      i += papers.length;
    }
    return units.sort((a, b) => (a.optional ? 1 : 0) - (b.optional ? 1 : 0));
  }

  function hsMakeUnit(papers: typeof rows[number]["subjects"]): HsUnit {
    const obtained = papers.reduce((a, x) => a + (x.obtained ?? 0), 0);
    const full = papers.reduce((a, x) => a + x.full, 0);
    const highest = papers.reduce((a, x) => a + (x.highest ?? 0), 0);
    const percent = full > 0 ? (obtained / full) * 100 : 0;
    const g = gradeFromPercent(percent);
    // Bangladesh rule for a 1st+2nd paper pair: pass is judged on the
    // COMBINED marks (sum >= 33% of the combined full, e.g. 66/200) — the
    // admin can switch to per-paper 33% with the pass-rule toggle
    const combinedPass =
      hsPassRule === "COMBINED" && papers.length === 2
        ? full > 0 && obtained >= Math.ceil(full * 0.33)
        : null;
    return {
      papers,
      base: hsBase(papers[0].subject),
      optional: papers.some((x) => (x.subjectItemId ?? null) !== null && hsOptionalIds.has(x.subjectItemId as number)),
      obtained,
      full,
      highest,
      failed: combinedPass !== null ? !combinedPass : papers.some((x) => x.failed),
      point: g.point,
      grade: g.grade,
      hasMarks: papers.every((x) => x.obtained !== null),
    };
  }

  /** reference design: obtained and full as two separate badge cells,
      colored by the schedule-configured pass mark ("Out of" minimum),
      falling back to the 33% line when not configured */
  function hsInOut(
    v: number | null | undefined,
    full: number | null | undefined,
    pass: number | null | undefined,
    forceOk?: boolean
  ) {
    if (v === null || v === undefined) {
      return (
        <>
          <th><span className="hs-muted">—</span></th>
          <th><span className="hs-muted">{full ? num(full.toFixed(0)) : "—"}</span></th>
        </>
      );
    }
    if (!full) {
      return (
        <>
          <th><span className="hs-badge neutral">{fmt2(v)}</span></th>
          <th><span className="hs-muted">—</span></th>
        </>
      );
    }
    const passLine = pass ?? Math.ceil(full * 0.33);
    // forceOk: the Bangladesh combined pass decision for a paired paper
    const ok = forceOk !== undefined ? forceOk : v >= passLine;
    const cls = ok ? "pass" : "fail";
    return (
      <>
        <th><span className={`hs-badge ${cls}`}>{fmt2(v)}</span></th>
        <th><span className={`hs-badge ${cls}`}>{num(full.toFixed(0))}</span></th>
      </>
    );
  }

  function hsUnitRow(u: HsUnit, key: number) {
    const first = u.papers[0];
    const second = u.papers[1];
    const optTag = hsOptional && u.optional ? <span className="hs-opt-tag">Optional</span> : null;
    const rowCls = hsOptional && u.optional ? "hs-opt" : "";
    // under the combined (Bangladesh) pass rule both papers of a pair are
    // coloured by the unit's combined pass decision
    const pairOk = hsPassRule === "COMBINED" && second ? !u.failed : undefined;
    const pointCell = (
      <th rowSpan={u.papers.length} className="hs-point">
        {u.hasMarks ? num(u.point.toFixed(2)) : "—"}
      </th>
    );
    const gradeCell = (
      <th rowSpan={u.papers.length}>
        <span className={`grade-badge${u.grade === "F" ? " f" : ""}`}>{u.hasMarks ? u.grade : "—"}</span>
      </th>
    );
    return (
      <Fragment key={key}>
        <tr className={rowCls}>
          <th className="hs-subject">
            <span>{locale === "bn" && first.subjectBn ? first.subjectBn : first.subject}</span>
            {optTag}
          </th>
          {hsInOut(first.mcq, first.mcqFull, first.mcqPass, pairOk)}
          {hsInOut(first.cq, first.cqFull, first.cqPass, pairOk)}
          {hsInOut(first.applied, first.appliedFull, first.appliedPass, pairOk)}
          <th className="hs-num f-w-700">{fmt2(first.obtained)}</th>
          <th className="hs-num text-muted">{first.highest !== null ? fmt2(first.highest) : "—"}</th>
          {second ? pointCell : <th className="hs-point">{u.hasMarks ? num(u.point.toFixed(2)) : "—"}</th>}
          {second ? gradeCell : (
            <th><span className={`grade-badge${u.grade === "F" ? " f" : ""}`}>{u.hasMarks ? u.grade : "—"}</span></th>
          )}
        </tr>
        {second && (
          <tr className={rowCls}>
            <th className="hs-subject">
              <span>{locale === "bn" && second.subjectBn ? second.subjectBn : second.subject}</span>
            </th>
            {hsInOut(second.mcq, second.mcqFull, second.mcqPass, pairOk)}
            {hsInOut(second.cq, second.cqFull, second.cqPass, pairOk)}
            {hsInOut(second.applied, second.appliedFull, second.appliedPass, pairOk)}
            <th className="hs-num f-w-700">{fmt2(second.obtained)}</th>
            <th className="hs-num text-muted">{second.highest !== null ? fmt2(second.highest) : "—"}</th>
          </tr>
        )}
      </Fragment>
    );
  }

  /** per-row metrics shared by the sheet and the merit formula.
      The optional (4th) subject row always SHOWS on the sheet —
      "With Optional" applies the (GP − 2) GPA bonus, "Without" shows it
      for information only and leaves totals/GPA to required subjects. */
  function hsMetrics(r: typeof rows[number]) {
    const units = hsUnits(r.subjects, new Set<number>());
    const required = units.filter((u) => !u.optional);
    const optionalUnits = units.filter((u) => u.optional);
    const shown = [...required, ...optionalUnits];
    // totals follow the sheet mode: with-optional counts its marks
    const countable = hsOptional ? shown : required;
    const totalObtained = countable.reduce((a, u) => a + u.obtained, 0);
    const totalFull = countable.reduce((a, u) => a + u.full, 0);
    const graded = shown.filter((u) => u.hasMarks);
    let gpa = 0;
    let optExcess: number | null = null;
    if (graded.length) {
      const pts = required.filter((u) => u.hasMarks).map((u) => u.point);
      const sum = pts.reduce((a, b) => a + b, 0);
      if (hsOptional && optionalUnits.length && optionalUnits[0].hasMarks && pts.length) {
        optExcess = Math.max(0, optionalUnits[0].point - 2);
        gpa = Math.min(5, (sum + optExcess) / pts.length);
      } else {
        gpa = pts.length ? sum / pts.length : 0;
      }
    }
    const failedUnits = countable.filter((u) => u.failed);
    return {
      units,
      shown,
      totalObtained,
      totalFull,
      gpa,
      // a single failed subject fails the sheet — the footer letter grade is F
      gpaGrade: failedUnits.length > 0 ? "F" : gradeFromPercent((gpa / 5) * 100).grade,
      optExcess,
      optPoint:
        optionalUnits.length && optionalUnits[0].hasMarks ? optionalUnits[0].point : null,
      optName: optionalUnits.length ? optionalUnits[0].base : null,
      failedUnits,
      present: r.attendance?.present ?? 0,
    };
  }

  /** merit formula — students passing every subject come first, ranked by
      highest total marks, then highest GPA, then highest attendance; students
      with failures follow, ranked by fewest failed subjects first, then the
      same marks → GPA → attendance chain */
  const hsPosition = new Map<number, number>();
  if (format === "HIGHSCHOOL") {
    rows
      .filter((r) => r.missingSubjects === 0)
      .map((r) => ({ r, m: hsMetrics(r) }))
      .sort((a, b) => {
        const aFail = a.m.failedUnits.length > 0;
        const bFail = b.m.failedUnits.length > 0;
        if (aFail !== bFail) return aFail ? 1 : -1;
        if (aFail && a.m.failedUnits.length !== b.m.failedUnits.length) {
          return a.m.failedUnits.length - b.m.failedUnits.length;
        }
        if (b.m.totalObtained !== a.m.totalObtained) return b.m.totalObtained - a.m.totalObtained;
        if (b.m.gpa !== a.m.gpa) return b.m.gpa - a.m.gpa;
        return b.m.present - a.m.present;
      })
      .forEach((x, i) => hsPosition.set(x.r.studentId, i + 1));
  }

  /** Board Pattern transcript — SSC-style Academic Transcript. Paper pairs
      (English 1st + 2nd, Bangla 1st + 2nd) are already graded internally as
      one unit and rendered as a single "English" / "Bangla" row; the
      additional subject's grade point is capped at 2 per board rule. */
  function boardCalc(r: typeof rows[number]) {
    const units = hsUnits(r.subjects, new Set<number>()).filter((u) => u.hasMarks);
    const required = units.filter((u) => !u.optional);
    const optional = units.filter((u) => u.optional);
    const reqSum = required.reduce((a, u) => a + (u.failed ? 0 : u.point), 0);
    const gpaWithout = required.length ? Math.round((reqSum / required.length) * 100) / 100 : 0;
    let addCapped: number | null = null;
    let gpaWith = gpaWithout;
    if (optional.length && optional[0].hasMarks) {
      addCapped = Math.min(optional[0].failed ? 0 : optional[0].point, 2);
      gpaWith = Math.round(((reqSum + addCapped) / (required.length + 1)) * 100) / 100;
    }
    const anyFailed = units.some((u) => u.failed);
    return { units, required, optional, gpaWithout, gpaWith, addCapped, anyFailed };
  }

  function renderBoardSheet(r: typeof rows[number], examName: string) {
    const bc = boardCalc(r);
    const today = new Intl.DateTimeFormat("en-GB", {
      day: "numeric",
      month: "long",
      year: "numeric",
    }).format(new Date());
    const B = "#7a9bb5";
    const bd = { border: `1px solid #000` };
    const thS = { ...bd, padding: "2px 6px", fontWeight: 400 as const, background: "#e6e6e6", textAlign: "center" as const };
    const tdC = { ...bd, padding: "5px 6px", textAlign: "center" as const };
    const scale: Array<[string, string, string]> = [
      ["A+", "80-100", "5"],
      ["A", "70-79", "4"],
      ["A-", "60-69", "3.5"],
      ["B", "50-59", "3"],
      ["C", "40-49", "2"],
      ["D", "33-39", "1"],
      ["F", "00-32", "0"],
    ];
    const dobStr = r.dob
      ? new Intl.DateTimeFormat("en-GB", { day: "2-digit", month: "2-digit", year: "numeric" }).format(new Date(r.dob))
      : null;
    const info = (k: string, v: React.ReactNode) => (
      <>
        <div style={{ color: "#000" }}>{k}</div>
        <div style={{ fontStyle: "italic", fontWeight: "bold" }}>: {v}</div>
      </>
    );
    let sl = 0;
    return (
      <div className="ems-board" key={r.studentId}>
        <div style={{ width: "100%", background: "#fcfaf5", border: `3px solid ${B}`, padding: 8, boxSizing: "border-box" }}>
          <div style={{ border: `1px solid ${B}`, padding: "20px 26px", position: "relative" }}>
            {/* header */}
            <div style={{ textAlign: "center", marginBottom: 14 }}>
              <div style={{ fontSize: 19, fontWeight: "bold", color: "#000", letterSpacing: 0.5 }}>
                BOARD OF INTERMEDIATE AND SECONDARY EDUCATION, DHAKA
              </div>
              <div style={{ fontSize: 15, fontWeight: "bold", color: "#000", marginTop: 4 }}>BANGLADESH</div>
              <div style={{ fontSize: 15, fontWeight: "bold", color: "#2b579a", marginTop: 7 }}>
                {examName ? `${examName} — ` : ""}
                {num(sessionBaseYear2)}
              </div>
            </div>

            {/* serial / emblem / grade scale */}
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 8 }}>
              <div style={{ fontSize: 13, paddingTop: 22, width: "24%", color: "#000" }}>
                Serial No. {sheet.data?.institution.code ?? "—"}{" "}
                <span style={{ fontWeight: "bold", fontSize: 16, color: "#000" }}>{num(r.roll)}</span>
              </div>
              <div style={{ textAlign: "center", flexGrow: 1, display: "flex", flexDirection: "column", alignItems: "center" }}>
                {sheet.data?.institution.logo ? (
                  <img
                    src={sheet.data.institution.logo}
                    alt=""
                    style={{ width: 62, height: 62, borderRadius: "50%", objectFit: "cover", border: "2px solid #ccc" }}
                  />
                ) : (
                  <div
                    style={{
                      width: 62, height: 62, borderRadius: "50%", background: "#8b0000", border: "2px solid #ccc",
                      display: "flex", alignItems: "center", justifyContent: "center", color: "#fff",
                      fontSize: 10, fontWeight: "bold", textAlign: "center", lineHeight: 1.2,
                      boxShadow: "inset 0 0 5px rgba(0,0,0,0.5)",
                    }}
                  >
                    BISE<br />DHAKA
                  </div>
                )}
                <div style={{ fontSize: 15, color: "#7a7a7a", fontWeight: "bold", marginTop: 10, letterSpacing: 1 }}>
                  ACADEMIC TRANSCRIPT
                </div>
              </div>
              <div style={{ width: "30%", display: "flex", justifyContent: "flex-end" }}>
                <table style={{ borderCollapse: "collapse", fontSize: 10.5, fontFamily: "Arial, sans-serif" }}>
                  <tr>
                    <th style={thS}>Letter Grade</th>
                    <th style={thS}>Class Interval</th>
                    <th style={thS}>Grade Point</th>
                  </tr>
                  {scale.map(([g, range, pt]) => (
                    <tr key={g}>
                      <td style={{ ...tdC, padding: "1px 6px" }}>{g}</td>
                      <td style={{ ...tdC, padding: "1px 6px" }}>{range}</td>
                      <td style={{ ...tdC, padding: "1px 6px" }}>{pt}</td>
                    </tr>
                  ))}
                </table>
              </div>
            </div>

            {/* student information */}
            <div
              style={{
                display: "grid", gridTemplateColumns: "190px 1fr", rowGap: 7,
                fontSize: 13, marginTop: 16, marginLeft: 16, color: "#000",
              }}
            >
              {info("Name of Student", (locale === "bn" && r.nameBn ? r.nameBn : r.name))}
              {info("Father's Name", ((locale === "bn" && r.guardianNameBn) || r.guardianName) ?? "—")}
              {info("Mother's Name", ((locale === "bn" && r.motherNameBn) || r.motherName) ?? "—")}
              {info("Name of Institution", `${sheet.data?.institution.name ?? "—"}${sheet.data?.institution.code ? ` [ ${sheet.data.institution.code} ]` : ""}`)}
              {sheet.data?.institution.address && info("Name of Centre", sheet.data.institution.address)}
              {info("Roll No.", `${num(r.roll)}          Registration No. : ${num(r.roll)}`)}
              {r.groupName && info("Group", r.groupName)}
              {info("Type of Student", "Regular")}
              {dobStr && info("Date of Birth", dobStr)}
            </div>

            {/* subject table */}
            <table style={{ width: "100%", borderCollapse: "collapse", marginTop: 18, fontSize: 13 }}>
              <tr>
                <th style={{ ...bd, padding: 5, width: 44, fontWeight: 400, background: "#f2f2f2" }}>Sl. No.</th>
                <th style={{ ...bd, padding: 5, textAlign: "left", fontWeight: 400, background: "#f2f2f2" }}>Name of Subjects</th>
                <th style={{ ...bd, padding: 5, width: 84, fontWeight: 400, background: "#f2f2f2" }}>Letter Grade</th>
                <th style={{ ...bd, padding: 5, width: 74, fontWeight: 400, background: "#f2f2f2" }}>Grade Point</th>
                <th style={{ ...bd, padding: 4, width: 96, fontWeight: 400, background: "#f2f2f2", fontSize: 11, lineHeight: 1.2 }}>
                  GPA<br /><span style={{ fontSize: 9.5 }}>(Without additional Subject)</span>
                </th>
                <th style={{ ...bd, padding: 5, width: 56, fontWeight: 400, background: "#f2f2f2" }}>GPA</th>
              </tr>
              {bc.required.map((u, idx) => {
                sl += 1;
                return (
                  <tr key={u.base + idx}>
                    <td style={tdC}>{sl}</td>
                    <td style={{ ...bd, padding: "5px 6px" }}>{u.base}</td>
                    <td style={tdC}>{u.failed ? "F" : u.grade}</td>
                    <td style={tdC}>{u.failed ? 0 : u.point}</td>
                    {idx === 0 && (
                      <>
                        <td
                          rowSpan={bc.required.length}
                          style={{ ...bd, padding: 6, textAlign: "center", verticalAlign: "middle", fontSize: 15, fontWeight: "bold" }}
                        >
                          {bc.gpaWithout.toFixed(2)}
                        </td>
                        <td
                          rowSpan={bc.required.length + (bc.optional.length ? 1 : 0)}
                          style={{ ...bd, padding: 6, textAlign: "center", verticalAlign: "middle", fontSize: 15, fontWeight: "bold" }}
                        >
                          {bc.gpaWith.toFixed(2)}
                        </td>
                      </>
                    )}
                  </tr>
                );
              })}
              {bc.optional.length > 0 && (
                <tr>
                  <td colSpan={4} style={{ ...bd, padding: 5, fontWeight: "bold" }}>Additional Subject:</td>
                </tr>
              )}
              {bc.optional.map((u, idx) => {
                sl += 1;
                const capped = Math.min(u.failed ? 0 : u.point, 2);
                return (
                  <tr key={u.base + idx}>
                    <td style={tdC}>{sl}</td>
                    <td style={{ ...bd, padding: "5px 6px" }}>{u.base}</td>
                    <td style={tdC}>{u.failed ? "F" : u.grade}</td>
                    <td style={tdC}>{u.failed ? 0 : u.point}</td>
                    <td style={{ ...bd, padding: 4, textAlign: "center", fontSize: 11.5, lineHeight: 1.3 }}>
                      <span style={{ display: "block", borderBottom: "1px solid #000", paddingBottom: 2, marginBottom: 2 }}>
                        {u.failed ? "Failed" : u.point > 2 ? "GP Above 2" : "GP"}
                      </span>
                      {capped.toFixed(1)}
                    </td>
                    <td style={bd} />
                  </tr>
                );
              })}
            </table>

            {/* footer — publication date + signatures */}
            <div style={{ display: "flex", justifyContent: "space-between", marginTop: 34, fontSize: 13, color: "#000" }}>
              <div style={{ width: "30%" }}>
                <div style={{ marginBottom: 4 }}>Date of Publication of Results</div>
                <div style={{ fontWeight: "bold" }}>{today}.</div>
              </div>
              <div style={{ width: "62%", display: "flex", justifyContent: "space-between", alignItems: "flex-end", paddingBottom: 8 }}>
                <div style={{ textAlign: "center", width: "30%" }}>
                  <div style={{ fontFamily: "'Brush Script MT', cursive", fontSize: 17, marginBottom: 4, transform: "rotate(-5deg)" }}>AnCA</div>
                  <div style={{ borderTop: "1px solid #000", paddingTop: 4, fontSize: 12 }}>Written by</div>
                </div>
                <div style={{ textAlign: "center", width: "30%" }}>
                  <div style={{ fontFamily: "'Brush Script MT', cursive", fontSize: 17, marginBottom: 4, transform: "rotate(-3deg)" }}>SA</div>
                  <div style={{ borderTop: "1px solid #000", paddingTop: 4, fontSize: 12 }}>Compared by</div>
                </div>
                <div style={{ textAlign: "center", width: "34%" }}>
                  <div style={{ fontFamily: "'Brush Script MT', cursive", fontSize: 17, marginBottom: 4, transform: "rotate(-2deg)" }}>Controller</div>
                  <div style={{ borderTop: "1px solid #000", paddingTop: 4, fontSize: 12 }}>Controller of Examinations</div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }

  const hsSheetsBlock = format === "HIGHSCHOOL" ? (
    <div className="d-flex flex-column gap-4">
      {rows.map((r) => {
        const { shown, totalObtained, totalFull, gpa, gpaGrade, failedUnits, optExcess, optPoint, optName } = hsMetrics(r);
        const examName = sheet.data?.exam
          ? locale === "bn" && sheet.data.exam.nameBn
            ? sheet.data.exam.nameBn
            : sheet.data.exam.name
          : "";
        if (hsPattern === "BOARD") {
          return renderBoardSheet(r, examName);
        }
        return (
          <div key={r.studentId} className="ems-hs" style={mksThemeVars}>
            {/* header — same pattern as the primary school marksheet */}
            <div className="ems-mks">
              <div className="ems-mks-header">
                {sheet.data?.institution.logo ? (
                  <img src={sheet.data.institution.logo} className="ems-mks-logo" alt="" />
                ) : (
                  <img
                    src="/assets/images/increlog-logo.png"
                    alt="Increlog"
                    width={52}
                    height={52}
                    draggable={false}
                    style={{ height: 52, width: "auto" }}
                  />
                )}
                <div className="ems-mks-school">
                  <h5>{sheet.data?.institution.name}</h5>
                  {sheet.data?.institution.address && (
                    <p className="addr">{sheet.data.institution.address}</p>
                  )}
                </div>
                {visibleFields.photo &&
                  (r.photoUrl ? (
                    <img src={r.photoUrl} className="ems-mks-photo" alt="" />
                  ) : (
                    <div className="ems-mks-photo">
                      {r.name.split(" ").map((w) => w[0]).slice(0, 2).join("").toUpperCase()}
                    </div>
                  ))}
              </div>

              <p className="ems-mks-title">
                {t.portal.resultsPage.resultSheetTitle} — {num(sessionBaseYear2)}
              </p>

              <div className="ems-mks-body hs-split">
                <div className="ems-final-profile">
                  <div className="ems-mks-info">
                    <div className="ems-mks-name">{locale === "bn" && r.nameBn ? r.nameBn : r.name}</div>
                    {(visibleFields.father || visibleFields.mother) && (
                    <div className="ems-mks-guardian">
                      {visibleFields.father && (
                        <span>
                          <strong>{t.portal.resultsPage.fatherLabel}:</strong>{" "}
                          {((locale === "bn" && r.guardianNameBn) || r.guardianName) ?? "—"}
                        </span>
                      )}
                      {visibleFields.father && visibleFields.mother && <span> &nbsp;·&nbsp; </span>}
                      {visibleFields.mother && (
                        <span>
                          <strong>{t.portal.resultsPage.motherLabel}:</strong>{" "}
                          {((locale === "bn" && r.motherNameBn) || r.motherName) ?? "—"}
                        </span>
                      )}
                    </div>
                    )}
                    <div className="ems-mks-fields">
                      {visibleFields.roll && (
                        <div className="f">
                          <span className="k">{t.portal.admissionsPage.roll}</span>
                          <span className="v">{num(r.roll)}</span>
                        </div>
                      )}
                      {visibleFields.className && (
                        <div className="f">
                          <span className="k">{t.portal.studentsPage.classLabel}</span>
                          <span className="v">{sheet.data?.exam?.className ?? "—"}</span>
                        </div>
                      )}
                      {visibleFields.section && (
                        <div className="f">
                          <span className="k">{t.portal.resultsPage.fieldNames.section}</span>
                          <span className="v">{(locale === "bn" && r.sectionNameBn ? r.sectionNameBn : r.sectionName) ?? "—"}</span>
                        </div>
                      )}
                      {visibleFields.shift && (
                        <div className="f">
                          <span className="k">{t.portal.resultsPage.fieldNames.shift}</span>
                          <span className="v">{(locale === "bn" && r.shiftNameBn ? r.shiftNameBn : r.shiftName) ?? "—"}</span>
                        </div>
                      )}
                      {visibleFields.session && (
                        <div className="f">
                          <span className="k">{t.portal.resultsPage.sessionLabel}</span>
                          <span className="v">{num(sessionLabel(sheet.data, new Date()))}</span>
                        </div>
                      )}
                    </div>
                  </div>
                </div>

                <div className="ems-final-grades">
                  <table>
                    <thead>
                      <tr>
                        <th>{t.portal.resultsPage.gradeCol}</th>
                        <th>{t.portal.resultsPage.gradeMarksCol}</th>
                        <th>{t.portal.resultsPage.gradePointCol}</th>
                      </tr>
                    </thead>
                    <tbody>
                      {PRIMARY_GRADE_SCALE.map((gs) => (
                        <tr key={gs.grade}>
                          <td className="g">{gs.grade}</td>
                          <td className="r">{gradeScaleRange(gs.min, locale)}</td>
                          <td className="r">{num(gs.point.toFixed(1))}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>

                <div className="ems-mks-qr">
                  {qrMap[r.studentId] ? (
                    <>
                      <div className="qr-frame">
                        <img src={qrMap[r.studentId]} alt="verify" />
                      </div>
                      <p className="cap mb-0">{t.portal.resultsPage.scanToVerify}</p>
                    {r.verifyCode && (
                      <p className="cap mb-0" style={{ fontFamily: "Rubik, Consolas, monospace", fontWeight: 600 }}>
                        {r.verifyCode}
                      </p>
                    )}
                    </>
                  ) : (
                    <span className="ems-fs-11 text-muted">QR…</span>
                  )}
                </div>
              </div>
            </div>

            {/* result table */}
            <div className="hs-table-wrapper">
              <table className="hs-table">
                <thead>
                  <tr>
                    <th rowSpan={3} className="hs-subject-head">{t.categories.SUBJECT}</th>
                    <th colSpan={6} className="hs-term">{examName}</th>
                    <th rowSpan={2}>{t.portal.resultsPage.marksCol}</th>
                    <th rowSpan={2}>{t.portal.resultsPage.highestCol}</th>
                    <th rowSpan={2}>{t.portal.resultsPage.gradePointCol}</th>
                    <th rowSpan={2}>{t.portal.resultsPage.letterGradeCol}</th>
                  </tr>
                  <tr>
                    <th colSpan={2}>MCQ</th>
                    <th colSpan={2}>CQ</th>
                    <th colSpan={2}>{t.portal.resultsPage.applied}</th>
                  </tr>
                </thead>
                <tbody>
                  {shown.filter((u) => !u.optional).map((u, i) => hsUnitRow(u, i))}
                  {hsOptional && shown.some((u) => u.optional) && optPoint !== null && optExcess !== null && (
                    <tr className="hs-opt-note-row">
                      <th colSpan={11} className="hs-opt-note">
                        {t.portal.resultsPage.optNote
                          .replace("{subject}", optName ?? "")
                          .replace("{gp}", num(optPoint!.toFixed(2)))
                          .replace("{excess}", num(optExcess!.toFixed(2)))}
                      </th>
                    </tr>
                  )}
                  {/* the optional row always prints — with-optional adds the
                      divider + note + highlight; without prints it as a plain row */}
                  {shown.filter((u) => u.optional).map((u, i) => hsUnitRow(u, 100 + i))}
                </tbody>
                <tfoot>
                  <tr className="hs-total">
                    <th colSpan={7}>{t.portal.resultsPage.total}</th>
                    <th className="hs-num">{fmt2(totalObtained)}</th>
                    <th>—</th>
                    <th className="hs-point">{num(gpa.toFixed(2))}</th>
                    <th>
                      <span className={`grade-badge${gpaGrade === "F" ? " f" : ""}`}>{gpaGrade}</span>
                    </th>
                  </tr>
                  <tr className="hs-meta-row">
                    <th><span className="hs-badge neutral">{t.portal.resultsPage.meritPos}</span></th>
                    <th colSpan={10}>
                      <div className="hs-merit">
                        <span className="hs-merit-pos">
                          {hsPosition.has(r.studentId) ? num(hsPosition.get(r.studentId)!) : "—"}
                        </span>
                        <span className="hs-merit-sep" />
                        <span className="hs-merit-lbl">{t.portal.resultsPage.failed}</span>
                        <span className={`hs-badge ${failedUnits.length ? "fail" : "pass"}`}>
                          {num(failedUnits.length)}
                        </span>
                        {failedUnits.length > 0 && (
                          <span className="hs-merit-subj">
                            ({failedUnits.map((u) => u.base).join(", ")})
                          </span>
                        )}
                      </div>
                    </th>
                  </tr>
                  {visibleFields.attendance && (
                  <>
                  <tr className="hs-meta-row">
                    <th><span className="hs-badge neutral">{t.portal.resultsPage.academicDay}</span></th>
                    <th colSpan={10}><span className="hs-badge neutral">{num(r.attendance?.academicDay ?? 0)}</span></th>
                  </tr>
                  <tr className="hs-meta-row">
                    <th><span className="hs-badge pass">{t.portal.resultsPage.present}</span></th>
                    <th colSpan={10}><span className="hs-badge pass">{num(r.attendance?.present ?? 0)}</span></th>
                  </tr>
                  <tr className="hs-meta-row">
                    <th><span className="hs-badge fail">{t.portal.resultsPage.absent}</span></th>
                    <th colSpan={10}><span className="hs-badge fail">{num(r.attendance?.absent ?? 0)}</span></th>
                  </tr>
                  </>
                  )}
                  {visibleFields.progress && (
                  <tr className="hs-meta-row">
                    <th>{t.portal.resultsPage.progress}</th>
                    <th colSpan={10}>
                      <div className="progress-check">
                        <label className="mb-0"><input type="checkbox" readOnly /> {t.portal.resultsPage.good}</label>
                        <label className="mb-0"><input type="checkbox" readOnly /> {t.portal.resultsPage.needImprovement}</label>
                        <label className="mb-0"><input type="checkbox" readOnly /> {t.portal.resultsPage.bad}</label>
                      </div>
                    </th>
                  </tr>
                  )}
                  <tr className="hs-sign-head">
                    <th rowSpan={3}>{t.portal.resultsPage.authorization}</th>
                    <th colSpan={3}>{t.portal.resultsPage.signTeacher}</th>
                    <th colSpan={3}>{t.portal.resultsPage.signGuardian}</th>
                    <th colSpan={4}>{t.portal.resultsPage.signPrincipal}</th>
                  </tr>
                  <tr>
                    <th colSpan={3} className="hs-sign-line">
                      {teacherSig ? (
                        <img
                          src={teacherSig}
                          alt={overview.data?.teacherName ?? "Teacher"}
                          className="ems-sig-img"
                          draggable={false}
                        />
                      ) : (
                        "_________________"
                      )}
                    </th>
                    <th colSpan={3} className="hs-sign-line">_________________</th>
                    <th colSpan={4} className="hs-sign-line">
                      {principalSig ? (
                        <img
                          src={principalSig}
                          alt={overview.data?.principalName ?? "Principal"}
                          className="ems-sig-img"
                          draggable={false}
                        />
                      ) : (
                        "_________________"
                      )}
                    </th>
                  </tr>
                  <tr>
                    <th colSpan={10} style={{ border: "1px solid var(--hs-line)" }}></th>
                  </tr>
                </tfoot>
              </table>
            </div>

            <div className="ems-sheet-footer">
              <img
                src="/assets/images/increlog-logo.png"
                alt="Increlog"
                width={16}
                height={16}
                draggable={false}
                style={{ height: 16, width: "auto", verticalAlign: -3 }}
              />
              <span>{t.portal.resultsPage.developedBy}</span>
            </div>
          </div>
        );
      })}
    </div>
  ) : null;

  const finalSheetsBlock = combinedMeta ? (
    <div className="d-flex flex-column gap-4">
      {combinedRows.map((r) => (
        <div key={r.studentId} className="ems-final" style={mksThemeVars}>
          {/* Header — institution band on top, then a three-zone split:
              Student Profile | Grading Scale | Verification QR */}
          <div className="ems-mks">
            <div className="ems-mks-header">
              {sheet.data?.institution.logo ? (
                <img src={sheet.data.institution.logo} className="ems-mks-logo" alt="" />
              ) : (
                <img src="/assets/images/increlog-logo.png" alt="Increlog" width="62" height="62" draggable="false" style={{ height: 62, width: "auto" }} />
              )}
              <div className="ems-mks-school">
                <h5>{sheet.data?.institution.name}</h5>
                {sheet.data?.institution.address && (
                  <p className="addr">{sheet.data.institution.address}</p>
                )}
                {sheet.data?.institution.phone && (
                  <p className="contact">{sheet.data.institution.phone}</p>
                )}
              </div>
              {r.photoUrl ? (
                <img src={r.photoUrl} className="ems-mks-photo" alt="" />
              ) : (
                <div className="ems-mks-photo">
                  {r.name.split(" ").map((w) => w[0]).slice(0, 2).join("").toUpperCase()}
                </div>
              )}
            </div>

            {/* Sheet heading — "Result Sheet" with the session base year, above the student name section */}
            <p className="ems-mks-title">
              {t.portal.resultsPage.resultSheetTitle} — {num(sessionBaseYear)}
            </p>

            <div className="ems-mks-body ems-final-split">
              {/* Student profile — name banner, guardian band, field grid */}
              <div className="ems-final-profile">
                <div className="ems-mks-info">
                  <div className="ems-mks-name">
                    {locale === "bn" && r.nameBn ? r.nameBn : r.name}
                  </div>
                  <div className="ems-mks-guardian">
                    <span>
                      <strong>{t.portal.resultsPage.fatherLabel}:</strong>{" "}
                      {((locale === "bn" && r.guardianNameBn) || r.guardianName) ?? "—"}
                    </span>
                    <span> &nbsp;·&nbsp; </span>
                    <span>
                      <strong>{t.portal.resultsPage.motherLabel}:</strong>{" "}
                      {((locale === "bn" && r.motherNameBn) || r.motherName) ?? "—"}
                    </span>
                  </div>
                  <div className="ems-mks-fields">
                    <div className="f">
                      <span className="k">{t.portal.admissionsPage.roll}</span>
                      <span className="v">{num(r.roll)}</span>
                    </div>
                    <div className="f">
                      <span className="k">{t.portal.studentsPage.classLabel}</span>
                      <span className="v">
                        {combinedMeta.classItem
                          ? locale === "bn" && combinedMeta.classItem.nameBn
                            ? combinedMeta.classItem.nameBn
                            : combinedMeta.classItem.name
                          : "—"}
                      </span>
                    </div>
                    <div className="f">
                      <span className="k">{t.portal.resultsPage.fieldNames.section}</span>
                      <span className="v">{(locale === "bn" && r.sectionNameBn ? r.sectionNameBn : r.sectionName) ?? "—"}</span>
                    </div>
                    <div className="f">
                      <span className="k">{t.portal.resultsPage.fieldNames.shift}</span>
                      <span className="v">{(locale === "bn" && r.shiftNameBn ? r.shiftNameBn : r.shiftName) ?? "—"}</span>
                    </div>
                    <div className="f">
                      <span className="k">{t.portal.resultsPage.sessionLabel}</span>
                      <span className="v">{num(cSession || sessionLabel(sheet.data, new Date()))}</span>
                    </div>
                  </div>
                </div>
              </div>

              {/* Grading scale — letter grades per the primary scale, as a compact table */}
              <div className="ems-final-grades">
                <p className="gt">{t.portal.resultsPage.gradeScaleTitle}</p>
                <table>
                  <thead>
                    <tr>
                      <th>{t.portal.resultsPage.gradeCol}</th>
                      <th>{t.portal.resultsPage.gradeMarksCol}</th>
                      <th>{t.portal.resultsPage.gradePointCol}</th>
                    </tr>
                  </thead>
                  <tbody>
                    {PRIMARY_GRADE_SCALE.map((s) => (
                      <tr key={s.grade}>
                        <td className="g">{s.grade}</td>
                        <td className="r">{gradeScaleRange(s.min, locale)}</td>
                        <td className="r">{num(s.point.toFixed(1))}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>

              <div className="ems-mks-qr">
                {qrMap[r.studentId] ? (
                  <>
                    <div className="qr-frame">
                      <img src={qrMap[r.studentId]} alt="verify" />
                    </div>
                    <p className="cap mb-0">{t.portal.resultsPage.scanToVerify}</p>
                    {r.verifyCode && (
                      <p className="cap mb-0" style={{ fontFamily: "Rubik, Consolas, monospace", fontWeight: 600 }}>
                        {r.verifyCode}
                      </p>
                    )}
                  </>
                ) : (
                  <span className="ems-fs-11 text-muted">QR…</span>
                )}
              </div>
            </div>
          </div>

          {/* Journal report table - one unified table per the reference design:
              3-row header (terms + parts + weights), subject + total rows, and a
              tfoot with per-term attendance + merit, progress and signatures. */}
          <div className="journalReportTable">
            <table className="journal-table">
              <thead>
                <tr>
                  <th rowSpan={3} className="subject-cell" style={{ minWidth: 110 }}>
                    {t.categories.SUBJECT}
                  </th>
                  {combinedMeta.sets.map((s, i) => (
                    <th key={i} colSpan={8} className="term g-start">
                      {i === 0 ? t.portal.resultsPage.setFull1 : i === 1 ? t.portal.resultsPage.setFull2 : t.portal.resultsPage.setFull3}
                      {(s.tutorial || s.semester) && (
                        <span className="d-block ems-fs-10 f-w-500 opacity-75">
                          {[s.tutorial, s.semester]
                            .filter(Boolean)
                            .map((e) => (locale === "bn" && e!.nameBn ? e!.nameBn : e!.name))
                            .join(" + ")}
                        </span>
                      )}
                    </th>
                  ))}
                  <th colSpan={9} className="term g-start">{t.portal.resultsPage.finalBlock}</th>
                </tr>
                <tr>
                  {combinedMeta.sets.map((_, i) => (
                    <Fragment key={i}>
                      <th colSpan={2} className="sub2 g-start">{t.portal.resultsPage.tutorialLabel}</th>
                      <th colSpan={2} className="sub2">{t.portal.resultsPage.semesterLabel}</th>
                      <th colSpan={2} className="sub2">{t.portal.resultsPage.marksCol}</th>
                      <th colSpan={2} className="sub2">{t.portal.resultsPage.highestCol}</th>
                    </Fragment>
                  ))}
                  {combinedMeta.weights.map((w, i) => (
                    <th key={`w${i}`} colSpan={2} className={`sub2${i === 0 ? " g-start" : ""}`}>
                      {setShortLabels[i]} {num(w)}%
                    </th>
                  ))}
                  <th colSpan={2} className="sub2">{t.portal.resultsPage.totalMarksCol}</th>
                  <th className="sub2">{t.portal.resultsPage.statusCol}</th>
                </tr>
              </thead>
              <tbody>
                {r.subjects.map((sub) => (
                  <tr key={sub.key}>
                    <td className="subject-cell">{locale === "bn" && sub.subjectBn ? sub.subjectBn : sub.subject}</td>
                    {sub.sets.map((cell, i) => (
                      <Fragment key={i}>
                        <td colSpan={2} className="num-cell g-start">{fmt2(cell.tutorial)}</td>
                        <td colSpan={2} className="num-cell">{fmt2(cell.semester)}</td>
                        <td colSpan={2} className="num-cell f-w-700">{fmt2(cell.marks)}</td>
                        <td colSpan={2} className="num-cell text-muted">{fmt2(cell.highest)}</td>
                      </Fragment>
                    ))}
                    {sub.final.c.map((c, i) => (
                      <td key={`c${i}`} colSpan={2} className={`num-cell f-w-700${i === 0 ? " g-start" : ""}`}>{fmt2(c)}</td>
                    ))}
                    <td colSpan={2} className="num-cell f-w-800">{fmt2(sub.final.total)}</td>
                    <td>
                      {sub.final.passed === null ? (
                        <span className="text-muted">—</span>
                      ) : (
                        <span className={`grade-badge${letterFor(sub.final.total, sub.final.totalFull) === "F" ? " f" : ""}`}>
                          {letterFor(sub.final.total, sub.final.totalFull)}
                        </span>
                      )}
                    </td>
                  </tr>
                ))}
                {/* Total row - per-term tutorial/semester/marks sums + weighted final */}
                <tr className="total-line">
                  <th>{t.portal.resultsPage.total}:</th>
                  {combinedMeta.sets.map((_, i) => (
                    <Fragment key={i}>
                      <td colSpan={2} className="num-cell g-start">
                        {fmt2(r.subjects.reduce((a, s) => a + (s.sets[i].tutorial ?? 0), 0))}
                      </td>
                      <td colSpan={2} className="num-cell">
                        {fmt2(r.subjects.reduce((a, s) => a + (s.sets[i].semester ?? 0), 0))}
                      </td>
                      <td colSpan={2} className="num-cell">{fmt2(r.perSetTotals[i])}</td>
                      <td colSpan={2}>-</td>
                    </Fragment>
                  ))}
                  {combinedMeta.weights.map((w, i) => (
                    <td key={`w${i}`} colSpan={2} className={`num-cell${i === 0 ? " g-start" : ""}`}>
                      {fmt2(r.subjects.reduce((a, s) => a + (s.sets[i].marks !== null ? (s.sets[i].marks * w) / 100 : 0), 0))}
                    </td>
                  ))}
                  <td colSpan={2} className="num-cell f-w-800">{fmt2(r.total)}</td>
                  <td>-</td>
                </tr>
              </tbody>
              <tfoot>
                {/* Attendance per set + Merit (spans the three attendance rows) */}
                <tr className="att-row">
                  <th className="att-label">{t.portal.resultsPage.academicDay}</th>
                  {r.attendance.map((a, i) => (
                    <th key={`d${i}`} colSpan={8}>{num(a.academicDay)}</th>
                  ))}
                  <th rowSpan={3} colSpan={4} className="merit-cell">{t.portal.resultsPage.meritPos}</th>
                  <th rowSpan={3} colSpan={5} className="merit-cell">{r.position === null ? "—" : num(r.position)}</th>
                </tr>
                <tr className="att-row">
                  <th className="att-label">{t.portal.resultsPage.present}</th>
                  {r.attendance.map((a, i) => (
                    <th key={`p${i}`} colSpan={8}>{num(a.present)}</th>
                  ))}
                </tr>
                <tr className="att-row">
                  <th className="att-label">{t.portal.resultsPage.absent}</th>
                  {r.attendance.map((a, i) => (
                    <th key={`a${i}`} colSpan={8}>{num(a.absent)}</th>
                  ))}
                </tr>
                {/* Progress */}
                <tr>
                  <th className="att-label">{t.portal.resultsPage.progress}</th>
                  <td colSpan={33} className="progress-opts">
                    <label className="mb-0"><input type="checkbox" readOnly /> {t.portal.resultsPage.good}</label>
                    <label className="mb-0"><input type="checkbox" readOnly /> {t.portal.resultsPage.needImprovement}</label>
                    <label className="mb-0"><input type="checkbox" readOnly /> {t.portal.resultsPage.bad}</label>
                  </td>
                </tr>
                {/* Authorization + signatures (double-rule separation) */}
                <tr>
                  <th rowSpan={3} className="auth-sep">{t.portal.resultsPage.authorization}</th>
                  <th colSpan={11} className="sig-sep">{t.portal.resultsPage.signTeacher}</th>
                  <th colSpan={11} className="sig-sep">{t.portal.resultsPage.signGuardian}</th>
                  <th colSpan={11} className="sig-sep">{t.portal.resultsPage.signPrincipal}</th>
                </tr>
                <tr>
                  <td colSpan={11} className="sig-space">
                    {teacherSig && (
                      // eslint-disable-next-line @next/next/no-img-element
                      <img
                        src={teacherSig}
                        alt={overview.data?.teacherName ?? "Teacher"}
                        className="ems-sig-img"
                        draggable={false}
                      />
                    )}
                  </td>
                  <td colSpan={11} className="sig-space"></td>
                  <td colSpan={11} className="sig-space">
                    {principalSig && (
                      <img
                        src={principalSig}
                        alt={overview.data?.principalName ?? "Principal"}
                        className="ems-sig-img"
                        draggable={false}
                      />
                    )}
                  </td>
                </tr>
                <tr>
                  <td colSpan={34} style={{ border: "1px solid #8a9ba0" }}></td>
                </tr>
              </tfoot>
            </table>
          </div>

          <div className="ems-sheet-footer">
            <img src="/assets/images/increlog-logo.png" alt="Increlog" width="16" height="16" draggable="false" style={{ height: 16, width: "auto", verticalAlign: -3 }} />
            <span>{t.portal.resultsPage.developedBy}</span>
          </div>
        </div>
      ))}
    </div>
  ) : null;

  /* ---------- Final Result merit rank list (like the periodical report) ----------
     Rendered as an on-screen card AND as the last printed page. */
  const combinedMerit = combinedRows
    .filter((r) => r.position !== null)
    .sort((a, b) => (a.position ?? 0) - (b.position ?? 0));
  const combinedMeritTable = (
    <table className="ems-merit-table">
      <thead>
        <tr>
          <th className="pos-col">{t.portal.resultsPage.meritPos}</th>
          <th>{t.common.name}</th>
          <th className="num-col">{t.portal.resultsPage.total}</th>
          <th className="num-col">{t.portal.resultsPage.failed}</th>
          <th>{t.portal.resultsPage.failedSubjects}</th>
          <th className="num-col">{t.portal.resultsPage.grade}</th>
        </tr>
      </thead>
      <tbody>
        {combinedMerit.map((r) => {
          const failedSubs = r.subjects.filter((s) => s.final.passed === false);
          const g = gradeFromPercent(r.totalFull > 0 ? (r.total / r.totalFull) * 100 : 0);
          return (
            <tr key={r.studentId}>
              <td className="pos">{r.position === null ? "—" : num(r.position)}</td>
              <td className="f-w-700 ems-fs-13">
                <span className="ems-roll-badge me-2">{num(r.roll)}</span>
                {locale === "bn" && r.nameBn ? r.nameBn : r.name}
              </td>
              <td className="num f-w-700">{fmt2(r.total)}/{fmt2(r.totalFull)}</td>
              <td className={`num ${failedSubs.length ? "fail-n" : "pass-n"}`}>
                {failedSubs.length ? num(failedSubs.length) : "—"}
              </td>
              <td className="subj">
                {failedSubs.length
                  ? failedSubs
                      .map((s) => (locale === "bn" && s.subjectBn ? s.subjectBn : s.subject))
                      .join(", ")
                  : "—"}
              </td>
              <td className="num">
                <span className={`badge ${g.grade === "F" ? "badge-danger" : g.point >= 4 ? "badge-success" : "badge-warning"}`}>
                  {g.grade}
                </span>
              </td>
            </tr>
          );
        })}
      </tbody>
    </table>
  );
  const combinedMeritContext = combinedMeta
    ? `${t.portal.resultsPage.formats.COMBINED}${
        combinedMeta.classItem
          ? ` — ${locale === "bn" && combinedMeta.classItem.nameBn ? combinedMeta.classItem.nameBn : combinedMeta.classItem.name}`
          : ""
      }`
    : "";
  const combinedMeritHead = (
    <div className="ems-mks-header ems-merit-head">
      {sheet.data?.institution.logo ? (
        <img src={sheet.data.institution.logo} className="ems-mks-logo" alt="" />
      ) : (
        <img src="/assets/images/increlog-logo.png" alt="Increlog" width="52" height="52" draggable="false" style={{ height: 52, width: "auto" }} />
      )}
      <div className="ems-mks-school">
        <h5>{sheet.data?.institution.name}</h5>
        {sheet.data?.institution.address && (
          <p className="addr">{sheet.data.institution.address}</p>
        )}
        {sheet.data?.institution.phone && (
          <p className="contact">{sheet.data.institution.phone}</p>
        )}
      </div>
      <div className="ems-merit-head-meta">
        <span className="title">{t.portal.resultsPage.meritList}</span>
        <span className="ctx">{combinedMeritContext}</span>
      </div>
    </div>
  );
  const combinedMeritPrintPage = (
    <div className="ems-merit-print" style={mksThemeVars}>
      {combinedMeritHead}
      {combinedMeritTable}
      <div className="ems-sheet-footer">
        <img src="/assets/images/increlog-logo.png" alt="Increlog" width="16" height="16" draggable="false" style={{ height: 16, width: "auto", verticalAlign: -3 }} />
        <span>{t.portal.resultsPage.developedBy}</span>
      </div>
    </div>
  );

  return (
    <div>
      <div className="no-print">
        <PageHeader title={t.portal.resultsPage.title} subtitle={t.portal.resultsPage.subtitle} />
      </div>

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

      {overview.loading ? (
        <PageLoader text={t.common.loading} />
      ) : !operational ? (
        /* ---------------- Setup-only screen (non-PRIMARY types) ---------------- */
        <Card title={t.portal.resultsPage.systemFor} icon={<IconLayers className="svg-20" />}>
          <div className="d-flex flex-wrap align-items-center gap-2 mb-3">
            <span className="f-w-700">{t.portal.resultsPage.currentType}:</span>
            <span className={`ems-type-pill ems-type-${instType}`}>
              {t.types[instType as keyof typeof t.types]}
            </span>
          </div>
          <div className="row g-3">
            {RESULT_SYSTEM_TYPES.map((type) => {
              const live = RESULT_OPERATIONAL_TYPES.includes(type);
              return (
                <div className="col-md-4 col-6" key={type}>
                  <div className={`card h-100 ${live ? "" : "opacity-75"}`}>
                    <div className="card-body d-flex align-items-center gap-3 py-3">
                      <span className={`ems-cat ems-cat-${type}`} style={{ width: 42, height: 42 }}>
                        <IconFile />
                      </span>
                      <div className="min-w-0">
                        <h6 className="mb-1 f-w-700 text-truncate">{t.types[type]}</h6>
                        {live ? (
                          <span className="badge badge-success">{t.portal.resultsPage.operational}</span>
                        ) : (
                          <span className="badge badge-secondary">{t.portal.resultsPage.setupOnly}</span>
                        )}
                      </div>
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
          <div className="mt-3">
            <Alert type="info">{t.portal.resultsPage.setupOnlyNote}</Alert>
          </div>
        </Card>
      ) : (
        <div className="row g-4">
          <div className="col-12">
            <Card
              className="no-print"
              title={t.portal.resultsPage.systemFor}
              icon={<IconLayers className="svg-20" />}
              action={
                <span className="d-inline-flex align-items-center gap-2">
                  <span className="f-w-600 ems-fs-13">{t.portal.resultsPage.currentType}:</span>
                  <span className={`ems-type-pill ems-type-${instType}`}>
                    {t.types[instType as keyof typeof t.types]}
                  </span>
                  <span className="badge badge-success">{t.portal.resultsPage.operationalFor}</span>
                </span>
              }
            >
              {/* -------- Format pills -------- */}
              <div className="d-flex flex-wrap gap-2 mb-3">
                {((instType === "PRIMARY_AND_HIGH_SCHOOL" || instType === "COACHING"
                  ? (["SINGLE", "PERIODICAL", "FINAL", "COMBINED", "HIGHSCHOOL"] as const)
                  : (["SINGLE", "PERIODICAL", "FINAL", "COMBINED"] as const)
                ) as Format[]).map((f) => (
                  <button
                    key={f}
                    type="button"
                    className={`btn btn-sm f-w-700 ${format === f ? "btn-primary" : "btn-outline-secondary"}`}
                    onClick={() => {
                      // switching format is still configuring — don't jump to the
                      // results. Arm the skip only when this switch really starts a
                      // reload (selection persists and the url changes); arming
                      // without a following fetch would linger and swallow the
                      // next selection's scroll.
                      let nextCls = classId;
                      if (f !== "SINGLE" && !classId && examId) {
                        // carry the selected exam's class over so switching to an
                        // aggregate format keeps results on screen (no empty collapse)
                        const cls = overview.data?.exams.find((e) => String(e.id) === examId)?.classItemId;
                        if (cls !== undefined && cls !== null) {
                          nextCls = String(cls);
                          setClassId(nextCls);
                        }
                      }
                      const next = f === "COMBINED" ? combinedQuery : buildSheetUrl(f, examId, nextCls, selectedExamIds);
                      if (next !== null && next !== sheetUrl) skipNextAutoScroll.current = true;
                      setFormat(f);
                      setMessage(null);
                      setCombinedError(null);
                    }}
                  >
                    {t.portal.resultsPage.formats[f]}
                  </button>
                ))}
              </div>
              <p className="ems-fs-12 text-muted mb-2">{t.portal.resultsPage.formatHint[format]}</p>

              {/* formula & logic info badge — explains how THIS format's result is generated */}
              <div className="mb-3">
                <button
                  type="button"
                  className={`ems-formula-badge${formulaOpen ? " open" : ""}`}
                  onClick={() => setFormulaOpen((v) => !v)}
                  aria-expanded={formulaOpen}
                >
                  <IconInfo className="svg-14" />
                  <span className="ms-1">{t.portal.resultsPage.formulaBadge}</span>
                  <span className="fmt">{t.portal.resultsPage.formats[format]}</span>
                </button>
                {formulaOpen && (
                  <div className="ems-formula-box">
                    <p className="gt mb-2">
                      {t.portal.resultsPage.formulaTitle} — {t.portal.resultsPage.formats[format]}
                    </p>
                    <ul className="mb-0">
                      {(format === "SINGLE"
                        ? t.portal.resultsPage.formulaSingle
                        : format === "PERIODICAL"
                          ? t.portal.resultsPage.formulaPeriodical
                          : format === "FINAL"
                            ? t.portal.resultsPage.formulaFinal
                            : format === "COMBINED"
                              ? t.portal.resultsPage.formulaCombined
                              : t.portal.resultsPage.formulaHighSchool
                      ).map((line) => (
                        <li key={line}>{line}</li>
                      ))}
                    </ul>
                  </div>
                )}
              </div>

              {format === "COMBINED" ? (
                /* ---------- Final Result (3 exam sets) query form ---------- */
                <div className="ems-final-query">
                  {combinedError && (
                    <div className="mb-2">
                      <Alert type="error" onClose={() => setCombinedError(null)}>{combinedError}</Alert>
                    </div>
                  )}
                  <div className="row g-2 align-items-end">
                    <div className="col-xl-2 col-md-4 col-6">
                      <Select
                        label={t.portal.studentsPage.classLabel}
                        wrapperClassName="form-group mb-2"
                        value={cClassId}
                        onChange={(e) => {
                          setCClassId(e.target.value);
                          setCSets([{ tut: "", sem: "" }, { tut: "", sem: "" }, { tut: "", sem: "" }]);
                          setCombinedQuery(null);
                        }}
                      >
                        <option value="">{t.portal.resultsPage.selectClass}</option>
                        {(overview.data?.classes ?? []).map((c) => (
                          <option key={c.id} value={c.id}>
                            {locale === "bn" && c.nameBn ? c.nameBn : c.name}
                          </option>
                        ))}
                      </Select>
                    </div>
                    <div className="col-xl-2 col-md-4 col-6">
                      <Select
                        label={t.portal.resultsPage.fieldNames.section}
                        wrapperClassName="form-group mb-2"
                        value={cSectionId}
                        onChange={(e) => setCSectionId(e.target.value)}
                        disabled={!cClassId}
                      >
                        <option value="">{t.common.all}</option>
                        {(overview.data?.sectionItems ?? []).map((s) => (
                          <option key={s.id} value={s.id}>
                            {locale === "bn" && s.nameBn ? s.nameBn : s.name}
                          </option>
                        ))}
                      </Select>
                    </div>
                    <div className="col-xl-2 col-md-4 col-6">
                      <Select
                        label={t.portal.resultsPage.fieldNames.shift}
                        wrapperClassName="form-group mb-2"
                        value={cShiftId}
                        onChange={(e) => setCShiftId(e.target.value)}
                        disabled={!cClassId}
                      >
                        <option value="">{t.common.all}</option>
                        {(overview.data?.shiftItems ?? []).map((s) => (
                          <option key={s.id} value={s.id}>
                            {locale === "bn" && s.nameBn ? s.nameBn : s.name}
                          </option>
                        ))}
                      </Select>
                    </div>
                    <div className="col-xl-3 col-md-4 col-6">
                      <div className="form-group mb-2">
                        <label className="col-form-label pt-0 f-w-600">{t.portal.resultsPage.instituteLabel}</label>
                        <input className="form-control" readOnly value={overview.data?.institution.name ?? ""} />
                      </div>
                    </div>
                    <div className="col-xl-2 col-md-4 col-6">
                      <div className="form-group mb-2">
                        <label className="col-form-label pt-0 f-w-600">{t.portal.resultsPage.sessionLabel}</label>
                        <input
                          className="form-control"
                          value={cSession}
                          onChange={(e) => setCSession(e.target.value)}
                          placeholder={sessionLabel(sheet.data, new Date())}
                        />
                      </div>
                    </div>
                    <div className="col-xl-1 col-md-4 col-6">
                      <div className="form-group mb-2">
                        <label className="col-form-label pt-0 f-w-600">{t.portal.resultsPage.passInPct}</label>
                        <input
                          type="number" min={0} max={100} className="form-control"
                          value={cPass}
                          onChange={(e) => setCPass(e.target.value)}
                        />
                      </div>
                    </div>
                  </div>
                  <div className="row g-2 align-items-end">
                    {[0, 1, 2].map((i) => (
                      <div className="col-xl-3 col-md-6" key={i}>
                        <div className="row g-2">
                          <div className="col-6">
                            <Select
                              label={`${i === 0 ? t.portal.resultsPage.setLabel1 : i === 1 ? t.portal.resultsPage.setLabel2 : t.portal.resultsPage.setLabel3} — ${t.portal.resultsPage.tutorialLabel}`}
                              wrapperClassName="form-group mb-2"
                              value={cSets[i].tut}
                              onChange={(e) => {
                                const next = [...cSets];
                                next[i] = { ...next[i], tut: e.target.value };
                                setCSets(next);
                              }}
                              disabled={!cClassId}
                            >
                              <option value="">{t.portal.resultsPage.examNone}</option>
                              {classExams.map((e) => (
                                <option
                                  key={`t${e.id}`}
                                  value={e.id}
                                  disabled={takenElsewhere(i, "tut").has(String(e.id)) && cSets[i].tut !== String(e.id)}
                                >
                                  {locale === "bn" && e.nameBn ? e.nameBn : e.name}
                                </option>
                              ))}
                            </Select>
                          </div>
                          <div className="col-6">
                            <Select
                              label={`${i === 0 ? t.portal.resultsPage.setLabel1 : i === 1 ? t.portal.resultsPage.setLabel2 : t.portal.resultsPage.setLabel3} — ${t.portal.resultsPage.semesterLabel}`}
                              wrapperClassName="form-group mb-2"
                              value={cSets[i].sem}
                              onChange={(e) => {
                                const next = [...cSets];
                                next[i] = { ...next[i], sem: e.target.value };
                                setCSets(next);
                              }}
                              disabled={!cClassId}
                            >
                              <option value="">{t.portal.resultsPage.examNone}</option>
                              {classExams.map((e) => (
                                <option
                                  key={`s${e.id}`}
                                  value={e.id}
                                  disabled={takenElsewhere(i, "sem").has(String(e.id)) && cSets[i].sem !== String(e.id)}
                                >
                                  {locale === "bn" && e.nameBn ? e.nameBn : e.name}
                                </option>
                              ))}
                            </Select>
                          </div>
                        </div>
                      </div>
                    ))}
                    <div className="col-xl-3 col-md-12">
                      <div className="row g-2 align-items-end">
                        <div className="col-4">
                          <div className="form-group mb-2">
                            <label className="col-form-label pt-0 f-w-600 ems-fs-12">
                              {t.portal.resultsPage.setShort1} {t.portal.resultsPage.ratioLabel}
                            </label>
                            <input
                              type="number" min={0} max={100} className="form-control"
                              value={cWeights[0]}
                              onChange={(e) => setCWeights([e.target.value, cWeights[1], cWeights[2]])}
                            />
                          </div>
                        </div>
                        <div className="col-4">
                          <div className="form-group mb-2">
                            <label className="col-form-label pt-0 f-w-600 ems-fs-12">
                              {t.portal.resultsPage.setShort2} {t.portal.resultsPage.ratioLabel}
                            </label>
                            <input
                              type="number" min={0} max={100} className="form-control"
                              value={cWeights[1]}
                              onChange={(e) => setCWeights([cWeights[0], e.target.value, cWeights[2]])}
                            />
                          </div>
                        </div>
                        <div className="col-4">
                          <div className="form-group mb-2">
                            <label className="col-form-label pt-0 f-w-600 ems-fs-12">
                              {t.portal.resultsPage.setShort3} {t.portal.resultsPage.ratioLabel}
                            </label>
                            <input
                              type="number" min={0} max={100} className="form-control"
                              value={cWeights[2]}
                              onChange={(e) => setCWeights([cWeights[0], cWeights[1], e.target.value])}
                            />
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                  <div className="d-flex flex-wrap align-items-center gap-3">
                    <Button onClick={applyCombined} disabled={!cClassId}>
                      <IconUsers className="svg-16" />
                      <span className="ms-1">{t.portal.resultsPage.studentListBtn}</span>
                    </Button>
                    {(() => {
                      const sum = cWeights.reduce((a, x) => a + (Number(x) || 0), 0);
                      if (sum === 100) return null;
                      return (
                        <span className="ems-fs-12 text-warning f-w-600">
                          {t.portal.resultsPage.weightsSumHint} ({sum}%)
                        </span>
                      );
                    })()}
                  </div>
                </div>
              ) : (
              <div className="row g-3 align-items-center">
                {format === "SINGLE" || format === "HIGHSCHOOL" ? (
                  <>
                    <div className="col-md-5">
                      <Select wrapperClassName="mb-0" value={examId} onChange={(e) => setExamId(e.target.value)}>
                        <option value="">{t.portal.resultsPage.selectExam}</option>
                        {(overview.data?.exams ?? []).map((e) => (
                          <option key={e.id} value={e.id}>
                            {locale === "bn" && e.nameBn ? e.nameBn : e.name}
                            {e.className ? ` — ${locale === "bn" && e.classNameBn ? e.classNameBn : e.className}` : ""}
                          </option>
                        ))}
                      </Select>
                    </div>
                    {format === "HIGHSCHOOL" && (
                      <>
                        <div className="col-md-5">
                          <div className="btn-group w-100">
                            <button
                              type="button"
                              className={`btn btn-sm f-w-700 ${hsPattern === "INCRELOG" ? "btn-primary" : "btn-outline-secondary"}`}
                              onClick={() => setHsPattern("INCRELOG")}
                              title={t.portal.resultsPage.hsIncrelogPatternHint}
                            >
                              {t.portal.resultsPage.hsIncrelogPattern}
                            </button>
                            <button
                              type="button"
                              className={`btn btn-sm f-w-700 ${hsPattern === "BOARD" ? "btn-primary" : "btn-outline-secondary"}`}
                              onClick={() => setHsPattern("BOARD")}
                              title={t.portal.resultsPage.hsBoardPatternHint}
                            >
                              {t.portal.resultsPage.hsBoardPattern}
                            </button>
                          </div>
                        </div>
                        <div className="col-md-5">
                          <div className="btn-group w-100">
                            <button
                              type="button"
                              className={`btn btn-sm f-w-700 ${!hsOptional ? "btn-primary" : "btn-outline-secondary"}`}
                              onClick={() => setHsOptional(false)}
                            >
                              {t.portal.resultsPage.hsWithoutOptional}
                            </button>
                            <button
                              type="button"
                              className={`btn btn-sm f-w-700 ${hsOptional ? "btn-primary" : "btn-outline-secondary"}`}
                              onClick={() => setHsOptional(true)}
                            >
                              {t.portal.resultsPage.hsWithOptional}
                            </button>
                          </div>
                        </div>
                        <div className="col-md-5">
                          <div className="btn-group w-100">
                            <button
                              type="button"
                              className={`btn btn-sm f-w-700 ${hsPassRule === "COMBINED" ? "btn-primary" : "btn-outline-secondary"}`}
                              onClick={() => setHsPassRule("COMBINED")}
                              title={t.portal.resultsPage.hsPassCombinedHint}
                            >
                              {t.portal.resultsPage.hsPassCombined}
                            </button>
                            <button
                              type="button"
                              className={`btn btn-sm f-w-700 ${hsPassRule === "EACH" ? "btn-primary" : "btn-outline-secondary"}`}
                              onClick={() => setHsPassRule("EACH")}
                              title={t.portal.resultsPage.hsPassEachHint}
                            >
                              {t.portal.resultsPage.hsPassEach}
                            </button>
                          </div>
                        </div>
                      </>
                    )}
                  </>
                ) : (
                  <div className="col-md-5">
                    <Select
                      wrapperClassName="mb-0"
                      value={classId}
                      onChange={(e) => {
                        setClassId(e.target.value);
                        setSelectedExamIds([]);
                      }}
                    >
                      <option value="">{t.portal.resultsPage.selectClass}</option>
                      {(overview.data?.classes ?? []).map((c) => (
                        <option key={c.id} value={c.id}>
                          {locale === "bn" && c.nameBn ? c.nameBn : c.name}
                          {format === "PERIODICAL" && !c.hasPeriodical ? " ⚠" : ""}
                        </option>
                      ))}
                    </Select>
                  </div>
                )}

                {format !== "SINGLE" && classId && (
                  <div className="col-12">
                    <p className="ems-fs-12 f-w-700 text-muted mb-2">
                      {t.portal.resultsPage.pickExams}
                      <span className="f-w-500"> ({t.portal.resultsPage.pickExamsHint})</span>
                    </p>
                    <div className="d-flex flex-wrap align-items-center gap-2">
                      {/* grouped dropdown: add exams by group (periodical / final / single) */}
                      <div style={{ maxWidth: 320 }}>
                        <Select
                          wrapperClassName="mb-0"
                          value=""
                          disabled={classExams.length === 0}
                          onChange={(e) => {
                            const id = Number(e.target.value);
                            if (id && !selectedExamIds.includes(id)) {
                              skipNextAutoScroll.current = true; // stay put — still composing the combination
                              setSelectedExamIds((prev) => [...prev, id]);
                            }
                          }}
                        >
                          <option value="">
                            {classExams.length === 0 ? t.portal.resultsPage.noExamsForClass : t.portal.resultsPage.addExam}
                          </option>
                          {(["PERIODICAL", "FINAL", "SINGLE"] as const).map((grp) => {
                            const items = classExams.filter((e) => e.format === grp);
                            if (items.length === 0) return null;
                            return (
                              <optgroup key={grp} label={t.portal.resultsPage.formats[grp]}>
                                {items.map((e) => (
                                  <option key={e.id} value={e.id}>
                                    {locale === "bn" && e.nameBn ? e.nameBn : e.name}
                                    {selectedExamIds.includes(e.id) ? " ✓" : ""}
                                  </option>
                                ))}
                              </optgroup>
                            );
                          })}
                        </Select>
                      </div>
                      {selectedExamIds.length > 0 && (
                        <Button
                          variant="secondary"
                          size="sm"
                          onClick={() => {
                            skipNextAutoScroll.current = true;
                            setSelectedExamIds([]);
                          }}
                        >
                          {t.portal.resultsPage.clearAll}
                        </Button>
                      )}
                    </div>
                    {/* selected exams as removable chips */}
                    {selectedExamIds.length > 0 && (
                      <div className="d-flex flex-wrap gap-2 mt-2">
                        {selectedExamIds.map((id) => {
                          const e = classExams.find((x) => x.id === id);
                          if (!e) return null;
                          return (
                            <span key={id} className="badge badge-primary d-inline-flex align-items-center gap-1 px-3 py-2">
                              {locale === "bn" && e.nameBn ? e.nameBn : e.name}
                              <button
                                type="button"
                                className="btn btn-link p-0 text-white text-decoration-none"
                                style={{ lineHeight: 1 }}
                                onClick={() => toggleExamPick(id)}
                              >
                                ×
                              </button>
                            </span>
                          );
                        })}
                      </div>
                    )}
                  </div>
                )}

                {exam && (format === "SINGLE" || format === "HIGHSCHOOL") && (
                  <div className="col-md-7 d-flex flex-wrap justify-content-md-end gap-2">
                    {exam.resultPublished ? (
                      <Button variant="danger" size="sm" loading={busy} onClick={() => togglePublish(false)}>
                        {t.portal.resultsPage.unpublish}
                      </Button>
                    ) : (
                      <Button size="sm" loading={busy} onClick={() => togglePublish(true)}>
                        {t.portal.resultsPage.publish}
                      </Button>
                    )}
                  </div>
                )}
              </div>
              )}

              {/* Marksheet theme — color presets like the ID card / certificates */}
              <div className="mt-3 pt-3 border-top">
                <p className="ems-fs-12 f-w-700 text-muted mb-2">{t.portal.resultsPage.colorsLabel}</p>                <div className="d-flex flex-wrap align-items-center gap-2 mb-2">
                  {MKS_PRESETS.map((preset, i) => {
                    const active = mksPrimary === preset.primary && mksAccent === preset.accent;
                    return (
                      <button
                        key={i}
                        type="button"
                        className={`btn btn-sm p-0 ${active ? "" : "btn-outline-secondary"}`}
                        style={{
                          width: 34, height: 30, borderRadius: 8,
                          background: `linear-gradient(135deg, ${preset.primary} 55%, ${preset.accent} 55%)`,
                          border: active ? `2px solid ${preset.primary}` : undefined,
                          boxShadow: active ? `0 0 0 3px ${preset.primary}33` : undefined,
                        }}
                        onClick={() => { setMksPrimary(preset.primary); setMksAccent(preset.accent); }}
                        aria-label={`theme-${i}`}
                      >
                        {active && <span style={{ color: "#fff", fontSize: 13, lineHeight: 1 }}>✓</span>}
                      </button>
                    );
                  })}
                  <input
                    type="color"
                    className="form-control form-control-color cursor-pointer"
                    style={{ width: 38, height: 30 }}
                    value={mksPrimary}
                    onChange={(e) => setMksPrimary(e.target.value)}
                    title={t.portal.resultsPage.primaryLabel}
                  />
                  <input
                    type="color"
                    className="form-control form-control-color cursor-pointer"
                    style={{ width: 38, height: 30 }}
                    value={mksAccent}
                    onChange={(e) => setMksAccent(e.target.value)}
                    title={t.portal.resultsPage.accentLabel}
                  />
                </div>

                {format !== "COMBINED" && (
                  <>
                    <p className="ems-fs-12 f-w-700 text-muted mb-2 mt-2">{t.portal.resultsPage.fieldsLabel}</p>
                    <div className="d-flex flex-wrap gap-3">
                      {(Object.keys(visibleFields) as MksFieldKey[]).map((k) => (
                        <label key={k} className="form-check d-flex align-items-center gap-2 ems-fs-13 f-w-600 cursor-pointer">
                          <input
                            className="form-check-input cursor-pointer"
                            type="checkbox"
                            checked={visibleFields[k]}
                            onChange={() => toggleField(k)}
                          />
                          {t.portal.resultsPage.fieldNames[k]}
                        </label>
                      ))}
                    </div>
                  </>
                )}
              </div>

              {/* CQ / MCQ / Applied display toggle */}
              {format !== "COMBINED" && (
                <div className="form-check form-switch d-inline-flex align-items-center gap-2 mt-3">
                  <input
                    className="form-check-input cursor-pointer"
                    type="checkbox"
                    role="switch"
                    id="partsSwitch"
                    checked={showParts}
                    disabled={!hasAnyPart && !sheet.loading && rows.length > 0}
                    onChange={(e) => setShowParts(e.target.checked)}
                  />
                  <label className="form-check-label f-w-600 ems-fs-13 cursor-pointer" htmlFor="partsSwitch">
                    {showParts ? t.portal.resultsPage.showParts : t.portal.resultsPage.partsOff}
                  </label>
                </div>
              )}
            </Card>
          </div>

          {/* full-page loader only on the very first load — afterwards the
              previous sheet stays mounted (dimmed) so the page height never
              collapses and the view never snaps during a refresh */}
          {sheetUrl && sheet.loading && !sheet.data && (
            <div className="col-12" ref={resultsAnchor} style={{ scrollMarginTop: 105 }}>
              <PageLoader text={t.common.loading} />
            </div>
          )}

          {sheetUrl && sheet.data && (
            <>
              {sheet.data && (sheet.data.exam || sheet.data.aggregate) && (
                <div className="col-12" ref={resultsAnchor} style={{ scrollMarginTop: 105 }}>
                  <Card
                    className={`ems-sheet-card${sheet.loading ? " ems-refreshing" : ""}`}
                    title={t.portal.resultsPage.resultSheet}
                    icon={<IconFile className="svg-20" />}
                    action={
                      <Button variant="secondary" size="sm" onClick={handlePrint}>
                        <IconPrinter className="svg-16" />
                        <span className="ms-1">{t.portal.resultsPage.print}</span>
                      </Button>
                    }
                  >
                    {/* build stamp — confirms the page is running the latest code */}
                    <p className='mb-0 ems-fs-10 text-muted no-print text-end' style={{ letterSpacing: 1 }}>
                      EMS build 2026.09.19-R2
                    </p>

                    {/* Sheet caption (screen only — each marksheet carries its own header) */}
                    <div className="mb-3 no-print">
                      {sheet.data.exam ? (
                        <h6 className="f-w-800 mb-1">
                          {locale === "bn" && sheet.data.exam.nameBn ? sheet.data.exam.nameBn : sheet.data.exam.name}
                          {sheet.data.exam.className
                            ? ` — ${locale === "bn" && sheet.data.exam.classNameBn ? sheet.data.exam.classNameBn : sheet.data.exam.className}`
                            : ""}
                          <span className="badge badge-light ms-2">
                            {t.portal.resultsPage.formats[sheet.data.exam.format as Format]}
                          </span>
                        </h6>
                      ) : sheet.data.aggregate ? (
                        <h6 className="f-w-800 mb-1">
                          {t.portal.resultsPage.formats[sheet.data.aggregate]}
                          {sheet.data.classItem
                            ? ` — ${locale === "bn" && sheet.data.classItem.nameBn ? sheet.data.classItem.nameBn : sheet.data.classItem.name}`
                            : ""}
                        </h6>
                      ) : null}
                      {sheet.data.examNames && sheet.data.examNames.length > 0 && (
                        <p className="ems-fs-12 text-muted mb-0">
                          {t.portal.resultsPage.aggregatedFrom} {sheet.data.examNames.length}{" "}
                          {t.portal.resultsPage.examsWord}:{" "}
                          {sheet.data.examNames
                            .map((e, i) => `${i + 1}. ${locale === "bn" && e.nameBn ? e.nameBn : e.name}`)
                            .join(" · ")}
                        </p>
                      )}
                    </div>

                    {rows.length === 0 && combinedRows.length === 0 ? (
                      <EmptyState
                        icon={<IconFile />}
                        title={
                          format === "PERIODICAL"
                            ? t.portal.resultsPage.noPeriodicalForClass
                            : t.portal.resultsPage.noExamsForClass
                        }
                      />
                    ) : isCombined ? (
                      /* Final Result — one landscape sheet per student */
                      finalSheetsBlock
                    ) : format === "HIGHSCHOOL" ? (
                      /* High School — one portrait sheet per student */
                      hsSheetsBlock
                    ) : (
                      /* Student-wise sheets: every student gets a block with all
                         subjects as rows (reference format) */
                      <>
                      {sheetsBlock}

                      </>
                    )}
                  </Card>

                  {/* Print root — portaled to <body> so it escapes the app
                      wrapper entirely: on print #pageWrapper is hidden and ONLY
                      these marksheet cards + the merit page appear in the preview. */}
                  {typeof document !== "undefined" &&
                    createPortal(
                      <div id="emsPrintRoot" className="ems-print-root">
                        {isCombined
                          ? finalSheetsBlock
                          : format === "HIGHSCHOOL"
                            ? hsSheetsBlock
                            : sheetsBlock}
                        {isCombined
                          ? combinedMerit.length > 0 && combinedMeritPrintPage
                          : merit.length > 0 && meritPrintPage}
                      </div>,
                      document.body
                    )}
                </div>
              )}

              {/* Merit list (themed identity header + failure detail) + grade scale */}
              {(isCombined ? combinedRows.length > 0 : rows.length > 0) && (
                <div className="col-12">
                  <Card className="no-print" title={t.portal.resultsPage.meritList} icon={<IconAward className="svg-20" />}>
                    <div style={mksThemeVars}>
                      {isCombined ? combinedMeritHead : meritHeadBlock}
                      <div className="table-responsive">{isCombined ? combinedMeritTable : meritListTable}</div>
                    </div>
                  </Card>
                </div>
              )}

              {(isCombined ? combinedRows.length > 0 : rows.length > 0) && (
                <div className="col-lg-6">
                  <Card className="no-print" title={t.portal.resultsPage.gradeScale} icon={<IconTrend className="svg-20" />}>
                    <div className="d-flex flex-wrap gap-2">
                      {PRIMARY_GRADE_SCALE.map((g, i) => (
                        <span key={g.grade} className={`badge ${g.grade === "F" ? "badge-danger" : "badge-light"} px-3 py-2`}>
                          <b className="me-1">{g.grade}</b>
                          {gradeRangeLabel(i)}
                        </span>
                      ))}
                    </div>
                    <p className="mb-0 ems-fs-11 text-muted mt-2">
                      {PRIMARY_GRADE_SCALE.map((g, i) => `${g.grade} ${gradeRangeLabel(i)}`).join(" · ")}
                    </p>
                  </Card>
                </div>
              )}
            </>
          )}

          {(overview.data?.exams ?? []).length === 0 && (
            <div className="col-12">
              <div className="card">
                <EmptyState icon={<IconFile />} title={t.portal.resultsPage.noExams} />
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}
