/* ============================================================
   Certificates — a confirmed delegate/observer enters the full
   name and event ID exactly as printed on their physical BMUN
   card. If a matching `confirmed` record exists AND at least one
   attendance day is marked, we render a certificate that mirrors
   the physical design and let them download it as a PNG.

   Reads window.bmunFetchCertificate (added in index.html) —
   looks up the `confirmed` collection by serialId (e.g.
   BMUN-DEL-007) and cross-checks the full name, so a guessed ID
   alone can't pull up someone else's certificate.

   ---- A note on the export, because it is easy to break ----
   The PNG is produced by html2canvas, which does NOT use the real
   renderer: it walks the DOM and repaints it onto a canvas. Three
   things it cannot do, all of which the certificate used to rely on:
     1. An <image href="assets/…"> inside inline SVG. html2canvas
        serialises inline SVG to a data URL and draws it as an image,
        and a browser will not load external files from inside an
        SVG-as-image. The BMUN emblem vanished for exactly this reason.
        It is now a plain <img> layered over the seal.
     2. CSS custom properties inside SVG (fill="var(--gold)"), which
        do not survive that serialisation and fall back to black.
        Every colour in the seal and flourish is a literal hex value.
     3. clip-path (used by the old ribbon tails) and box-shadow.
   The artwork is also a fixed 900px-wide design rather than clamp()/vw
   sizing, so the downloaded file is identical from any screen size.
   ============================================================ */
const { useState: useStateCt, useEffect: useEffectCt, useRef: useRefCt } = React;

const CERT_ROLES = [
  { id: "delegate", label: "Delegate", prefix: "BMUN-DEL-" },
  { id: "observer", label: "Observer (OBS)", prefix: "BMUN-OBS-" },
];

const CERT_INSTA_HANDLE = "balochistanmun";
const CERT_INSTA_URL = `https://instagram.com/${CERT_INSTA_HANDLE}`;

const CERT_ASSET_PATHS = {
  logo: "assets/bmun-logo-nobg.png",
  fahad: "assets/signature-fahad.png",
  pmu: "assets/partners/pmu.png",
  youth: "assets/partners/youth-affairs.png",
  bboit: "assets/partners/bboit.png",
  afnan: "assets/signature-afnan.png",
};

/* Seal palette — literal values on purpose (see the note above). */
const CERT_GOLD = "#c78f60";
const CERT_PAPER = "#fcfbf7";
const CERT_MEDALLION_CREAM = "#fbf3e7";
const CERT_RULE = "#c08a5a";

/* The scalloped medallion is a union of overlapping circles rather than a
   hand-written path: bump circles sitting on a base circle merge into a
   soft flower edge, and plain <circle>s are the one thing every renderer
   (including html2canvas) reproduces identically. */
const CERT_SEAL = { cx: 58.5, cy: 54, base: 43.5, bump: 10.5, halo: 4.5, count: 14 };
const CERT_SEAL_BUMPS = (() => {
  const out = [];
  for (let i = 0; i < CERT_SEAL.count; i++) {
    const a = (i / CERT_SEAL.count) * Math.PI * 2 - Math.PI / 2;
    out.push({
      x: +(CERT_SEAL.cx + Math.cos(a) * CERT_SEAL.base).toFixed(2),
      y: +(CERT_SEAL.cy + Math.sin(a) * CERT_SEAL.base).toFixed(2),
    });
  }
  return out;
})();

/* Loads the emblem and both signatures once and hands back data URLs, so
   the export never depends on a network round-trip or on how the page is
   being served. Falls back to the plain path if anything goes wrong. */
function useCertAssets() {
  const [assets, setAssets] = useStateCt(CERT_ASSET_PATHS);
  useEffectCt(() => {
    let alive = true;
    const toDataUrl = (url) =>
      fetch(url, { cache: "force-cache" })
        .then((r) => (r.ok ? r.blob() : Promise.reject(new Error(String(r.status)))))
        .then(
          (blob) =>
            new Promise((res, rej) => {
              const fr = new FileReader();
              fr.onload = () => res(fr.result);
              fr.onerror = rej;
              fr.readAsDataURL(blob);
            })
        )
        .catch(() => url);
    const keys = Object.keys(CERT_ASSET_PATHS);
    Promise.all(keys.map((k) => toDataUrl(CERT_ASSET_PATHS[k]))).then((vals) => {
      if (!alive) return;
      const next = {};
      keys.forEach((k, i) => { next[k] = vals[i]; });
      setAssets(next);
    });
    return () => { alive = false; };
  }, []);
  return assets;
}

