// ============ IMPORT FROM WEB — WishTrak ============
// 3-step flow: input → scanning → review
// Calls /api/scrape-url for each URL, then lets the owner
// review/edit before committing items to the wish list.

const { useState: useStateI, useEffect: useEffectI, useRef: useRefI } = React;

// ── Retailer registry ─────────────────────────────────────────
const RETAILERS = [
  {
    id:    "riverstore",
    mono:  "RS",
    name:  "Riverstore",
    color: "#ffd84d",
    desc:  "amazon.com · co.uk · ca",
    glyph: "◈",
    match: /amazon\./i,
    example: "https://www.amazon.com/dp/B08N5WRWNW",
  },
  {
    id:    "bidbay",
    mono:  "BB",
    name:  "BidBay",
    color: "#7af09a",
    desc:  "ebay.com · mercari.com",
    glyph: "⊕",
    match: /ebay\.|mercari\./i,
    example: "https://www.ebay.com/itm/123456789",
  },
  {
    id:    "martco",
    mono:  "MC",
    name:  "MartCo",
    color: "#5fd3e0",
    desc:  "walmart.com · target.com · costco.com",
    glyph: "◎",
    match: /walmart\.|target\.|costco\./i,
    example: "https://www.walmart.com/ip/123456",
  },
  {
    id:    "orbtech",
    mono:  "OT",
    name:  "OrbTech",
    color: "#a78bfa",
    desc:  "bestbuy.com · newegg.com",
    glyph: "◉",
    match: /bestbuy\.|newegg\./i,
    example: "https://www.bestbuy.com/site/product/123.p",
  },
  {
    id:    "loommade",
    mono:  "LM",
    name:  "LoomMade",
    color: "#ff8aa8",
    desc:  "etsy.com · reverb.com",
    glyph: "⊞",
    match: /etsy\.|reverb\./i,
    example: "https://www.etsy.com/listing/123456/item-name",
  },
];

function retailerForUrl(url) {
  try {
    const host = new URL(url).hostname;
    return RETAILERS.find(r => r.match.test(host)) || null;
  } catch (_) { return null; }
}

