/* global React */
const { useState, useEffect, useMemo } = React;

/* =========================================================================
   CONVERSATION DETAIL — historical viewer
   ========================================================================= */
function AnalysisDetail() {
  const { tier, setRoute, routeParams } = useApp();
  const id = routeParams?.id;
  const [tab, setTab] = useState('diagram');
  const [data, setData] = useState(null);
  const [diagram, setDiagram] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    if (!id) { setError('Missing conversation id'); setLoading(false); return; }
    let cancelled = false;
    setLoading(true);
    (async () => {
      try {
        const convo = await window.API.getConversation(id);
        const v = convo?.header?.currentVersion;
        if (!v || v < 1) {
          if (!cancelled) {
            setData({
              title: convo?.header?.title,
              createdAt: convo?.header?.createdAt,
              status: 'pending',
            });
          }
          return;
        }
        const snap = await window.API.getConversationVersion(id, v);
        if (cancelled) return;
        const review = snap.wafReview ?? null;
        setData({
          title: convo.header.title,
          createdAt: convo.header.createdAt,
          status: 'complete',
          architecture: snap.version?.architecture ?? null,
          // The assistant writes runId === analysisId on every submit
          // (assistant/handler.ts:193). Surface it here so the diagram
          // feedback widget can hit /analyses/{analysisId}/diagram/feedback
          // — passing the conversation id would 404 inside the feedback
          // handler's ANALYSIS#{id} lookup.
          analysisId: snap.version?.runId ?? null,
          review: review ? { scorecard: review.scorecard, recommendations: review.recommendations } : null,
          costEstimate: snap.costEstimate ?? null,
        });
        if (snap.diagram) setDiagram(snap.diagram);
      } catch (e) {
        if (!cancelled) setError(e.message);
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => { cancelled = true; };
  }, [id]);

  const scorecard = data?.review?.scorecard;
  const pillars = window.scorecardToPillars(scorecard);
  const findings = window.scorecardToFindings(scorecard);
  const lines = window.costToLines(data?.costEstimate);
  const regions = Array.from(new Set((data?.costEstimate?.lineItems || []).map(l => l.region).filter(Boolean)));
  const overall = scorecard?.overallScore ?? (pillars.length ? Math.round(pillars.reduce((s, p) => s + p.score, 0) / pillars.length) : 0);
  const total = lines.reduce((s, l) => s + (l.mo || 0), 0);
  const hiddenTotal = lines.filter(l => l.hidden).reduce((s, l) => s + (l.mo || 0), 0);
  const failCount = findings.filter(f => f.sev === 'HIGH').length;
  const warnCount = findings.filter(f => f.sev === 'MED' || f.sev === 'LOW').length;

  // Free users can export PDF — the handler stamps a watermark for them.
  // Cost + recommendations stay Pro-only.
  const canPdf = true;
  const canCost = tier !== 'free';
  const canRecs = tier === 'pro' || tier === 'team' || tier === 'enterprise' || tier === 'admin';

  if (loading) {
    return <div className="page"><div className="empty">Loading conversation…</div></div>;
  }
  if (error) {
    return <div className="page"><div className="empty" style={{borderColor:'var(--err)'}}>Failed to load: {error}</div></div>;
  }

  return (
    <div className="page">
      <div style={{display:'flex', alignItems:'center', gap:10, marginBottom:16, fontSize:12.5, color:'var(--ink-2)'}}>
        <button className="btn sm ghost" onClick={() => setRoute('dashboard')} style={{padding:'0 4px'}}>← Dashboard</button>
        <span style={{color:'var(--ink-3)'}}>/</span>
        <button className="btn sm ghost" onClick={() => setRoute('history')} style={{padding:'0 4px'}}>History</button>
        <span style={{color:'var(--ink-3)'}}>/</span>
        <span style={{fontFamily:'var(--font-mono)'}}>{id}</span>
      </div>
      <div className="page-head">
        <div>
          <div className="eyebrow">conversation · {(data?.createdAt || '').replace('T', ' ').slice(0, 19)}</div>
          <h1 className="display">{data?.title || id}</h1>
          <div style={{display:'flex', gap:10, marginTop:10, alignItems:'center'}}>
            {data?.status === 'failed'
              ? <span className="pill err"><span className="dot" style={{background:'var(--err)'}}/>{data.status}</span>
              : <span className="pill ok"><span className="dot" style={{background:'var(--ok)'}}/>{data?.status || 'complete'}</span>}
            {data?.architecture?.services && <span className="pill ghost">{data.architecture.services.length} services · {data.architecture.connections?.length || 0} edges</span>}
            {scorecard?.results && <span className="pill ghost">{scorecard.results.length} rules</span>}
          </div>
        </div>
        <div style={{display:'flex', gap:8}}>
          <button className="btn" onClick={() => setRoute('new')}><Icon name="retry" size={12}/>Re-run</button>
          <button className="btn primary" onClick={() => window.API.exportPdf(id).then(r => r.pdfUrl && window.open(r.pdfUrl)).catch(() => {})}>
            <Icon name="download" size={12}/>Export PDF{tier === 'free' ? ' · Watermarked' : ''}
          </button>
        </div>
      </div>

      <div className="bento cols-4" style={{marginBottom: 20}}>
        <div className="stat">
          <div className="label">WAF score</div>
          <div style={{display:'flex', alignItems:'center', gap:12}}>
            <ScoreRing value={overall} size={72} stroke={6}/>
            <div>
              <div style={{fontSize:12.5, color:'var(--ink-2)'}}>{scorecard ? 'Overall' : 'No review yet'}</div>
              {scorecard && (
                <div style={{fontSize:11.5, color:'var(--ink-3)', marginTop:2}}>
                  <span style={{color:'var(--err)'}}>{failCount} fail</span> · <span style={{color:'var(--warn)'}}>{warnCount} warn</span>
                </div>
              )}
            </div>
          </div>
        </div>
        <div className="stat">
          <div className="label">Monthly cost</div>
          <div className="val">{lines.length ? `€${total.toFixed(0)}` : '—'}<span className="unit">/mo</span></div>
          <div className="sub">{hiddenTotal > 0 ? `€${hiddenTotal.toFixed(0)} hidden` : 'no hidden flags'}</div>
        </div>
        <div className="stat">
          <div className="label">Line items</div>
          <div className="val">{lines.length}</div>
          <div className="sub">{data?.costEstimate?.savingsSuggestions?.length || 0} savings hints</div>
        </div>
        <div className="stat">
          <div className="label">Critical findings</div>
          <div className="val" style={{color: failCount > 0 ? 'var(--err)' : undefined}}>{failCount}</div>
          <div className="sub">{failCount > 0 ? 'require attention' : 'all HIGH rules pass'}</div>
        </div>
      </div>

      <div className="tabs" style={{marginBottom: 20}}>
        <button className={`tab ${tab==='diagram'?'active':''}`} onClick={() => setTab('diagram')}><Icon name="grid" size={12}/>Diagram</button>
        <button className={`tab ${tab==='score'?'active':''}`} onClick={() => setTab('score')}><Icon name="shield" size={12}/>WAF Scorecard <span className="count">{overall}</span></button>
        <button className={`tab ${tab==='cost'?'active':''}`} onClick={() => setTab('cost')}><Icon name="dollar" size={12}/>Cost estimate {!canCost && <Icon name="lock" size={10}/>}</button>
        <button className={`tab ${tab==='recs'?'active':''}`} onClick={() => setTab('recs')}><Icon name="sparkle" size={12}/>Recommendations {!canRecs && <Icon name="lock" size={10}/>}</button>
      </div>

      {tab === 'diagram' && (
        <div>
          <div style={{display:'flex', gap:12, marginBottom:12, alignItems:'center'}}>
            <div className="label">— architecture —</div>
            <div style={{flex:1}}/>
            {diagram?.drawioUrl && <a className="btn sm" href={diagram.drawioUrl} download><Icon name="download" size={11}/>diagram.drawio</a>}
            {diagram?.pngUrl && <a className="btn sm" href={diagram.pngUrl} download><Icon name="download" size={11}/>diagram.png</a>}
          </div>
          <DiagramImage url={diagram?.pngUrl} svgUrl={diagram?.svgUrl} drawioUrl={diagram?.drawioUrl} height={560}/>
          {diagram?.pngUrl && data?.analysisId && <DiagramFeedback analysisId={data.analysisId}/>}
        </div>
      )}

      {tab === 'score' && (scorecard ? <ScorePanel pillars={pillars} findings={findings} overall={overall}/> : <div className="empty">No scorecard available for this conversation.</div>)}

      {tab === 'cost' && (
        canCost
          ? (data?.costEstimate ? <CostPanel lines={lines} total={total} hiddenTotal={hiddenTotal} regions={regions} savings={data?.costEstimate?.savingsSuggestions || []} hiddenFlags={data?.costEstimate?.hiddenCostFlags || []}/> : <div className="empty">No cost estimate yet.</div>)
          : <GatedPreview title="Cost estimate is Pro-only" sub="Upgrade to unlock line-item cost breakdowns, hidden cost detection, and savings suggestions.">
              <CostPanel lines={lines} total={total} hiddenTotal={hiddenTotal} regions={regions} savings={data?.costEstimate?.savingsSuggestions || []} hiddenFlags={data?.costEstimate?.hiddenCostFlags || []}/>
            </GatedPreview>
      )}

      {tab === 'recs' && (
        canRecs
          ? <RecsPanel recs={data?.review?.recommendations || []}/>
          : <GatedPreview title="AI recommendations are Pro-only" sub="Upgrade to get ranked, actionable recommendations.">
              <RecsPanel recs={data?.review?.recommendations || []}/>
            </GatedPreview>
      )}
    </div>
  );
}
window.AnalysisDetail = AnalysisDetail;

/* =========================================================================
   DIAGRAM FEEDBACK — thumbs up/down + free-text comment.
   Persists to DDB via POST /analyses/{id}/diagram/feedback. Feeds the
   diagram-quality learning loop: thumbs-down submissions become inputs
   to the corpus that drives prompt + layout improvements over time.
   ========================================================================= */
function DiagramFeedback({ analysisId }) {
  const [rating, setRating] = useState(null); // 'up' | 'down' | null
  const [comment, setComment] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [submitted, setSubmitted] = useState(false);
  const [error, setError] = useState(null);

  const onSubmit = async () => {
    if (!rating || submitting) return;
    setSubmitting(true);
    setError(null);
    try {
      await window.API.submitDiagramFeedback(analysisId, rating, comment.trim());
      setSubmitted(true);
    } catch (e) {
      setError(e?.message || 'Failed to save feedback');
    } finally {
      setSubmitting(false);
    }
  };

  const reset = () => {
    setRating(null);
    setComment('');
    setSubmitted(false);
    setError(null);
  };

  if (submitted) {
    return (
      <div className="card" style={{marginTop:16, padding:'12px 16px', display:'flex', alignItems:'center', gap:10}}>
        <Icon name="check" size={14}/>
        <div style={{flex:1, fontSize:13}}>Thanks — your feedback helps us tune the diagram pipeline.</div>
        <button className="btn sm ghost" onClick={reset}>Submit again</button>
      </div>
    );
  }

  const placeholder = rating === 'up'
    ? 'Optional — what worked well? (e.g. layout, icons, grouping)'
    : rating === 'down'
      ? 'What was wrong? (e.g. overlapping boxes, wrong arrows, missing services)'
      : 'Pick a rating to leave a comment.';

  return (
    <div className="card" style={{marginTop:16, padding:'14px 16px'}}>
      <div style={{display:'flex', alignItems:'center', gap:12, marginBottom:10}}>
        <div className="label">— rate this diagram —</div>
        <div style={{flex:1}}/>
        <button
          className={`btn sm ${rating === 'up' ? 'primary' : ''}`}
          onClick={() => setRating('up')}
          aria-pressed={rating === 'up'}
          aria-label="Thumbs up"
        ><Icon name="thumbs-up" size={12}/>Good</button>
        <button
          className={`btn sm ${rating === 'down' ? 'primary' : ''}`}
          onClick={() => setRating('down')}
          aria-pressed={rating === 'down'}
          aria-label="Thumbs down"
        ><Icon name="thumbs-down" size={12}/>Needs work</button>
      </div>
      <textarea
        className="field"
        rows={3}
        maxLength={2000}
        placeholder={placeholder}
        value={comment}
        disabled={!rating}
        onChange={e => setComment(e.target.value)}
        style={{width:'100%', resize:'vertical', fontFamily:'inherit'}}
      />
      <div style={{display:'flex', alignItems:'center', gap:10, marginTop:10}}>
        <div style={{fontSize:11.5, color:'var(--ink-3)'}}>
          {comment.length > 0 && `${comment.length}/2000`}
        </div>
        {error && <div style={{fontSize:12, color:'var(--err)'}}>{error}</div>}
        <div style={{flex:1}}/>
        <button
          className="btn sm primary"
          disabled={!rating || submitting}
          onClick={onSubmit}
        >{submitting ? 'Saving…' : 'Submit'}</button>
      </div>
    </div>
  );
}
window.DiagramFeedback = DiagramFeedback;

/* =========================================================================
   HISTORY
   ========================================================================= */
function HistoryScreen() {
  const { setRoute } = useApp();
  const [q, setQ] = useState('');
  const [items, setItems] = useState(null);
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = window.usePersistedPageSize('history');
  useEffect(() => {
    let cancelled = false;
    window.API.listConversations(200)
      .then(r => {
        if (cancelled) return;
        const rows = (r.items || []).map(c => {
          const currentVersion = c.currentVersion ?? 0;
          return {
            id: c.convoId,
            name: c.title || c.convoId,
            status: currentVersion > 0 ? 'complete' : 'pending',
            score: null, cost: null,
            date: (c.updatedAt || c.createdAt || '').replace('T', ' ').slice(0, 16),
            currentVersion,
          };
        });
        setItems(rows);
        for (const row of rows) {
          if (row.status !== 'complete' || row.currentVersion < 1) continue;
          window.API.getConversationVersion(row.id, row.currentVersion)
            .then(snap => {
              if (cancelled) return;
              const patch = window.extractScoreCost(snap);
              setItems(prev => (prev || []).map(r => r.id === row.id ? { ...r, ...patch } : r));
            })
            .catch(() => { /* leave row as-is */ });
        }
      })
      .catch(() => { if (!cancelled) setItems([]); });
    return () => { cancelled = true; };
  }, []);
  const source = items || [];
  const filtered = source.filter(a => a.name.toLowerCase().includes(q.toLowerCase()) || a.id.includes(q));
  const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
  const safePage = Math.min(page, totalPages);
  const pageItems = filtered.slice((safePage - 1) * pageSize, safePage * pageSize);
  return (
    <div className="page">
      <div className="page-head">
        <div>
          <div className="eyebrow">history</div>
          <h1 className="display">All conversations</h1>
          <div className="meta">{source.length} conversations · click any row to open.</div>
        </div>
        <div style={{display:'flex', gap:8}}>
          <input className="field" placeholder="Search…" style={{width: 240}} value={q} onChange={e => { setQ(e.target.value); setPage(1); }}/>
          <button className="btn accent" onClick={() => setRoute('new')}><Icon name="plus" size={13}/>New chat</button>
        </div>
      </div>
      <div className="card">
        <table className="tbl">
          <thead><tr><th>ID</th><th style={{width:'36%'}}>Name</th><th>Status</th><th>Score</th><th>Cost</th><th>Updated</th><th></th></tr></thead>
          <tbody>
            {pageItems.map(a => (
              <tr key={a.id} style={{cursor:'pointer'}} onClick={() => setRoute('detail', { id: a.id })}>
                <td className="mono" style={{color:'var(--ink-3)', fontSize:11.5}}>{a.id}</td>
                <td style={{fontWeight:500}}>{a.name}</td>
                <td>
                  {a.status === 'complete' && <span className="pill ok"><span className="dot" style={{background:'var(--ok)'}}/>complete</span>}
                  {a.status === 'failed'   && <span className="pill err"><span className="dot" style={{background:'var(--err)'}}/>failed</span>}
                </td>
                <td className="mono">{a.score ?? '—'}</td>
                <td className="mono">{a.cost ? `€${a.cost.toFixed(2)}` : '—'}</td>
                <td className="mono" style={{color:'var(--ink-2)', fontSize:11.5}}>{a.date}</td>
                <td style={{textAlign:'right'}}><Icon name="chev" size={14} className="diag-edge"/></td>
              </tr>
            ))}
          </tbody>
        </table>
        <window.Pagination
          total={filtered.length}
          page={safePage}
          pageSize={pageSize}
          onPage={setPage}
          onPageSize={n => { setPageSize(n); setPage(1); }}
        />
      </div>
    </div>
  );
}
window.HistoryScreen = HistoryScreen;

/* =========================================================================
   PRICING
   ========================================================================= */
function PricingScreen() {
  const { tier, setTier, setRoute } = useApp();
  const [cycle, setCycle] = useState('month');
  const [busy, setBusy] = useState(null); // tier id currently checking out
  const [error, setError] = useState(null);
  const billingEnabled = window.API?.billingEnabled === true;

  // Surface a banner after a checkout redirect. Stripe sends us back to
  // `/?status=success&session_id=…#pricing` (or `…?status=cancelled`); we
  // read URLSearchParams once and clear the params from history so a
  // refresh doesn't re-show the banner. The webhook drives the actual
  // tier flip — invalidate the /user cache so the next fetch is fresh.
  const [postCheckout, setPostCheckout] = useState(null);
  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const status = params.get('status');
    if (status === 'success' || status === 'cancelled') {
      setPostCheckout(status);
      window.API?.invalidate?.('user');
      // Strip the params so they don't survive a refresh.
      window.history.replaceState({}, '', `${window.location.pathname}#pricing`);
    }
  }, []);

  // Real Stripe handoff. When billing is disabled (pre-Stripe activation),
  // the demo path falls back to setTier so the marketing flows still work.
  const handleUpgrade = async (targetTier) => {
    if (!billingEnabled) { setTier(targetTier); return; }
    setError(null); setBusy(targetTier);
    try {
      const interval = cycle === 'year' ? 'yearly' : 'monthly';
      const { url } = await window.API.startCheckout(targetTier, interval);
      window.location.assign(url);
    } catch (e) {
      setBusy(null);
      setError(e?.message || 'Could not start checkout. Please try again.');
    }
  };

  const handleManageSubscription = async () => {
    setError(null); setBusy('manage');
    try {
      const { url } = await window.API.openBillingPortal();
      window.location.assign(url);
    } catch (e) {
      setBusy(null);
      setError(e?.message || 'Could not open billing portal.');
    }
  };

  const tiers = [
    { id:'free', name:'Free', price:0, desc:'Kick the tires — diagram & scorecard, forever free.', limit:'3 conversations / month',
      features:[
        ['Plain-language + IaC input', true],
        ['Architecture diagram (.drawio, .png)', true],
        ['WAF scorecard · 6 pillars', true],
        ['Cost estimate', false],
        ['AI recommendations', false],
        ['PDF report export', false],
        ['Priority support', false],
      ]},
    { id:'pro', name:'Pro', price:29, desc:'For solo architects — the whole pipeline, on tap.', limit:'25 conversations / month',
      features:[
        ['Everything in Free', true],
        ['Cost estimate + hidden items', true],
        ['AI recommendations w/ IaC diffs', true],
        ['PDF report export', true],
        ['Conversation history — unlimited', true],
        ['Email support', true],
        ['SSO / SAML', false],
      ]},
    { id:'team', name:'Team', price:79, desc:'Share conversations across your squad.', limit:'100 conversations / month',
      features:[
        ['Everything in Pro', true],
        ['Shared workspace', true, 'coming soon'],
        ['Role-based access', true, 'coming soon'],
        ['Comments on findings', true, 'coming soon'],
        ['Webhook / Slack notifications', true],
        ['Priority support', true],
        ['SSO / SAML', false],
      ]},
    { id:'enterprise', name:'Enterprise', price:null, desc:'Custom SLAs, on-prem review runners, audit trails.', limit:'Custom quota',
      features:[
        ['Everything in Team', true],
        ['SSO / SAML / SCIM', true],
        ['Audit logs', true],
        ['Dedicated VPC review runners', true],
        ['Custom compliance frameworks', true],
        ['99.95% uptime SLA', true],
        ['Named support engineer', true],
      ]},
  ];

  return (
    <div className="page">
      <div style={{textAlign:'center', marginBottom: 28}}>
        <div className="eyebrow" style={{justifyContent:'center'}}>pricing</div>
        <h1 className="marketing-display" style={{fontSize:56, margin:'8px 0 12px', fontWeight:400, lineHeight:1.05}}>Pick your altitude.</h1>
        <div style={{color:'var(--ink-2)', fontSize:15, maxWidth: 540, margin:'0 auto 20px', lineHeight:1.55}}>Start free. Upgrade when you need the full review pipeline, cost estimates, and PDF reports.</div>
        <div style={{display:'inline-flex', background:'var(--bg-2)', border:'1px solid var(--line-strong)', borderRadius:6, padding:3}}>
          <button className={`btn sm ${cycle==='month'?'primary':'ghost'}`} onClick={() => setCycle('month')}>Monthly</button>
          <button className={`btn sm ${cycle==='year'?'primary':'ghost'}`} onClick={() => setCycle('year')}>Yearly <span style={{color: cycle==='year'?'currentColor':'var(--ok)', fontSize:10, marginLeft:4}}>2 months free</span></button>
        </div>
      </div>

      <PricingRecommender onSelect={setTier}/>

      {postCheckout === 'success' && (
        <div style={{margin:'0 auto 16px', maxWidth:520, padding:'10px 14px', background:'var(--bg-1)', border:'1px solid var(--ok)', borderRadius:6, fontSize:13, color:'var(--ok)'}}>
          Subscription confirmed. Your new plan will be live within a few seconds.
        </div>
      )}
      {postCheckout === 'cancelled' && (
        <div style={{margin:'0 auto 16px', maxWidth:520, padding:'10px 14px', background:'var(--bg-1)', border:'1px solid var(--line-strong)', borderRadius:6, fontSize:13, color:'var(--ink-2)'}}>
          Checkout cancelled. No charge was made.
        </div>
      )}
      {error && (
        <div style={{margin:'0 auto 16px', maxWidth:520, padding:'10px 14px', background:'var(--bg-1)', border:'1px solid var(--err)', borderRadius:6, fontSize:13, color:'var(--err)'}}>
          {error}
        </div>
      )}

      <div className="price-grid">
        {tiers.map(t => {
          // Yearly: 2 months free → effective €/month is base * 10/12.
          const price = t.price === null
            ? null
            : cycle === 'year'
              ? Math.round((t.price * 10 / 12) * 100) / 100
              : t.price;
          const current = tier === t.id;
          const isCheckingOut = busy === t.id;
          return (
            <div key={t.id} className={`price-col ${current?'current':''}`}>
              <div className="name">{t.name}</div>
              <div className="price">
                {t.price === null ? <span style={{fontSize:22}}>Custom</span> :
                  <><span>€{price}</span><span className="unit">/ mo</span></>}
              </div>
              <div className="desc">{t.desc}</div>
              <div style={{fontFamily:'var(--font-mono)', fontSize:11, color:'var(--ink-2)', padding:'8px 0', borderTop:'1px dashed var(--line)', borderBottom:'1px dashed var(--line)'}}>
                {t.limit}
              </div>
              {current ? (
                t.id === 'pro' || t.id === 'team' ? (
                  <button className="btn" onClick={handleManageSubscription} disabled={busy === 'manage'}>
                    {busy === 'manage' ? 'Opening…' : 'Manage subscription'}
                  </button>
                ) : (
                  <button className="btn" disabled>Current plan</button>
                )
              ) : t.id === 'enterprise' ? (
                <a className="btn primary" href="mailto:sales@cloudarchitectcopilot.com?subject=Enterprise%20enquiry">Contact sales</a>
              ) : t.id === 'free' ? (
                <button className="btn" disabled>Always free</button>
              ) : (
                <button
                  className={`btn ${t.id === 'pro' ? 'accent' : 'primary'}`}
                  onClick={() => handleUpgrade(t.id)}
                  disabled={isCheckingOut}
                >
                  {isCheckingOut
                    ? 'Redirecting to Stripe…'
                    : billingEnabled
                      ? `${TIERS.indexOf(t.id) > TIERS.indexOf(tier) ? 'Upgrade' : 'Switch'} to ${t.name}`
                      : 'Join waitlist'}
                </button>
              )}
              <ul>
                {t.features.map(([label, on, note], i) => (
                  <li key={i} className={on ? '' : 'off'}>
                    <span className="chk">{on ? '✓' : '—'}</span>
                    <span>{label}{note && <span style={{fontFamily:'var(--font-mono)', fontSize:10, color:'var(--ink-3)', marginLeft:6}}>· {note}</span>}</span>
                  </li>
                ))}
              </ul>
            </div>
          );
        })}
      </div>

      <div style={{marginTop: 20, padding:'14px 18px', background:'var(--bg-1)', border:'1px solid var(--line)', borderRadius:6, display:'flex', gap:14, alignItems:'center', fontSize:12.5, color:'var(--ink-2)'}}>
        <Icon name="warn" size={13} className="diag-edge"/>
        <div>
          <b style={{color:'var(--ink-1)'}}>Overage</b> · Exceeding your monthly quota is charged at <span className="mono">€0.80/conversation</span> on Pro and <span className="mono">€0.50/conversation</span> on Team. Hard cap on Free (block at quota).
        </div>
      </div>

      <div style={{marginTop: 40}}>
        <div className="label" style={{marginBottom:14}}>— frequently asked —</div>
        <div className="bento cols-2">
          {[
            ['Does the conversation reach my cloud account?', 'No. All parsing and review runs against the text/IaC you submit. We never call your AWS APIs or read cloud credentials.'],
            ['How accurate is the cost estimate?', 'Typically within 8–12%. We pull regional pricing from the Pricing API and flag hidden items (NAT, egress, CW) that users often forget.'],
            ['Can I cancel anytime?', 'Yes. Pro and Team are monthly with no commitment. Annual plans refund unused months pro rata.'],
            ['Is this affiliated with AWS?', 'No. We\'re an independent tool. Well-Architected pillars are a public framework; we implement our own rule engine on top.'],
          ].map(([q, a], i) => (
            <div key={i} style={{padding:16, border:'1px solid var(--line)', borderRadius:6, background:'var(--bg-2)'}}>
              <div style={{fontWeight:600, fontSize:13.5, marginBottom:6}}>{q}</div>
              <div style={{fontSize:13, color:'var(--ink-2)', lineHeight:1.55}}>{a}</div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}
window.PricingScreen = PricingScreen;

/* Persona → tier recommender */
function PricingRecommender({ onSelect }) {
  const [persona, setPersona] = useState(null);
  const personas = [
    { id:'solo',  title:'Solo architect', desc:'I review my own designs a few times a month.', rec:'pro', reason:'25 conversations/mo with the full pipeline covers weekly design reviews plus ad-hoc debugging.' },
    { id:'team',  title:'Platform team', desc:'Several of us work on shared infra and need to compare notes.', rec:'team', reason:'Shared workspace, comments on findings, and webhooks fit a squad iterating together.' },
    { id:'cons',  title:'Consultancy', desc:'I run many audits for different clients each month.', rec:'team', reason:'100 conversations covers 2–3 client audits/week; Pro would cap you out by mid-month.' },
    { id:'ent',   title:'Regulated enterprise', desc:'We need SSO, audit logs, and a signed DPA.', rec:'enterprise', reason:'SAML, audit logs, dedicated runners, and custom compliance frameworks.' },
    { id:'eval',  title:'Just evaluating', desc:'I want to see if this is useful before committing.', rec:'free', reason:'3 conversations/mo is plenty to kick the tires on the diagram + scorecard.' },
  ];
  const picked = personas.find(p => p.id === persona);
  return (
    <div className="card" style={{padding:'18px 20px', marginBottom:24, background:'var(--bg-2)', border:'1px solid var(--line)'}}>
      <div style={{display:'flex', alignItems:'center', gap:10, marginBottom:12}}>
        <div className="label" style={{margin:0}}>Find your tier</div>
        <div style={{flex:1}}/>
        <div style={{fontSize:11.5, color:'var(--ink-3)', fontFamily:'var(--font-mono)'}}>pick what sounds like you</div>
      </div>
      <div style={{display:'grid', gridTemplateColumns:'repeat(auto-fit, minmax(180px, 1fr))', gap:8}}>
        {personas.map(p => (
          <button key={p.id} onClick={() => setPersona(p.id)}
            style={{textAlign:'left', padding:'12px 14px', borderRadius:5, border:'1px solid '+(persona===p.id?'var(--ink-0)':'var(--line)'), background: persona===p.id?'var(--bg-1)':'var(--bg-2)', cursor:'pointer', transition:'all .12s'}}>
            <div style={{fontSize:12.5, fontWeight:600, marginBottom:3}}>{p.title}</div>
            <div style={{fontSize:11.5, color:'var(--ink-2)', lineHeight:1.4}}>{p.desc}</div>
          </button>
        ))}
      </div>
      {picked && (
        <div className="ai-border" style={{marginTop:14, padding:'12px 14px', border:'1px solid var(--line)', borderRadius:5, background:'var(--accent-soft)', display:'flex', alignItems:'center', gap:14}}>
          <div style={{flex:1, minWidth:0}}>
            <div style={{fontSize:11, letterSpacing:'0.1em', color:'var(--accent-ink)', textTransform:'uppercase', fontFamily:'var(--font-mono)'}}>Recommended for you</div>
            <div style={{fontSize:16, fontWeight:600, marginTop:2}}>{TIER_LABEL[picked.rec]}</div>
            <div style={{fontSize:12.5, color:'var(--ink-1)', marginTop:4, lineHeight:1.5}}>{picked.reason}</div>
          </div>
          <button className="btn primary" onClick={() => onSelect(picked.rec)}>
            Switch to {TIER_LABEL[picked.rec]}
          </button>
        </div>
      )}
    </div>
  );
}

/* =========================================================================
   ACCOUNT (basic)
   ========================================================================= */
function AccountScreen() {
  const { user, refreshUser, hasBackend } = useApp();
  const initialName = user?.name || '';
  const email = user?.email || '';

  const splitName = (full) => {
    const parts = (full || '').trim().split(/\s+/).filter(Boolean);
    if (parts.length === 0) return { given: '', family: '' };
    if (parts.length === 1) return { given: parts[0], family: '' };
    return { given: parts[0], family: parts.slice(1).join(' ') };
  };

  const [fullName, setFullName] = useState(initialName);
  const [saving, setSaving]     = useState(false);
  const [status, setStatus]     = useState(null); // {ok|err, msg}
  useEffect(() => { setFullName(initialName); }, [initialName]);

  async function save() {
    if (!hasBackend) { setStatus({ ok: false, msg: 'Backend not configured.' }); return; }
    const { given, family } = splitName(fullName);
    setSaving(true);
    setStatus(null);
    try {
      await window.API.updateProfile({ givenName: given, familyName: family });
      refreshUser();
      setStatus({ ok: true, msg: 'Saved.' });
    } catch (e) {
      setStatus({ ok: false, msg: e.message || 'Could not save.' });
    } finally {
      setSaving(false);
    }
  }

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <div className="eyebrow">account</div>
          <h1 className="display">Account settings</h1>
        </div>
      </div>
      <div className="bento cols-2">
        <div className="card">
          <div className="card-header"><div className="label">Profile</div></div>
          <div className="card-body">
            <FormRow label="Full name"><input className="field" value={fullName} onChange={e => setFullName(e.target.value)}/></FormRow>
            <FormRow label="Email"><input key={`email-${email}`} className="field" defaultValue={email} readOnly/></FormRow>
            <FormRow label="Default region"><input className="field mono" defaultValue="eu-west-1"/></FormRow>
            <div style={{display:'flex', gap:10, alignItems:'center'}}>
              <button className="btn primary" onClick={save} disabled={saving}>
                {saving ? <span className="spinner"/> : null}Save changes
              </button>
              {status && (
                <span style={{fontSize:12, color: status.ok ? 'var(--ok)' : 'var(--err)'}}>{status.msg}</span>
              )}
            </div>
          </div>
        </div>
        <div className="card">
          <div className="card-header"><div className="label">API keys</div><button className="btn sm">+ New key</button></div>
          <div className="card-body">
            <div style={{fontFamily:'var(--font-mono)', fontSize:12, background:'var(--bg-1)', border:'1px solid var(--line)', borderRadius:4, padding:10, display:'flex', alignItems:'center', gap:10}}>
              <span className="pill ok">active</span>
              <span style={{flex:1}}>cac_sk_live_••••••••_fa21</span>
              <span style={{color:'var(--ink-3)', fontSize:11}}>created 2026-02-14</span>
              <button className="btn sm">Revoke</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
window.AccountScreen = AccountScreen;

/* =========================================================================
   Detail panels — full-page versions of the rail panels
   ========================================================================= */
function ScorePanel({ pillars, findings, overall }) {
  const [expanded, setExpanded] = useState('rel');
  return (
    <div className="card">
      <div style={{display:'grid', gridTemplateColumns:'auto 1fr', gap:24, padding:24, borderBottom:'1px solid var(--line)', alignItems:'center'}}>
        <ScoreRing value={overall} size={140} stroke={9}/>
        <div>
          <div className="label">Overall WAF score</div>
          <div style={{fontSize:32, fontFamily:'var(--font-display)', fontWeight:600, letterSpacing:'-0.02em', lineHeight:1, marginTop:4}}>
            {overall}<span style={{fontSize:14, color:'var(--ink-3)', fontFamily:'var(--font-mono)', fontWeight:400, marginLeft:6}}>/ 100</span>
          </div>
          <div style={{display:'flex', gap:14, marginTop:10, fontSize:12.5, color:'var(--ink-2)', fontFamily:'var(--font-mono)'}}>
            <span>142 rules</span>
            <span style={{color:'var(--err)'}}>5 fail</span>
            <span style={{color:'var(--warn)'}}>14 warn</span>
            <span style={{color:'var(--ok)'}}>123 pass</span>
          </div>
        </div>
      </div>
      <div style={{padding:'8px 24px 20px'}}>
        {pillars.map(p => (
          <div key={p.key}>
            <div className="pillar-row" onClick={() => setExpanded(e => e === p.key ? null : p.key)}>
              <div className="name">
                <Icon name="chev" size={11} style={{transform: expanded === p.key ? 'rotate(0deg)' : 'rotate(-90deg)', transition:'transform .12s'}} className="diag-edge"/>
                {p.name}
                <span style={{fontFamily:'var(--font-mono)', fontSize:11, color:'var(--ink-3)', marginLeft:4}}>· {p.rules} rules · {p.fail} fail · {p.warn} warn</span>
              </div>
              <div className="bar"><span style={{width: `${p.score}%`, background: p.score >= 80 ? 'var(--ok)' : p.score >= 60 ? 'var(--warn)' : 'var(--err)'}}/></div>
              <div className="pct">{p.score}</div>
            </div>
            {expanded === p.key && (
              <div style={{padding:'4px 0 14px 18px'}}>
                {findings.filter(f => f.pillar === p.key).length === 0 ? (
                  <div style={{fontSize:12.5, color:'var(--ink-3)', padding:'8px 12px'}}>No findings.</div>
                ) : findings.filter(f => f.pillar === p.key).map((f, i) => (
                  <div key={i} style={{padding:'10px 14px', border:'1px solid var(--line)', background:'var(--bg-2)', borderRadius:5, marginBottom:8}}>
                    <div style={{display:'flex', alignItems:'center', gap:8, marginBottom:6}}>
                      <span className={`pill ${f.sev==='HIGH'?'err':f.sev==='MED'?'warn':'ghost'}`}>{f.sev}</span>
                      <span style={{fontFamily:'var(--font-mono)', fontSize:12, color:'var(--ink-1)'}}>{f.rule}</span>
                      <div style={{flex:1}}/>
                      <span style={{fontFamily:'var(--font-mono)', fontSize:11, color:'var(--ink-3)'}}>{f.ref}</span>
                    </div>
                    <div style={{fontSize:12.5, color:'var(--ink-2)', lineHeight:1.55}}>{f.desc}</div>
                  </div>
                ))}
              </div>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

function CostPanel({ lines, total, hiddenTotal, regions = [], savings = [], hiddenFlags = [] }) {
  const regionLabel = regions.length === 0
    ? 'live AWS Pricing API'
    : regions.length === 1
      ? `live AWS Pricing API · region ${regions[0]}`
      : `live AWS Pricing API · regions ${regions.join(', ')}`;
  return (
    <div>
      <div className="bento cols-3" style={{marginBottom:16}}>
        <div className="stat">
          <div className="label">Monthly total</div>
          <div className="val">€{total.toFixed(2)}<span className="unit">/mo</span></div>
          <div className="sub">{regionLabel}</div>
        </div>
        <div className="stat">
          <div className="label">Hidden line items</div>
          <div className="val" style={{color:'var(--warn)'}}>€{hiddenTotal.toFixed(0)}<span className="unit">/mo</span></div>
          <div className="sub">{lines.filter(l => l.hidden).length} items not in original spec</div>
        </div>
        <div className="stat">
          <div className="label">Annualized</div>
          <div className="val">€{(total*12).toFixed(0)}<span className="unit">/yr</span></div>
          <div className="sub">no commitment / on-demand</div>
        </div>
      </div>
      <div className="card">
        <div className="card-header">
          <div className="label">— line items —</div>
          <div style={{display:'flex', gap:6}}>
            <button className="btn sm"><Icon name="download" size={11}/>CSV</button>
            <button className="btn sm"><Icon name="download" size={11}/>JSON</button>
          </div>
        </div>
        <table className="tbl">
          <thead><tr><th>Resource</th><th>Detail</th><th>Quantity</th><th>Unit</th><th style={{textAlign:'right'}}>Monthly</th></tr></thead>
          <tbody>
            {lines.map((l, i) => (
              <tr key={i}>
                <td style={{fontWeight:500}}>
                  {l.resource}
                  {l.hidden && <span className="pill warn" style={{marginLeft:8}}>hidden</span>}
                  {l.unavailable && <span className="pill ghost" style={{marginLeft:8}}>unavailable</span>}
                </td>
                <td style={{color:'var(--ink-2)', fontFamily:'var(--font-mono)', fontSize:11.5}}>{l.detail}</td>
                <td className="mono">{l.qty}</td>
                <td className="mono">{l.unit}</td>
                <td className="mono" style={{textAlign:'right', fontWeight: l.hidden ? 600 : 500, color: l.hidden ? 'var(--warn)' : l.unavailable ? 'var(--ink-3)' : undefined}}>{l.unavailable ? '—' : `€${l.mo.toFixed(2)}`}</td>
              </tr>
            ))}
            <tr style={{background:'var(--bg-1)'}}>
              <td colSpan={4} style={{fontWeight:600}}>Total</td>
              <td className="mono" style={{textAlign:'right', fontWeight:600, fontSize:14}}>€{total.toFixed(2)}</td>
            </tr>
          </tbody>
        </table>
      </div>
      {savings.length > 0 && (
        <div className="card" style={{marginTop:16}}>
          <div className="card-header">
            <div className="label">— savings opportunities —</div>
            <span className="pill ok">{savings.length}</span>
          </div>
          <ul style={{margin:0, padding:'12px 20px 16px 32px', display:'flex', flexDirection:'column', gap:8}}>
            {savings.map((s, i) => (
              <li key={i} style={{fontSize:13, lineHeight:1.55, color:'var(--ink-1)'}}>{s}</li>
            ))}
          </ul>
        </div>
      )}
      {hiddenFlags.length > 0 && (
        <div className="card" style={{marginTop:16}}>
          <div className="card-header">
            <div className="label">— hidden cost flags —</div>
            <span className="pill warn">{hiddenFlags.length}</span>
          </div>
          <ul style={{margin:0, padding:'12px 20px 16px 32px', display:'flex', flexDirection:'column', gap:8}}>
            {hiddenFlags.map((f, i) => (
              <li key={i} style={{fontSize:13, lineHeight:1.55, color:'var(--ink-1)'}}>{f}</li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}

function RecsPanel({ recs = [] }) {
  if (!recs.length) {
    return <div className="empty">No recommendations yet — they appear after the review step finishes.</div>;
  }
  return (
    <div style={{display:'flex', flexDirection:'column', gap:12}}>
      {recs.map((r, i) => (
        <div key={i} className="ai-border card">
          <div className="card-body" style={{padding:'14px 18px', fontSize:13.5, lineHeight:1.55, color:'var(--ink-1)'}}>
            <div style={{display:'flex', gap:10, alignItems:'flex-start'}}>
              <span className="pill accent" style={{flexShrink:0}}>REC {i + 1}</span>
              <div style={{flex:1, minWidth:0, whiteSpace:'pre-wrap'}}>{r}</div>
            </div>
          </div>
        </div>
      ))}
    </div>
  );
}

function GatedPreview({ title, sub, children }) {
  return (
    <div className="locked-wrap">
      <div className="locked-content">{children}</div>
      <div className="locked-overlay">
        <div className="locked-card">
          <div className="lock-icon"><Icon name="lock" size={15}/></div>
          <div className="title">{title}</div>
          <div className="sub">{sub}</div>
          <UpgradeCta/>
        </div>
      </div>
    </div>
  );
}

window.ScorePanel = ScorePanel;
window.CostPanel = CostPanel;
window.RecsPanel = RecsPanel;
window.GatedPreview = GatedPreview;
