// client.jsx — Client-facing onboarding portal

// ─────────────────────────────────────────────────────────────────────
// First-visit welcome tour — teaches the client how to navigate
// ─────────────────────────────────────────────────────────────────────
function ClientTour({ open, onClose, freelancer, steps }) {
  const first = (freelancer.name || "your contact").split(" ")[0];
  // Describe only the actions this client will actually do (respects skipped steps).
  const ids = (steps || []).map(s => s.id);
  const actions = [];
  if (ids.includes("agree")) actions.push("review and sign your agreement");
  if (ids.includes("invoice")) actions.push("pay your invoice");
  if (ids.includes("files")) actions.push("share your brand assets");
  if (ids.includes("kickoff")) actions.push("book a kickoff time");
  const actionText = actions.length === 0
    ? "Work through each step right here — no email back-and-forth."
    : actions.length === 1
      ? `You'll ${actions[0]}, right here — no email back-and-forth.`
      : `You'll ${actions.slice(0, -1).join(", ")}, and ${actions[actions.length - 1]} — all in this one place. No email back-and-forth.`;
  const slides = [
    { icon: Icon.layers, title: "Welcome to your portal", body: `This is your private space to get set up with ${freelancer.brand}. It only takes a few minutes — here's how it works.` },
    { icon: Icon.arrow, title: "Follow the steps on the left", body: "Your onboarding is split into a few short steps. Work through them top to bottom — the highlighted one is where you are now." },
    { icon: Icon.check, title: "Everything saves automatically", body: "Close the tab and come back whenever — your progress is saved. The green dot at the top means you're securely connected." },
    { icon: Icon.signature, title: "Everything in one place", body: actionText },
    { icon: Icon.mail, title: `Questions? Message ${first}`, body: `Use the “Send a message” button at the bottom-left anytime. Replies usually come within a few hours.` },
  ];
  const [i, setI] = React.useState(0);
  if (!open) return null;
  const s = slides[i];
  const last = i === slides.length - 1;
  const Ico = s.icon;
  const finish = () => { try { localStorage.setItem("relay_tour_seen", "1"); } catch {} setI(0); onClose(); };

  return (
    <div onClick={finish} style={{ position: "fixed", inset: 0, background: "rgba(15,26,20,0.45)", backdropFilter: "blur(3px)", zIndex: 3000, display: "grid", placeItems: "center", padding: 24 }}>
      <div onClick={e => e.stopPropagation()} className="card card-pad fade-up" style={{ maxWidth: 420, width: "100%", position: "relative" }}>
        <button onClick={finish} className="btn btn-ghost btn-sm" style={{ position: "absolute", top: 10, right: 10, padding: 6 }}><Icon.x cls="ico-sm"/></button>
        <div className="col gap-16" style={{ alignItems: "center", textAlign: "center", padding: "8px 4px" }}>
          <div style={{ width: 52, height: 52, borderRadius: 14, background: "var(--primary-soft)", color: "var(--primary)", display: "grid", placeItems: "center" }}><Ico cls="ico-lg"/></div>
          <div className="col gap-6">
            <div className="h-display" style={{ fontSize: 24 }}>{s.title}</div>
            <div className="ink-3" style={{ fontSize: 13.5, lineHeight: 1.55 }}>{s.body}</div>
          </div>
          <div className="row gap-6">
            {slides.map((_, idx) => (
              <span key={idx} style={{ width: idx === i ? 18 : 6, height: 6, borderRadius: 999, background: idx === i ? "var(--primary)" : "var(--line)", transition: "all .2s" }}/>
            ))}
          </div>
          <div className="row gap-8" style={{ width: "100%", justifyContent: "space-between", marginTop: 4 }}>
            <Button variant="ghost" onClick={finish}>Skip</Button>
            <div className="row gap-8">
              {i > 0 && <Button onClick={() => setI(i - 1)} icon={<Icon.arrowL cls="ico-sm"/>}>Back</Button>}
              <Button variant="primary" onClick={() => last ? finish() : setI(i + 1)} iconR={last ? <Icon.check cls="ico-sm"/> : <Icon.arrow cls="ico-sm"/>}>
                {last ? "Let's go" : "Next"}
              </Button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function ClientPortal({ clientId }) {
  const { clients, template, freelancer, updateClient } = useApp();
  // Strict match only — never fall back to clients[0]. If the slug in the URL
  // doesn't resolve, the "Portal not available" screen below should render.
  const client = clients.find(c => c.id === clientId) || null;
  // Only show steps that are enabled in the template AND not skipped for this specific client
  const steps = template.steps.filter(s => s.enabled !== false && !((client?.skippedSteps) || []).includes(s.id));
  // Hooks must run unconditionally — use optional chaining so they're null-safe.
  const [step, setStep] = React.useState(Math.min((client?.progress) || 0, steps.length));
  const [showTour, setShowTour] = React.useState(() => {
    try { return localStorage.getItem("relay_tour_seen") !== "1"; } catch { return true; }
  });

  React.useEffect(() => { setStep(Math.min((client?.progress) || 0, steps.length)); }, [clientId, steps.length]);

  // Admin email notifications — fire once per event per client.
  // "opened" runs on first mount; step completions run from `advance` below.
  const notifyOnce = React.useCallback(async (event, extra) => {
    if (!client) return;
    const notified = client.notified || {};
    if (notified[event]) return; // already sent — skip
    if (!window.notifyAdminOfClientEvent) return;
    // Merge any just-saved fields (e.g. signature) into the client object passed
    // to the email builder, since React state hasn't refreshed within this tick.
    const clientForEmail = extra ? { ...client, ...extra } : client;
    const ok = await window.notifyAdminOfClientEvent({ client: clientForEmail, event, freelancer });
    if (ok) {
      updateClient(client.id, { notified: { ...notified, [event]: new Date().toISOString() } });
    }
  }, [client, freelancer, updateClient]);

  React.useEffect(() => {
    if (!client) return;
    // Track portal visit (fires every time they load the portal)
    const visits = client.portalVisits || [];
    const lastVisit = visits.length > 0 ? visits[visits.length - 1] : null;
    const now = new Date().toISOString();
    // Only add new visit if last one was >5 min ago (debounce rapid refreshes)
    if (!lastVisit || (new Date(now) - new Date(lastVisit.ts) > 5 * 60 * 1000)) {
      updateClient(client.id, { portalVisits: [...visits, { ts: now }] });
    }
    // Notify admin of first portal open
    if (!(client.notified && client.notified.opened)) notifyOnce("opened");
  }, [client?.id]);

  // No client to show (e.g. all deleted) — guard AFTER hooks
  if (!client) {
    return (
      <div style={{ minHeight: "100vh", display: "grid", placeItems: "center", background: "var(--bg)", padding: 24 }}>
        <div className="card card-pad" style={{ maxWidth: 380, textAlign: "center" }}>
          <div className="col gap-10" style={{ alignItems: "center" }}>
            <LogoMark size={36} color="var(--primary)"/>
            <div className="h-display" style={{ fontSize: 22 }}>Portal not available</div>
            <div className="ink-3" style={{ fontSize: 13 }}>This onboarding link isn't active. Please contact {freelancer.name} for an updated link.</div>
          </div>
        </div>
      </div>
    );
  }

  // `extraPatch` lets a step persist extra fields to the client at the same
  // moment it advances (e.g. the Agreement step saves the signature record).
  const advance = (extraPatch) => {
    const completedId = steps[step]?.id;
    const next = Math.min(steps.length, step + 1);
    setStep(next);
    const patch = { progress: Math.max(client.progress, next) };
    if (extraPatch && typeof extraPatch === "object" && !extraPatch.nativeEvent) {
      Object.assign(patch, extraPatch);
    }
    updateClient(client.id, patch);
    // Map step id → notification event
    const EVENT_FOR_STEP = { intake: "intake", agree: "signed", invoice: "paid" };
    const evt = EVENT_FOR_STEP[completedId];
    if (evt) notifyOnce(evt, extraPatch);
  };

  // Map current step index → step id, then render the right view
  const currentId = steps[step]?.id;

  return (
    <div className="portal-shell">
      <ClientTour open={showTour} onClose={() => setShowTour(false)} freelancer={freelancer} steps={steps}/>
      <ClientSidebar client={client} steps={steps} step={step} setStep={setStep} freelancer={freelancer}/>
      <main className="portal-main">
        <ClientTopbar client={client} freelancer={freelancer} step={step} steps={steps} onHelp={() => setShowTour(true)}/>
        <div key={step} className="portal-content fade-up">
          {currentId === "welcome" && <ClientWelcome client={client} freelancer={freelancer} template={template} advance={advance} steps={steps}/>}
          {currentId === "intake"  && <ClientIntake client={client} template={template} advance={advance}/>}
          {currentId === "agree"   && <ClientAgreement client={client} freelancer={freelancer} template={template} advance={advance}/>}
          {currentId === "invoice" && <ClientInvoice client={client} freelancer={freelancer} advance={advance}/>}
          {currentId === "files"   && <ClientFilesUpload advance={advance} client={client} freelancer={freelancer}/>}
          {currentId === "kickoff" && <ClientKickoff client={client} freelancer={freelancer} advance={advance}/>}
          {!currentId && <ClientComplete client={client} freelancer={freelancer}/>}
        </div>
      </main>
    </div>
  );
}

function ClientSidebar({ client, steps, step, setStep, freelancer }) {
  const { toast } = useToast();
  return (
    <aside className="portal-sidebar">
      <div className="row gap-10 portal-brand-row" style={{ marginBottom: 28 }}>
        <LogoMark size={26} color={freelancer.accent}/>
        <div className="col" style={{ lineHeight: 1.2 }}>
          <div style={{ fontSize: 13.5, fontWeight: 600, letterSpacing: "-0.01em" }}>{freelancer.brand}</div>
          <div className="muted" style={{ fontSize: 11 }}>Your private portal</div>
        </div>
      </div>

      <div className="col gap-4 portal-project" style={{ marginBottom: 24 }}>
        <div className="label" style={{ fontSize: 10 }}>Project</div>
        <div style={{ fontSize: 14, fontWeight: 500, lineHeight: 1.35 }}>{client.role_title}</div>
        <div className="ink-3" style={{ fontSize: 12 }}>for {client.company}</div>
      </div>

      <div className="col gap-4" style={{ marginBottom: 10 }}>
        <div className="row" style={{ justifyContent: "space-between" }}>
          <span className="label" style={{ fontSize: 10 }}>Progress</span>
          <span className="ink-3 mono" style={{ fontSize: 11 }}>{Math.min(steps.length, step)} / {steps.length}</span>
        </div>
        <div style={{ height: 4, background: "var(--bg-2)", borderRadius: 999, overflow: "hidden" }}>
          <div style={{ width: `${(step / steps.length) * 100}%`, height: "100%", background: freelancer.accent, borderRadius: 999, transition: "width .4s cubic-bezier(.2,.7,.3,1)" }}/>
        </div>
      </div>

      <nav className="col gap-2 portal-steps" style={{ marginTop: 18, marginBottom: "auto" }}>
        {steps.map((s, i) => {
          const done = i < step;
          const current = i === step;
          return (
            <button key={s.id} onClick={() => setStep(i)} disabled={i > step}
              style={{
                display: "flex", alignItems: "center", gap: 12, padding: "10px 10px", borderRadius: 8,
                background: current ? "var(--surface)" : "transparent",
                border: "1px solid " + (current ? "var(--line)" : "transparent"),
                boxShadow: current ? "var(--shadow-sm)" : "none",
                color: "var(--ink)", cursor: i <= step ? "pointer" : "not-allowed",
                textAlign: "left", opacity: i > step ? 0.5 : 1,
              }}>
              <span style={{ width: 22, height: 22, borderRadius: "50%", background: done ? freelancer.accent : current ? "var(--primary-soft)" : "transparent", border: "1px solid " + (done || current ? freelancer.accent : "var(--line)"), color: done ? "#fff" : current ? freelancer.accent : "var(--ink-3)", display: "grid", placeItems: "center", fontSize: 11, fontWeight: 600, flexShrink: 0 }}>
                {done ? <Icon.check cls="ico-sm"/> : i+1}
              </span>
              <span className="col" style={{ lineHeight: 1.2 }}>
                <span style={{ fontSize: 13, fontWeight: current ? 500 : 400 }}>{s.label}</span>
                <span className="ink-3" style={{ fontSize: 11 }}>{s.est}</span>
              </span>
            </button>
          );
        })}
      </nav>

      <div className="portal-footer" style={{ padding: "12px 0", borderTop: "1px solid var(--line)", marginTop: 14 }}>
        <div className="row gap-10">
          <Avatar name={freelancer.name} size={32}/>
          <div className="col" style={{ lineHeight: 1.2, flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 12.5, fontWeight: 500 }}>{freelancer.name}</div>
            <div className="ink-3" style={{ fontSize: 11 }}>{freelancer.title}</div>
          </div>
        </div>
        <button className="btn btn-sm btn-ghost" style={{ width: "100%", justifyContent: "flex-start", marginTop: 8, color: "var(--ink-3)" }} onClick={() => { window.location.href = `mailto:${freelancer.email}`; toast(`Opening email to ${freelancer.name}…`); }}>
          <Icon.mail cls="ico-sm"/> Send a message
        </button>
      </div>
    </aside>
  );
}

function ClientTopbar({ client, freelancer, step, steps, onHelp }) {
  return (
    <div className="portal-topbar">
      <div className="row gap-8" style={{ fontSize: 12 }}>
        <span className="ink-3">Welcome,</span>
        <Avatar name={client.contact} size={22}/>
        <span style={{ fontWeight: 500 }}>{client.contact}</span>
      </div>
      <div className="row gap-12 topbar-right">
        <span className="ink-3" style={{ fontSize: 12 }}>Saved automatically · just now</span>
        <span className="row gap-6" style={{ fontSize: 12 }}>
          <span style={{ width: 6, height: 6, borderRadius: "50%", background: "#2D6A4F" }}/>
          <span className="ink-3">Secure session</span>
        </span>
        {onHelp && (
          <button onClick={onHelp} className="btn btn-sm btn-ghost" style={{ gap: 6 }} title="How this portal works">
            <span style={{ width: 16, height: 16, borderRadius: "50%", border: "1.5px solid var(--ink-3)", color: "var(--ink-3)", display: "grid", placeItems: "center", fontSize: 10, fontWeight: 700 }}>?</span>
            How it works
          </button>
        )}
      </div>
    </div>
  );
}

function StepHeader({ eyebrow, title, sub }) {
  return (
    <div className="col gap-8 portal-step-header">
      {eyebrow && <div className="label" style={{ color: "var(--primary)", fontSize: 10.5 }}>{eyebrow}</div>}
      <div className="h-display portal-step-title">{title}</div>
      {sub && <div className="ink-3 portal-step-sub">{sub}</div>}
    </div>
  );
}

function StepFooter({ onBack, onNext, nextLabel = "Continue", nextIcon, disabled, hint }) {
  return (
    <div className="step-footer">
      <div className="ink-3" style={{ fontSize: 12 }}>{hint}</div>
      <div className="step-footer-actions">
        {onBack && <Button onClick={onBack} icon={<Icon.arrowL cls="ico-sm"/>}>Back</Button>}
        {onNext && <Button variant="primary" size="lg" onClick={onNext} disabled={disabled} iconR={nextIcon || <Icon.arrow cls="ico-sm"/>}>{nextLabel}</Button>}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// Step 0: Welcome
// ─────────────────────────────────────────────────────────────────────
function ClientWelcome({ client, freelancer, template, advance, steps }) {
  const welcomeText = template.welcome_message
    .replace("{{client.contact}}", client.contact.split(" ")[0])
    .replace("{{client.company}}", client.company)
    .replace("{{freelancer.name}}", freelancer.name);
  // Only preview the steps THIS client will actually see (respects skipped steps),
  // so the welcome matches their sidebar — no mention of turned-off steps.
  const previewSteps = (steps || template.steps).filter(s => s.id !== "welcome");

  return (
    <div className="col gap-32">
      <StepHeader eyebrow="Welcome aboard" title={`Hi ${client.contact.split(" ")[0]}, let's get ${client.company} set up.`}
        sub={welcomeText}/>

      <Card>
        <div className="col gap-16">
          <div className="row gap-16" style={{ paddingBottom: 16, borderBottom: "1px solid var(--line-2)" }}>
            <Avatar name={freelancer.name} size={56}/>
            <div className="col gap-2" style={{ flex: 1 }}>
              <div style={{ fontSize: 15, fontWeight: 500 }}>{freelancer.name}</div>
              <div className="ink-3" style={{ fontSize: 13 }}>{freelancer.title} · {freelancer.brand}</div>
              <div className="row gap-12" style={{ marginTop: 6, fontSize: 12 }}>
                <span className="row gap-4 ink-3"><Icon.clock cls="ico-sm"/> Replies within 4h</span>
                <span className="row gap-4 ink-3"><Icon.globe cls="ico-sm"/> {freelancer.timezone}</span>
                <span className="row gap-4 ink-3"><Icon.mail cls="ico-sm"/> {freelancer.email}</span>
              </div>
            </div>
          </div>

          <div>
            <div className="label-lc" style={{ marginBottom: 10 }}>Here's what we'll do in this portal</div>
            <div className="responsive-3">
              {previewSteps.map((s, i) => (
                <div key={s.id} className="col gap-6" style={{ padding: 14, background: "var(--surface-2)", borderRadius: 10, border: "1px solid var(--line-2)" }}>
                  <span style={{ width: 22, height: 22, borderRadius: 6, background: "var(--surface)", border: "1px solid var(--line)", display: "grid", placeItems: "center", fontSize: 11, fontWeight: 600, color: "var(--ink-3)" }}>{i+1}</span>
                  <div className="col gap-2">
                    <div style={{ fontSize: 13, fontWeight: 500 }}>{s.label}</div>
                    <div className="ink-3" style={{ fontSize: 11.5, lineHeight: 1.4 }}>{s.est}</div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </Card>

      <Card>
        <div className="col gap-12">
          <div className="label-lc">The engagement at a glance</div>
          <div className="responsive-4">
            <KV label="Role" value={client.role_title}/>
            <KV label="Engagement" value={client.engagementType}/>
            <KV label="Rate" value={client.rateLabel}/>
            <KV label="Proposed start" value={fmtDate(client.startDate)}/>
          </div>
        </div>
      </Card>

      <StepFooter onNext={advance} nextLabel="Let's get started" hint="Everything saves as you go — close the tab anytime."/>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// Step 1: Intake
// ─────────────────────────────────────────────────────────────────────
function ClientIntake({ client, template, advance }) {
  // Pre-fill from anything already known about the client; the client fills the rest.
  // (Previously these defaults held hardcoded demo text — wrong for a real client.)
  const [values, setValues] = React.useState(() => ({
    legal_name: client.company || "", primary_contact: client.contact || "", primary_email: client.email || "",
    website: client.website || "", industry: client.industry || "", company_size: client.size || "",
    timezone: client.timezone || "PT", comm_pref: "Slack",
    goals: "", kpi: "", tools: "",
    // If this client already submitted once, re-show their saved answers.
    ...(client.intake || {}),
  }));
  const set = (k, v) => setValues({ ...values, [k]: v });
  const submit = () => advance({ intake: { ...values, submittedAt: new Date().toISOString() } });

  const required = template.intake_fields.filter(f => f.required);
  const valid = required.every(f => (values[f.id] || "").toString().trim().length > 0);

  return (
    <div className="col">
      <StepHeader eyebrow="About you" title="Tell me about your company"
        sub="The basics about the team, project, and goals. Two minutes — I'll use this to pre-fill everything else."/>

      <Card>
        <div className="col gap-16">
          <div className="label-lc">Company</div>
          <div className="responsive-2">
            {template.intake_fields.filter(f => ["legal_name", "website", "industry", "company_size"].includes(f.id)).map(f => (
              <IntakeInput key={f.id} field={f} value={values[f.id]} onChange={v => set(f.id, v)}/>
            ))}
          </div>
          <div className="hr"/>
          <div className="label-lc">Contact</div>
          <div className="responsive-2">
            {template.intake_fields.filter(f => ["primary_contact", "primary_email", "phone", "timezone"].includes(f.id)).map(f => (
              <IntakeInput key={f.id} field={f} value={values[f.id]} onChange={v => set(f.id, v)}/>
            ))}
          </div>
          <div className="hr"/>
          <div className="label-lc">Goals</div>
          <div className="col gap-14">
            {template.intake_fields.filter(f => ["goals", "kpi", "tools", "comm_pref"].includes(f.id)).map(f => (
              <IntakeInput key={f.id} field={f} value={values[f.id]} onChange={v => set(f.id, v)} full/>
            ))}
          </div>
        </div>
      </Card>

      <StepFooter onNext={submit} disabled={!valid} hint={valid ? "Looking good." : "A few required fields are still empty."}/>
    </div>
  );
}

function IntakeInput({ field, value, onChange, full }) {
  const id = "f-" + field.id;
  return (
    <div className="col gap-6" style={{ gridColumn: full ? "1 / -1" : "auto" }}>
      <label htmlFor={id} style={{ fontSize: 12.5, color: "var(--ink-2)", fontWeight: 500 }}>
        {field.label}{field.required && <span style={{ color: "var(--danger)" }}> *</span>}
      </label>
      {field.type === "textarea" ? (
        <textarea id={id} className="input" rows={3} value={value || ""} onChange={e => onChange(e.target.value)}/>
      ) : field.type === "select" ? (
        <select id={id} className="input" value={value || ""} onChange={e => onChange(e.target.value)}>
          <option value="">Select…</option>
          {(field.options || []).map(o => <option key={o} value={o}>{o}</option>)}
        </select>
      ) : (
        <input id={id} className="input" type={field.type} value={value || ""} onChange={e => onChange(e.target.value)}/>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// Step 2: Agreement signing
// ─────────────────────────────────────────────────────────────────────
function ClientAgreement({ client, freelancer, template, advance }) {
  const [docTab, setDocTab] = React.useState("agreement");
  const [signedName, setSignedName] = React.useState("");
  const [accepted, setAccepted] = React.useState({ agreement: false, sow: false, nda: false });
  const allDone = accepted.agreement && accepted.sow && accepted.nda && signedName.trim().length > 1;

  // Persist the actual signature record to Firestore when the client signs.
  // This is the legal proof — without it the typed name is thrown away.
  const onSign = () => {
    const signature = {
      name: signedName.trim(),
      signedAt: new Date().toISOString(),
      docsAccepted: Object.keys(accepted).filter(k => accepted[k]),
      userAgent: (typeof navigator !== "undefined" && navigator.userAgent) || "",
      screen: (typeof window !== "undefined") ? `${window.screen?.width || 0}x${window.screen?.height || 0}` : "",
      tz: (() => { try { return Intl.DateTimeFormat().resolvedOptions().timeZone; } catch { return ""; } })(),
    };
    // Mark the executed docs as signed so the admin's status badges reflect reality.
    const docs = { ...(client.docs || {}), agreement: "signed", sow: "signed", nda: "signed" };
    advance({ signature, docs });
  };

  return (
    <div className="col">
      <StepHeader eyebrow="Agreement & signature" title="Review and sign"
        sub="Three documents bundled into one signature: Service Agreement, Statement of Work, and Mutual NDA. Read carefully — your typed signature is legally binding."/>

      <div className="agreement-grid">
        <Card pad={false}>
          <div className="agreement-doc-tabs">
            {[
              { id: "agreement", label: "Service Agreement", icon: Icon.shield },
              { id: "sow", label: "Statement of Work", icon: Icon.briefcase },
              { id: "nda", label: "NDA", icon: Icon.shield },
            ].map(t => {
              const Ico = t.icon;
              return (
                <button key={t.id} onClick={() => setDocTab(t.id)} className="row gap-6" style={{
                  padding: "6px 12px", borderRadius: 6, fontSize: 12.5, fontWeight: 500,
                  background: docTab === t.id ? "var(--surface)" : "transparent",
                  border: docTab === t.id ? "1px solid var(--line)" : "1px solid transparent",
                  color: docTab === t.id ? "var(--ink)" : "var(--ink-3)", cursor: "pointer",
                }}>
                  <Ico cls="ico-sm"/> {t.label}
                  {accepted[t.id] && <Icon.check cls="ico-sm" style={{ color: "var(--success)" }}/>}
                </button>
              );
            })}
            <div style={{ marginLeft: "auto" }}>
              <Button size="sm" variant="ghost" icon={<Icon.download cls="ico-sm"/>} onClick={() => window.print()}>Save PDF</Button>
            </div>
          </div>
          <div className="agreement-doc-scroll">
            {docTab === "agreement" && <AgreementDoc client={client} freelancer={freelancer} template={template}/>}
            {docTab === "sow" && <div style={{ padding: 16 }}><SOWDocument client={client}/></div>}
            {docTab === "nda" && <NDADoc client={client} freelancer={freelancer} template={template}/>}
          </div>
        </Card>

        <div className="agreement-sign-col">
          <Card>
            <div className="col gap-14">
              <div className="row gap-8" style={{ alignItems: "center" }}>
                <Icon.signature cls="ico-sm"/>
                <span style={{ fontSize: 14, fontWeight: 500 }}>Sign all three</span>
              </div>
              <div className="col gap-10">
                {[
                  { id: "agreement", label: "Service Agreement" },
                  { id: "sow", label: "Statement of Work" },
                  { id: "nda", label: "Mutual NDA" },
                ].map(d => (
                  <label key={d.id} className="row gap-10" style={{ padding: "10px 12px", border: "1px solid var(--line)", borderRadius: 8, cursor: "pointer", background: accepted[d.id] ? "var(--primary-soft-2)" : "var(--surface)" }}>
                    <input type="checkbox" checked={accepted[d.id]} onChange={e => setAccepted({ ...accepted, [d.id]: e.target.checked })}/>
                    <span style={{ fontSize: 13, flex: 1 }}>I've read & agree to the <strong>{d.label}</strong></span>
                  </label>
                ))}
              </div>
              <div className="hr"/>
              <div className="col gap-6">
                <span className="label-lc" style={{ fontSize: 12 }}>Type your full legal name</span>
                <input className="input" value={signedName} onChange={e => setSignedName(e.target.value)} placeholder={client.contact} style={{ fontFamily: "Instrument Serif", fontSize: 24, padding: "12px 14px", fontStyle: "italic" }}/>
                <div className="ink-3" style={{ fontSize: 11.5 }}>This counts as your e-signature ({fmtDate(new Date())} · IP logged).</div>
              </div>
              <Button variant="primary" size="lg" onClick={onSign} disabled={!allDone} style={{ justifyContent: "center" }}
                iconR={<Icon.signature cls="ico-sm"/>}>
                {allDone ? "Sign & continue" : "Complete all three"}
              </Button>
            </div>
          </Card>

          <Card>
            <div className="col gap-8">
              <div className="label-lc" style={{ fontSize: 12 }}>What you're agreeing to</div>
              <div className="col gap-6" style={{ fontSize: 12.5, lineHeight: 1.5, color: "var(--ink-3)" }}>
                <span>· {client.engagementType}</span>
                <span>· {client.rateLabel}, net {template.net_days} days</span>
                <span>· 14-day mutual termination notice</span>
                <span>· IP transfers on full payment</span>
                <span>· Confidentiality survives termination</span>
              </div>
            </div>
          </Card>
        </div>
      </div>
    </div>
  );
}

function AgreementDoc({ client, freelancer, template }) {
  const overrideHtml = window.buildDocInlineHTML && window.buildDocInlineHTML({ docKey: "service_agreement", client, freelancer, template });
  return (
    <div className="doc-paper" style={{ borderRadius: 0, border: 0, boxShadow: "none", padding: "32px 48px" }}>
      <div className="row" style={{ justifyContent: "space-between", alignItems: "flex-start", marginBottom: 24 }}>
        <div>
          <h1>Services Agreement</h1>
          <div className="ink-3" style={{ fontSize: 12 }}>Between {freelancer.brand} and {client.company}</div>
        </div>
        <div className="col" style={{ textAlign: "right", fontSize: 12 }}>
          <span className="ink-3">Effective</span>
          <span className="mono">{fmtDate(client.startDate)}</span>
        </div>
      </div>

      {overrideHtml
        ? <div dangerouslySetInnerHTML={{ __html: overrideHtml }} />
        : <>
            <p>This agreement ("Agreement") is entered into on {fmtDate(new Date())} by and between <strong>{freelancer.name}</strong>, doing business as <strong>{freelancer.brand}</strong>, an independent contractor ("Contractor"), and <strong>{client.company}</strong> ("Client"), regarding the services described in Exhibit A — Statement of Work.</p>
            {template.agreement_clauses.map((c, i) => (
              <div key={c.id}>
                <h2>{i+1}. {c.label}</h2>
                <p>{c.body
                  .replace("{{date}}", fmtDate(new Date()))
                  .replace("{{rate}}", client.rateLabel)
                  .replace("{{start_date}}", fmtDate(client.startDate))}</p>
              </div>
            ))}
          </>
      }

      <div className="responsive-2" style={{ marginTop: 36, gap: 32, borderTop: "1px solid var(--line)", paddingTop: 24 }}>
        <div>
          <div className="ink-3" style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: 0.05, marginBottom: 4 }}>Contractor</div>
          <div style={{ fontFamily: "Instrument Serif", fontSize: 24, fontStyle: "italic" }}>{freelancer.name}</div>
          <div style={{ borderTop: "1px solid var(--ink)", paddingTop: 6, fontSize: 11.5, color: "var(--ink-3)" }}>{freelancer.name} · {fmtDate(new Date())}</div>
        </div>
        <div>
          <div className="ink-3" style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: 0.05, marginBottom: 4 }}>Client</div>
          <div style={{ fontFamily: "Instrument Serif", fontSize: 24, fontStyle: "italic", color: client.signature ? "var(--ink)" : "var(--ink-3)", minHeight: 36 }}>{(client.signature && client.signature.name) || "—"}</div>
          <div style={{ borderTop: "1px solid " + (client.signature ? "var(--ink)" : "var(--line)"), paddingTop: 6, fontSize: 11.5, color: "var(--ink-3)" }}>{client.contact} · {client.signature && client.signature.signedAt ? "signed " + fmtDate(client.signature.signedAt) : "pending"}</div>
        </div>
      </div>
    </div>
  );
}

function NDADoc({ client, freelancer, template }) {
  const overrideHtml = window.buildDocInlineHTML && window.buildDocInlineHTML({ docKey: "nda", client, freelancer, template });
  return (
    <div className="doc-paper" style={{ borderRadius: 0, border: 0, boxShadow: "none", padding: "32px 48px" }}>
      <h1>Mutual NDA</h1>
      <div className="ink-3" style={{ fontSize: 12, marginBottom: 20 }}>Effective {fmtDate(new Date())}</div>
      {overrideHtml
        ? <div dangerouslySetInnerHTML={{ __html: overrideHtml }} />
        : <>
            <p>{freelancer.name} ("Contractor") and {client.company} ("Client") agree to keep confidential all non-public information shared in connection with the engagement.</p>
            <h2>Definition</h2>
            <p>"Confidential Information" means any business, technical, financial, customer or product information that is marked or reasonably understood to be confidential, including but not limited to credentials, pricing, customer lists, source code, and unreleased product plans.</p>
            <h2>Obligations</h2>
            <p>Each party will (a) use Confidential Information only to perform under the engagement, (b) protect it with reasonable care, and (c) limit access to people with a need to know who are bound by similar obligations.</p>
            <h2>Exceptions</h2>
            <p>Confidential Information does not include information that is publicly available, independently developed without reference to the disclosing party, or rightfully received from a third party.</p>
            <h2>Term</h2>
            <p>This NDA is effective from the date above and survives termination of any underlying engagement in perpetuity.</p>
          </>
      }
      <div className="responsive-2" style={{ marginTop: 36, gap: 32, borderTop: "1px solid var(--line)", paddingTop: 24 }}>
        <div>
          <div className="ink-3" style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: 0.05, marginBottom: 4 }}>Contractor</div>
          <div style={{ fontFamily: "Instrument Serif", fontSize: 24, fontStyle: "italic" }}>{freelancer.name}</div>
          <div style={{ borderTop: "1px solid var(--ink)", paddingTop: 6, fontSize: 11.5, color: "var(--ink-3)" }}>{freelancer.name} · {client.signature && client.signature.signedAt ? fmtDate(client.signature.signedAt) : fmtDate(new Date())}</div>
        </div>
        <div>
          <div className="ink-3" style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: 0.05, marginBottom: 4 }}>Client</div>
          <div style={{ fontFamily: "Instrument Serif", fontSize: 24, fontStyle: "italic", color: client.signature ? "var(--ink)" : "var(--ink-3)", minHeight: 36 }}>{(client.signature && client.signature.name) || "—"}</div>
          <div style={{ borderTop: "1px solid " + (client.signature ? "var(--ink)" : "var(--line)"), paddingTop: 6, fontSize: 11.5, color: "var(--ink-3)" }}>{client.contact} · {client.signature && client.signature.signedAt ? "signed " + fmtDate(client.signature.signedAt) : "pending"}</div>
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// PayPal Smart Buttons — fully embedded, zero backend
// ─────────────────────────────────────────────────────────────────────
function usePayPalSDK(clientId, currency) {
  const [ready, setReady] = React.useState(!!window.paypal);
  const [error, setError] = React.useState(null);
  React.useEffect(() => {
    if (!clientId) return;
    if (window.paypal) { setReady(true); return; }
    // Remove any existing PayPal script first
    const existing = document.querySelector('script[data-paypal-sdk]');
    if (existing) existing.remove();
    const script = document.createElement("script");
    script.src = `https://www.paypal.com/sdk/js?client-id=${clientId}&currency=${currency || "USD"}`;
    script.setAttribute("data-paypal-sdk", "1");
    script.onload = () => setReady(true);
    script.onerror = () => setError("PayPal SDK failed to load — check your Client ID");
    document.head.appendChild(script);
  }, [clientId, currency]);
  return { ready, error };
}

function PayPalSmartButtons({ clientId, amount, currency, onSuccess, onError }) {
  const containerRef = React.useRef(null);
  const { ready, error } = usePayPalSDK(clientId, currency);
  const [rendered, setRendered] = React.useState(false);

  React.useEffect(() => {
    if (!ready || !containerRef.current || rendered) return;
    setRendered(true);
    const container = containerRef.current;
    container.innerHTML = "";
    try {
      window.paypal.Buttons({
        style: { layout: "vertical", color: "blue", shape: "rect", label: "pay", height: 44 },
        createOrder: (data, actions) => actions.order.create({
          purchase_units: [{ amount: { value: String(amount), currency_code: currency || "USD" } }],
        }),
        onApprove: (data, actions) => actions.order.capture().then((details) => {
          onSuccess(details);
        }),
        onError: (err) => {
          console.error("PayPal error:", err);
          if (onError) onError(err);
        },
        onCancel: () => console.log("PayPal payment cancelled"),
      }).render(container);
    } catch (e) {
      console.error("PayPal render error:", e);
    }
  }, [ready, amount, currency]);

  if (error) return (
    <div style={{ padding: 12, background: "var(--danger-soft)", borderRadius: 8, fontSize: 12.5, color: "var(--danger)" }}>
      {error}
    </div>
  );
  if (!ready) return (
    <div style={{ padding: 14, background: "var(--surface-2)", borderRadius: 8, textAlign: "center" }}>
      <div style={{ width: 20, height: 20, border: "2px solid #003087", borderTopColor: "transparent", borderRadius: "50%", animation: "spin 0.8s linear infinite", margin: "0 auto 8px" }}/>
      <div style={{ fontSize: 12.5, color: "var(--ink-3)" }}>Loading PayPal…</div>
      <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
    </div>
  );
  return <div ref={containerRef} style={{ minHeight: 50 }}/>;
}

// ─────────────────────────────────────────────────────────────────────
// Step 3: Invoice / payment
// ─────────────────────────────────────────────────────────────────────
function ClientInvoice({ client, freelancer, advance }) {
  const { paymentProviders } = useApp();
  // A method only counts if it's REALLY configured — a real Stripe/PayPal link,
  // a PayPal client id, or a real Wise/Payoneer account. The demo "connected"
  // flag alone doesn't qualify (that's what showed fake options before).
  const isUsable = (p) =>
    (p.id === "stripe" && !!p.paymentUrl) ||
    (p.id === "paypal" && (!!p.clientId || !!p.paymentUrl)) ||
    ((p.id === "wise" || p.id === "payoneer") && !!p.account && /^https?:|\./.test(String(p.account)));
  // Usable AND not hidden by the "Show to clients" toggle in Settings → Payments.
  const connected = paymentProviders.filter(p => isUsable(p) && p.portalEnabled !== false);
  const [method, setMethod] = React.useState(connected[0]?.id || "stripe");
  const [paying, setPaying] = React.useState(false);
  const total = client.rate;
  const billing = client.billing;
  let deposit, label;
  if (billing && billing.frequency) {
    if (billing.frequency === "onetime") {
      deposit = Math.round((billing.amount || 0) * ((billing.depositPct || 50) / 100));
      label = `${billing.depositPct || 50}% deposit`;
    } else {
      deposit = billing.amount || 0;
      label = ({ weekly: "Week 1", biweekly: "First period", monthly: "Month 1" }[billing.frequency]) || "First payment";
    }
  } else {
    deposit = client.hoursPerWeek ? total : Math.round(total * 0.5);
    label = client.hoursPerWeek ? "First payment" : "50% project deposit";
  }
  const billingPayLink = billing && billing.payLink;
  const cur = freelancer.currency;
  const selected = connected.find(p => p.id === method) || connected[0];

  const pay = () => {
    if (!selected) return;

    // PayPal Smart Buttons — handled by the PayPalSmartButtons component directly
    if (selected.id === "paypal" && selected.clientId) return;

    // Stripe — open Payment Link in a centered popup
    if (selected.id === "stripe" && selected.paymentUrl) {
      const w = 520, h = 700;
      const left = Math.max(0, (window.screen.width - w) / 2);
      const top = Math.max(0, (window.screen.height - h) / 2);
      window.open(selected.paymentUrl, "stripe-checkout",
        `width=${w},height=${h},left=${left},top=${top},resizable=yes,scrollbars=yes`);
      setPaying(true);
      setTimeout(() => setPaying(false), 1500);
      return;
    }

    // PayPal.me fallback — popup
    if (selected.id === "paypal" && selected.paymentUrl) {
      const url = `https://www.${selected.paymentUrl}/${deposit}`;
      const w = 520, h = 700;
      const left = Math.max(0, (window.screen.width - w) / 2);
      const top = Math.max(0, (window.screen.height - h) / 2);
      window.open(url, "paypal-payment", `width=${w},height=${h},left=${left},top=${top}`);
      setPaying(true);
      setTimeout(() => setPaying(false), 1500);
      return;
    }

    // Wise / Payoneer — popup
    if ((selected.id === "wise" || selected.id === "payoneer") && selected.account) {
      const url = selected.account.startsWith("http") ? selected.account : `https://www.${selected.account}`;
      window.open(url, "_blank", "noopener");
      setPaying(true);
      setTimeout(() => setPaying(false), 1500);
      return;
    }

    // Demo fallback
    setPaying(true);
    setTimeout(advance, 1200);
  };

  return (
    <div className="col">
      <StepHeader eyebrow="Deposit invoice" title="Activate the engagement"
        sub={`A ${client.hoursPerWeek ? "first month" : "50% deposit"} unlocks scheduling and kicks off the work. The remainder follows the payment schedule in your SOW.`}/>

      <div className="agreement-grid">
        {/* Invoice doc */}
        <div className="doc-paper" style={{ padding: "40px 48px" }}>
          <div className="row" style={{ justifyContent: "space-between", alignItems: "flex-start", marginBottom: 28 }}>
            <div>
              <h1>Invoice</h1>
              <div className="ink-3 mono" style={{ fontSize: 12, marginTop: 2 }}>#INV-{clientSlug(client.company).toUpperCase()}-001</div>
            </div>
            <LogoMark size={36} color="var(--primary)"/>
          </div>

          <div className="responsive-2" style={{ gap: 28, marginBottom: 28 }}>
            <div className="col gap-2">
              <div className="ink-3" style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: 0.05 }}>From</div>
              <div style={{ fontSize: 13, fontWeight: 500 }}>{freelancer.name}</div>
              <div className="ink-3" style={{ fontSize: 12 }}>{freelancer.brand}<br/>{freelancer.email}</div>
            </div>
            <div className="col gap-2">
              <div className="ink-3" style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: 0.05 }}>Bill to</div>
              <div style={{ fontSize: 13, fontWeight: 500 }}>{client.company}</div>
              <div className="ink-3" style={{ fontSize: 12 }}>Attn: {client.contact}<br/>{client.email}</div>
            </div>
            <div className="col gap-2">
              <div className="ink-3" style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: 0.05 }}>Issued</div>
              <div className="mono" style={{ fontSize: 12 }}>{fmtDate(new Date())}</div>
            </div>
            <div className="col gap-2">
              <div className="ink-3" style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: 0.05 }}>Due</div>
              <div className="mono" style={{ fontSize: 12 }}>{fmtDate(daysAhead(7))}</div>
            </div>
          </div>

          <div style={{ borderTop: "1px solid var(--ink)", borderBottom: "1px solid var(--line)" }}>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 80px 110px", padding: "10px 0", fontSize: 11, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: 0.05, fontWeight: 600, borderBottom: "1px solid var(--line-2)" }}>
              <span>Description</span><span style={{ textAlign: "right" }}>Qty</span><span style={{ textAlign: "right" }}>Amount</span>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 80px 110px", padding: "14px 0", fontSize: 13, borderBottom: "1px solid var(--line-2)" }}>
              <div className="col">
                <span>{label}</span>
                <span className="ink-3" style={{ fontSize: 12 }}>{client.role_title} — {fmtDate(client.startDate)} onward</span>
              </div>
              <span className="mono" style={{ textAlign: "right" }}>1</span>
              <span className="mono" style={{ textAlign: "right" }}>{fmtMoney(deposit, cur)}</span>
            </div>
          </div>

          <div className="col gap-4" style={{ marginTop: 16, marginLeft: "auto", width: 200 }}>
            <div className="row" style={{ justifyContent: "space-between", fontSize: 12.5 }}>
              <span className="ink-3">Subtotal</span><span className="mono">{fmtMoney(deposit, cur)}</span>
            </div>
            <div className="row" style={{ justifyContent: "space-between", fontSize: 12.5 }}>
              <span className="ink-3">Tax</span><span className="mono">{fmtMoney(0, cur)}</span>
            </div>
            <div className="row" style={{ justifyContent: "space-between", paddingTop: 10, marginTop: 4, borderTop: "1px solid var(--ink)", fontSize: 16, fontWeight: 600 }}>
              <span>Total due</span><span className="mono">{fmtMoney(deposit, cur)}</span>
            </div>
          </div>

          <div className="ink-3" style={{ fontSize: 11.5, marginTop: 28, paddingTop: 16, borderTop: "1px solid var(--line-2)", lineHeight: 1.6 }}>
            Payable in {cur} via card, ACH, or wire. Net 7 days. Late payments accrue 1.5% interest per month. Reference invoice number on bank transfers.
          </div>
        </div>

        {/* Payment panel */}
        <Card style={{ position: "sticky", top: 20 }}>
          <div className="col gap-16">
            <div className="row" style={{ justifyContent: "space-between", alignItems: "flex-end" }}>
              <div className="col gap-2">
                <span className="label-lc" style={{ fontSize: 12 }}>Pay now</span>
                <span className="h-display" style={{ fontSize: 30, lineHeight: 1 }}>{fmtMoney(deposit, cur)}</span>
              </div>
              <span className="badge pill-active">Secure</span>
            </div>

            {/* Direct pay link set by your freelancer */}
            {billingPayLink && (
              <div className="col gap-6">
                <a href={billingPayLink} target="_blank" rel="noreferrer" className="btn btn-primary btn-lg" style={{ justifyContent: "center", width: "100%" }}>
                  <Icon.external cls="ico-sm"/> Pay {fmtMoney(deposit, cur)} now
                </a>
                <div className="row gap-8" style={{ alignItems: "center" }}>
                  <span style={{ flex: 1, height: 1, background: "var(--line)" }}/>
                  <span className="ink-3" style={{ fontSize: 11 }}>or choose a method</span>
                  <span style={{ flex: 1, height: 1, background: "var(--line)" }}/>
                </div>
              </div>
            )}

            {/* No payment method configured AND no direct link — don't fake it. */}
            {!billingPayLink && connected.length === 0 && (
              <div className="col gap-10">
                <div style={{ padding: 12, background: "#FFF4E5", border: "1px solid #F4D9A8", borderRadius: 8, fontSize: 12.5, lineHeight: 1.55 }}>
                  <strong>No online payment method is set up yet.</strong> {(freelancer && freelancer.name ? freelancer.name.split(" ")[0] : "Your freelancer")} will send you a payment link or instructions separately. You can continue for now.
                </div>
                <button className="btn btn-sm" style={{ alignSelf: "flex-start" }} onClick={advance}><Icon.check cls="ico-sm"/> Continue</button>
              </div>
            )}

            {/* Method selector */}
            <div className="col gap-6">
              {connected.map(p => (
                <button key={p.id} onClick={() => setMethod(p.id)} style={{
                  display: "flex", alignItems: "center", gap: 10, padding: 12, borderRadius: 8,
                  background: method === p.id ? "var(--primary-soft-2)" : "var(--surface)",
                  border: "1px solid " + (method === p.id ? "var(--primary)" : "var(--line)"),
                  cursor: "pointer", textAlign: "left", width: "100%",
                }}>
                  <span style={{ width: 30, height: 22, borderRadius: 4, background: p.color, color: "#fff", display: "grid", placeItems: "center", fontSize: 9, fontWeight: 700, letterSpacing: "-0.02em" }}>{p.name.slice(0,3).toUpperCase()}</span>
                  <div className="col" style={{ lineHeight: 1.25, flex: 1 }}>
                    <span style={{ fontSize: 13, fontWeight: 500 }}>{p.name}</span>
                    <span className="ink-3" style={{ fontSize: 11 }}>
                      {p.id === "paypal" && p.clientId ? "Smart Buttons · embedded · no redirect" :
                       p.id === "stripe" && p.paymentUrl ? "Checkout opens in popup" :
                       p.tagline}
                    </span>
                  </div>
                  {p.id === "paypal" && p.clientId && (
                    <span className="badge pill-active" style={{ fontSize: 9 }}>Direct</span>
                  )}
                  <span style={{ width: 16, height: 16, borderRadius: "50%", border: "1px solid var(--line)", background: method === p.id ? "var(--primary)" : "transparent", flexShrink: 0 }}/>
                </button>
              ))}
            </div>

            {/* ── PayPal Smart Buttons (embedded, zero backend) ── */}
            {selected?.id === "paypal" && selected?.clientId && (
              <div className="col gap-10">
                <div className="row gap-6" style={{ alignItems: "center", fontSize: 12, color: "var(--ink-3)" }}>
                  <span style={{ width: 6, height: 6, borderRadius: "50%", background: "#003087" }}/>
                  Pay with PayPal, card, Venmo, or Pay Later — securely inside this portal
                </div>
                <PayPalSmartButtons
                  clientId={selected.clientId}
                  amount={deposit}
                  currency={cur}
                  onSuccess={(details) => {
                    advance();
                  }}
                  onError={(err) => {}}
                />
              </div>
            )}

            {/* ── Stripe — popup checkout ── */}
            {selected?.id === "stripe" && selected?.paymentUrl && (
              <div className="col gap-10">
                <Button variant="primary" size="lg" onClick={pay}
                  disabled={paying}
                  style={{ justifyContent: "center", width: "100%" }}
                  iconR={paying ? null : <Icon.external cls="ico-sm"/>}>
                  {paying ? "Opening Stripe checkout…" : `Pay ${fmtMoney(deposit, cur)} via Stripe`}
                </Button>
                <div className="row gap-6" style={{ padding: 10, background: "var(--surface-2)", borderRadius: 8, border: "1px solid var(--line-2)", fontSize: 12 }}>
                  <Icon.shield cls="ico-sm" style={{ color: "var(--primary)", flexShrink: 0 }}/>
                  <div className="col gap-4">
                    <span style={{ color: "var(--ink-2)" }}>Stripe checkout opens in a popup. After payment, come back here and click below.</span>
                    <button className="btn btn-sm" style={{ alignSelf: "flex-start", color: "var(--primary)", borderColor: "var(--primary-soft)" }} onClick={advance}>
                      <Icon.check cls="ico-sm"/> Payment complete — continue
                    </button>
                  </div>
                </div>
                <div className="ink-3" style={{ fontSize: 11, textAlign: "center" }}>Powered by Stripe · 256-bit TLS · PCI DSS compliant</div>
              </div>
            )}

            {/* ── PayPal .me fallback (no clientId) ── */}
            {selected?.id === "paypal" && !selected?.clientId && (
              <div className="col gap-10">
                <Button variant="primary" size="lg" onClick={pay}
                  disabled={paying}
                  style={{ justifyContent: "center", width: "100%" }}
                  iconR={<Icon.external cls="ico-sm"/>}>
                  {paying ? "Opening PayPal…" : `Pay ${fmtMoney(deposit, cur)} via PayPal`}
                </Button>
                <button className="btn btn-sm" style={{ alignSelf: "flex-start" }} onClick={advance}>
                  <Icon.check cls="ico-sm"/> I've paid — continue
                </button>
              </div>
            )}

            {/* ── Stripe no payment URL configured ── */}
            {selected?.id === "stripe" && !selected?.paymentUrl && (
              <div className="col gap-10">
                <div style={{ padding: 12, background: "#FFF4E5", border: "1px solid #F4D9A8", borderRadius: 8, fontSize: 12.5 }}>
                  <strong>Set up your Stripe link</strong> in Settings → Payments → Stripe to enable card payments.
                </div>
                <Button variant="primary" size="lg" onClick={pay} style={{ justifyContent: "center", width: "100%" }} disabled={paying}>
                  {paying ? "Processing…" : `Pay ${fmtMoney(deposit, cur)} (demo)`}
                </Button>
              </div>
            )}

            {/* ── Wise / Payoneer ── */}
            {selected && (selected.id === "wise" || selected.id === "payoneer") && (
              <div className="col gap-10">
                <div className="col gap-6" style={{ padding: 12, background: "var(--surface-2)", borderRadius: 8, border: "1px solid var(--line-2)" }}>
                  <div className="row gap-6"><Icon.link cls="ico-sm"/>
                    <span className="mono" style={{ fontSize: 11.5, color: "var(--ink-3)" }}>{(selected.account || selected.linkFormat).replace("yourname", "alex-mira")}</span>
                  </div>
                  <div className="ink-3" style={{ fontSize: 12, lineHeight: 1.55 }}>Opens {selected.name} with amount and reference pre-filled.</div>
                </div>
                <Button variant="primary" size="lg" onClick={pay} style={{ justifyContent: "center", width: "100%" }} iconR={<Icon.external cls="ico-sm"/>}>
                  Pay via {selected.name}
                </Button>
                <button className="btn btn-sm" style={{ alignSelf: "flex-start" }} onClick={advance}>
                  <Icon.check cls="ico-sm"/> I've paid — continue
                </button>
              </div>
            )}

            {/* ── GCash ── */}
            {selected?.id === "gcash" && (
              <div className="col gap-10" style={{ alignItems: "center" }}>
                <div className="label-lc" style={{ fontSize: 11.5 }}>Scan with GCash</div>
                <div style={{ width: 130, height: 130, background: "#fff", border: "1px solid var(--line)", borderRadius: 8, display: "grid", gridTemplateColumns: "repeat(8, 1fr)", gridTemplateRows: "repeat(8, 1fr)", gap: 1, padding: 8 }}>
                  {Array.from({ length: 64 }).map((_, i) => (
                    <div key={i} style={{ background: ((i * 17 + 31) % 7) > 3 ? "#0F1A14" : "transparent" }}/>
                  ))}
                </div>
                <div className="mono" style={{ fontSize: 11.5 }}>Ref: INV-{clientSlug(client.company).toUpperCase()}-001</div>
                <button className="btn btn-sm btn-primary" style={{ marginTop: 4 }} onClick={advance}>
                  <Icon.check cls="ico-sm"/> Receipt sent — continue
                </button>
              </div>
            )}

            {/* ── Bank transfer ── */}
            {selected?.id === "bank" && (
              <div className="col gap-10">
                <div className="col gap-6" style={{ padding: 12, background: "var(--surface-2)", borderRadius: 8, border: "1px solid var(--line-2)", fontSize: 12 }}>
                  <div className="label-lc" style={{ fontSize: 11.5 }}>Wire / ACH instructions</div>
                  <div className="mono" style={{ fontSize: 11.5, lineHeight: 1.7, color: "var(--ink-2)" }}>
                    Beneficiary: {freelancer.name}<br/>
                    Bank: First Bank · ••••4421<br/>
                    Routing: 121000358<br/>
                    Reference: INV-{clientSlug(client.company).toUpperCase()}-001
                  </div>
                </div>
                <button className="btn btn-sm" style={{ alignSelf: "flex-start" }} onClick={advance}>
                  <Icon.check cls="ico-sm"/> Wire sent — continue
                </button>
              </div>
            )}

            {!selected && (
              <div style={{ padding: 12, background: "var(--danger-soft)", borderRadius: 8, fontSize: 12.5, color: "var(--danger)" }}>
                No payment methods connected. Go to Settings → Payments to set up Stripe or PayPal.
              </div>
            )}
          </div>
        </Card>
      </div>

      <div style={{ marginTop: 24 }}>
        <StepFooter onNext={null} hint="Or pay later — your portal stays open."/>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// Step 4: File upload
// ─────────────────────────────────────────────────────────────────────
function ClientFilesUpload({ advance, client, freelancer }) {
  const { toast } = useToast();
  const { updateClient } = useApp();
  // Real, persisted uploads — start from whatever this client already uploaded.
  const [files, setFiles] = React.useState(() => client.files || []);
  const [drag, setDrag] = React.useState(false);
  const [uploading, setUploading] = React.useState(0);
  const fileInputRef = React.useRef(null);

  const sizeLabel = (b) => b > 1024 * 1024 ? (b / 1024 / 1024).toFixed(1) + " MB" : Math.round(b / 1024) + " KB";
  const kindOf = (name) => (String(name).split(".").pop() || "file").slice(0, 4).toLowerCase();

  const remove = (i) => {
    if (!confirm("Remove this file?")) return;
    const next = files.filter((_, ix) => ix !== i);
    setFiles(next); updateClient(client.id, { files: next });
    toast("File removed", { kind: "warn" });
  };

  const addFiles = async (list) => {
    const all = [...(list || [])];
    const arr = all.filter(f => f.size <= 50 * 1024 * 1024);
    if (arr.length < all.length) toast("Some files were over 50 MB and skipped", { kind: "warn" });
    if (!arr.length) return;
    const storage = window.getStorage && window.getStorage();
    if (!storage) { toast("Upload isn't available right now — please email the files instead.", { kind: "danger", duration: 5000 }); return; }
    setUploading(u => u + arr.length);
    let current = files;
    for (const f of arr) {
      try {
        const path = `client-uploads/${client.id}/${Date.now()}-${f.name}`;
        const ref = storage.ref().child(path);
        await ref.put(f, { contentType: f.type || "application/octet-stream" });
        const url = await ref.getDownloadURL();
        current = [...current, { name: f.name, size: sizeLabel(f.size), kind: kindOf(f.name), url, progress: 100, uploadedAt: new Date().toISOString() }];
        setFiles(current); updateClient(client.id, { files: current });
      } catch (e) {
        toast(`Couldn't upload ${f.name}: ${String(e.message || e)}`, { kind: "danger", duration: 5000 });
      } finally {
        setUploading(u => Math.max(0, u - 1));
      }
    }
    toast("Files uploaded — your freelancer can see them now.", { kind: "success" });
  };
  const onDrop = (e) => {
    e.preventDefault(); setDrag(false);
    addFiles(e.dataTransfer?.files);
  };

  return (
    <div className="col">
      <StepHeader eyebrow="Brand & assets" title="Drop in everything I'll need"
        sub="Logos, brand guidelines, fonts, screenshots of current systems, access credentials. Anything you have. We'll store it securely and use it across the project."/>

      <div className="col gap-20">
        <input ref={fileInputRef} type="file" multiple style={{ display: "none" }} onChange={e => { addFiles(e.target.files); e.target.value = ""; }}/>
        <div onDragOver={e => { e.preventDefault(); setDrag(true); }} onDragLeave={() => setDrag(false)} onDrop={onDrop} onClick={() => fileInputRef.current && fileInputRef.current.click()}
          style={{
            border: "2px dashed " + (drag ? "var(--primary)" : "var(--line)"),
            background: drag ? "var(--primary-soft-2)" : "var(--surface)",
            borderRadius: 12, padding: 40, textAlign: "center", transition: "all .15s", cursor: "pointer",
          }}>
          <div className="col gap-8" style={{ alignItems: "center" }}>
            <div style={{ width: 48, height: 48, borderRadius: 12, background: "var(--primary-soft)", color: "var(--primary)", display: "grid", placeItems: "center" }}>
              <Icon.upload cls="ico-lg"/>
            </div>
            <div className="h-display" style={{ fontSize: 22 }}>Drop files here</div>
            <div className="ink-3" style={{ fontSize: 13 }}>or <span style={{ color: "var(--primary)", textDecoration: "underline" }}>browse</span> · up to 50 MB per file</div>
          </div>
        </div>

        {(files.length > 0 || uploading > 0) && (
          <div className="col gap-10">
            <div className="row" style={{ justifyContent: "space-between" }}>
              <span className="label-lc">Uploaded files ({files.length})</span>
              {uploading > 0 && <span className="ink-3" style={{ fontSize: 12 }}>Uploading {uploading}…</span>}
            </div>
            {files.length > 0 && (
              <Card pad={false}>
                {files.map((f, i) => (
                  <div key={i} className="row gap-12" style={{ padding: "12px 16px", borderBottom: i < files.length - 1 ? "1px solid var(--line-2)" : "none" }}>
                    <div style={{ width: 30, height: 36, borderRadius: 4, background: "var(--bg-2)", color: "var(--ink-3)", fontSize: 9, fontWeight: 600, display: "grid", placeItems: "center", textTransform: "uppercase" }}>{f.kind}</div>
                    <div className="col" style={{ flex: 1, lineHeight: 1.3, minWidth: 0 }}>
                      {f.url
                        ? <a href={f.url} target="_blank" rel="noreferrer" style={{ fontSize: 13, color: "var(--primary)", textDecoration: "none" }}>{f.name}</a>
                        : <div style={{ fontSize: 13 }}>{f.name}</div>}
                      <div className="ink-3" style={{ fontSize: 11.5 }}>{f.size}</div>
                    </div>
                    <span className="ink-3 mono" style={{ fontSize: 11 }}>Done</span>
                    <button className="btn btn-sm btn-ghost" onClick={() => remove(i)}><Icon.trash cls="ico-sm"/></button>
                  </div>
                ))}
              </Card>
            )}
          </div>
        )}

        <Card>
          <div className="col gap-12">
            <div className="col gap-2">
              <div className="label-lc">Share tool access (optional)</div>
              <div className="ink-3" style={{ fontSize: 12.5, lineHeight: 1.55 }}>
                Need to give {(freelancer && freelancer.name ? freelancer.name.split(" ")[0] : "me")} a login (Notion, Slack, Stripe, etc.)? <strong>Never email or DM a password.</strong> Use Bitwarden Send — it's free, no account needed, and the link auto-expires after it's viewed.
              </div>
            </div>

            <div className="col gap-8" style={{ padding: 14, background: "#EEF3FF", border: "1px solid #C7D6F5", borderRadius: 10 }}>
              <div className="row gap-8" style={{ alignItems: "center" }}>
                <span style={{ width: 26, height: 26, borderRadius: 6, background: "#175DDC", color: "#fff", display: "grid", placeItems: "center", fontWeight: 700, fontSize: 13 }}>B</span>
                <span style={{ fontSize: 13.5, fontWeight: 500 }}>Share a login securely in 4 steps</span>
              </div>
              <ol style={{ margin: 0, paddingLeft: 18, fontSize: 12.5, lineHeight: 1.7, color: "var(--ink-2)" }}>
                <li>Open <strong>send.bitwarden.com</strong></li>
                <li>Choose <strong>Text</strong> → paste the username + password</li>
                <li>Set deletion to <strong>1 day</strong> and toggle <strong>"Hide text by default"</strong></li>
                <li>Copy the link and send it to {(freelancer && freelancer.email) ? freelancer.email : "your contact"}</li>
              </ol>
              <a href="https://send.bitwarden.com" target="_blank" rel="noreferrer" className="btn btn-sm" style={{ alignSelf: "flex-start", background: "#175DDC", color: "#fff", borderColor: "#175DDC" }}>
                <Icon.external cls="ico-sm"/> Open Bitwarden Send
              </a>
            </div>

            <div className="ink-3" style={{ fontSize: 11.5, lineHeight: 1.5 }}>
              Prefer to just invite {(freelancer && freelancer.name ? freelancer.name.split(" ")[0] : "me")} as a guest/collaborator inside each app? That works too — that way you never share a password at all. Message me if you're unsure which apps I need.
            </div>
          </div>
        </Card>
      </div>

      <StepFooter onNext={advance} hint="You can come back and add more later." nextLabel="Continue to scheduling"/>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// Step 5: Kickoff scheduling
// ─────────────────────────────────────────────────────────────────────
function ClientKickoff({ client, freelancer, advance }) {
  const { toast } = useToast();
  const [date, setDate] = React.useState(2);
  const [time, setTime] = React.useState("10:00 AM");
  const [confirmed, setConfirmed] = React.useState(false);
  const scheduling = loadSchedulingConfig();

  const week = [];
  const today = new Date(TODAY);
  for (let i = 1; i <= 7; i++) {
    const d = new Date(today); d.setDate(d.getDate() + i);
    week.push({ idx: i, d, day: d.toLocaleDateString("en-US", { weekday: "short" }), date: d.getDate(), busy: i === 1 || i === 5 });
  }
  const times = ["9:00 AM", "10:00 AM", "11:00 AM", "1:00 PM", "2:00 PM", "3:30 PM"];

  if (confirmed) {
    const d = week.find(w => w.idx === date)?.d || new Date();
    const start = combineDateTime(d, time);
    const title = `Kickoff: ${client.company} × ${freelancer.brand}`;
    const details = `30-minute kickoff call for "${client.role_title}".\n\nWalk through the SOW, set communication norms, and answer questions.\n\nWith ${freelancer.name} (${freelancer.email}).`;
    const location = "Google Meet (link to follow)";

    const addToCalendar = () => {
      const ics = buildICS({
        title, description: details, start, durationMin: 30, location,
        organizerName: freelancer.name, organizerEmail: freelancer.email,
      });
      downloadICS(`kickoff-${client.id}.ics`, ics);
      toast("Calendar invite downloaded — opens in Apple/Outlook/Google", { kind: "success" });
    };
    const addToGoogle = () => {
      window.open(googleCalUrl({ title, details, start, durationMin: 30, location }), "_blank", "noopener");
      toast("Opening Google Calendar…", { kind: "success" });
    };

    return (
      <div className="col gap-20" style={{ alignItems: "center", textAlign: "center", padding: "40px 0" }}>
        <div style={{ width: 64, height: 64, borderRadius: 16, background: "var(--primary)", color: "#fff", display: "grid", placeItems: "center" }}><Icon.calendar cls="ico-lg"/></div>
        <div className="col gap-6">
          <div className="h-display" style={{ fontSize: 36 }}>Kickoff booked.</div>
          <div className="ink-3" style={{ fontSize: 14 }}>{fmtDate(d)} · {time} {client.timezone} · 30 minutes with {freelancer.name}</div>
        </div>
        <div className="row gap-8" style={{ flexWrap: "wrap", justifyContent: "center" }}>
          <Button icon={<Icon.download cls="ico-sm"/>} onClick={addToCalendar}>Download invite (.ics)</Button>
          <Button icon={<Icon.calendar cls="ico-sm"/>} onClick={addToGoogle}>Add to Google Calendar</Button>
          <Button variant="primary" onClick={advance} iconR={<Icon.arrow cls="ico-sm"/>}>Continue</Button>
        </div>
        <div className="ink-3" style={{ fontSize: 11.5 }}>The .ics file works with Apple Calendar, Outlook, and any calendar app.</div>
      </div>
    );
  }

  return (
    <div className="col">
      <StepHeader eyebrow="Kickoff call" title="Pick a time for our kickoff"
        sub="A 30-minute video call to walk through the SOW, set communication norms, and answer questions. Choose any slot in the next week."/>

      {scheduling.bookingUrl && (
        <Card className="fade-in" style={{ marginBottom: 16 }}>
          <div className="row gap-12" style={{ alignItems: "center" }}>
            <div style={{ width: 38, height: 38, borderRadius: 10, background: "var(--primary-soft)", color: "var(--primary)", display: "grid", placeItems: "center", flexShrink: 0 }}>
              <Icon.calendar cls="ico"/>
            </div>
            <div className="col" style={{ flex: 1, lineHeight: 1.4 }}>
              <div style={{ fontSize: 13.5, fontWeight: 500 }}>Book from {freelancer.name.split(" ")[0]}'s live calendar</div>
              <div className="ink-3" style={{ fontSize: 12 }}>Shows real availability and adds the event to both calendars automatically.</div>
            </div>
            <Button variant="primary" icon={<Icon.external cls="ico-sm"/>} onClick={() => window.open(scheduling.bookingUrl, "_blank", "noopener")}>
              Open booking page
            </Button>
          </div>
        </Card>
      )}

      <Card>
        <div className="col gap-16">
          <div className="row gap-8">
            <Icon.clock cls="ico-sm"/>
            <span style={{ fontSize: 13 }}>30 minutes · {freelancer.timezone} (currently shown in your timezone, {client.timezone})</span>
          </div>
          <div className="hr"/>

          <div className="col gap-10">
            <span className="label-lc">Date</span>
            <div className="kickoff-grid" style={{ display: "grid", gridTemplateColumns: "repeat(7, 1fr)", gap: 8 }}>
              {week.map(w => (
                <button key={w.idx} onClick={() => !w.busy && setDate(w.idx)} disabled={w.busy} style={{
                  padding: "12px 0", borderRadius: 10,
                  background: date === w.idx ? "var(--primary)" : w.busy ? "var(--bg-2)" : "var(--surface)",
                  color: date === w.idx ? "#fff" : w.busy ? "var(--muted)" : "var(--ink)",
                  border: "1px solid " + (date === w.idx ? "var(--primary)" : "var(--line)"),
                  cursor: w.busy ? "not-allowed" : "pointer", textAlign: "center",
                }}>
                  <div style={{ fontSize: 11, opacity: 0.7 }}>{w.day}</div>
                  <div className="h-display" style={{ fontSize: 22, lineHeight: 1.2 }}>{w.date}</div>
                  {w.busy && <div style={{ fontSize: 9 }}>Booked</div>}
                </button>
              ))}
            </div>
          </div>

          <div className="col gap-10">
            <span className="label-lc">Time</span>
            <div className="kickoff-times" style={{ display: "grid", gridTemplateColumns: "repeat(6, 1fr)", gap: 8 }}>
              {times.map(t => (
                <button key={t} onClick={() => setTime(t)} style={{
                  padding: "10px 0", borderRadius: 8,
                  background: time === t ? "var(--primary-soft-2)" : "var(--surface)",
                  color: "var(--ink)", border: "1px solid " + (time === t ? "var(--primary)" : "var(--line)"),
                  cursor: "pointer", fontSize: 12.5, fontWeight: time === t ? 500 : 400,
                }}>{t}</button>
              ))}
            </div>
          </div>

          <div className="hr"/>
          <div className="row gap-10" style={{ alignItems: "center", padding: 12, background: "var(--surface-2)", borderRadius: 8, border: "1px solid var(--line-2)" }}>
            <Icon.calendar cls="ico-sm"/>
            <div className="col" style={{ flex: 1, lineHeight: 1.3 }}>
              <div style={{ fontSize: 13.5, fontWeight: 500 }}>
                {(week.find(w => w.idx === date)?.d || new Date()).toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric" })} · {time}
              </div>
              <div className="ink-3" style={{ fontSize: 12 }}>30 min · Google Meet · {freelancer.name}</div>
            </div>
            <Button variant="primary" onClick={() => setConfirmed(true)} iconR={<Icon.arrow cls="ico-sm"/>}>Book this slot</Button>
          </div>
        </div>
      </Card>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────
// Step 6: All done
// ─────────────────────────────────────────────────────────────────────
function ClientComplete({ client, freelancer }) {
  const { toast } = useToast();
  const { template } = useApp();
  // Open the ACTUAL signed documents (not the celebration page) for download/print.
  const openDocs = () => {
    const w = window.open("", "_blank");
    if (!w) { toast("Allow pop-ups to open your documents", { kind: "warn" }); return; }
    const keys = ["service_agreement", "sow", "nda"];
    const frags = keys.map(k => window.buildDocHTML({ docKey: k, client, freelancer, template, forPdf: true }))
      .join('<div style="page-break-after:always;height:24px"></div>');
    w.document.open();
    w.document.write(`<!doctype html><html><head><meta charset="utf-8"><title>Your documents — ${freelancer.brand}</title></head>
      <body style="margin:0;background:#fff;">
      <div style="position:sticky;top:0;background:#0F1A14;color:#fff;padding:10px 16px;display:flex;justify-content:space-between;align-items:center;font-family:system-ui,sans-serif;font-size:13px;">
        <span>Your signed documents · ${client.company}</span>
        <button onclick="window.print()" style="background:#fff;color:#0F1A14;border:0;padding:7px 16px;border-radius:6px;font-weight:600;cursor:pointer;">⬇ Save as PDF / Print</button>
      </div>
      <div style="max-width:760px;margin:0 auto;padding:24px;">${frags}</div>
      </body></html>`);
    w.document.close();
    toast("Opening your signed documents…", { kind: "success" });
  };
  return (
    <div className="col gap-24" style={{ alignItems: "center", textAlign: "center", padding: "40px 0" }}>
      <div style={{ width: 80, height: 80, borderRadius: 20, background: "linear-gradient(135deg, var(--primary), #2D6A4F)", color: "#fff", display: "grid", placeItems: "center" }}>
        <Icon.check cls="ico-lg" style={{ width: 36, height: 36 }}/>
      </div>
      <div className="col gap-8" style={{ maxWidth: 540 }}>
        <div className="h-display" style={{ fontSize: 44, lineHeight: 1.05 }}>You're all set, {client.contact.split(" ")[0]}.</div>
        <div className="ink-3" style={{ fontSize: 15, lineHeight: 1.55 }}>
          Welcome to the {freelancer.brand} family — you're all set. {freelancer.name.split(" ")[0]} will be in touch within 24 hours with next steps.
        </div>
      </div>
      <div className="responsive-3" style={{ gap: 12, width: "100%", maxWidth: 640 }}>
        {[
          { label: "Project starts", value: fmtDateShort(client.startDate), icon: Icon.flag },
          { label: "Next milestone", value: fmtDateShort(client.milestones[0]?.date), icon: Icon.layers },
          { label: "Kickoff call", value: client.kickoff ? `${fmtDateShort(client.kickoff.date)} · ${client.kickoff.time || ""}`.trim() : "To be scheduled", icon: Icon.calendar },
        ].map((s, i) => {
          const Ico = s.icon;
          return (
            <Card key={i}>
              <div className="col gap-6" style={{ alignItems: "flex-start", textAlign: "left" }}>
                <Ico cls="ico-sm"/>
                <div className="label-lc" style={{ fontSize: 11 }}>{s.label}</div>
                <div style={{ fontSize: 15, fontWeight: 500 }}>{s.value}</div>
              </div>
            </Card>
          );
        })}
      </div>
      <div className="row gap-8">
        <Button icon={<Icon.download cls="ico-sm"/>} onClick={openDocs}>Download / Print docs</Button>
        <Button variant="primary" icon={<Icon.mail cls="ico-sm"/>} onClick={() => { window.location.href = `mailto:${freelancer.email}`; toast("Opening email…"); }}>Send a message</Button>
      </div>
    </div>
  );
}

Object.assign(window, { ClientPortal });
