// ===========================================================
// BestDig (Part 6): a celebration card for the record with the
// biggest uplift over what the owner paid, plus a one-tap share
// that renders a 1080x1920 story image client-side (canvas).
//
// OWNER-ONLY. This is rendered inside CollectionAppV2, which is
// only ever the signed-in owner's own collection (the public
// collection view is a different component). Purchase cost never
// leaves this view: it is drawn into an image only when the owner
// themselves taps Share. Nothing here runs automatically.
//
// Best dig = the largest positive (est value - purchase price).
// Requires a real purchase price > 0; gifts (is_gift / £0) are
// excluded because a gift is not a dig. If nothing qualifies the
// card does not render at all (no placeholder).
//
// Globals in: React, Sleeve. Exposes window.BestDig.
// ===========================================================
const { useState: useBdState, useMemo: useBdMemo } = React;

function bdGbp(n) { return "£" + Math.round(Number(n) || 0).toLocaleString("en-GB"); }

// The single best dig, or null. Est value only vs the entered price.
function computeBestDig(items) {
  let best = null;
  (items || []).forEach((r) => {
    if (r.is_gift) return;                                   // a gift is not a dig
    const price = (r.purchase_price === null || r.purchase_price === undefined) ? null : Number(r.purchase_price);
    if (!(price > 0)) return;                                // needs a real price paid
    const value = typeof r.value === "number" ? r.value : 0;
    const uplift = value - price;
    if (uplift <= 0) return;                                 // only positive digs
    if (!best || uplift > best.uplift) best = { rec: r, price, value, uplift };
  });
  if (!best) return null;
  return {
    rec: best.rec, title: best.rec.title, artist: best.rec.artist, album: best.rec.album,
    slug: best.rec.slug || null, price: best.price, value: best.value, uplift: best.uplift,
    pct: Math.round((best.uplift / best.price) * 100),
  };
}

// ---- share-image rendering (canvas) ----------------------------------------
// Cover art is only drawn from the SAME-ORIGIN /covers path (canon slugs). A
// non-canon cover is a cross-origin URL that would taint the canvas and make
// toBlob throw, so those fall back to a paper placeholder, the card still
// exports cleanly.
function bdLoadCover(dig) {
  return new Promise((resolve) => {
    if (!dig.slug) { resolve(null); return; }
    const img = new Image();
    img.onload = () => resolve(img);
    img.onerror = () => resolve(null);
    img.src = "/covers/" + dig.slug + ".jpg?v=2";
  });
}

// The equaliser-and-dot brand mark, drawn in code so nothing external is loaded.
function bdDrawMark(ctx, x, y, accent, ink) {
  const bars = [24, 44, 32, 52], bw = 10, gap = 7;
  let bx = x;
  ctx.fillStyle = ink;
  bars.forEach((h) => { ctx.fillRect(bx, y + (52 - h), bw, h); bx += bw + gap; });
  ctx.fillStyle = accent;
  ctx.beginPath(); ctx.arc(bx + 8, y + 46, 8, 0, Math.PI * 2); ctx.fill();
}

// Wrap `text` to <= maxLines lines within maxWidth (ellipsis on the last line).
function bdWrap(ctx, text, maxWidth, maxLines) {
  const words = String(text || "").split(/\s+/).filter(Boolean);
  const lines = [];
  let line = "";
  for (let i = 0; i < words.length; i++) {
    const test = line ? line + " " + words[i] : words[i];
    if (ctx.measureText(test).width > maxWidth && line) {
      lines.push(line); line = words[i];
      if (lines.length === maxLines - 1) break;
    } else { line = test; }
  }
  // remaining words onto the final line, trimmed with ellipsis if needed
  let rest = line;
  const used = lines.join(" ").split(/\s+/).filter(Boolean).length;
  if (used < words.length) rest = words.slice(used).join(" ");
  if (rest) lines.push(rest);
  const capped = lines.slice(0, maxLines);
  if (lines.length > maxLines || (capped.length && ctx.measureText(capped[capped.length - 1]).width > maxWidth)) {
    let last = capped[capped.length - 1] || "";
    while (last && ctx.measureText(last + "…").width > maxWidth) last = last.slice(0, -1);
    capped[capped.length - 1] = last + "…";
  }
  return capped;
}