// Generate a placeholder SVG in the retailer's colour
function makeProductSvg(title, retailer) {
  const r = retailer || { mono: "?", color: "#4a5a78", glyph: "◇" };
  const label = (title || "Product").slice(0, 22);
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="400" height="220" viewBox="0 0 400 220">
  <rect width="400" height="220" fill="#0d1f3c"/>
  <rect x="10" y="10" width="380" height="200" rx="4" fill="none" stroke="${r.color}" stroke-width="1.5" stroke-dasharray="6,4" opacity=".5"/>
  <text x="200" y="95" font-family="VT323,monospace" font-size="52" fill="${r.color}" text-anchor="middle" opacity=".85">${r.glyph || r.mono}</text>
  <text x="200" y="130" font-family="VT323,monospace" font-size="14" fill="${r.color}" text-anchor="middle" letter-spacing="4" opacity=".7">${r.name.toUpperCase()}</text>
  <text x="200" y="158" font-family="VT323,monospace" font-size="13" fill="#8899cc" text-anchor="middle">${label}</text>
</svg>`;
  return "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svg)));
}

// Parse URL textarea (newline / space / comma separated)
function parseUrls(raw) {
  return raw
    .split(/[\n,]+/)
    .map(s => s.trim())
    .filter(s => /^https?:\/\/.+/.test(s));
}

// ── scrapeOne: calls /api/scrape-url ─────────────────────────
async function scrapeOne(url) {
  const res = await fetch("/api/scrape-url", {
    method:  "POST",
    headers: { "Content-Type": "application/json" },
    body:    JSON.stringify({ url }),
  });
  const data = await res.json().catch(() => ({ ok: false, error: "Bad response" }));
  return data;
}

// Convert a scrape result to a wish item draft
function draftToWish(draft) {
  const ret = RETAILERS.find(r => r.id === draft.retailer);
  // Use the real product photo if the server fetched it; fall back to SVG placeholder
  const cover = draft.imageDataUrl || makeProductSvg(draft.title, ret);
  return {
    id:         "w_" + Date.now().toString(36) + Math.random().toString(36).slice(2, 5),
    category:   "product",
    title:      draft.title || "Untitled",
    desc:       draft.description || "",
    notes:      "",
    cover,
    target:     draft.price ? Math.ceil(draft.price) : 0,
    saved:      0,
    hours:      0,
    targetHours:0,
    pct:        0,
    checklist:  [],
    completed:  false,
    completedAt:null,
    createdAt:  Date.now(),
    sourceUrl:  draft.sourceUrl || "",
    donors:     [],
  };
}

// ── Step 1: URL Input ─────────────────────────────────────────
function ImportInput({ onScan }) {
  const { play } = useSound();
  const [activeTab, setActiveTab] = useStateI("riverstore");
  const [text, setText] = useStateI("");

  const urls = parseUrls(text);
  const canScan = urls.length > 0;

  const activeRetailer = RETAILERS.find(r => r.id === activeTab);

  const fillExample = () => {
    if (!activeRetailer) return;
    play("tick");
    setText(t => {
      const lines = t.split("\n").filter(Boolean);
      if (!lines.includes(activeRetailer.example)) {
        lines.push(activeRetailer.example);
      }
      return lines.join("\n");
    });
  };

  return (
    <div className="import-input">
      <div className="import-section-head">
        <div className="import-section-title">▮ IMPORT FROM WEB</div>
        <div className="import-section-meta">Paste product URLs to scan · one per line</div>
      </div>

      {/* Retailer tabs */}
      <div className="ret-tabs">
        {RETAILERS.map(r => (
          <div
            key={r.id}
            className={`ret-tab ${activeTab === r.id ? "active" : ""}`}
            style={{ "--ret-color": r.color }}
            onMouseEnter={() => play("hover")}
            onClick={() => { play("tick"); setActiveTab(r.id); }}
          >
            <span className="ret-mono">{r.mono}</span>
            <span className="ret-name">{r.name}</span>
          </div>
        ))}
      </div>

      {/* Active retailer info */}
      {activeRetailer && (
        <div className="ret-info" style={{ borderColor: activeRetailer.color }}>
          <span className="ret-glyph" style={{ color: activeRetailer.color }}>{activeRetailer.glyph}</span>
          <div>
            <div className="ret-info-name" style={{ color: activeRetailer.color }}>{activeRetailer.name}</div>
            <div className="ret-info-desc">{activeRetailer.desc}</div>
          </div>
          <button
            className="ret-example-btn"
            onMouseEnter={() => play("hover")}
            onClick={fillExample}
          >
            + Example URL
          </button>
        </div>
      )}

      {/* URL textarea */}
      <div className="ret-field">
        <label className="ret-label">PRODUCT URLs</label>
        <textarea
          className="ret-textarea"
          value={text}
          onChange={e => setText(e.target.value)}
          placeholder={"Paste links here — one per line:\nhttps://www.amazon.com/dp/...\nhttps://www.walmart.com/ip/..."}
          spellCheck={false}
        />
        {urls.length > 0 && (
          <div className="ret-url-count">▮ {urls.length} URL{urls.length > 1 ? "s" : ""} detected</div>
        )}
      </div>

      <div className="import-actions">
        <button
          className={`btn primary import-scan-btn ${!canScan ? "disabled" : ""}`}
          disabled={!canScan}
          onMouseEnter={() => play("hover")}
          onClick={() => { if (canScan) { play("select"); onScan(urls); } }}
        >
          ⊕ Scan {canScan ? `${urls.length} URL${urls.length > 1 ? "s" : ""}` : "URLs"}
        </button>
      </div>
    </div>
  );
}

// ── Step 2: Scanning animation ────────────────────────────────
function ImportScanning({ urls, onDone }) {
  const [current, setCurrent]   = useStateI(0);
  const [results, setResults]   = useStateI([]);
  const [hexStr,  setHexStr]    = useStateI("0000000000000000");
  const doneRef = useRefI(false);

  // Hex ticker effect
  useEffectI(() => {
    const tick = setInterval(() => {
      setHexStr(() => Array.from({ length: 16 }, () =>
        Math.floor(Math.random() * 16).toString(16)
      ).join(""));
    }, 80);
    return () => clearInterval(tick);
  }, []);

  // Process URLs sequentially
  useEffectI(() => {
    let cancelled = false;
    async function run() {
      const out = [];
      for (let i = 0; i < urls.length; i++) {
        if (cancelled) return;
        setCurrent(i);
        const res = await scrapeOne(urls[i]);
        if (cancelled) return;
        out.push(res);
        setResults([...out]);
      }
      if (!cancelled && !doneRef.current) {
        doneRef.current = true;
        // Brief pause so the final state is visible
        setTimeout(() => { if (!cancelled) onDone(out); }, 600);
      }
    }
    run();
    return () => { cancelled = true; };
  }, []);

  const pct = urls.length ? Math.round(((current + 1) / urls.length) * 100) : 0;
  const currentHost = (() => {
    try { return new URL(urls[current] || "").hostname.replace("www.", ""); }
    catch (_) { return urls[current] || ""; }
  })();

  return (
    <div className="scan-stage">
      <div className="scan-disc-wrap">
        <div className="scan-disc">
          <div className="scan-disc-inner">
            <div className="scan-disc-label">
              <div className="sdl-top">SCANNING</div>
              <div className="sdl-num">{current + 1}/{urls.length}</div>
            </div>
          </div>
        </div>
      </div>

      <div className="scan-hex">{hexStr}</div>

      <div className="scan-host">▮ {currentHost}</div>

      <div className="scan-bar-wrap">
        <div className="scan-bar">
          <div className="scan-fill" style={{ width: `${pct}%` }}></div>
        </div>
        <div className="scan-pct">{pct}%</div>
      </div>

      <div className="scan-log">
        {results.map((r, i) => (
          <div key={i} className={`scan-log-line ${r.ok ? "ok" : "fail"}`}>
            {r.ok ? "✓" : "✕"} {(() => { try { return new URL(r.sourceUrl).hostname.replace("www.",""); } catch(_){ return r.sourceUrl; }})()}
            {r.ok ? ` — ${(r.title || "").slice(0, 36)}` : ` — ${r.error || "Failed"}`}
          </div>
        ))}
      </div>
    </div>
  );
}

// ── Step 3: Review cards ──────────────────────────────────────
function ReviewCard({ draft, onChange, onRemove }) {
  const { play } = useSound();
  const ret = RETAILERS.find(r => r.id === draft._retailer) || null;
  // cover is either a real photo data-URL or the SVG placeholder
  const hasCover = draft.cover && draft.cover !== "";
  const isRealPhoto = hasCover && !draft.cover.startsWith("data:image/svg");

  return (
    <div className="rv-card" style={{ "--ret-color": ret?.color || "#4a5a78" }}>
      <div className="rv-card-head">
        {ret && (
          <div className="rv-badge" style={{ background: ret.color, color: "#0a1845" }}>
            {ret.mono} {ret.name}
          </div>
        )}
        {isRealPhoto && (
          <div className="rv-photo-badge">◎ photo</div>
        )}
        {draft._fuzzy && (
          <div className="rv-fuzzy-badge">⚠ fuzzy</div>
        )}
        <button
          className="rv-remove"
          onMouseEnter={() => play("hover")}
          onClick={() => { play("back"); onRemove(); }}
        >✕</button>
      </div>

      {/* Product photo preview */}
      {hasCover && (
        <div className="rv-photo-wrap">
          <img
            src={draft.cover}
            alt={draft.title}
            className={`rv-photo ${isRealPhoto ? "real" : "placeholder"}`}
          />
        </div>
      )}

      <div className="form-grid rv-form">
        <div className="field full">
          <label>Title</label>
          <input
            value={draft.title}
            onChange={e => onChange({ title: e.target.value })}
            placeholder="Product title"
          />
        </div>
        <div className="field">
          <label>Category</label>
          <select
            value={draft._cat}
            onChange={e => onChange({ _cat: e.target.value })}
          >
            {CAT_LIST.map(c => (
              <option key={c.id} value={c.id}>{c.label}</option>
            ))}
          </select>
        </div>
        <div className="field">
          <label>Target Price ($)</label>
          <input
            type="number"
            value={draft._price || ""}
            onChange={e => onChange({ _price: e.target.value })}
            placeholder="0"
            min="0"
          />
        </div>
        <div className="field full">
          <label>Description</label>
          <textarea
            value={draft.desc}
            onChange={e => onChange({ desc: e.target.value })}
            placeholder="Why do you want this?"
            style={{ minHeight: 56 }}
          />
        </div>
      </div>

      <div className="rv-source">
        <span className="rv-source-label">▮ SOURCE</span>
        <a
          className="rv-source-link"
          href={draft.sourceUrl}
          target="_blank"
          rel="noopener noreferrer"
          style={{ color: ret?.color || "#8899cc" }}
        >
          {(() => { try { return new URL(draft.sourceUrl).hostname.replace("www.", ""); } catch(_){ return draft.sourceUrl; }})()}
          {" ↗"}
        </a>
      </div>
    </div>
  );
}

function ReviewError({ result, onRemove }) {
  const { play } = useSound();
  return (
    <div className="rv-error-card">
      <div className="rv-error-head">
        <span className="rv-error-icon">✕</span>
        <span className="rv-error-url">
          {(() => { try { return new URL(result.sourceUrl).hostname.replace("www.",""); } catch(_){ return result.sourceUrl || "Unknown"; }})()}
        </span>
        <button className="rv-remove" onMouseEnter={() => play("hover")} onClick={() => { play("back"); onRemove(); }}>✕</button>
      </div>
      <div className="rv-error-msg">{result.error || "Could not scrape this URL."}</div>
      <div className="rv-error-url-full">{result.sourceUrl}</div>
    </div>
  );
}

// ── Main ImportScreen ─────────────────────────────────────────
function ImportScreen({ onImport, onCancel, onHome, onStats }) {
  const { play } = useSound();
  const [step,    setStep]    = useStateI("input");   // input | scanning | review
  const [scanUrls, setScanUrls] = useStateI([]);
  const [rawResults, setRawResults] = useStateI([]);
  const [drafts,  setDrafts]  = useStateI([]);        // editable wish drafts
  const [errors,  setErrors]  = useStateI([]);        // failed scrapes
  const [saving,  setSaving]  = useStateI(false);

  const handleScan = (urls) => {
    setScanUrls(urls);
    setStep("scanning");
  };

  const handleScanDone = (results) => {
    setRawResults(results);
    const ok  = results.filter(r => r.ok);
    const bad = results.filter(r => !r.ok);

    const newDrafts = ok.map(r => {
      const ret = RETAILERS.find(rt => rt.id === r.retailer);
      return {
        ...draftToWish(r),
        _retailer: r.retailer,
        _fuzzy:    r.fuzzy,
        _cat:      "product",
        _price:    r.price ? String(Math.ceil(r.price)) : "",
      };
    });

    setDrafts(newDrafts);
    setErrors(bad);
    setStep("review");
    play("ok");
  };

  const updateDraft = (idx, patch) => {
    setDrafts(ds => ds.map((d, i) => i === idx ? { ...d, ...patch } : d));
  };

  const removeDraft = (idx) => {
    setDrafts(ds => ds.filter((_, i) => i !== idx));
  };

  const removeError = (idx) => {
    setErrors(es => es.filter((_, i) => i !== idx));
  };

  const handleCommit = async () => {
    if (drafts.length === 0) return;
    setSaving(true);
    play("select");

    // Build final wish items from drafts
    const finalItems = drafts.map(d => ({
      id:          d.id,
      category:    d._cat || "product",
      title:       d.title.trim() || "Untitled",
      desc:        d.desc || "",
      notes:       d.notes || "",
      // Preserve real photo if scraped; generate SVG placeholder only as fallback
      cover:       d.cover || makeProductSvg(d.title, RETAILERS.find(r => r.id === d._retailer)),
      target:      Number(d._price) || 0,
      saved:       0,
      hours:       0,
      targetHours: 0,
      pct:         0,
      checklist:   [],
      completed:   false,
      completedAt: null,
      createdAt:   Date.now(),
      sourceUrl:   d.sourceUrl || "",
      donors:      [],
    }));

    try {
      await onImport(finalItems);
      play("trophy");
    } catch (e) {
      console.error("Import failed:", e);
      play("bad");
      setSaving(false);
    }
  };

  const handleBack = () => {
    if (step === "review") { setStep("input"); setDrafts([]); setErrors([]); }
    else if (step === "scanning") { setStep("input"); }
    else onCancel();
  };

  return (
    <div className="screen">
      <ChromeBar onHome={onHome} onAdd={() => {}} onStats={onStats} ownerMode={true} />
      <div className="import-screen">

        {/* Step indicator */}
        <div className="import-steps">
          {["input", "scanning", "review"].map((s, i) => (
            <div key={s} className={`import-step ${step === s ? "active" : (
              (s === "scanning" && (step === "review")) ||
              (s === "input"    && (step === "scanning" || step === "review"))
              ? "done" : ""
            )}`}>
              <div className="is-dot">{
                (s === "scanning" && (step === "review")) ||
                (s === "input"    && (step === "scanning" || step === "review"))
                ? "✓" : (i + 1)
              }</div>
              <div className="is-label">{s === "input" ? "Paste URLs" : s === "scanning" ? "Scanning" : "Review"}</div>
            </div>
          ))}
        </div>

        {/* Step content */}
        {step === "input" && (
          <ImportInput onScan={handleScan} />
        )}

        {step === "scanning" && (
          <ImportScanning urls={scanUrls} onDone={handleScanDone} />
        )}

        {step === "review" && (
          <div className="import-review">
            <div className="import-section-head">
              <div className="import-section-title">
                ▮ REVIEW · {drafts.length} item{drafts.length !== 1 ? "s" : ""} ready
              </div>
              <div className="import-section-meta">
                Edit titles, categories, and prices before importing
              </div>
            </div>

            {errors.map((e, i) => (
              <ReviewError key={i} result={e} onRemove={() => removeError(i)} />
            ))}

            {drafts.map((d, i) => (
              <ReviewCard
                key={d.id}
                draft={d}
                onChange={patch => updateDraft(i, patch)}
                onRemove={() => removeDraft(i)}
              />
            ))}

            {drafts.length === 0 && errors.length === 0 && (
              <div className="import-empty">No items to import.</div>
            )}

            <div className="import-actions">
              <button
                className="btn"
                onMouseEnter={() => play("hover")}
                onClick={handleBack}
                disabled={saving}
              >◀ Back</button>
              {drafts.length > 0 && (
                <button
                  className={`btn primary ${saving ? "disabled" : ""}`}
                  onMouseEnter={() => play("hover")}
                  onClick={handleCommit}
                  disabled={saving}
                >
                  {saving ? "▮ Saving…" : `✦ Add ${drafts.length} Wish${drafts.length !== 1 ? "es" : ""}`}
                </button>
              )}
            </div>
          </div>
        )}

        {step !== "review" && (
          <div className="import-actions" style={{ marginTop: 24 }}>
            <button className="btn" onMouseEnter={() => play("hover")} onClick={handleBack}>◀ Cancel</button>
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { ImportScreen });
