// FPDS Account — user settings dashboard.
// Route: #/account (magic-link login, ?token=... for link redemption).
// Session token stored in localStorage (24h expiry). Sign out clears it.

const API_BASE = 'https://analytics-api.kenosaconsulting.com';
const SESSION_KEY = 'fpds_dash_session';

const TIER_META = {
  public:  { label:'Public',       price:'Free',        color:'#64748B', reqDay:'50',     rows:'50' },
  beta:    { label:'Beta',         price:'Free · beta', color:'#0369A1', reqDay:'250',    rows:'125' },
  t05:     { label:'Explorer',     price:'$75/mo',      color:'#0369A1', reqDay:'250',    rows:'125' },
  tier1:   { label:'Professional', price:'$800/mo',     color:'#0D9488', reqDay:'1,250',  rows:'250' },
  tier2:   { label:'Advanced',     price:'$5,000/mo',   color:'#7C3AED', reqDay:'5,000',  rows:'500' },
  tier3:   { label:'Enterprise',   price:'$18,000/mo',  color:'#BE185D', reqDay:'12,500', rows:'1,000' },
  partner: { label:'Partner',      price:'Internal',    color:'#0369A1', reqDay:'—',      rows:'—' },
  internal:{ label:'Internal',     price:'Internal',    color:'#0369A1', reqDay:'—',      rows:'—' },
  custom:  { label:'Custom',       price:'Negotiated',  color:'#991B1B', reqDay:'Negotiated', rows:'Negotiated' },
};

const inputStyle = {
  width:'100%', padding:'12px 16px', border:'1px solid #CBD5E1',
  borderRadius:9, fontSize:15, color:'#0F172A', outline:'none',
  fontFamily:'var(--font-sans)', boxSizing:'border-box',
  transition:'border-color 0.15s',
};

const ErrorBox = ({ message }) => (
  <div style={{
    background:'#FEF2F2', border:'1px solid #FECACA',
    borderRadius:10, padding:14, marginBottom:20,
    fontSize:14, color:'#B91C1C', maxWidth:440,
  }}>
    {message}
  </div>
);

const PageHead = ({ eyebrow, title, sub }) => (
  <div style={{ marginBottom:40 }}>
    <div style={{
      display:'inline-block', padding:'4px 12px', borderRadius:5,
      background:'#00008010', color:'#000080',
      fontSize:12, fontWeight:700, letterSpacing:'0.06em',
      textTransform:'uppercase', fontFamily:'var(--font-mono)',
      marginBottom:16,
    }}>
      {eyebrow}
    </div>
    <h1 style={{
      fontSize:'clamp(28px, 3.5vw, 40px)', fontWeight:800,
      color:'#0F172A', lineHeight:1.10, letterSpacing:'-0.02em',
      margin:'0 0 8px',
    }}>
      {title}
    </h1>
    {sub && (
      <p style={{ fontSize:16, lineHeight:1.55, color:'#64748B', margin:0 }}>{sub}</p>
    )}
  </div>
);

// ── Login (magic-link request) ──

const LoginView = ({ onSent, onError }) => {
  const [email, setEmail] = React.useState('');
  const [loading, setLoading] = React.useState(false);

  const submit = async (e) => {
    e.preventDefault();
    if (!email.includes('@')) return;
    setLoading(true);
    try {
      const res = await fetch(`${API_BASE}/v1/auth/request`, {
        method:'POST',
        headers:{'Content-Type':'application/json'},
        body:JSON.stringify({ email }),
      });
      const data = await res.json();
      if (!res.ok) {
        onError((data && data.error && data.error.message) || 'Could not send the login link.');
        setLoading(false);
        return;
      }
      onSent(email);
    } catch (err) {
      onError('Network error. Please try again.');
      setLoading(false);
    }
  };

  return (
    <form onSubmit={submit} style={{ maxWidth:440 }}>
      <div style={{ marginBottom:20 }}>
        <label style={{ display:'block', fontSize:13, fontWeight:600, color:'#334155', marginBottom:6 }}>
          Work email
        </label>
        <input
          type="email" value={email}
          onChange={e => setEmail(e.target.value)}
          placeholder="jane@agency.gov"
          style={inputStyle}
          onFocus={e => e.target.style.borderColor = '#000080'}
          onBlur={e => e.target.style.borderColor = '#CBD5E1'}
        />
      </div>
      <button
        type="submit" disabled={!email.includes('@') || loading}
        style={{
          width:'100%', padding:'13px 20px',
          background: email.includes('@') ? '#000080' : '#CBD5E1',
          color:'#FFFFFF', border:'none', borderRadius:9,
          fontSize:15, fontWeight:600,
          cursor: email.includes('@') ? 'pointer' : 'not-allowed',
          fontFamily:'var(--font-sans)',
        }}
      >
        {loading ? 'Sending…' : 'Email me a sign-in link'}
      </button>
      <p style={{ fontSize:13, color:'#94A3B8', lineHeight:1.55, margin:'16px 0 0' }}>
        No passwords. We email you a one-time link that signs you into your
        account dashboard — keys, plan, and billing in one place.
      </p>
    </form>
  );
};

