// MomentIQ Creator Portal — 3-step flow: your info → posts → payment (production)
// Submits to the live backend:
//   POST /api/submit-post    { email, handle, campaign, postLinks[], sparkCode }
//   POST /api/payment-info   { email, name, method, ach{...}|paypalEmail, w9PdfBase64?, w9FileName? }

const isEmail = (s) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s.trim());
// Loose: scheme + www optional — "tiktok.com/@you/video/123" is fine
const isTikTokLink = (s) => /^(https?:\/\/)?((www|vm|vt)\.)?tiktok\.com\/.+/i.test(s.trim());
const normHandle = (s) => {
  const c = String(s || "").trim().replace(/^@/, "").replace(/\/+$/, "");
  return c ? "@" + c : "";
};

async function postJSON(url, body) {
  const res = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  const data = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(data.error || `Request failed (${res.status})`);
  return data;
}

const fileToBase64 = (file) => new Promise((resolve, reject) => {
  const r = new FileReader();
  r.onload = () => resolve(String(r.result).split(",")[1] || "");
  r.onerror = reject;
  r.readAsDataURL(file);
});

function PortalFlow({ onCreator, onDone }) {
  const steps = ["Your info", "Your posts", "Get paid"];
  const [step, setStep] = React.useState(0); // 0 info, 1 posts, 2 payment, 3 done
  const [checking, setChecking] = React.useState(false);
  const [submitting, setSubmitting] = React.useState(false);

  // Pre-fill from URL params: ?email=…&campaign=…&handle=…&spark=…
  const params = React.useMemo(() => new URLSearchParams(window.location.search), []);

  // Step 1 state
  const [email, setEmail] = React.useState(params.get("email") || "");
  const [campaign, setCampaign] = React.useState(params.get("campaign") || "");
  const [handle, setHandle] = React.useState(normHandle(params.get("handle") || ""));
  const [links, setLinks] = React.useState([""]);
  const [sparkCodes, setSparkCodes] = React.useState([params.get("spark") || ""]);

  // Feed picker state (loaded through /api/tiktok-posts once a handle is given)
  const [feed, setFeed] = React.useState(null);          // null | "loading" | {posts, avatarUrl}
  const [selected, setSelected] = React.useState(new Set());
  const [suggested, setSuggested] = React.useState(new Set());
  const [pasteMode, setPasteMode] = React.useState(false);
  const [showAllPosts, setShowAllPosts] = React.useState(false);
  const [analyzing, setAnalyzing] = React.useState(false);
  const [errors, setErrors] = React.useState({});

  // Creator identity comes from what they type (no demo roster)
  const creator = handle ? { handle, name: handle, campaign, posts: 1 } : null;

  const emitCreator = () => { if (onCreator) onCreator(creator); };
  React.useEffect(() => { emitCreator(); }, [handle]);

  // Step 2 state
  const [w9Status, setW9Status] = React.useState(null); // {onFile, name, handle}
  const [w9File, setW9File] = React.useState(null);     // {name, base64}
  const w9InputRef = React.useRef(null);
  const [method, setMethod] = React.useState(null); // 'paypal' | 'ach'
  const [paypalEmail, setPaypalEmail] = React.useState("");
  const [achName, setAchName] = React.useState("");
  const [achRouting, setAchRouting] = React.useState("");
  const [achAccount, setAchAccount] = React.useState("");
  const [achType, setAchType] = React.useState("Checking");

  const clearError = (key) => setErrors((e) => (e[key] ? { ...e, [key]: null } : e));
  const setLink = (i, v) => { setLinks(links.map((l, j) => (j === i ? v : l))); clearError("links"); };
  const removeLink = (i) => setLinks(links.length > 1 ? links.filter((_, j) => j !== i) : links);
  const usePicker = !!(creator && feed && feed !== "loading" && !pasteMode);
  const filledLinks = usePicker
    ? feed.posts.filter((p) => selected.has(p.id)).map((p) => p.url)
    : links.map((l) => l.trim()).filter(Boolean);
  const togglePost = (id) => {
    setSelected((s) => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; });
    clearError("links");
  };

  /* ---- Step 1 → 2: who you are ---- */
  const feedReq = React.useRef(0);
  const continueToPosts = () => {
    const errs = {};
    if (!isEmail(email)) errs.email = "We need your email to match you to your file.";
    if (!campaign.trim()) errs.campaign = "Which campaign are you posting for?";
    setErrors(errs);
    if (Object.keys(errs).length) return;
    setStep(1);

    // Real scan behind the analyzing splash (min 2.4s so the steps read naturally)
    if (handle && (!feed || feed === "loading")) {
      const req = ++feedReq.current;
      setAnalyzing(true);
      setFeed("loading");
      setShowAllPosts(false);
      const started = Date.now();
      fetchCreatorFeed(handle, campaign).then((res) => {
        if (req !== feedReq.current) return;
        const finish = () => {
          if (req !== feedReq.current) return;
          setAnalyzing(false);
          if (!res.posts) { setFeed(null); setPasteMode(true); return; }
          const sug = suggestCampaignPosts(res.posts);
          setFeed({ posts: res.posts, avatarUrl: res.avatarUrl || null });
          setSuggested(sug);
          setSelected(new Set([...sug]));
        };
        window.setTimeout(finish, Math.max(0, 2400 - (Date.now() - started)));
      });
    } else if (!handle) {
      setPasteMode(true);
    }
  };

  /* ---- Step 2 → 3: validate + submit post links ---- */
  const continueToPayment = () => {
    const errs = {};
    if (filledLinks.length === 0) errs.links = usePicker ? "Tap the posts that were for this campaign." : "Drop in at least one post link.";
    if (!usePicker) {
      const bad = filledLinks.find((l) => !isTikTokLink(l));
      if (bad) errs.links = `Hmm — that one doesn't look like a TikTok link: ${bad}`;
    }
    setErrors(errs);
    if (Object.keys(errs).length) return;

    setChecking(true);
    const normalized = filledLinks.map((l) => (/^https?:\/\//i.test(l) ? l : `https://${l.replace(/^\/+/, "")}`));
    const linkParams = new URLSearchParams(window.location.search);
    postJSON("/api/submit-post", {
      email: email.trim(),
      handle: handle || "",
      campaign: campaign.trim(),
      postLinks: normalized,
      sparkCode: sparkCodes.map((c) => c.trim()).filter(Boolean).join(", "),
      briefToken: linkParams.get("bt") || undefined,
      token: linkParams.get("t") || undefined,
    }).then(() => {
      setW9Status({ onFile: false, name: null, handle: handle || null });
      setChecking(false);
      setStep(2);
    }).catch((e) => {
      setChecking(false);
      setErrors((er) => ({ ...er, links: e.message }));
    });
  };

  /* ---- W-9 file pick ---- */
  const onW9Pick = async (e) => {
    const f = e.target.files && e.target.files[0];
    e.target.value = "";
    if (!f) return;
    if (f.size > 8 * 1024 * 1024) { setErrors((er) => ({ ...er, w9: "Keep it under 8 MB." })); return; }
    try {
      const base64 = await fileToBase64(f);
      setW9File({ name: f.name, base64 });
      clearError("w9");
    } catch (err) {
      setErrors((er) => ({ ...er, w9: "Couldn't read that file — try again." }));
    }
  };

  /* ---- Step 3 → done: submit payment info ---- */
  const finish = () => {
    const errs = {};
    if (!method) errs.method = "Pick where the money goes.";
    if (method === "paypal" && !isEmail(paypalEmail)) errs.paypal = "Enter a valid PayPal email.";
    if (method === "ach") {
      if (!achName.trim()) errs.achName = "Required.";
      if (!/^\d{9}$/.test(achRouting.trim())) errs.achRouting = "Routing numbers are exactly 9 digits.";
      if (!/^\d{6,17}$/.test(achAccount.trim())) errs.achAccount = "Enter your account number (digits only).";
    }
    setErrors(errs);
    if (Object.keys(errs).length) return;

    setSubmitting(true);
    const body = {
      email: email.trim(),
      name: achName.trim() || (handle ? handle.replace("@", "") : email.trim()),
      method,
    };
    if (method === "paypal") body.paypalEmail = paypalEmail.trim();
    if (method === "ach") {
      body.ach = {
        accountHolder: achName.trim(),
        routingNumber: achRouting.trim(),
        accountNumber: achAccount.trim(),
        accountType: achType === "Savings" ? "personalSavings" : "personalChecking",
      };
    }
    if (w9File) { body.w9PdfBase64 = w9File.base64; body.w9FileName = w9File.name; }
    const payParams = new URLSearchParams(window.location.search);
    if (payParams.get("bt")) body.briefToken = payParams.get("bt");
    if (payParams.get("t")) body.token = payParams.get("t");

    postJSON("/api/payment-info", body).then(() => {
      setSubmitting(false);
      setStep(3);
    }).catch((e) => {
      setSubmitting(false);
      setErrors((er) => ({ ...er, submit: e.message }));
    });
  };

  const onEnter = (fn) => (e) => { if (e.key === "Enter") fn(); };

  // Keep the card top in view when moving between steps (no scrollIntoView — host-safe)
  const cardRef = React.useRef(null);
  React.useEffect(() => {
    if (onDone) onDone(step === 3);
    if (cardRef.current) {
      const top = cardRef.current.getBoundingClientRect().top + window.pageYOffset - 24;
      window.scrollTo({ top: Math.max(0, top), behavior: "smooth" });
    }
  }, [step]);

  /* ================= Done ================= */
  if (step === 3) {
    return (
      <section className="cp-flow-card" aria-live="polite" ref={cardRef}>
        <SuccessSplash title={handle ? `All set, ${handle}` : "All set — you're in the payout queue"}>
          <ul className="cp-receipt">
            <li><IconCheck size={14} strokeWidth={2.4} /> <span>{filledLinks.length} {filledLinks.length === 1 ? "post link" : "post links"} submitted to <strong>{campaign}</strong></span></li>
            <li><IconCheck size={14} strokeWidth={2.4} /> <span>{w9File ? "W-9 received & filed" : "No W-9 attached — if we don't have one on file, we'll email you a fillable copy"}</span></li>
            <li><IconCheck size={14} strokeWidth={2.4} /> <span>Paying you by <strong>{method === "ach" ? "direct deposit" : "PayPal"}</strong> once your posts are verified</span></li>
          </ul>
          <p>We'll confirm everything at {email.trim()}.</p>
          <button type="button" className="mq-btn-ghost cp-btn-ghost cp-btn-sm cp-btn-center"
            onClick={() => { setLinks([""]); setSparkCodes([""]); setSelected(new Set()); setStep(0); }}>
            Drop more links
          </button>
        </SuccessSplash>
      </section>
    );
  }

  return (
    <section className="cp-flow-card" ref={cardRef}>
      <Stepper steps={steps} current={step} />

      {/* ================= Step 1: Your info ================= */}
      {step === 0 && (
        <div className="cp-step-body">
          <div className="cp-field-stack">
            <Field label="Campaign" error={errors.campaign} row={true}>
              <TextInput value={campaign} onChange={(v) => { setCampaign(v); clearError("campaign"); }}
                placeholder="e.g. APLIN" invalid={!!errors.campaign} />
            </Field>
            <Field label="Email" error={errors.email} row={true}>
              <TextInput value={email} onChange={(v) => { setEmail(v); clearError("email"); }} type="email"
                placeholder="you@example.com" invalid={!!errors.email} autoFocus={!email} />
            </Field>
            <Field label="TikTok handle" row={true} hint="Optional — lets us pull up your posts so you can tap instead of paste">
              <TextInput value={handle} onChange={(v) => { setHandle(v); setFeed(null); setPasteMode(false); }}
                placeholder="@yourhandle" onKeyDown={onEnter(continueToPosts)} />
            </Field>
          </div>
          <div className="cp-form-foot cp-foot-center">
            <button type="button" className="mq-btn-primary cp-btn-primary" onClick={continueToPosts}>
              Show us the Goods <IconArrowRight size={17} strokeWidth={2} />
            </button>
          </div>
        </div>
      )}

      {/* ================= Step 2: Your posts ================= */}
      {step === 1 && (
        <div className="cp-step-body">
          {creator && (
            <div className="cp-intro-row">
              <div className="cp-intro">
                <div>
                  <h3 className="cp-intro-title">The vibes were immaculate 💁‍♀️</h3>
                  <p className="cp-intro-sub">{creator.handle} · {campaign}</p>
                </div>
              </div>
              <CreatorAvatar creator={creator} feed={feed} size={48} />
            </div>
          )}
          {!analyzing && (
            <ol className="cp-instructions">
              <li><span className="cp-instructions-num">1</span> Select the posts that were part of this campaign</li>
              <li><span className="cp-instructions-num">2</span> Add URLs for any we missed</li>
            </ol>
          )}
          {analyzing ? (
            <AnalyzingPanel handle={creator ? creator.handle : "your profile"} brand={campaign} />
          ) : usePicker ? (
            <Field label="Your recent posts" error={errors.links}>
              {feed === "loading" ? <FeedSkeleton /> : (
                <FeedPicker feed={feed} selected={selected} onToggle={togglePost} suggested={suggested}
                  orderedCount={Math.max(1, suggested.size || 1)} showAll={showAllPosts} onShowAll={() => setShowAllPosts(true)}
                  onPasteMode={() => { setPasteMode(true); clearError("links"); }}
                  brandName={campaign}
                  onSelectAllTagged={(on) => {
                    setSelected((s) => {
                      const n = new Set(s);
                      feed.posts.filter((p) => suggested.has(p.id)).forEach((p) => on ? n.add(p.id) : n.delete(p.id));
                      return n;
                    });
                    clearError("links");
                  }} />
              )}
            </Field>
          ) : (
          <div className="cp-form-grid">
          <Field label="Post links" error={errors.links}>
            <div className="cp-link-list">
              {links.map((l, i) => (
                <div className="cp-link-row" key={i}>
                  {links.length > 1 && <span className="cp-link-num">{i + 1}</span>}
                  <TextInput value={l} onChange={(v) => setLink(i, v)} mono
                    placeholder={"tiktok.com/" + (creator ? creator.handle : "@yourhandle") + "/video/…"}
                    invalid={!!l.trim() && !isTikTokLink(l)} />
                  {links.length > 1 && (
                    <button type="button" className="cp-icon-btn" aria-label="Remove link" onClick={() => removeLink(i)}><IconX size={15} /></button>
                  )}
                </div>
              ))}
              <button type="button" className="cp-add-link" onClick={() => setLinks([...links, ""])}>
                <IconPlus size={14} strokeWidth={2.2} /> Add another post link
              </button>
              {creator && feed && feed !== "loading" && pasteMode && (
                <button type="button" className="cp-linklike" onClick={() => { setPasteMode(false); clearError("links"); }}>← Back to picking from my posts</button>
              )}
            </div>
          </Field>
          <Field label="Spark Ad code" hint="Optional — only if the team asked you to generate one">
            <div className="cp-link-list">
              {sparkCodes.map((c, i) => (
                <div className="cp-link-row" key={"m" + i}>
                  <TextInput value={c} onChange={(v) => setSparkCodes(sparkCodes.map((x, j) => (j === i ? v : x)))} mono
                    placeholder="#7xxxxxxxxxxxxxxxxxx" onKeyDown={onEnter(continueToPayment)} />
                  {sparkCodes.length > 1 && (
                    <button type="button" className="cp-icon-btn" aria-label="Remove code"
                      onClick={() => setSparkCodes(sparkCodes.filter((_, j) => j !== i))}><IconX size={15} /></button>
                  )}
                </div>
              ))}
              {sparkCodes.length === 1 && sparkCodes[0].trim() !== "" && (
                <button type="button" className="cp-add-link" onClick={() => setSparkCodes([...sparkCodes, ""])}>
                  <IconPlus size={14} strokeWidth={2.2} /> Add a second code
                </button>
              )}
            </div>
          </Field>
          </div>
          )}
          {usePicker && !analyzing && (
          <div className="cp-form-grid">
          <Field label="Spark Ad code" hint="Optional — only if the team asked you to generate one">
            <div className="cp-link-list">
              {sparkCodes.map((c, i) => (
                <div className="cp-link-row" key={"p" + i}>
                  <TextInput value={c} onChange={(v) => setSparkCodes(sparkCodes.map((x, j) => (j === i ? v : x)))} mono
                    placeholder="#7xxxxxxxxxxxxxxxxxx" onKeyDown={onEnter(continueToPayment)} />
                  {sparkCodes.length > 1 && (
                    <button type="button" className="cp-icon-btn" aria-label="Remove code"
                      onClick={() => setSparkCodes(sparkCodes.filter((_, j) => j !== i))}><IconX size={15} /></button>
                  )}
                </div>
              ))}
              {sparkCodes.length === 1 && sparkCodes[0].trim() !== "" && (
                <button type="button" className="cp-add-link" onClick={() => setSparkCodes([...sparkCodes, ""])}>
                  <IconPlus size={14} strokeWidth={2.2} /> Add a second code
                </button>
              )}
            </div>
          </Field>
          <span></span>
          </div>
          )}
          {!analyzing && (
          <div className="cp-form-foot">
            <button type="button" className="mq-btn-ghost cp-btn-ghost cp-btn-sm" onClick={() => setStep(0)}><IconChevronLeft size={15} /> Back</button>
            <button type="button" className="mq-btn-primary cp-btn-primary" onClick={continueToPayment} disabled={checking}>
              {checking ? "Sending your links…" : <React.Fragment>Next — get paid <IconArrowRight size={17} strokeWidth={2} /></React.Fragment>}
            </button>
          </div>
          )}
        </div>
      )}

      {/* ================= Step 3: Get paid ================= */}
      {step === 2 && w9Status && (
        <div className="cp-step-body">
          {creator && (
            <div className="cp-intro-row">
              <div className="cp-intro">
                <div>
                  <h3 className="cp-intro-title">Get paid, {creator.handle}.</h3>
                  <p className="cp-intro-sub">{campaign} · {filledLinks.length} {filledLinks.length === 1 ? "link" : "links"} submitted</p>
                </div>
              </div>
              <div className="cp-intro-right">
                <CreatorAvatar creator={creator} feed={feed} size={48} />
              </div>
            </div>
          )}
          <div className="cp-callout">
            <span className="cp-callout-icon"><IconFileText size={16} /></span>
            <div>
              <strong>One quick tax form and we're square: a W-9.</strong>
              <p>Upload one if you have it handy. Already sent us one before, or don't have it right now? Skip this — we'll match your file or email you a fillable copy.</p>
            </div>
          </div>
          <input ref={w9InputRef} type="file" accept=".pdf,.jpg,.jpeg,.png,application/pdf,image/jpeg,image/png"
            style={{ display: "none" }} onChange={onW9Pick} />
          <button type="button" className={"cp-dropzone" + (w9File ? " is-filled" : "")}
            onClick={() => { if (w9File) { setW9File(null); } else if (w9InputRef.current) { w9InputRef.current.click(); } }}>
            {w9File ? (
              <React.Fragment><IconCheck size={20} strokeWidth={2.2} /><span><strong>{w9File.name}</strong> attached — click to remove</span></React.Fragment>
            ) : (
              <React.Fragment><IconUpload size={20} /><span><strong>Upload your W-9</strong> — PDF, JPG, or PNG (optional)</span></React.Fragment>
            )}
          </button>
          {errors.w9 && <p className="cp-field-error">{errors.w9}</p>}

          <div className="cp-section-label"><span>Where should the money go?</span></div>
          <div className="cp-method-grid" role="radiogroup" aria-label="Payment method">
            <MethodCard icon={<IconBank size={20} />} title="Direct deposit" badge="ACH"
              desc="Straight to your U.S. bank account. Usually next business day."
              selected={method === "ach"} onClick={() => { setMethod("ach"); clearError("method"); }} />
            <MethodCard icon={<IconPaypal size={20} />} title="PayPal"
              desc="Sent to your PayPal email. Arrives within minutes."
              selected={method === "paypal"} onClick={() => { setMethod("paypal"); clearError("method"); }} />
          </div>
          {errors.method && <p className="cp-field-error">{errors.method}</p>}

          {method === "paypal" && (
            <Field label="PayPal email" error={errors.paypal}>
              <TextInput value={paypalEmail} onChange={(v) => { setPaypalEmail(v); clearError("paypal"); }} type="email"
                placeholder="you@example.com" invalid={!!errors.paypal} autoFocus={true} onKeyDown={onEnter(finish)} />
            </Field>
          )}
          {method === "ach" && (
            <React.Fragment>
              <div className="cp-form-grid">
                <Field label="Account holder name" error={errors.achName}>
                  <TextInput value={achName} onChange={(v) => { setAchName(v); clearError("achName"); }}
                    placeholder="Name exactly as it appears on the account" invalid={!!errors.achName} autoFocus={true} />
                </Field>
                <Field label="Account type">
                  <SelectInput value={achType} onChange={setAchType} options={["Checking", "Savings"]} placeholder="Account type" />
                </Field>
              </div>
              <div className="cp-form-grid">
                <Field label="Routing number" error={errors.achRouting}>
                  <TextInput value={achRouting} onChange={(v) => { setAchRouting(v.replace(/[^\d]/g, "")); clearError("achRouting"); }}
                    mono inputMode="numeric" placeholder="9 digits" invalid={!!errors.achRouting} />
                </Field>
                <Field label="Account number" error={errors.achAccount}>
                  <TextInput value={achAccount} onChange={(v) => { setAchAccount(v.replace(/[^\d]/g, "")); clearError("achAccount"); }}
                    mono inputMode="numeric" placeholder="Account number" invalid={!!errors.achAccount} onKeyDown={onEnter(finish)} />
                </Field>
              </div>
            </React.Fragment>
          )}

          <p className="cp-secure-note"><IconLock size={13} /> Encrypted in transit. Bank details go straight to Mercury — never stored on our servers.</p>
          {errors.submit && <p className="cp-field-error" role="alert">{errors.submit}</p>}
          <div className="cp-form-foot">
            <button type="button" className="mq-btn-ghost cp-btn-ghost cp-btn-sm" onClick={() => setStep(1)}><IconChevronLeft size={15} /> Back to posts</button>
            <button type="button" className="mq-btn-primary cp-btn-primary" onClick={finish} disabled={submitting}>
              {submitting ? "Setting up your payout…" : <React.Fragment>Finish <IconArrowRight size={17} strokeWidth={2} /></React.Fragment>}
            </button>
          </div>
        </div>
      )}
    </section>
  );
}

Object.assign(window, { PortalFlow });