/* Scales the fixed 900px artwork down to whatever width the card has,
   without touching the artwork itself. */
function CertFit({ children }) {
  const outer = useRefCt(null);
  const inner = useRefCt(null);
  const [height, setHeight] = useStateCt(0);

  useEffectCt(() => {
    const box = outer.current, art = inner.current;
    if (!box || !art) return;
    const fit = () => {
      const scale = Math.min(1, (box.clientWidth || 1064) / 1064);
      art.style.transform = `scale(${scale})`;
      setHeight(Math.round(art.offsetHeight * scale));
    };
    fit();
    let ro;
    if (window.ResizeObserver) { ro = new ResizeObserver(fit); ro.observe(box); }
    else window.addEventListener("resize", fit);
    return () => { if (ro) ro.disconnect(); else window.removeEventListener("resize", fit); };
  }, []);

  return (
    <div className="cert-fit" ref={outer} style={height ? { height } : undefined}>
      <div className="cert-fit-inner" ref={inner}>{children}</div>
    </div>
  );
}

function CertSeal({ logo }) {
  const { cx, cy, base, bump, halo } = CERT_SEAL;
  return (
    <div className="cert-seal">
      <svg width="117" height="157" viewBox="0 0 117 157" aria-hidden="true">
        {/* ribbon tails — rounded via a matching stroke, since clip-path
            does not survive the export */}
        <g fill={CERT_GOLD} stroke={CERT_GOLD} strokeWidth="7" strokeLinejoin="round">
          <polygon points="24,84 55,84 55,151 39.5,138 24,151" transform="rotate(20 58.5 90)" />
          <polygon points="93,84 62,84 62,151 77.5,138 93,151" transform="rotate(-20 58.5 90)" />
        </g>
        {/* paper-coloured halo lifts the medallion off the tails */}
        <g fill={CERT_PAPER}>
          <circle cx={cx} cy={cy} r={base + halo} />
          {CERT_SEAL_BUMPS.map((b, i) => <circle key={`h${i}`} cx={b.x} cy={b.y} r={bump + halo} />)}
        </g>
        <g fill={CERT_GOLD}>
          <circle cx={cx} cy={cy} r={base} />
          {CERT_SEAL_BUMPS.map((b, i) => <circle key={`b${i}`} cx={b.x} cy={b.y} r={bump} />)}
        </g>
        <circle cx={cx} cy={cy} r="30.5" fill={CERT_MEDALLION_CREAM} />
      </svg>
      <img className="cert-seal-logo" src={logo} alt="" aria-hidden="true" />
    </div>
  );
}

function CertFlourish() {
  /* Background image rather than inline SVG: html2canvas silently drops
     inline <svg> that is sized by CSS, but paints background images fine. */
  return <div className="cert-flourish" aria-hidden="true" />;
}

