import { useState, useEffect, useCallback, useRef } from 'react';
import { gsc, sheets } from '../lib/api';

const ANNOTATION_TYPES = [
  { key: 'quick',  label: 'Quick update',      color: '#2563eb', icon: '⚡' },
  { key: 'full',   label: 'Full optimization', color: '#16a34a', icon: '🔧' },
  { key: 'custom', label: 'Custom',            color: '#7c3aed', icon: '📝' },
];
const PRIORITIES  = ['High', 'Medium', 'Low'];
const COMPARISONS = [
  { key: 'wow', label: 'Week / Week',   days: 7,  prevDays: 7  },
  { key: 'mom', label: 'Month / Month', days: 30, prevDays: 30 },
  { key: 'custom', label: 'Custom',     days: null, prevDays: null },
];
const STORAGE_KEY = (site) => `kpi_v3_${site}`;

function loadKpis(site)       { try { return JSON.parse(localStorage.getItem(STORAGE_KEY(site)) || '[]'); } catch { return []; } }
function saveKpis(site, kpis) { try { localStorage.setItem(STORAGE_KEY(site), JSON.stringify(kpis)); } catch {} }
function genId()  { return Math.random().toString(36).slice(2, 9); }
function today()  { return new Date().toISOString().split('T')[0]; }
function fmtNum(n){ if (n == null) return '—'; if (n >= 1000) return (n/1000).toFixed(1)+'K'; return String(n); }
function normalisePath(p) { try { if (p.startsWith('http')) return new URL(p).pathname; } catch {} return p.startsWith('/') ? p : '/'+p; }
function ch(color, bg) { return { fontSize: 10, fontWeight: 500, padding: '2px 7px', borderRadius: 20, color, background: bg, whiteSpace: 'nowrap', display: 'inline-block' }; }

// ── Badges ────────────────────────────────────────────────────
function MoveBadge({ delta }) {
  if (delta == null) return <span style={ch('var(--text3)', 'var(--surface2)')}>—</span>;
  if (Math.abs(delta) < 0.5) return <span style={ch('var(--text3)', 'var(--surface2)')}>Stable</span>;
  if (delta > 0) return <span style={ch('var(--green-text)', 'var(--green-bg)')}>↑ +{Math.round(delta)}</span>;
  return <span style={ch('var(--red-text)', 'var(--red-bg)')}>↓ {Math.round(delta)}</span>;
}
function PosBadge({ pos }) {
  if (pos == null) return <span style={{ fontSize: 11, color: 'var(--text3)' }}>—</span>;
  const p = Math.round(pos);
  const color = p <= 3 ? 'var(--green-text)' : p <= 10 ? 'var(--amber-text)' : 'var(--text)';
  return <span style={{ fontSize: 13, fontWeight: 600, color }}>#{p}</span>;
}
function PriorityBadge({ priority }) {
  const s = { High: ch('var(--red-text)', 'var(--red-bg)'), Medium: ch('var(--amber-text)', 'var(--amber-bg)'), Low: ch('var(--text3)', 'var(--surface2)') };
  return <span style={s[priority] || s.Low}>{priority}</span>;
}
function VisScore({ score }) {
  if (score == null) return <span style={{ fontSize: 11, color: 'var(--text3)' }}>—</span>;
  const color = score >= 70 ? 'var(--green-text)' : score >= 40 ? 'var(--amber-text)' : 'var(--red-text)';
  const bg    = score >= 70 ? 'var(--green-bg)'   : score >= 40 ? 'var(--amber-bg)'   : 'var(--red-bg)';
  return <span style={ch(color, bg)}>{score}</span>;
}
function DistBar({ dist }) {
  if (!dist) return null;
  const total = dist.top3 + dist.top10 + dist.top20 + dist.beyond20;
  if (!total) return null;
  const p = (n) => Math.round(n / total * 100);
  return (
    <div title={`#1-3: ${dist.top3}  #4-10: ${dist.top10}  #11-20: ${dist.top20}  20+: ${dist.beyond20}`}>
      <div style={{ display: 'flex', height: 5, borderRadius: 3, overflow: 'hidden', width: 72, background: 'var(--surface2)' }}>
        <div style={{ width: p(dist.top3)+'%',    background: '#16a34a' }} />
        <div style={{ width: p(dist.top10)+'%',   background: '#d97706' }} />
        <div style={{ width: p(dist.top20)+'%',   background: '#2563eb' }} />
        <div style={{ width: p(dist.beyond20)+'%',background: '#d1d5db'}} />
      </div>
      <div style={{ fontSize: 9, color: 'var(--text3)', marginTop: 2, fontFamily: 'monospace' }}>
        {dist.top3}·{dist.top10}·{dist.top20}·{dist.beyond20}
      </div>
    </div>
  );
}
function MobileGap({ gap }) {
  if (gap == null) return <span style={{ fontSize: 11, color: 'var(--text3)' }}>—</span>;
  if (Math.abs(gap) < 1) return <span style={ch('var(--green-text)', 'var(--green-bg)')}>≈ equal</span>;
  if (gap > 0) return <span style={ch('var(--red-text)', 'var(--red-bg)')}>mob +{Math.round(gap)}</span>;
  return <span style={ch('var(--green-text)', 'var(--green-bg)')}>mob {Math.round(gap)}</span>;
}
function CtrBadge({ val }) {
  if (val == null) return <span style={{ fontSize: 11, color: 'var(--text3)' }}>—</span>;
  if (val >= 10)  return <span style={ch('var(--green-text)', 'var(--green-bg)')}>+{val}%</span>;
  if (val < -20)  return <span style={ch('var(--red-text)',   'var(--red-bg)'  )}>{val}%</span>;
  return <span style={ch('var(--text2)', 'var(--surface2)')}>{val > 0 ? '+' : ''}{val}%</span>;
}