// ── Sent confirmation ──

const SentView = ({ email, onBack }) => (
  <div style={{ maxWidth:440 }}>
    <div style={{
      background:'#F0FDFA', border:'1px solid #99F6E4',
      borderRadius:10, padding:20, marginBottom:24,
    }}>
      <div style={{ fontSize:15, fontWeight:700, color:'#0F766E', marginBottom:8 }}>
        Check your inbox
      </div>
      <p style={{ fontSize:14, lineHeight:1.55, color:'#0F766E', margin:0 }}>
        We sent a sign-in link to <strong>{email}</strong>. It expires in
        30 minutes and works once.
      </p>
    </div>
    <button onClick={onBack} style={{
      background:'transparent', border:'none', cursor:'pointer',
      color:'#000080', fontSize:14, fontWeight:600,
      fontFamily:'var(--font-sans)', padding:0,
    }}>
      ← Use a different email
    </button>
  </div>
);

// ── New key reveal ──

const KeyReveal = ({ apiKey, onDone }) => {
  const [copied, setCopied] = React.useState(false);
  const copy = () => {
    navigator.clipboard.writeText(apiKey).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    }).catch(() => {});
  };
  return (
    <div style={{
      background:'#F0FDFA', border:'1px solid #99F6E4',
      borderRadius:10, padding:20, marginBottom:24,
    }}>
      <div style={{ fontSize:15, fontWeight:700, color:'#0F766E', marginBottom:12 }}>
        New key created
      </div>
      <div style={{
        display:'flex', alignItems:'center', gap:10,
        background:'#FFFFFF', border:'1px solid #99F6E4',
        borderRadius:8, padding:'12px 16px', marginBottom:12,
      }}>
        <code style={{
          flex:1, fontFamily:'var(--font-mono)', fontSize:13,
          color:'#0F172A', wordBreak:'break-all',
        }}>
          {apiKey}
        </code>
        <button onClick={copy} style={{
          flexShrink:0, padding:'6px 14px',
          background: copied ? '#D1FAE5' : '#F0FDFA',
          color: copied ? '#065F46' : '#0D9488',
          border:'1px solid', borderColor: copied ? '#6EE7B7' : '#5EEAD4',
          borderRadius:6, fontSize:11, fontWeight:700,
          letterSpacing:'0.04em', cursor:'pointer',
          fontFamily:'var(--font-mono)',
        }}>
          {copied ? 'COPIED' : 'COPY'}
        </button>
      </div>
      <p style={{ fontSize:13, lineHeight:1.5, color:'#0F766E', margin:0 }}>
        This key is shown once. Store it securely.
      </p>
      <button onClick={onDone} style={{
        marginTop:14, background:'transparent', border:'none', cursor:'pointer',
        color:'#000080', fontSize:13, fontWeight:600,
        fontFamily:'var(--font-sans)', padding:0,
      }}>
        Done
      </button>
    </div>
  );
};

// ── Dashboard ──