/* ---- The certificate artwork itself. Fixed 900 x 629 design. ---- */
function CertificateArt({ person, assets, domId, exportMode }) {
  const isObs = person.type === "Observer";
  return (
    <div className={`cert ${exportMode ? "cert--export" : ""}`} id={domId}>
      <div className="cert-frame">
        <div className="cert-inner">
          <div className="cert-title">Certificate</div>
          <div className="cert-subtitle">Of Participation Balochistan Model United Nations(BMUN) 2026</div>

          <CertFlourish />

          <div className="cert-presented">This Certificate Is Presented To</div>
          <div className="cert-name">{person.fullName}</div>

          {isObs ? (
            <div className="cert-line cert-line--observer">for participating as an Observer in BMUN 2026</div>
          ) : (
            <>
              <div className="cert-line">as the delegate of</div>
              <div className="cert-highlight">{person.delegation || "—"}</div>
              <div className="cert-line cert-line--second">in committee</div>
              <div className="cert-highlight cert-highlight--lg">{person.committee || "—"}</div>
            </>
          )}

          <div className="cert-footer">
            <div className="cert-sig">
              <div className="cert-sig-mark">
                <img src={assets.fahad} alt="" aria-hidden="true" />
              </div>
              <div className="cert-sig-line" />
              <div className="cert-sig-name">Fahad Farooq</div>
              <div className="cert-sig-role">Senior Vice-President</div>
              <div className="cert-sig-org">BMUN</div>
            </div>

            <CertSeal logo={assets.logo} />

            <div className="cert-sig">
              <div className="cert-sig-mark">
                <img src={assets.afnan} alt="" aria-hidden="true" />
              </div>
              <div className="cert-sig-line" />
              <div className="cert-sig-name">Muhammad Afnan</div>
              <div className="cert-sig-role">President</div>
              <div className="cert-sig-org">BMUN</div>
            </div>
          </div>

          <div className="cert-partners">
            <span className="cert-partners-label">Supported by</span>
            <div className="cert-partners-row">
              <img src={assets.pmu} alt="" aria-hidden="true" />
              <img src={assets.bboit} alt="" aria-hidden="true" />
              <img src={assets.youth} alt="" aria-hidden="true" />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function Certificates() {
  const [fullName, setFullName] = useStateCt("");
  const [role, setRole] = useStateCt("delegate");
  const [idNum, setIdNum] = useStateCt("");
  // status: idle | loading | ready | pending | notfound | error
  const [status, setStatus] = useStateCt("idle");
  const [person, setPerson] = useStateCt(null);
  const [errMsg, setErrMsg] = useStateCt("");
  const [downloading, setDownloading] = useStateCt(false);
  const [dlErr, setDlErr] = useStateCt("");
  const [copied, setCopied] = useStateCt(false);
  const assets = useCertAssets();

  const roleDef = CERT_ROLES.find(r => r.id === role) || CERT_ROLES[0];

  const reset = () => { setStatus("idle"); setPerson(null); setErrMsg(""); setDlErr(""); };

  const cleanDigits = (v) => v.trim().replace(/[^0-9A-Za-z]/g, "");
  const idPreview = roleDef.prefix + (cleanDigits(idNum).padStart(3, "0") || "—");

  const check = async () => {
    const name = fullName.trim();
    const digits = cleanDigits(idNum);
    if (!name) { setStatus("error"); setErrMsg("Enter your full name exactly as it appears on your card."); return; }
    if (!digits) { setStatus("error"); setErrMsg("Enter the ID number from your card."); return; }
    const serialId = roleDef.prefix + digits.padStart(3, "0").toUpperCase();
    setStatus("loading");
    setErrMsg("");
    setPerson(null);
    try {
      let fetcher = window.bmunFetchCertificate;
      if (typeof fetcher !== "function") {
        await new Promise(r => setTimeout(r, 900));
        fetcher = window.bmunFetchCertificate;
      }
      if (typeof fetcher !== "function") throw new Error("Lookup not ready");
      const record = await withTimeout(fetcher(serialId, name), 30000, "Lookup");
      if (!record) { setStatus("notfound"); return; }
      const a = record.attendance || {};
      const attended = !!(a.day1 || a.day2 || a.day3);
      setPerson({ ...record, fullName: name });
      setStatus(attended ? "ready" : "pending");
    } catch (err) {
      console.error("BMUN certificate lookup failed", err);
      setStatus("error");
      setErrMsg(
        /timed out|network|unavailable|offline/i.test(err.message || "")
          ? "The connection timed out. Please check your internet and try again."
          : "We couldn't look up your certificate just now. Please try again in a moment."
      );
    }
  };

  const onKey = (e) => { if (e.key === "Enter") check(); };

  const igMessage = status === "notfound"
    ? `Hi! My data wasn't found on the BMUN certificate portal. My ID is ${idPreview} and my name is ${fullName.trim()}.`
    : `Hi! My attendance isn't marked yet on the BMUN certificate portal. My name is ${fullName.trim()} and my ID is ${idPreview}.`;

  const copyMessage = async () => {
    try {
      if (navigator.clipboard && navigator.clipboard.writeText) {
        await navigator.clipboard.writeText(igMessage);
      } else {
        const ta = document.createElement("textarea");
        ta.value = igMessage;
        ta.style.position = "fixed";
        ta.style.opacity = "0";
        document.body.appendChild(ta);
        ta.focus();
        ta.select();
        document.execCommand("copy");
        document.body.removeChild(ta);
      }
      setCopied(true);
      setTimeout(() => setCopied(false), 1800);
    } catch (err) {
      console.error("BMUN copy failed", err);
    }
  };

  const download = async () => {
    if (!person || downloading) return;
    setDownloading(true);
    setDlErr("");
    try {
      // Always export the off-screen full-size copy, never the scaled preview.
      const el = document.getElementById(`cert-export-${person.serialId}`);
      if (!el) throw new Error("Certificate not ready");
      if (!window.html2canvas) throw new Error("Export library unavailable");

      // Every image must be decoded before html2canvas reads the DOM,
      // otherwise it paints a blank box where the emblem should be.
      await Promise.all(Array.from(el.querySelectorAll("img")).map(img =>
        (img.complete && img.naturalWidth)
          ? Promise.resolve()
          : new Promise(res => {
              img.addEventListener("load", res, { once: true });
              img.addEventListener("error", res, { once: true });
            })
      ));
      if (document.fonts && document.fonts.ready) {
        try { await document.fonts.ready; } catch (e) { /* non-fatal */ }
      }

      const canvas = await window.html2canvas(el, {
        scale: 2.5,
        backgroundColor: "#fcfbf7",
        useCORS: true,
        imageTimeout: 20000,
        logging: false,
      });

      const filename = `BMUN-2026-Certificate-${person.serialId}.png`;
      const blob = await new Promise(res => {
        if (canvas.toBlob) canvas.toBlob(res, "image/png"); else res(null);
      });
      const href = blob ? URL.createObjectURL(blob) : canvas.toDataURL("image/png");
      const link = document.createElement("a");
      link.download = filename;
      link.href = href;
      document.body.appendChild(link);
      link.click();
      link.remove();
      if (blob) setTimeout(() => URL.revokeObjectURL(href), 5000);
    } catch (err) {
      console.error("BMUN certificate download failed", err);
      setDlErr("We couldn't build the image just now. Please refresh the page and try again — or take a screenshot of the certificate above.");
    } finally {
      setDownloading(false);
    }
  };

  const igBlock = (
    <div className="ig-msg">
      <p>{igMessage}</p>
      <div className="ig-msg-actions">
        <button className="btn btn-ghost btn-sm" onClick={copyMessage} type="button">{copied ? "Copied!" : "Copy message"}</button>
        <a className="btn btn-gold btn-sm" href={CERT_INSTA_URL} target="_blank" rel="noopener noreferrer">
          <Icon name="instagram" size={15} /> Open Instagram
        </a>
      </div>
    </div>
  );

  return (
    <section className="section cert-portal" id="certificates">
      <div className="wrap">
        <Reveal>
          <SectionHead center
            eyebrow="Certificates"
            title="Get your certificate of participation."
            sub="Enter your full name exactly as it appears on your BMUN card, choose Delegate or Observer, and enter your ID number. Once your attendance for at least one day is marked, your certificate appears here — ready to download."
          />
        </Reveal>
        <Reveal>
          <div className="pay-card cert-card">
            <div className="field">
              <label>Full name (as on your card) <span className="req">*</span></label>
              <input
                className={`input ${status === "error" && !fullName.trim() ? "err" : ""}`}
                placeholder="Full name, as printed on your card"
                value={fullName}
                onChange={e => { setFullName(e.target.value); if (status !== "idle" && status !== "loading") reset(); }}
                onKeyDown={onKey}
                autoComplete="off"
              />
            </div>

            <div className="field">
              <label>I am a <span className="req">*</span></label>
              <div className="seg">
                {CERT_ROLES.map(r => (
                  <button key={r.id} type="button" className={role === r.id ? "on" : ""}
                    onClick={() => { setRole(r.id); if (status !== "idle" && status !== "loading") reset(); }}>
                    {r.label}
                  </button>
                ))}
              </div>
            </div>

            <div className="field" style={{ marginBottom: 0 }}>
              <label>Your ID number <span className="req">*</span></label>
              <div className={`id-input-group ${status === "error" && !idNum.trim() ? "err" : ""}`}>
                <span className="id-prefix">{roleDef.prefix}</span>
                <input
                  className="id-input"
                  placeholder="007"
                  value={idNum}
                  onChange={e => { setIdNum(e.target.value.replace(/[^0-9A-Za-z]/g, "")); if (status !== "idle" && status !== "loading") reset(); }}
                  onKeyDown={onKey}
                  autoComplete="off"
                  spellCheck="false"
                />
              </div>
              <p className="pay-note" style={{ marginTop: 6 }}>
                Just the number from your card — e.g. enter <b>7</b> for {roleDef.prefix}007.
              </p>
            </div>

            <div className="cert-actions-row">
              <button className="btn btn-primary" onClick={check} disabled={status === "loading"}>
                {status === "loading" ? "Checking…" : <>Find my certificate <Icon name="arrowRight" size={18} /></>}
              </button>
            </div>

            {status === "error" && errMsg && <div className="err-msg" style={{ marginTop: 12 }}>{errMsg}</div>}

            {status === "notfound" && (
              <div className="pay-state pay-state--warn" style={{ marginTop: 22 }}>
                <span className="pay-state-ic"><Icon name="plus" size={26} stroke={2.2} style={{ transform: "rotate(45deg)" }} /></span>
                <div>
                  <h4>We couldn&rsquo;t find that</h4>
                  <p>
                    Double-check your name spelling and ID number. If they&rsquo;re correct and this still
                    doesn&rsquo;t work, message us on Instagram <a href={CERT_INSTA_URL} target="_blank" rel="noopener noreferrer">@{CERT_INSTA_HANDLE}</a> with the message below.
                  </p>
                  {igBlock}
                </div>
              </div>
            )}

            {status === "pending" && person && (
              <div className="pay-state pay-state--pending" style={{ marginTop: 22 }}>
                <span className="pay-state-ic"><Icon name="clock" size={26} /></span>
                <div>
                  <h4>Hi {person.fullName.split(" ")[0]} — your attendance isn&rsquo;t marked yet</h4>
                  <p>
                    We found your record, but no attendance day is marked yet, so your certificate isn&rsquo;t
                    ready. Message us on Instagram <a href={CERT_INSTA_URL} target="_blank" rel="noopener noreferrer">@{CERT_INSTA_HANDLE}</a> with the message below and we&rsquo;ll sort it out.
                  </p>
                  {igBlock}
                </div>
              </div>
            )}

            {status === "ready" && person && (
              <div className="cert-result">
                <div className="pay-verified-banner">
                  <span className="pay-state-ic ok"><Icon name="check" size={24} stroke={2.4} /></span>
                  <div>
                    <h4>Your certificate is ready, {person.fullName.split(" ")[0]}</h4>
                    <p>Here it is — download it as an image below.</p>
                  </div>
                </div>

                <CertFit>
                  <CertificateArt person={person} assets={assets} domId={`cert-view-${person.serialId}`} />
                </CertFit>

                {/* Full-size copy: this is the one that becomes the PNG. */}
                <div className="cert-offscreen" aria-hidden="true">
                  <CertificateArt person={person} assets={assets} domId={`cert-export-${person.serialId}`} exportMode />
                </div>

                <div className="cert-actions-row">
                  <button className="btn btn-primary" onClick={download} disabled={downloading}>
                    {downloading ? "Preparing…" : <>Download certificate <Icon name="download" size={17} /></>}
                  </button>
                  <button className="btn btn-ghost" onClick={() => { setFullName(""); setIdNum(""); reset(); }}>Check another</button>
                </div>

                {dlErr && <div className="err-msg" style={{ marginTop: 12 }}>{dlErr}</div>}
              </div>
            )}
          </div>
        </Reveal>
      </div>
    </section>
  );
}

window.Certificates = Certificates;