async function bdRenderStory(dig) {
  const W = 1080, H = 1920;
  const canvas = document.createElement("canvas");
  canvas.width = W; canvas.height = H;
  const ctx = canvas.getContext("2d");

  const PAPER = "#f3ede1", INK = "#17130f", INK2 = "#3a322a", MUTE = "#8a8072", RULE = "#d8d0bd", ACCENT = "#d94e2c";

  // Fonts must be resident before drawing or the canvas falls back to a system
  // face. These are the site's Google fonts (loaded on the page already).
  try {
    await Promise.all([
      document.fonts.load("400 120px 'DM Serif Display'"),
      document.fonts.load("italic 400 120px 'DM Serif Display'"),
      document.fonts.load("600 40px 'JetBrains Mono'"),
      document.fonts.load("900 120px 'Inter'"),
      document.fonts.load("700 40px 'Inter'"),
    ]);
    await document.fonts.ready;
  } catch (e) { /* proceed with whatever is available */ }

  // Background + inset frame
  ctx.fillStyle = PAPER; ctx.fillRect(0, 0, W, H);
  ctx.strokeStyle = RULE; ctx.lineWidth = 2; ctx.strokeRect(44, 44, W - 88, H - 88);

  // Header: mark + wordmark
  bdDrawMark(ctx, 92, 104, ACCENT, INK);
  ctx.textBaseline = "alphabetic";
  ctx.fillStyle = INK; ctx.font = "600 32px 'JetBrains Mono'";
  ctx.fillText("THE LEAD-IN", 190, 150);

  // Eyebrow
  ctx.fillStyle = ACCENT; ctx.font = "600 36px 'JetBrains Mono'";
  ctx.fillText("YOUR BEST DIG", 92, 300);

  // Cover (square), same-origin only
  const cover = await bdLoadCover(dig);
  const cx = 92, cy = 350, cs = W - 184; // 896
  ctx.save();
  ctx.shadowColor = "rgba(0,0,0,0.32)"; ctx.shadowBlur = 70; ctx.shadowOffsetY = 34;
  if (cover) {
    ctx.drawImage(cover, cx, cy, cs, cs);
  } else {
    ctx.fillStyle = "#e0d7c4"; ctx.fillRect(cx, cy, cs, cs);
    ctx.shadowColor = "transparent";
    ctx.fillStyle = MUTE; ctx.font = "italic 400 64px 'DM Serif Display'"; ctx.textAlign = "center";
    ctx.fillText("The Lead-In", cx + cs / 2, cy + cs / 2 + 20);
    ctx.textAlign = "left";
  }
  ctx.restore();

  // Title + artist
  let y = cy + cs + 120;
  ctx.fillStyle = INK; ctx.font = "italic 400 78px 'DM Serif Display'";
  const titleLines = bdWrap(ctx, dig.title, W - 184, 2);
  titleLines.forEach((ln) => { ctx.fillText(ln, 92, y); y += 92; });
  ctx.fillStyle = INK2; ctx.font = "700 40px 'Inter'";
  ctx.fillText(bdWrap(ctx, dig.artist, W - 184, 1)[0] || "", 92, y + 6);
  y += 96;

  // Bought / now worth
  ctx.font = "600 34px 'JetBrains Mono'"; ctx.fillStyle = MUTE;
  ctx.fillText("BOUGHT FOR " + bdGbp(dig.price).toUpperCase() + "   ·   NOW WORTH " + bdGbp(dig.value).toUpperCase(), 92, y);
  y += 110;

  // Big uplift + percent
  ctx.fillStyle = ACCENT; ctx.font = "900 128px 'Inter'";
  const upStr = "+" + bdGbp(dig.uplift);
  ctx.fillText(upStr, 92, y);
  const upW = ctx.measureText(upStr).width;
  ctx.fillStyle = INK2; ctx.font = "700 48px 'Inter'";
  ctx.fillText("+" + dig.pct + "%", 92 + upW + 28, y);

  // Footer
  ctx.fillStyle = MUTE; ctx.font = "600 30px 'JetBrains Mono'";
  ctx.fillText("THELEADIN.COM  ·  TRACK YOUR VINYL", 92, H - 96);

  return canvas;
}

function bdDownload(blob) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url; a.download = "the-lead-in-best-dig.png";
  document.body.appendChild(a); a.click(); a.remove();
  setTimeout(() => URL.revokeObjectURL(url), 4000);
}

function BestDig({ items }) {
  const dig = useBdMemo(() => computeBestDig(items), [items]);
  const [busy, setBusy] = useBdState(false);
  const [note, setNote] = useBdState("");

  if (!dig) return null;

  async function onShare() {
    if (busy) return;
    setBusy(true); setNote("");
    try {
      const canvas = await bdRenderStory(dig);
      const blob = await new Promise((res, rej) =>
        canvas.toBlob((b) => (b ? res(b) : rej(new Error("no blob"))), "image/png"));
      const file = new File([blob], "the-lead-in-best-dig.png", { type: "image/png" });
      const text = "My best dig on The Lead-In: bought for " + bdGbp(dig.price) + ", now worth " + bdGbp(dig.value) + ".";
      // Preferred: hand the image itself to the OS share sheet (same navigator.share
      // plumbing the invite sheet uses, extended to files).
      if (navigator.canShare && navigator.canShare({ files: [file] }) && navigator.share) {
        await navigator.share({ files: [file], text: text });
      } else {
        // Fallback: save the image to the device, then offer the share sheet with
        // text (image file sharing unsupported on this browser).
        bdDownload(blob);
        setNote("Image saved to your device.");
        if (navigator.share) { try { await navigator.share({ text: text, url: "https://www.theleadin.com" }); } catch (e) {} }
      }
    } catch (e) {
      if (!(e && e.name === "AbortError")) setNote("Couldn't create the image just now.");
    } finally { setBusy(false); }
  }

  return (
    <div className="bd-card">
      <div className="bd-eyebrow">Your best dig</div>
      <div className="bd-main">
        <div className="bd-cover">{window.Sleeve && <Sleeve album={dig.album} size={84} />}</div>
        <div className="bd-info">
          <div className="bd-title">{dig.title}</div>
          <div className="bd-artist">{dig.artist}</div>
          <div className="bd-nums">
            <span>Bought for <b>{bdGbp(dig.price)}</b></span>
            <span className="bd-sep">·</span>
            <span>Now worth <b>{bdGbp(dig.value)}</b></span>
          </div>
          <div className="bd-uplift">+{bdGbp(dig.uplift)} <span className="bd-pct">(+{dig.pct}%)</span></div>
        </div>
      </div>
      <div className="bd-actions">
        <button className="bd-share" onClick={onShare} disabled={busy}>
          {busy ? "Preparing…" : "Share this"}
        </button>
        {note && <span className="bd-note">{note}</span>}
      </div>
    </div>
  );
}

Object.assign(window, { BestDig, computeBestDig });