// ── Top queries table ─────────────────────────────────────────
function TopQueriesPanel({ queries = [] }) {
  if (!queries.length) return <div style={{ fontSize: 11, color: 'var(--text3)' }}>No query data found for this page.</div>;
  return (
    <div style={{ overflowX: 'auto' }}>
      <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11 }}>
        <thead>
          <tr style={{ borderBottom: '1px solid var(--border)' }}>
            {['Query','Pos','Δ','Clicks','Impr.','CTR','CTR vs exp.'].map(h => (
              <th key={h} style={{ padding: '3px 6px 6px', fontWeight: 500, color: 'var(--text3)', textAlign: h === 'Query' ? 'left' : 'right', whiteSpace: 'nowrap' }}>{h}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {queries.map((q, i) => (
            <tr key={i} style={{ borderBottom: '0.5px solid var(--border)' }}>
              <td style={{ padding: '5px 6px', maxWidth: 220, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', fontWeight: 500 }}>{q.query}</td>
              <td style={{ padding: '5px 6px', textAlign: 'right' }}><PosBadge pos={q.position} /></td>
              <td style={{ padding: '5px 6px', textAlign: 'right' }}><MoveBadge delta={q.positionDelta} /></td>
              <td style={{ padding: '5px 6px', textAlign: 'right', fontWeight: 500 }}>{fmtNum(q.clicks)}</td>
              <td style={{ padding: '5px 6px', textAlign: 'right', color: 'var(--text2)' }}>{fmtNum(q.impressions)}</td>
              <td style={{ padding: '5px 6px', textAlign: 'right', color: 'var(--text2)' }}>{q.ctr != null ? q.ctr + '%' : '—'}</td>
              <td style={{ padding: '5px 6px', textAlign: 'right' }}><CtrBadge val={q.ctrVsExpected} /></td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

// ── Annotation history ────────────────────────────────────────
function AnnotationHistory({ annotations = [], currentPosition, onDelete }) {
  if (!annotations.length) return <div style={{ fontSize: 11, color: 'var(--text3)', fontStyle: 'italic' }}>No annotations yet. Click "+ Log optimization" to start tracking changes.</div>;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
      {[...annotations].sort((a, b) => b.date.localeCompare(a.date)).map(ann => {
        const t = ANNOTATION_TYPES.find(x => x.key === ann.type) || ANNOTATION_TYPES[2];
        const improvement = ann.positionBefore && currentPosition ? parseFloat((parseFloat(ann.positionBefore) - currentPosition).toFixed(1)) : null;
        return (
          <div key={ann.id} style={{ display: 'flex', gap: 8, padding: '9px 11px', background: 'var(--surface)', borderRadius: 8, border: `1px solid ${t.color}25` }}>
            <div style={{ width: 3, borderRadius: 2, background: t.color, flexShrink: 0 }} />
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 3, alignItems: 'center' }}>
                <span style={{ fontSize: 10, fontWeight: 600, color: t.color }}>{t.icon} {ann.typeLabel || t.label}</span>
                <span style={{ fontSize: 10, color: 'var(--text3)' }}>{ann.date}</span>
                {ann.positionBefore && <span style={{ fontSize: 10, color: 'var(--text2)' }}>was #{Math.round(ann.positionBefore)}</span>}
                {improvement > 0.5  && <span style={ch('var(--green-text)', 'var(--green-bg)')}>+{Math.round(improvement)} spots gained</span>}
                {improvement < -0.5 && <span style={ch('var(--red-text)', 'var(--red-bg)')}>{Math.round(improvement)} spots lost</span>}
              </div>
              <div style={{ fontSize: 11, color: 'var(--text)', lineHeight: 1.5 }}>{ann.note}</div>
            </div>
            <button onClick={() => onDelete(ann.id)} style={{ fontSize: 13, color: 'var(--text3)', background: 'none', border: 'none', cursor: 'pointer', padding: '0 2px', alignSelf: 'flex-start', flexShrink: 0 }}>×</button>
          </div>
        );
      })}
    </div>
  );
}

// ── Expanded row ──────────────────────────────────────────────
function ExpandedRow({ k, gscResult, onAddAnnotation, onDeleteAnnotation }) {
  const [sub, setSub] = useState('queries');
  const g = gscResult;
  const tabs = [
    { key: 'queries',     label: `Queries (${g?.topQueries?.length || 0})` },
    { key: 'annotations', label: `Log (${k.annotations?.length || 0})` },
    { key: 'technical',   label: 'Technical' },
  ];
  return (
    <tr style={{ borderBottom: '1px solid var(--border)' }}>
      <td colSpan={13} style={{ padding: '12px 14px 16px', background: 'var(--surface2)' }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
          <div style={{ display: 'flex', gap: 4 }}>
            {tabs.map(t => (
              <button key={t.key} onClick={() => setSub(t.key)}
                style={{ fontSize: 11, padding: '4px 12px', borderRadius: 20, border: '1px solid var(--border2)', cursor: 'pointer',
                  background: sub === t.key ? 'var(--blue)' : 'transparent',
                  color: sub === t.key ? '#fff' : 'var(--text2)',
                  fontWeight: sub === t.key ? 500 : 400 }}>
                {t.label}
              </button>
            ))}
          </div>
          <button onClick={onAddAnnotation}
            style={{ fontSize: 11, fontWeight: 500, padding: '4px 12px', borderRadius: 20, border: 'none', background: 'var(--blue)', color: '#fff', cursor: 'pointer' }}>
            + Log optimization
          </button>
        </div>

        {sub === 'queries' && (
          <div>
            {g?.cannibalization?.length > 0 && (
              <div style={{ background: 'var(--amber-bg)', border: '1px solid var(--amber)', borderRadius: 7, padding: '7px 12px', marginBottom: 10, fontSize: 11, color: 'var(--amber-text)', lineHeight: 1.5 }}>
                ⚠ <strong>Cannibalization:</strong> {g.cannibalization.map(c => (
                  <span key={c.query}><em>{c.query}</em> also targets {c.pages.filter(p => p !== k.page).join(', ')} · </span>
                ))}
              </div>
            )}
            <TopQueriesPanel queries={g?.topQueries || []} />
          </div>
        )}

        {sub === 'annotations' && (
          <AnnotationHistory
            annotations={k.annotations || []}
            currentPosition={g?.position}
            onDelete={onDeleteAnnotation}
          />
        )}

        {sub === 'technical' && (
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(170px,1fr))', gap: 8 }}>
            {[
              { label: 'Weighted avg pos',   value: g?.position != null ? `#${g.position}` : '—' },
              { label: 'Mobile position',    value: g?.mobilePosition != null ? `#${Math.round(g.mobilePosition)}` : '—' },
              { label: 'Desktop position',   value: g?.desktopPosition != null ? `#${Math.round(g.desktopPosition)}` : '—' },
              { label: 'Mobile vs desktop',  value: g?.mobileDesktopGap != null ? (g.mobileDesktopGap > 0 ? `+${Math.round(g.mobileDesktopGap)} worse on mobile` : `${Math.round(g.mobileDesktopGap)} better on mobile`) : '—' },
              { label: 'Total queries',      value: g?.queryCount ?? '—' },
              { label: 'Actual CTR',         value: g?.ctr != null ? `${g.ctr}%` : '—' },
              { label: 'Expected CTR',       value: g?.expectedCTR != null ? `${g.expectedCTR}%` : '—' },
              { label: 'CTR vs expected',    value: g?.ctrVsExpected != null ? `${g.ctrVsExpected > 0 ? '+' : ''}${g.ctrVsExpected}%` : '—' },
              { label: 'Visibility score',   value: g?.visibilityScore ?? '—' },
              { label: 'Featured snippet',   value: g?.hasFeaturedSnippet ? '✅ Yes' : '—' },
              { label: 'People Also Ask',    value: g?.hasPAA ? '✅ Yes' : '—' },
              { label: 'SERP features',      value: g?.serpFeatures?.length ? g.serpFeatures.slice(0,3).join(', ') : 'None' },
            ].map(item => (
              <div key={item.label} style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 8, padding: '9px 11px' }}>
                <div style={{ fontSize: 10, color: 'var(--text3)', marginBottom: 3 }}>{item.label}</div>
                <div style={{ fontSize: 12, fontWeight: 500 }}>{item.value}</div>
              </div>
            ))}
          </div>
        )}
      </td>
    </tr>
  );
}

// ── Annotation modal ──────────────────────────────────────────
function AnnotationModal({ kpi, positionAtTime, onSave, onClose }) {
  const [form, setForm] = useState({ type: 'quick', date: today(), note: '', customType: '', positionBefore: positionAtTime ? String(Math.round(positionAtTime)) : '' });
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const t = ANNOTATION_TYPES.find(x => x.key === form.type) || ANNOTATION_TYPES[0];
  const valid = form.note.trim().length > 0;
  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 300, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,.3)', backdropFilter: 'blur(2px)' }} />
      <div style={{ position: 'relative', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 14, padding: 24, width: 460, maxWidth: '94vw', boxShadow: '0 20px 60px rgba(0,0,0,.15)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
          <div style={{ fontWeight: 600, fontSize: 15 }}>Log optimization</div>
          <button onClick={onClose} style={{ fontSize: 22, background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text2)' }}>×</button>
        </div>
        <div style={{ fontSize: 12, color: 'var(--text3)', marginBottom: 14, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{kpi.page}</div>
        <div style={{ display: 'flex', gap: 6, marginBottom: 14, flexWrap: 'wrap' }}>
          {ANNOTATION_TYPES.map(tp => (
            <button key={tp.key} onClick={() => set('type', tp.key)}
              style={{ fontSize: 11, padding: '5px 12px', borderRadius: 20, cursor: 'pointer',
                border: `1px solid ${form.type === tp.key ? tp.color : 'var(--border2)'}`,
                background: form.type === tp.key ? tp.color+'18' : 'transparent',
                color: form.type === tp.key ? tp.color : 'var(--text2)',
                fontWeight: form.type === tp.key ? 500 : 400 }}>
              {tp.icon} {tp.label}
            </button>
          ))}
        </div>
        {form.type === 'custom' && (
          <input value={form.customType} onChange={e => set('customType', e.target.value)} placeholder="Custom type name…"
            style={{ width: '100%', fontSize: 12, padding: '7px 10px', borderRadius: 7, border: '1px solid var(--border2)', background: 'var(--surface)', color: 'var(--text)', marginBottom: 12, boxSizing: 'border-box', outline: 'none' }} />
        )}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          <div>
            <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text2)', marginBottom: 4 }}>Date</div>
            <input type="date" value={form.date} onChange={e => set('date', e.target.value)}
              style={{ width: '100%', fontSize: 12, padding: '7px 10px', borderRadius: 7, border: '1px solid var(--border2)', background: 'var(--surface)', color: 'var(--text)', boxSizing: 'border-box' }} />
          </div>
          <div>
            <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text2)', marginBottom: 4 }}>What did you change? *</div>
            <textarea value={form.note} onChange={e => set('note', e.target.value)} rows={3}
              placeholder="e.g. Rewrote intro, added FAQ section, updated title tag…"
              style={{ width: '100%', fontSize: 12, padding: '7px 10px', borderRadius: 7, border: '1px solid var(--border2)', background: 'var(--surface)', color: 'var(--text)', resize: 'vertical', fontFamily: 'inherit', boxSizing: 'border-box', outline: 'none' }} />
          </div>
          <div>
            <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text2)', marginBottom: 4 }}>
              Position at time of change
              {positionAtTime && <span style={{ color: 'var(--text3)', fontWeight: 400, marginLeft: 6 }}>current avg: #{Math.round(positionAtTime)}</span>}
            </div>
            <input type="number" value={form.positionBefore} onChange={e => set('positionBefore', e.target.value)} placeholder="e.g. 14"
              style={{ width: '100%', fontSize: 12, padding: '7px 10px', borderRadius: 7, border: '1px solid var(--border2)', background: 'var(--surface)', color: 'var(--text)', boxSizing: 'border-box', outline: 'none' }} />
            <div style={{ fontSize: 10, color: 'var(--text3)', marginTop: 3 }}>Tracks improvement after your change</div>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 18 }}>
          <button onClick={onClose} style={{ fontSize: 12, padding: '7px 16px', borderRadius: 8, border: '0.5px solid var(--border2)', background: 'transparent', color: 'var(--text2)', cursor: 'pointer' }}>Cancel</button>
          <button onClick={() => valid && onSave({ ...form, id: genId(), typeLabel: form.type === 'custom' && form.customType ? form.customType : t.label })} disabled={!valid}
            style={{ fontSize: 12, fontWeight: 500, padding: '7px 18px', borderRadius: 8, border: 'none', background: valid ? 'var(--blue)' : 'var(--surface2)', color: valid ? '#fff' : 'var(--text3)', cursor: valid ? 'pointer' : 'default' }}>
            Save annotation
          </button>
        </div>
      </div>
    </div>
  );
}

// ── Page modal ────────────────────────────────────────────────
function PageModal({ kpi, onSave, onClose }) {
  const [form, setForm] = useState(kpi || { page: '', keyword: '', priority: 'Medium', notes: '' });
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const valid = form.page.trim().length > 0;
  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 200, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,.3)', backdropFilter: 'blur(2px)' }} />
      <div style={{ position: 'relative', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 14, padding: 24, width: 440, maxWidth: '94vw', boxShadow: '0 20px 60px rgba(0,0,0,.15)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 18 }}>
          <div style={{ fontWeight: 600, fontSize: 15 }}>{kpi ? 'Edit page' : 'Add KPI page'}</div>
          <button onClick={onClose} style={{ fontSize: 22, background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text2)' }}>×</button>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          {[
            { key: 'page',    label: 'Page path *', placeholder: '/best-online-casinos', hint: 'Path only, must match GSC format exactly' },
            { key: 'keyword', label: 'Target keyword', placeholder: 'best online casinos', hint: null },
            { key: 'notes',   label: 'Notes', placeholder: 'Any notes about this page', hint: null },
          ].map(f => (
            <div key={f.key}>
              <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text2)', marginBottom: 4 }}>{f.label}</div>
              <input value={form[f.key]} onChange={e => set(f.key, e.target.value)} placeholder={f.placeholder}
                style={{ width: '100%', fontSize: 12, padding: '7px 10px', borderRadius: 7, border: '1px solid var(--border2)', background: 'var(--surface)', color: 'var(--text)', outline: 'none', boxSizing: 'border-box' }} />
              {f.hint && <div style={{ fontSize: 10, color: 'var(--text3)', marginTop: 3 }}>{f.hint}</div>}
            </div>
          ))}
          <div>
            <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text2)', marginBottom: 5 }}>Priority</div>
            <div style={{ display: 'flex', gap: 5 }}>
              {PRIORITIES.map(p => (
                <button key={p} onClick={() => set('priority', p)}
                  style={{ flex: 1, fontSize: 11, padding: '5px 0', borderRadius: 7, cursor: 'pointer',
                    border: `1px solid ${form.priority === p ? 'var(--blue)' : 'var(--border2)'}`,
                    background: form.priority === p ? 'var(--blue-bg)' : 'transparent',
                    color: form.priority === p ? 'var(--blue-text)' : 'var(--text2)',
                    fontWeight: form.priority === p ? 500 : 400 }}>
                  {p}
                </button>
              ))}
            </div>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 20 }}>
          <button onClick={onClose} style={{ fontSize: 12, padding: '7px 16px', borderRadius: 8, border: '0.5px solid var(--border2)', background: 'transparent', color: 'var(--text2)', cursor: 'pointer' }}>Cancel</button>
          <button onClick={() => valid && onSave(form)} disabled={!valid}
            style={{ fontSize: 12, fontWeight: 500, padding: '7px 18px', borderRadius: 8, border: 'none', background: valid ? 'var(--blue)' : 'var(--surface2)', color: valid ? '#fff' : 'var(--text3)', cursor: valid ? 'pointer' : 'default' }}>
            {kpi ? 'Save' : 'Add page'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ── Sheet import ──────────────────────────────────────────────
function SheetImportModal({ onImport, onClose }) {
  const [list, setList]   = useState([]);
  const [sel, setSel]     = useState(null);
  const [data, setData]   = useState(null);
  const [loading, setLd]  = useState(false);
  const [colMap, setCols] = useState({ page: '', keyword: '', priority: '', notes: '' });
  useEffect(() => { sheets.list().then(setList).catch(() => {}); }, []);
  const loadSheet = async (s) => {
    setSel(s); setLd(true);
    try {
      const d = await sheets.data(s.id, s.tab); setData(d);
      const h = d.headers || [];
      const find = (...names) => h.find(c => names.some(n => c.toLowerCase().includes(n))) || '';
      setCols({ page: find('page','url','path'), keyword: find('keyword','query'), priority: find('priority'), notes: find('notes','note') });
    } catch {} finally { setLd(false); }
  };
  const doImport = () => {
    const rows = (data?.rows || []).map(r => ({
      id: genId(), annotations: [],
      page:     (colMap.page     ? r._raw[colMap.page]     || '' : '').trim(),
      keyword:  (colMap.keyword  ? r._raw[colMap.keyword]  || '' : '').trim(),
      priority: (colMap.priority ? r._raw[colMap.priority] || 'Medium' : 'Medium').trim(),
      notes:    (colMap.notes    ? r._raw[colMap.notes]    || '' : '').trim(),
    })).filter(r => r.page);
    onImport(rows);
  };
  const headers = data?.headers || [];
  const count = (data?.rows || []).filter(r => colMap.page && r._raw[colMap.page]).length;
  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 200, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,.3)', backdropFilter: 'blur(2px)' }} />
      <div style={{ position: 'relative', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 14, padding: 24, width: 480, maxWidth: '94vw', maxHeight: '80vh', overflowY: 'auto', boxShadow: '0 20px 60px rgba(0,0,0,.15)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
          <div style={{ fontWeight: 600, fontSize: 15 }}>Import from Google Sheet</div>
          <button onClick={onClose} style={{ fontSize: 22, background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text2)' }}>×</button>
        </div>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 14 }}>
          {list.length === 0 && <div style={{ fontSize: 12, color: 'var(--text2)' }}>No sheets connected. Add GOOGLE_SHEETS to .env.</div>}
          {list.map(s => (
            <button key={s.id} onClick={() => loadSheet(s)}
              style={{ fontSize: 11, padding: '4px 12px', borderRadius: 20, cursor: 'pointer', border: `1px solid ${sel?.id===s.id?'var(--blue)':'var(--border2)'}`, background: sel?.id===s.id?'var(--blue-bg)':'transparent', color: sel?.id===s.id?'var(--blue-text)':'var(--text2)', display: 'flex', alignItems: 'center', gap: 5 }}>
              <span style={{ width: 7, height: 7, borderRadius: '50%', background: s.color||'#378ADD' }} />{s.name}
            </button>
          ))}
        </div>
        {loading && <div style={{ fontSize: 12, color: 'var(--text2)' }}>Loading…</div>}
        {data && !loading && (
          <div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 14 }}>
              {[{k:'page',l:'Page / URL *'},{k:'keyword',l:'Keyword'},{k:'priority',l:'Priority'},{k:'notes',l:'Notes'}].map(f => (
                <div key={f.k}>
                  <div style={{ fontSize: 11, color: 'var(--text2)', marginBottom: 4 }}>{f.l}</div>
                  <select value={colMap[f.k]} onChange={e => setCols(m => ({...m,[f.k]:e.target.value}))}
                    style={{ width: '100%', fontSize: 12, padding: '5px 8px', borderRadius: 6, border: '1px solid var(--border2)', background: 'var(--surface)', color: 'var(--text)', cursor: 'pointer' }}>
                    <option value="">— skip —</option>
                    {headers.map(h => <option key={h} value={h}>{h}</option>)}
                  </select>
                </div>
              ))}
            </div>
            <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
              <button onClick={onClose} style={{ fontSize: 12, padding: '7px 14px', borderRadius: 8, border: '0.5px solid var(--border2)', background: 'transparent', color: 'var(--text2)', cursor: 'pointer' }}>Cancel</button>
              <button onClick={doImport} disabled={!colMap.page}
                style={{ fontSize: 12, fontWeight: 500, padding: '7px 16px', borderRadius: 8, border: 'none', background: colMap.page?'var(--blue)':'var(--surface2)', color: colMap.page?'#fff':'var(--text3)', cursor: colMap.page?'pointer':'default' }}>
                Import {count} pages
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

// ── Comparison picker ─────────────────────────────────────────
function ComparisonPicker({ comparison, onChange }) {
  const [showCustom, setShowCustom] = useState(false);
  const [cA, setCA] = useState({ from: '', to: '' });
  const [cB, setCB] = useState({ from: '', to: '' });
  const applyCustom = () => {
    if (cA.from && cA.to && cB.from && cB.to) {
      onChange({ key: 'custom', label: 'Custom', days: Math.round((new Date(cA.to)-new Date(cA.from))/86400000)+1, prevDays: Math.round((new Date(cB.to)-new Date(cB.from))/86400000)+1, periodA: cA, periodB: cB });
      setShowCustom(false);
    }
  };
  const di = { fontSize: 12, padding: '6px 8px', borderRadius: 6, border: '1px solid var(--border2)', background: 'var(--surface)', color: 'var(--text)', width: '100%', boxSizing: 'border-box' };
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
      <span style={{ fontSize: 11, color: 'var(--text3)' }}>Compare:</span>
      {COMPARISONS.slice(0,2).map(c => (
        <button key={c.key} onClick={() => onChange(c)}
          style={{ fontSize: 11, padding: '3px 10px', borderRadius: 20, cursor: 'pointer', border: `1px solid ${comparison.key===c.key?'var(--blue)':'var(--border2)'}`, background: comparison.key===c.key?'var(--blue)':'transparent', color: comparison.key===c.key?'#fff':'var(--text2)', fontWeight: comparison.key===c.key?500:400 }}>
          {c.label}
        </button>
      ))}
      <button onClick={() => setShowCustom(s => !s)}
        style={{ fontSize: 11, padding: '3px 10px', borderRadius: 20, cursor: 'pointer', border: `1px solid ${comparison.key==='custom'?'var(--blue)':'var(--border2)'}`, background: comparison.key==='custom'?'var(--blue)':'transparent', color: comparison.key==='custom'?'#fff':'var(--text2)' }}>
        {comparison.key==='custom'?'Custom ✓':'Custom…'}
      </button>
      {showCustom && (
        <div style={{ position: 'fixed', inset: 0, zIndex: 200, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <div onClick={() => setShowCustom(false)} style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,.2)' }} />
          <div style={{ position: 'relative', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 12, padding: 20, width: 360, boxShadow: '0 8px 30px rgba(0,0,0,.12)' }}>
            <div style={{ fontWeight: 600, fontSize: 14, marginBottom: 14 }}>Custom comparison</div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginBottom: 14 }}>
              {[{label:'Period A (current)',st:cA,set:setCA},{label:'Period B (compare to)',st:cB,set:setCB}].map(({label,st,set}) => (
                <div key={label}>
                  <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text2)', marginBottom: 6 }}>{label}</div>
                  <input type="date" value={st.from} onChange={e => set(p=>({...p,from:e.target.value}))} style={{...di,marginBottom:5}} />
                  <input type="date" value={st.to}   onChange={e => set(p=>({...p,to:e.target.value}))}   style={di} />
                </div>
              ))}
            </div>
            <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
              <button onClick={()=>setShowCustom(false)} style={{ fontSize: 12, padding: '6px 14px', borderRadius: 7, border: '0.5px solid var(--border2)', background: 'transparent', color: 'var(--text2)', cursor: 'pointer' }}>Cancel</button>
              <button onClick={applyCustom} style={{ fontSize: 12, fontWeight: 500, padding: '6px 16px', borderRadius: 7, border: 'none', background: 'var(--blue)', color: '#fff', cursor: 'pointer' }}>Apply</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ── Main ──────────────────────────────────────────────────────
export default function KpiTracker({ site }) {
  const [kpis, setKpis]             = useState([]);
  const [gscData, setGscData]       = useState({});
  const [gscPrev, setGscPrev]       = useState({});
  const [cannib, setCannib]         = useState([]);
  const [loadingGsc, setLdGsc]      = useState(false);
  const [pageModal, setPageModal]   = useState(null);
  const [annotModal, setAnnotModal] = useState(null);
  const [importModal, setImportMod] = useState(false);
  const [expandedId, setExpandedId] = useState(null);
  const [filter, setFilter]         = useState({ priority: 'all', movement: 'all', search: '' });
  const [sortBy, setSortBy]         = useState('priority');
  const [sortDir, setSortDir]       = useState('asc');
  const [comparison, setComparison] = useState(COMPARISONS[1]);
  const timer = useRef(null);

  useEffect(() => { if (!site) return; setKpis(loadKpis(site)); setGscData({}); setGscPrev({}); setCannib([]); }, [site]);

  const fetchGsc = useCallback(async (kpiList, comp) => {
    if (!site || !kpiList.length) return;
    setLdGsc(true);
    try {
      const pages = kpiList.map(k => k.page);
      const daysA = comp.days || 30, daysB = comp.prevDays || 30;
      const [cur, prev] = await Promise.all([
        gsc.kpiPages(site, pages, daysA),
        gsc.kpiPages(site, pages, daysA + daysB),
      ]);
      // Handle both old array format and new { pages, cannibalization } format
      const curPages  = cur?.pages  || (Array.isArray(cur)  ? cur  : []);
      const prevPages = prev?.pages || (Array.isArray(prev) ? prev : []);
      const curMap = {}, prevMap = {};
      curPages.forEach(r  => { curMap[r.page]  = r; });
      prevPages.forEach(r => { prevMap[r.page] = r; });
      setGscData(curMap); setGscPrev(prevMap);
      setCannib(cur?.cannibalization || []);
    } catch (e) { console.warn('GSC KPI error:', e.message); }
    finally { setLdGsc(false); }
  }, [site]);

  useEffect(() => {
    if (kpis.length > 0) { clearTimeout(timer.current); timer.current = setTimeout(() => fetchGsc(kpis, comparison), 500); }
  }, [kpis, comparison]);

  const save = (updated) => { setKpis(updated); saveKpis(site, updated); };
  const handleAddPage    = (f) => { save([...kpis, { ...f, id: genId(), page: normalisePath(f.page), annotations: [] }]); setPageModal(null); };
  const handleEditPage   = (f) => { save(kpis.map(k => k.id === pageModal.id ? { ...k, ...f, page: normalisePath(f.page) } : k)); setPageModal(null); };
  const handleDeletePage = (id) => { if (!confirm('Remove?')) return; save(kpis.filter(k => k.id !== id)); };
  const handleImport     = (rows) => { const ex = new Set(kpis.map(k => k.page)); save([...kpis, ...rows.filter(r => r.page && !ex.has(normalisePath(r.page))).map(r => ({...r,page:normalisePath(r.page),id:genId(),annotations:[]}))]); setImportMod(false); };
  const handleAddAnn     = (id, ann) => { save(kpis.map(k => k.id === id ? { ...k, annotations: [...(k.annotations||[]), ann] } : k)); setAnnotModal(null); };
  const handleDelAnn     = (id, aid) => save(kpis.map(k => k.id === id ? { ...k, annotations: (k.annotations||[]).filter(a => a.id !== aid) } : k));
  const getLastAnn       = (k) => !k.annotations?.length ? null : k.annotations.reduce((m,a) => a.date>(m?.date||'')?a:m, null);

  const enriched = kpis.map(k => ({ ...k, gsc: gscData[k.page]||null, gscPrev: gscPrev[k.page]||null }));
  const filtered = enriched.filter(k => {
    if (filter.search && !k.page.toLowerCase().includes(filter.search.toLowerCase()) && !(k.keyword||'').toLowerCase().includes(filter.search.toLowerCase())) return false;
    if (filter.priority !== 'all' && k.priority !== filter.priority) return false;
    if (filter.movement !== 'all' && k.gsc?.movement !== filter.movement) return false;
    return true;
  }).sort((a, b) => {
    const d = sortDir === 'asc' ? 1 : -1;
    if (sortBy === 'position')    return ((a.gsc?.position??999)-(b.gsc?.position??999))*d;
    if (sortBy === 'clicks')      return ((b.gsc?.clicks||0)-(a.gsc?.clicks||0))*d;
    if (sortBy === 'visibility')  return ((b.gsc?.visibilityScore||0)-(a.gsc?.visibilityScore||0))*d;
    if (sortBy === 'mobile')      return ((a.gsc?.mobileDesktopGap??-999)-(b.gsc?.mobileDesktopGap??-999))*d;
    if (sortBy === 'priority')    { const o={High:0,Medium:1,Low:2}; return ((o[a.priority]||1)-(o[b.priority]||1))*d; }
    if (sortBy === 'annotations') return ((b.annotations?.length||0)-(a.annotations?.length||0))*d;
    if (sortBy === 'lastUpdated') { const la=getLastAnn(a)?.date||'',lb=getLastAnn(b)?.date||''; return la>lb?-d:la<lb?d:0; }
    return a.page.localeCompare(b.page)*d;
  });

  const improved  = enriched.filter(k=>k.gsc?.movement==='up').length;
  const declined  = enriched.filter(k=>k.gsc?.movement==='down').length;
  const annotated = enriched.filter(k=>(k.annotations?.length||0)>0).length;
  const mobIssues = enriched.filter(k=>(k.gsc?.mobileDesktopGap||0)>3).length;

  const SortTh = ({col,label,align='left'}) => (
    <th style={{...TH,textAlign:align,cursor:'pointer',userSelect:'none'}} onClick={()=>{ sortBy===col?setSortDir(d=>d==='asc'?'desc':'asc'):(setSortBy(col),setSortDir('asc')); }}>
      <span style={{color:sortBy===col?'var(--blue-text)':'var(--text2)'}}>{label}{sortBy===col?(sortDir==='asc'?' ↑':' ↓'):''}</span>
    </th>
  );

  if (!site) return <div style={{fontSize:12,color:'var(--text2)',padding:'20px 0'}}>Select a site to manage KPI pages.</div>;

  return (
    <div>
      {/* Summary strip */}
      <div style={{display:'grid',gridTemplateColumns:'repeat(6,minmax(0,1fr))',gap:8,marginBottom:16}}>
        {[
          {label:'KPI pages',    value:kpis.length,         color:null},
          {label:'Improved',     value:improved,             color:'var(--green-text)'},
          {label:'Declined',     value:declined,             color:'var(--red-text)'},
          {label:'Annotated',    value:annotated,            color:'var(--blue-text)'},
          {label:'Mobile issues',value:mobIssues,            color:mobIssues>0?'var(--amber-text)':null},
          {label:'Cannibalized', value:cannib.length,        color:cannib.length>0?'var(--red-text)':null},
        ].map(s=>(
          <div key={s.label} className="metric-card" style={{padding:'10px 12px'}}>
            <div className="metric-label">{s.label}</div>
            <div className="metric-value" style={{fontSize:18,color:s.color||'var(--text)'}}>{s.value}</div>
          </div>
        ))}
      </div>

      {/* Cannibalization alert */}
      {cannib.length > 0 && (
        <div style={{background:'var(--red-bg)',border:'1px solid var(--red)',borderRadius:8,padding:'9px 14px',marginBottom:12,fontSize:12,color:'var(--red-text)',lineHeight:1.6}}>
          <strong>⚠ {cannib.length} cannibalized {cannib.length===1?'query':'queries'}:</strong>{' '}
          {cannib.slice(0,4).map(c=><span key={c.query} style={{marginRight:10}}><em>{c.query}</em> → {c.pages.join(' vs ')}</span>)}
          {cannib.length>4&&<span>and {cannib.length-4} more</span>}
        </div>
      )}

      {/* Toolbar */}
      <div style={{display:'flex',gap:8,alignItems:'center',flexWrap:'wrap',marginBottom:10}}>
        <input placeholder="Search pages or keywords…" value={filter.search} onChange={e=>setFilter(f=>({...f,search:e.target.value}))}
          style={{fontSize:12,padding:'5px 10px',borderRadius:20,border:'1px solid var(--border2)',background:'var(--surface)',color:'var(--text)',width:200,outline:'none'}} />
        <select value={filter.priority} onChange={e=>setFilter(f=>({...f,priority:e.target.value}))}
          style={{fontSize:11,padding:'5px 8px',borderRadius:20,border:'1px solid var(--border2)',background:'var(--surface)',color:'var(--text2)',cursor:'pointer'}}>
          <option value="all">All priorities</option>
          {PRIORITIES.map(p=><option key={p} value={p}>{p}</option>)}
        </select>
        <select value={filter.movement} onChange={e=>setFilter(f=>({...f,movement:e.target.value}))}
          style={{fontSize:11,padding:'5px 8px',borderRadius:20,border:'1px solid var(--border2)',background:'var(--surface)',color:'var(--text2)',cursor:'pointer'}}>
          <option value="all">All movements</option>
          <option value="up">↑ Improved</option>
          <option value="down">↓ Declined</option>
          <option value="stable">Stable</option>
        </select>
        <div style={{flex:1}}/>
        <button onClick={()=>fetchGsc(kpis,comparison)} disabled={loadingGsc}
          style={{fontSize:11,padding:'5px 12px',borderRadius:20,border:'1px solid var(--border2)',background:'transparent',color:'var(--text2)',cursor:'pointer'}}>
          {loadingGsc?'Loading…':'↻ Refresh'}
        </button>
        <button onClick={()=>setImportMod(true)}
          style={{fontSize:11,padding:'5px 12px',borderRadius:20,border:'1px solid var(--border2)',background:'transparent',color:'var(--text2)',cursor:'pointer'}}>
          ↑ Import sheet
        </button>
        <button onClick={()=>setPageModal('new')}
          style={{fontSize:11,fontWeight:500,padding:'5px 14px',borderRadius:20,border:'none',background:'var(--blue)',color:'#fff',cursor:'pointer'}}>
          + Add page
        </button>
      </div>

      {/* Comparison + count */}
      <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:12,flexWrap:'wrap',gap:8}}>
        <ComparisonPicker comparison={comparison} onChange={setComparison} />
        <div style={{fontSize:11,color:'var(--text3)'}}>
          {filtered.length} of {kpis.length} pages
          {loadingGsc&&<span style={{marginLeft:6,color:'var(--blue-text)'}}>· Loading GSC data…</span>}
        </div>
      </div>

      {/* Empty state */}
      {kpis.length === 0 && (
        <div style={{background:'var(--surface2)',border:'1px dashed var(--border2)',borderRadius:12,padding:32,textAlign:'center'}}>
          <div style={{fontSize:14,fontWeight:500,marginBottom:8}}>No KPI pages yet</div>
          <div style={{fontSize:12,color:'var(--text2)',marginBottom:16,lineHeight:1.6}}>Track positions, detect cannibalization, log optimizations and monitor mobile vs desktop gaps.</div>
          <div style={{display:'flex',gap:8,justifyContent:'center'}}>
            <button onClick={()=>setPageModal('new')} style={{fontSize:12,fontWeight:500,padding:'7px 18px',borderRadius:8,border:'none',background:'var(--blue)',color:'#fff',cursor:'pointer'}}>+ Add first page</button>
            <button onClick={()=>setImportMod(true)} style={{fontSize:12,padding:'7px 16px',borderRadius:8,border:'1px solid var(--border2)',background:'transparent',color:'var(--text2)',cursor:'pointer'}}>Import from sheet</button>
          </div>
        </div>
      )}

      {/* Table */}
      {kpis.length > 0 && (
        <div style={{overflowX:'auto'}}>
          <table style={{width:'100%',borderCollapse:'collapse'}}>
            <thead>
              <tr style={{borderBottom:'1px solid var(--border)'}}>
                <SortTh col="page"        label="Page" />
                <th style={TH}>Keyword</th>
                <SortTh col="position"    label="Avg pos"    align="center"/>
                <th style={{...TH,textAlign:'center'}}>Change</th>
                <SortTh col="visibility"  label="Visibility" align="center"/>
                <th style={{...TH,textAlign:'center'}}>Queries dist.</th>
                <SortTh col="clicks"      label="Clicks"     align="right"/>
                <th style={{...TH,textAlign:'right'}}>vs prev</th>
                <SortTh col="mobile"      label="Mobile gap" align="center"/>
                <SortTh col="lastUpdated" label="Last log"   align="left"/>
                <SortTh col="annotations" label="Notes"      align="center"/>
                <SortTh col="priority"    label="Pri."       align="center"/>
                <th style={{...TH,width:60}}/>
              </tr>
            </thead>
            <tbody>
              {filtered.map(k => {
                const g = k.gsc, gp = k.gscPrev;
                const isExp = expandedId === k.id;
                const clicksDelta = g?.clicks!=null&&gp?.clicks!=null ? g.clicks-gp.clicks : null;
                const last = getLastAnn(k);
                const hasCannib = g?.cannibalization?.length > 0;
                return (
                  <>
                    <tr key={k.id}
                      style={{borderBottom:isExp?'none':'1px solid var(--border)',background:isExp?'var(--surface2)':'transparent',transition:'background .1s'}}
                      onMouseEnter={e=>{if(!isExp)e.currentTarget.style.background='var(--surface2)';}}
                      onMouseLeave={e=>{if(!isExp)e.currentTarget.style.background='transparent';}}>
                      <td style={TD}>
                        <div style={{fontWeight:500,fontSize:12,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap',maxWidth:180}} title={k.page}>
                          {hasCannib&&<span title="Cannibalization" style={{marginRight:4,color:'var(--red-text)'}}>⚠</span>}
                          {k.page}
                        </div>
                        {k.notes&&<div style={{fontSize:10,color:'var(--text3)',marginTop:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{k.notes}</div>}
                      </td>
                      <td style={TD}><div style={{fontSize:11,color:'var(--text2)',overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap',maxWidth:110}}>{k.keyword||(g?.topQueries?.[0]?.query?<span style={{color:'var(--text3)'}}>{g.topQueries[0].query}</span>:'—')}</div></td>
                      <td style={{...TD,textAlign:'center'}}><PosBadge pos={g?.position}/></td>
                      <td style={{...TD,textAlign:'center'}}><MoveBadge delta={g?.positionDelta}/></td>
                      <td style={{...TD,textAlign:'center'}}><VisScore score={g?.visibilityScore}/></td>
                      <td style={{...TD,textAlign:'center'}}><DistBar dist={g?.distribution}/></td>
                      <td style={{...TD,textAlign:'right',fontSize:12,fontWeight:500}}>{fmtNum(g?.clicks)}</td>
                      <td style={{...TD,textAlign:'right'}}>
                        {clicksDelta!=null
                          ? <span style={clicksDelta>=0?ch('var(--green-text)','var(--green-bg)'):ch('var(--red-text)','var(--red-bg)')}>{clicksDelta>=0?'+':''}{fmtNum(clicksDelta)}</span>
                          : <span style={{fontSize:11,color:'var(--text3)'}}>—</span>}
                      </td>
                      <td style={{...TD,textAlign:'center'}}><MobileGap gap={g?.mobileDesktopGap}/></td>
                      <td style={TD}>
                        {last?(
                          <div>
                            <div style={{fontSize:11,fontWeight:500}}>{(()=>{const d=Math.round((Date.now()-new Date(last.date))/86400000);return d===0?'Today':d===1?'Yesterday':`${d}d ago`;})()}</div>
                            <div style={{fontSize:10,color:ANNOTATION_TYPES.find(x=>x.key===last.type)?.color||'var(--text3)',marginTop:1}}>{ANNOTATION_TYPES.find(x=>x.key===last.type)?.icon} {last.typeLabel||last.type}</div>
                          </div>
                        ):<span style={{fontSize:11,color:'var(--text3)'}}>—</span>}
                      </td>
                      <td style={{...TD,textAlign:'center'}}>
                        <button onClick={()=>setExpandedId(isExp?null:k.id)}
                          style={{fontSize:11,padding:'2px 8px',borderRadius:20,border:'1px solid var(--border2)',background:(k.annotations?.length||0)>0?'var(--blue-bg)':'transparent',color:(k.annotations?.length||0)>0?'var(--blue-text)':'var(--text3)',cursor:'pointer',fontWeight:500}}>
                          {(k.annotations?.length||0)>0?`📝 ${k.annotations.length}`:'+ Log'}
                        </button>
                      </td>
                      <td style={{...TD,textAlign:'center'}}><PriorityBadge priority={k.priority}/></td>
                      <td style={{...TD,textAlign:'right'}}>
                        <div style={{display:'flex',gap:3,justifyContent:'flex-end'}}>
                          <button onClick={()=>setAnnotModal(k)} title="Add annotation" style={{fontSize:11,padding:'2px 6px',borderRadius:5,border:'0.5px solid var(--border2)',background:'transparent',color:'var(--blue-text)',cursor:'pointer'}}>+</button>
                          <button onClick={()=>setPageModal(k)} title="Edit" style={{fontSize:11,padding:'2px 6px',borderRadius:5,border:'0.5px solid var(--border2)',background:'transparent',color:'var(--text2)',cursor:'pointer'}}>✎</button>
                          <button onClick={()=>handleDeletePage(k.id)} title="Remove" style={{fontSize:11,padding:'2px 6px',borderRadius:5,border:'0.5px solid var(--border2)',background:'transparent',color:'var(--red-text)',cursor:'pointer'}}>×</button>
                        </div>
                      </td>
                    </tr>
                    {isExp&&(
                      <ExpandedRow key={k.id+'_exp'} k={k} gscResult={g}
                        onAddAnnotation={()=>setAnnotModal(k)}
                        onDeleteAnnotation={aid=>handleDelAnn(k.id,aid)} />
                    )}
                  </>
                );
              })}
              {filtered.length===0&&kpis.length>0&&(
                <tr><td colSpan={13} style={{padding:'24px 0',textAlign:'center',fontSize:12,color:'var(--text3)'}}>
                  No pages match. <button onClick={()=>setFilter({priority:'all',movement:'all',search:''})} style={{color:'var(--blue-text)',background:'none',border:'none',cursor:'pointer',fontSize:12}}>Clear filters</button>
                </td></tr>
              )}
            </tbody>
          </table>
        </div>
      )}

      {/* Legend */}
      {kpis.length>0&&(
        <div style={{fontSize:10,color:'var(--text3)',marginTop:8,display:'flex',gap:14,flexWrap:'wrap'}}>
          <span>Dist: <span style={{color:'#16a34a'}}>■</span>#1-3 <span style={{color:'#d97706'}}>■</span>#4-10 <span style={{color:'#2563eb'}}>■</span>#11-20 <span style={{color:'#9ca3af'}}>■</span>20+</span>
          <span>Visibility 0-100 = position × CTR efficiency</span>
          <span>Mobile gap = positions worse on mobile vs desktop</span>
          <span>Avg pos = weighted by impressions across all queries</span>
        </div>
      )}

      {/* Modals */}
      {pageModal&&<PageModal kpi={pageModal==='new'?null:pageModal} onSave={pageModal==='new'?handleAddPage:handleEditPage} onClose={()=>setPageModal(null)}/>}
      {annotModal&&<AnnotationModal kpi={annotModal} positionAtTime={gscData[annotModal.page]?.position} onSave={ann=>handleAddAnn(annotModal.id,ann)} onClose={()=>setAnnotModal(null)}/>}
      {importModal&&<SheetImportModal onImport={handleImport} onClose={()=>setImportMod(false)}/>}
    </div>
  );
}

const TH = { fontSize:11, fontWeight:500, color:'var(--text2)', textAlign:'left', padding:'0 6px 8px', whiteSpace:'nowrap' };
const TD = { padding:'8px 6px', verticalAlign:'middle' };