const DashboardView = ({ email, data, onRefresh, onError, onSignOut }) => {
  const [revealKey, setRevealKey] = React.useState(null);
  const [creating, setCreating] = React.useState(false);
  const [portalLoading, setPortalLoading] = React.useState(false);
  const meta = TIER_META[data.tier] || TIER_META.public;
  const sub = data.subscription;

  const createKey = async () => {
    setCreating(true);
    try {
      const res = await fetch(`${API_BASE}/v1/keys/create`, {
        method:'POST',
        headers:{'Authorization': `Bearer ${localStorage.getItem(SESSION_KEY)}`},
      });
      const body = await res.json();
      if (!res.ok) {
        onError((body && body.error && body.error.message) || 'Could not create a key.');
        setCreating(false);
        return;
      }
      setRevealKey(body.api_key);
      onRefresh();
    } catch (err) {
      onError('Network error. Please try again.');
    }
    setCreating(false);
  };

  const revokeKey = async (prefix) => {
    if (!window.confirm(`Revoke key ${prefix}? This cannot be undone.`)) return;
    try {
      const res = await fetch(`${API_BASE}/v1/dashboard/keys/revoke`, {
        method:'POST',
        headers:{
          'Content-Type':'application/json',
          'Authorization': `Bearer ${localStorage.getItem(SESSION_KEY)}`,
        },
        body:JSON.stringify({ key_prefix: prefix }),
      });
      const body = await res.json();
      if (!res.ok) {
        onError((body && body.error && body.error.message) || 'Could not revoke the key.');
        return;
      }
      onRefresh();
    } catch (err) {
      onError('Network error. Please try again.');
    }
  };

  const openPortal = async () => {
    setPortalLoading(true);
    try {
      const res = await fetch(`${API_BASE}/v1/billing/portal`, {
        method:'POST',
        headers:{'Authorization': `Bearer ${localStorage.getItem(SESSION_KEY)}`},
      });
      const body = await res.json();
      if (!res.ok) {
        onError((body && body.error && body.error.message) || 'Could not open the billing portal.');
        setPortalLoading(false);
        return;
      }
      window.location.href = body.portal_url;
    } catch (err) {
      onError('Network error. Please try again.');
      setPortalLoading(false);
    }
  };

  const cardStyle = {
    background:'#FFFFFF', border:'1px solid #E2E8F0',
    borderRadius:14, padding:'28px 28px 24px', marginBottom:24,
  };

  return (
    <div style={{ maxWidth:720 }}>
      <div style={{
        display:'flex', alignItems:'center', justifyContent:'space-between',
        gap:16, flexWrap:'wrap', marginBottom:28,
      }}>
        <div style={{ fontSize:14, color:'#64748B' }}>
          Signed in as <strong style={{ color:'#0F172A' }}>{email}</strong>
        </div>
        <button onClick={onSignOut} style={{
          background:'transparent', border:'1px solid #E2E8F0', borderRadius:8,
          padding:'8px 16px', fontSize:13, fontWeight:600, color:'#64748B',
          cursor:'pointer', fontFamily:'var(--font-sans)',
        }}>
          Sign out
        </button>
      </div>

      {revealKey && <KeyReveal apiKey={revealKey} onDone={() => setRevealKey(null)}/>}

      {/* Plan card */}
      <div style={cardStyle}>
        <div style={{
          display:'flex', alignItems:'flex-start', justifyContent:'space-between',
          gap:16, flexWrap:'wrap', marginBottom:20,
        }}>
          <div>
            <div style={{
              display:'inline-flex', alignItems:'center', gap:8,
              padding:'4px 12px', borderRadius:5,
              background:`${meta.color}10`, color:meta.color,
              fontSize:12, fontWeight:700, letterSpacing:'0.06em',
              textTransform:'uppercase', fontFamily:'var(--font-mono)',
            }}>
              {meta.label} plan
            </div>
            <div style={{ fontSize:22, fontWeight:800, color:'#0F172A', marginTop:12 }}>
              {meta.price}
            </div>
          </div>
          <div style={{ display:'flex', gap:10, flexWrap:'wrap' }}>
            <button onClick={openPortal} disabled={portalLoading || !sub} style={{
              padding:'10px 18px', borderRadius:8, fontSize:13, fontWeight:600,
              background: sub ? '#000080' : '#E2E8F0', color: sub ? '#FFFFFF' : '#94A3B8',
              border:'none', cursor: sub ? 'pointer' : 'not-allowed',
              fontFamily:'var(--font-sans)',
            }}>
              {portalLoading ? 'Opening…' : 'Manage billing'}
            </button>
            <a href="#/pricing" style={{
              display:'inline-flex', alignItems:'center',
              padding:'10px 18px', borderRadius:8, fontSize:13, fontWeight:600,
              color:'#000080', border:'1px solid rgba(0,0,128,0.20)',
              textDecoration:'none', fontFamily:'var(--font-sans)',
            }}>
              Upgrade plan
            </a>
          </div>
        </div>

        <div style={{
          display:'grid', gridTemplateColumns:'repeat(auto-fit, minmax(150px, 1fr))',
          gap:12, marginBottom:16,
        }}>
          {[
            { k:'Requests/day', v:meta.reqDay },
            { k:'Rows/request', v:meta.rows },
            { k:'MCP access', v: data.mcp_enabled ? 'Included' : 'Add-on $200/mo' },
          ].map(f => (
            <div key={f.k} style={{
              background:'#FAFBFC', border:'1px solid #F1F5F9',
              borderRadius:8, padding:'12px 14px',
            }}>
              <div style={{ fontSize:11, fontWeight:700, textTransform:'uppercase', letterSpacing:'0.08em', color:'#94A3B8', marginBottom:4 }}>
                {f.k}
              </div>
              <div style={{ fontSize:14, fontWeight:700, color:'#334155' }}>{f.v}</div>
            </div>
          ))}
        </div>

        {data.tier === 'beta' && (
          <div style={{
            background:'#F0F9FF', border:'1px solid #BAE6FD',
            borderRadius:8, padding:'12px 14px', marginBottom:12,
            fontSize:13, lineHeight:1.5, color:'#0C4A6E',
          }}>
            Beta is a pre-launch access tier. Beta keys expire 90 days after issue —
            subscribe to a paid plan to keep your limits.
          </div>
        )}

        {sub ? (
          <div style={{ fontSize:13, lineHeight:1.55, color:'#64748B' }}>
            {sub.tier_label ? `Subscribed to ${sub.tier_label} · ` : ''}
            Renews {new Date(sub.current_period_end * 1000).toLocaleDateString()}
            {sub.cancel_at_period_end ? ' · cancels at period end' : ''}
          </div>
        ) : (
          <div style={{ fontSize:13, lineHeight:1.55, color:'#94A3B8' }}>
            {data.tier === 'public'
              ? 'You\u2019re on the free plan. Subscribe to unlock paid tiers and billing management.'
              : 'No active Stripe subscription is linked to this email yet.'}
          </div>
        )}
      </div>

      {/* Keys card */}
      <div style={cardStyle}>
        <div style={{
          display:'flex', alignItems:'center', justifyContent:'space-between',
          gap:16, flexWrap:'wrap', marginBottom:16,
        }}>
          <h2 style={{ fontSize:17, fontWeight:700, color:'#0F172A', margin:0 }}>
            API keys
          </h2>
          <button onClick={createKey} disabled={creating} style={{
            padding:'10px 18px', borderRadius:8, fontSize:13, fontWeight:600,
            background:'#000080', color:'#FFFFFF', border:'none',
            cursor: creating ? 'wait' : 'pointer', fontFamily:'var(--font-sans)',
          }}>
            {creating ? 'Creating…' : 'Create another key'}
          </button>
        </div>
        <div style={{ overflowX:'auto' }}>
          <table style={{ width:'100%', borderCollapse:'collapse', fontSize:13, minWidth:520 }}>
            <thead>
              <tr style={{ borderBottom:'2px solid #E2E8F0' }}>
                {['Key', 'Tier', 'Created', 'Last used', 'Status', ''].map((h, i) => (
                  <th key={i} style={{
                    textAlign:'left', padding:'8px 10px',
                    fontSize:11, fontWeight:700, textTransform:'uppercase',
                    letterSpacing:'0.08em', color:'#94A3B8',
                  }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {(data.keys || []).map(k => {
                const km = TIER_META[k.tier] || TIER_META.public;
                return (
                  <tr key={k.key_prefix} style={{ borderBottom:'1px solid #F1F5F9' }}>
                    <td style={{ padding:'10px', fontFamily:'var(--font-mono)', fontSize:12, color:'#0F172A' }}>
                      {k.key_prefix}…
                    </td>
                    <td style={{ padding:'10px' }}>
                      <span style={{
                        fontSize:11, fontWeight:700, padding:'2px 8px', borderRadius:4,
                        color:km.color, background:`${km.color}10`,
                      }}>{km.label}</span>
                    </td>
                    <td style={{ padding:'10px', color:'#64748B' }}>
                      {k.created_at ? new Date(k.created_at).toLocaleDateString() : '—'}
                    </td>
                    <td style={{ padding:'10px', color:'#64748B' }}>
                      {k.last_used_at ? new Date(k.last_used_at).toLocaleDateString() : 'Never'}
                    </td>
                    <td style={{ padding:'10px' }}>
                      <span style={{
                        fontSize:11, fontWeight:700,
                        color: k.is_active ? '#0D9488' : '#94A3B8',
                      }}>
                        {k.is_active ? 'ACTIVE' : 'REVOKED'}
                      </span>
                    </td>
                    <td style={{ padding:'10px', textAlign:'right' }}>
                      {k.is_active && (
                        <button onClick={() => revokeKey(k.key_prefix)} style={{
                          background:'transparent', border:'none', cursor:'pointer',
                          fontSize:12, fontWeight:600, color:'#B91C1C',
                          fontFamily:'var(--font-sans)',
                        }}>
                          Revoke
                        </button>
                      )}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      <p style={{ fontSize:12, lineHeight:1.55, color:'#94A3B8', margin:0 }}>
        Sessions expire after 24 hours. Keys are stored as SHA-256 hashes —
        plaintext is shown exactly once, at creation.
      </p>
    </div>
  );
};

// ── Main Account Page ──

const AccountPage = () => {
  const [view, setView] = React.useState('login');
  const [email, setEmail] = React.useState('');
  const [error, setError] = React.useState(null);
  const [data, setData] = React.useState(null);

  const loadDashboard = async () => {
    try {
      const res = await fetch(`${API_BASE}/v1/dashboard`, {
        headers:{'Authorization': `Bearer ${localStorage.getItem(SESSION_KEY)}`},
      });
      const body = await res.json();
      if (!res.ok) {
        localStorage.removeItem(SESSION_KEY);
        setView('login');
        setError((body && body.error && body.error.message) || 'Session expired. Sign in again.');
        return;
      }
      setEmail(body.email);
      setData(body);
      setView('authed');
    } catch (err) {
      setView('login');
      setError('Network error. Please sign in again.');
    }
  };

  const verifyToken = async (token) => {
    setView('loading');
    try {
      const res = await fetch(`${API_BASE}/v1/auth/verify`, {
        method:'POST',
        headers:{'Content-Type':'application/json'},
        body:JSON.stringify({ token }),
      });
      const body = await res.json();
      if (!res.ok) {
        setError((body && body.error && body.error.message) || 'Sign-in link invalid.');
        setView('login');
        return;
      }
      localStorage.setItem(SESSION_KEY, body.session_token);
      window.location.hash = '#/account';
      await loadDashboard();
    } catch (err) {
      setError('Network error. Please try again.');
      setView('login');
    }
  };

  React.useEffect(() => {
    const hash = window.location.hash || '';
    const m = hash.match(/token=([A-Za-z0-9._\-]+)/);
    if (m) {
      verifyToken(m[1]);
      return;
    }
    if (localStorage.getItem(SESSION_KEY)) {
      setView('loading');
      loadDashboard();
    }
  }, []);

  return (
    <div style={{ background:'#FFFFFF', minHeight:'100vh' }}>
      <section style={{ padding:'100px 0 80px' }}>
        <div className="container" style={{ maxWidth:720 }}>
          {view === 'login' && (
            <div>
              <PageHead
                eyebrow="Account"
                title="Sign in to your dashboard"
                sub="Manage your plan, keys, and billing."
              />
              {error && <ErrorBox message={error}/>}
              <LoginView
                onSent={(em) => { setEmail(em); setError(null); setView('sent'); }}
                onError={setError}
              />
            </div>
          )}

          {view === 'sent' && (
            <div>
              <PageHead eyebrow="Account" title="Check your inbox" />
              <SentView email={email} onBack={() => { setError(null); setView('login'); }}/>
            </div>
          )}

          {view === 'loading' && (
            <div style={{ textAlign:'center', padding:'60px 0', color:'#94A3B8', fontSize:15 }}>
              Loading your account…
            </div>
          )}

          {view === 'authed' && data && (
            <div>
              <PageHead
                eyebrow="Account"
                title="Your account"
                sub="Everything attached to your email, in one place."
              />
              {error && <ErrorBox message={error}/>}
              <DashboardView
                email={email}
                data={data}
                onRefresh={loadDashboard}
                onError={setError}
                onSignOut={() => {
                  localStorage.removeItem(SESSION_KEY);
                  setData(null);
                  setError(null);
                  setView('login');
                }}
              />
            </div>
          )}
        </div>
      </section>
    </div>
  );
};

window.AccountPage = AccountPage;
