"use client";

import { useEffect, useRef, useState } from "react";
import { useLang } from "@/context/LanguageContext";
import { formatDate } from "@/lib/utils";
import { IconCheckCircle, IconClock, IconSearch, IconShield, IconX } from "@/components/icons";
import { Html5Qrcode } from "html5-qrcode";

/* Verification hub content — shared by the public /verify page and the
   in-portal Verify pages (institution admin, central, and the member
   portal for students/teachers/parents/staff). Hosts provide the frame:
   - Type the printed code (EMS-XXXX-XXXX) into the search bar, or
   - scan the QR with the built-in camera scanner,
   and see WHAT was verified: document kind, institution, and for exam
   results the student's identity (name, guardians, roll, class) with the
   issued total and grade. */

interface CodeVerifyResponse {
  valid: boolean;
  kind?: "RESULT" | "EXAM_SCHEDULE" | "INVENTORY" | "ADMIT_CARD";
  code?: string;
  institution?: { name: string };
  label?: string | null;
  issuedAt?: string;
  student?: {
    roll: string;
    name: string;
    nameBn: string | null;
    guardianName: string;
    guardianNameBn: string | null;
    guardianPhone: string;
    className: string | null;
    classNameBn: string | null;
  };
  marks?: { total: string | null; grade: string | null };
  schedule?: {
    name: string;
    nameBn: string | null;
    className: string | null;
    classNameBn: string | null;
    subjects: number;
    from: string | null;
    to: string | null;
  } | null;
  admit?: {
    name: string;
    nameBn: string | null;
    from: string | null;
    to: string | null;
  } | null;
}

const SCANNER_REGION_ID = "ems-verify-scanner-region";

export default function VerifyPanel({ prefill = "" }: { prefill?: string }) {
  const { t, locale } = useLang();
  const v = t.verifyPage;

  const [code, setCode] = useState(prefill);
  const [result, setResult] = useState<CodeVerifyResponse | null>(null);
  const [loading, setLoading] = useState(false);
  const [checked, setChecked] = useState(false);

  // scanner tab
  const [tab, setTab] = useState<"enter" | "scan">("enter");
  const [scanning, setScanning] = useState(false);
  const [cameraError, setCameraError] = useState("");
  const scannerRef = useRef<Html5Qrcode | null>(null);
  // html5-qrcode's stop() throws SYNCHRONOUSLY when the scanner never
  // started (camera denied/unavailable) — only stop() after start() resolved
  const startedRef = useRef(false);

  async function runVerify(value?: string) {
    const target = (value ?? code).trim();
    if (!target) return;
    setLoading(true);
    setChecked(false);
    try {
      const res = await fetch(`/api/public/verify-code?code=${encodeURIComponent(target)}`);
      setResult(await res.json());
      setChecked(true);
    } catch {
      setResult({ valid: false });
      setChecked(true);
    } finally {
      setLoading(false);
    }
  }

  // prefill from the host (?code=) runs once on mount
  useEffect(() => {
    if (prefill) runVerify(prefill);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  /** every scanner call goes through here — the library throws plain
      strings synchronously in several not-started/not-scanning paths, so
      BOTH the sync try/catch and the async .catch are required */
  async function teardownScanner() {
    const s = scannerRef.current;
    scannerRef.current = null;
    if (!s) return;
    try {
      if (startedRef.current) {
        await s.stop();
        try {
          await s.clear();
        } catch {
          /* element already detached */
        }
      } else {
        try {
          await s.clear();
        } catch {
          /* never started — nothing to clear */
        }
      }
    } catch {
      /* scanner already stopped */
    }
  }

  function stopScanner() {
    setScanning(false);
    void teardownScanner();
  }

  // camera lifecycle
  useEffect(() => {
    if (tab !== "scan" || !scanning) return;
    let disposed = false;
    startedRef.current = false;

    // reset any leftovers from a failed attempt before re-creating
    const region = document.getElementById(SCANNER_REGION_ID);
    if (region) region.innerHTML = "";

    let scanner: Html5Qrcode;
    try {
      scanner = new Html5Qrcode(SCANNER_REGION_ID, { verbose: false });
    } catch (err) {
      setCameraError(String(err instanceof Error ? err.message : err));
      setScanning(false);
      return;
    }
    scannerRef.current = scanner;

    scanner
      .start(
        { facingMode: "environment" },
        { fps: 10, qrbox: { width: 220, height: 220 } },
        (decoded) => {
          setCode(decoded);
          setTab("enter");
          stopScanner();
          runVerify(decoded);
        },
        () => {
          /* per-frame decode misses — ignore */
        },
      )
      .then(() => {
        startedRef.current = true;
      })
      .catch((err) => {
        if (disposed) return;
        setCameraError(String(err instanceof Error ? err.message : err));
        setScanning(false);
        void teardownScanner();
      });

    return () => {
      disposed = true;
      void teardownScanner();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [tab, scanning]);

  function switchTab(next: "enter" | "scan") {
    if (scanning) stopScanner();
    setCameraError("");
    setTab(next);
  }

  function retryCamera() {
    setCameraError("");
    setScanning(true);
  }

  const kindLabel = (kind?: string) =>
    kind === "RESULT"
      ? v.kindResult
      : kind === "EXAM_SCHEDULE"
        ? v.kindSchedule
        : kind === "ADMIT_CARD"
          ? v.kindAdmitCard
          : v.kindInventory;

  const name = (en: string | null | undefined, bn: string | null | undefined) =>
    locale === "bn" && bn ? bn : en ?? "—";

  return (
    <div>
      {/* tabs */}
      <ul className="nav nav-tabs mb-4" role="tablist">
        <li className="nav-item flex-fill text-center" role="presentation">
          <button
            type="button"
            className={`nav-link w-100 ${tab === "enter" ? "active" : ""}`}
            onClick={() => switchTab("enter")}
          >
            <IconSearch className="svg-14" /> {v.tabEnter}
          </button>
        </li>
        <li className="nav-item flex-fill text-center" role="presentation">
          <button
            type="button"
            className={`nav-link w-100 ${tab === "scan" ? "active" : ""}`}
            onClick={() => switchTab("scan")}
          >
            <IconShield className="svg-14" /> {v.tabScan}
          </button>
        </li>
      </ul>

      {tab === "enter" ? (
        <form
          className="mb-2"
          onSubmit={(e) => {
            e.preventDefault();
            runVerify();
          }}
        >
          <div className="input-group input-group-lg">
            <span className="input-group-text"><IconSearch className="svg-18" /></span>
            <input
              className="form-control text-uppercase"
              style={{ fontFamily: "Rubik, Consolas, monospace", letterSpacing: 1.5, fontWeight: 600 }}
              placeholder={v.placeholder}
              value={code}
              onChange={(e) => setCode(e.target.value.toUpperCase())}
              autoFocus
            />
            <button className="btn btn-primary" type="submit" disabled={loading || !code.trim()}>
              {loading && <span className="spinner-border spinner-border-sm me-1" />}
              {v.verifyButton}
            </button>
          </div>
          <p className="ems-fs-11 text-muted mt-2 mb-0 text-center">{v.hint}</p>
        </form>
      ) : (
        <div className="mb-2">
          {!scanning && !cameraError && (
            <button type="button" className="btn btn-primary w-100" onClick={() => setScanning(true)}>
              {v.startCamera}
            </button>
          )}
          <div
            id={SCANNER_REGION_ID}
            style={{ display: scanning ? "block" : "none", minHeight: 240 }}
            className="rounded overflow-hidden"
          />
          {scanning && (
            <button type="button" className="btn btn-outline-secondary w-100 mt-2" onClick={stopScanner}>
              {v.stopCamera}
            </button>
          )}
          {cameraError && (
            <div className="alert alert-warning ems-fs-12 mb-0 mt-2">
              {v.cameraError}{" "}
              <button type="button" className="btn btn-link p-0 ems-fs-12 ems-text-teal f-w-700" onClick={retryCamera}>
                {v.retryCamera}
              </button>
              {" · "}
              <button type="button" className="btn btn-link p-0 ems-fs-12 ems-text-teal f-w-700" onClick={() => switchTab("enter")}>
                {v.typeInstead}
              </button>
            </div>
          )}
        </div>
      )}

      {/* ── result ─────────────────────────────────────────── */}
      {checked && result && (
        <div className="mt-4">
          {result.valid ? (
            <div>
              <div className="text-center mb-3">
                <div
                  className="rounded-circle d-inline-flex align-items-center justify-content-center mb-2"
                  style={{ width: 64, height: 64, background: "rgba(40,167,69,0.12)", color: "#1e7e34" }}
                >
                  <span className="d-inline-flex" style={{ transform: "scale(2)" }}><IconCheckCircle /></span>
                </div>
                <h5 className="f-w-800 text-success mb-1">{v.validTitle}</h5>
                <p className="mb-0">
                  <span className="badge badge-soft-teal f-w-700">{kindLabel(result.kind)}</span>{" "}
                  <code className="ems-invoice-badge" style={{ fontFamily: "Rubik, Consolas, monospace" }}>
                    {result.code}
                  </code>
                </p>
              </div>

              <div className="text-start p-3 rounded" style={{ background: "rgba(36,105,92,0.06)", fontSize: 13 }}>
                <p className="mb-1">
                  <b>{v.institution}:</b> {result.institution?.name}
                </p>
                {result.label && (
                  <p className="mb-1">
                    <b>{v.exam}:</b> {result.label}
                  </p>
                )}
                <p className="mb-1">
                  <b>{v.issuedOn}:</b> {result.issuedAt ? formatDate(result.issuedAt, locale) : "—"}
                </p>

                {result.student && (
                  <>
                    <hr className="my-2" style={{ borderColor: "rgba(36,105,92,0.15)" }} />
                    <p className="mb-1">
                      <b>{v.student}:</b> {name(result.student.name, result.student.nameBn)}{" "}
                      <span className="text-muted">({v.roll} {result.student.roll})</span>
                    </p>
                    {result.student.className && (
                      <p className="mb-1">
                        <b>{v.classLabel}:</b> {name(result.student.className, result.student.classNameBn)}
                      </p>
                    )}
                    <p className="mb-1">
                      <b>{v.guardian}:</b> {name(result.student.guardianName, result.student.guardianNameBn)}
                    </p>
                    <p className="mb-1">
                      <b>{v.guardianPhone}:</b> {result.student.guardianPhone}
                    </p>
                    {(result.marks?.total || result.marks?.grade) && (
                      <p className="mb-1">
                        <b>{v.marks}:</b> {result.marks?.total ?? "—"}
                        {result.marks?.grade ? ` · ${v.grade}: ${result.marks.grade}` : ""}
                      </p>
                    )}
                  </>
                )}

                {result.schedule && (
                  <>
                    <hr className="my-2" style={{ borderColor: "rgba(36,105,92,0.15)" }} />
                    <p className="mb-1">
                      <b>{v.subjects}:</b> {result.schedule.subjects}
                    </p>
                    {result.schedule.className && (
                      <p className="mb-1">
                        <b>{v.classLabel}:</b> {name(result.schedule.className, result.schedule.classNameBn)}
                      </p>
                    )}
                    {result.schedule.from && (
                      <p className="mb-1">
                        <b>{v.window}:</b> {formatDate(result.schedule.from, locale)}
                        {result.schedule.to ? ` → ${formatDate(result.schedule.to, locale)}` : ""}
                      </p>
                    )}
                  </>
                )}

                {result.admit && (
                  <>
                    <hr className="my-2" style={{ borderColor: "rgba(36,105,92,0.15)" }} />
                    {result.admit.from && (
                      <p className="mb-1">
                        <b>{v.examDates}:</b> {formatDate(result.admit.from, locale)}
                        {result.admit.to ? ` — ${formatDate(result.admit.to, locale)}` : ""}
                      </p>
                    )}
                  </>
                )}
              </div>
            </div>
          ) : (
            <div className="text-center">
              <div
                className="rounded-circle d-inline-flex align-items-center justify-content-center mb-2"
                style={{ width: 64, height: 64, background: "rgba(220,53,69,0.12)", color: "#dc3545" }}
              >
                <span className="d-inline-flex" style={{ transform: "scale(2)" }}><IconX /></span>
              </div>
              <h5 className="f-w-800 text-danger mb-1">{v.invalidTitle}</h5>
              <p className="text-muted ems-fs-13 mb-0">
                <IconClock className="svg-12" /> {v.invalidNote}
              </p>
            </div>
          )}
        </div>
      )}
    </div>
  );
}
