// crm-reports.jsx — Reports: Overview charts, Report Library, Report Builder
const { useState, useEffect, useRef } = React;

// ── Canned reports (run through the generic engine) ────────
const CANNED_REPORTS = [
  // CRM
  { group:'CRM', name:'New Leads', def:{ source:'leads', dateCol:'createdAt', sort:{col:'createdAt',dir:'desc'},
      columns:['companyName','contactName','stage','estimatedValue','leadSource','rep','createdAt'] } },
  { group:'CRM', name:'Pipeline by Stage', def:{ source:'leads', groupBy:'stage', dateCol:'createdAt',
      columns:['stage','estimatedValue'] } },
  { group:'CRM', name:'Won Deals', def:{ source:'leads', dateCol:'updatedAt', sort:{col:'updatedAt',dir:'desc'},
      filters:[{col:'stage',op:'equals',value:'won'}],
      columns:['companyName','estimatedValue','singlePurchaseValue','rep','updatedAt'] } },
  { group:'CRM', name:'Sales by Account', def:{ source:'sales', groupBy:'account', dateCol:'saleDate',
      columns:['account','amount'] } },
  { group:'CRM', name:'Accounts by Industry', def:{ source:'accounts', groupBy:'industry', dateCol:'createdAt',
      columns:['industry','contractValue'] } },
  { group:'CRM', name:'Expiring Contracts', def:{ source:'accounts', dateCol:'contractEnd', sort:{col:'contractEnd',dir:'asc'},
      filters:[{col:'contractEnd',op:'notempty'},{col:'isActive',op:'equals',value:'Yes'}],
      columns:['companyName','contractEnd','contractValue','rep'] } },
  { group:'CRM', name:'Activity Log', def:{ source:'activities', dateCol:'createdAt', sort:{col:'createdAt',dir:'desc'},
      columns:['createdAt','type','user','account','lead','content'] } },
  // Helpdesk
  { group:'Helpdesk', name:'Tickets Created', def:{ source:'tickets', dateCol:'createdAt', sort:{col:'createdAt',dir:'desc'},
      columns:['ticketNumber','subject','status','priority','account','tech','createdAt'] } },
  { group:'Helpdesk', name:'Tickets by Status', def:{ source:'tickets', groupBy:'status', dateCol:'createdAt',
      columns:['status'] } },
  { group:'Helpdesk', name:'Tickets by Technician', def:{ source:'tickets', groupBy:'tech', dateCol:'createdAt',
      columns:['tech'] } },
  { group:'Helpdesk', name:'Tickets by Account', def:{ source:'tickets', groupBy:'account', dateCol:'createdAt',
      columns:['account'] } },
  { group:'Helpdesk', name:'Resolution Times', def:{ source:'tickets', dateCol:'resolvedAt', sort:{col:'resolutionHours',dir:'desc'},
      filters:[{col:'resolvedAt',op:'notempty'}],
      columns:['ticketNumber','subject','account','tech','createdAt','resolvedAt','resolutionHours'] } },
  { group:'Helpdesk', name:'Open Tickets Aging', def:{ source:'tickets', dateCol:'createdAt', sort:{col:'createdAt',dir:'asc'},
      filters:[{col:'status',op:'neq',value:'closed'}],
      columns:['ticketNumber','subject','status','priority','account','tech','createdAt'] } },
];

const FILTER_OPS = [
  { id:'contains', label:'contains' }, { id:'notcontains', label:"doesn't contain" },
  { id:'equals', label:'equals' }, { id:'neq', label:'not equal' },
  { id:'gt', label:'>' }, { id:'gte', label:'≥' }, { id:'lt', label:'<' }, { id:'lte', label:'≤' },
  { id:'empty', label:'is empty' }, { id:'notempty', label:'is not empty' },
];

function reportsIso(d) { return d.toISOString().split('T')[0]; }
function reportsDefaultFrom() { const d = new Date(); d.setMonth(d.getMonth() - 12); return reportsIso(d); }

// ── Shared runner: date range + run + results table + CSV ──
function ReportRunner({ def, title, onSaveAs }) {
  const [from, setFrom] = useState(reportsDefaultFrom());
  const [to, setTo] = useState(reportsIso(new Date()));
  const [result, setResult] = useState(null);
  const [error, setError] = useState(null);
  const [running, setRunning] = useState(false);
  const [page, setPage] = useState(0);
  const PAGE = 100;

  const run = async () => {
    setRunning(true); setError(null); setPage(0);
    try { setResult(await CRM.ReportsAPI.runReport({ ...def, from: from || null, to: to || null })); }
    catch (e) { setError(e.message); setResult(null); }
    finally { setRunning(false); }
  };
  useEffect(() => { run(); }, [JSON.stringify(def)]);

  const exportCsv = () => {
    if (!result) return;
    let lines;
    if (result.grouped) {
      const head = [result.groupBy, 'count', ...result.numeric];
      lines = [head.join(','), ...result.rows.map(g =>
        [g.group, g.count, ...result.numeric.map(n => g.sums[n] ?? 0)]
          .map(v => `"${String(v ?? '').replace(/"/g,'""')}"`).join(','))];
    } else {
      lines = [result.columns.map(c => c.label).join(','), ...result.rows.map(r =>
        r.map(v => `"${String(v ?? '').replace(/"/g,'""')}"`).join(','))];
    }
    const blob = new Blob([lines.join('\r\n')], { type:'text/csv' });
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = (title || 'report').replace(/[^a-z0-9]+/gi,'-').toLowerCase() + '.csv';
    a.click();
    URL.revokeObjectURL(a.href);
  };

  const pageCount = result && !result.grouped ? Math.max(1, Math.ceil(result.rows.length / PAGE)) : 1;
  const safePage = Math.min(page, pageCount - 1);
  const shown = result && !result.grouped ? result.rows.slice(safePage * PAGE, (safePage + 1) * PAGE) : [];

  return (
    <div>
      <div style={{display:'flex',gap:8,alignItems:'center',flexWrap:'wrap',marginBottom:12}}>
        <input type="date" className="search-input" style={{width:135,fontSize:12,padding:'5px 8px'}} value={from} onChange={e=>setFrom(e.target.value)} />
        <span style={{fontSize:12,color:'var(--g400)'}}>to</span>
        <input type="date" className="search-input" style={{width:135,fontSize:12,padding:'5px 8px'}} value={to} onChange={e=>setTo(e.target.value)} />
        <button className="btn btn-primary btn-sm" onClick={run} disabled={running}>{running ? 'Running…' : '▶ Run'}</button>
        <div style={{marginLeft:'auto',display:'flex',gap:8}}>
          {onSaveAs && <button className="btn btn-ghost btn-sm" onClick={onSaveAs}>💾 Save report</button>}
          <button className="btn btn-ghost btn-sm" onClick={exportCsv} disabled={!result}>⬇ Export CSV</button>
        </div>
      </div>

      {error && <div style={{background:'#FEF2F2',color:'#991B1B',border:'1px solid #FECACA',borderRadius:8,padding:'9px 12px',fontSize:13,marginBottom:12}}>{error}</div>}
      {!result && !error && <div style={{padding:32,textAlign:'center',color:'var(--g400)',fontSize:13}}>Running…</div>}

      {result && result.grouped && (
        <div className="card" style={{padding:0,overflowX:'auto'}}>
          <table className="tbl" style={{margin:0}}>
            <thead><tr>
              <th>{(result.columns.find(c => c.key === result.groupBy) || {label: result.groupBy}).label}</th>
              <th style={{textAlign:'right'}}>Count</th>
              {result.numeric.map(n => <th key={n} style={{textAlign:'right'}}>Sum: {(result.columns.find(c=>c.key===n)||{label:n}).label}</th>)}
            </tr></thead>
            <tbody>
              {result.rows.map(g => (
                <tr key={g.group}>
                  <td style={{fontWeight:600,color:'var(--navy)'}}>{g.group}</td>
                  <td style={{textAlign:'right',fontWeight:700}}>{g.count.toLocaleString()}</td>
                  {result.numeric.map(n => <td key={n} style={{textAlign:'right'}}>{(g.sums[n]||0).toLocaleString()}</td>)}
                </tr>
              ))}
            </tbody>
          </table>
          <div style={{padding:'8px 14px',fontSize:12,color:'var(--g400)',borderTop:'1px solid var(--g100)'}}>{result.total.toLocaleString()} record(s) in range</div>
        </div>
      )}

      {result && !result.grouped && (
        <div className="card" style={{padding:0,overflow:'hidden'}}>
          <div style={{display:'flex',alignItems:'center',gap:10,padding:'8px 14px',borderBottom:'1px solid var(--g200)',background:'var(--off)'}}>
            <span style={{fontSize:12,fontWeight:600,color:'var(--g600)'}}>
              {result.rows.length === 0 ? 'No rows' : `Showing ${(safePage*PAGE+1).toLocaleString()}–${Math.min(result.rows.length,(safePage+1)*PAGE).toLocaleString()} of ${result.rows.length.toLocaleString()}`}
              {result.total > result.rows.length ? ` (capped from ${result.total.toLocaleString()})` : ''}
            </span>
            <div style={{marginLeft:'auto',display:'flex',alignItems:'center',gap:6}}>
              <button className="btn btn-ghost btn-xs" disabled={safePage===0} style={{fontSize:15,padding:'2px 10px',opacity:safePage===0?.35:1}} onClick={()=>setPage(p=>Math.max(0,p-1))}>‹</button>
              <span style={{fontSize:12,color:'var(--g400)'}}>Page {safePage+1} of {pageCount}</span>
              <button className="btn btn-ghost btn-xs" disabled={safePage>=pageCount-1} style={{fontSize:15,padding:'2px 10px',opacity:safePage>=pageCount-1?.35:1}} onClick={()=>setPage(p=>Math.min(pageCount-1,p+1))}>›</button>
            </div>
          </div>
          <div style={{overflowX:'auto'}}>
            <table className="tbl" style={{margin:0}}>
              <thead><tr>{result.columns.map(c => <th key={c.key} style={{whiteSpace:'nowrap'}}>{c.label}</th>)}</tr></thead>
              <tbody>
                {shown.map((r, i) => (
                  <tr key={i}>{r.map((v, j) => (
                    <td key={j} style={{fontWeight: j===0 ? 600 : 'normal', color: j===0 ? 'var(--navy)' : 'var(--g600)', fontSize:13, whiteSpace: String(v||'').length > 60 ? 'normal' : 'nowrap'}}>
                      {result.columns[j].type === 'number' && v != null ? Number(v).toLocaleString() : (v ?? '—')}
                    </td>
                  ))}</tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}
    </div>
  );
}

// ── Report Library: canned + saved custom reports ──────────
function ReportLibrary({ user, showToast, onEditInBuilder }) {
  const [saved, setSaved] = useState([]);
  const [active, setActive] = useState(CANNED_REPORTS[0]);

  const loadSaved = () => CRM.ReportsAPI.getReportDefs().then(d => setSaved(Array.isArray(d) ? d : [])).catch(() => {});
  useEffect(() => { loadSaved(); }, []);

  const removeSaved = async (r) => {
    if (!confirm(`Delete saved report "${r.name}"?`)) return;
    const next = saved.filter(x => x.id !== r.id);
    try { await CRM.ReportsAPI.saveReportDefs(next); setSaved(next); if (active?.id === r.id) setActive(CANNED_REPORTS[0]); }
    catch (e) { showToast('Delete failed: ' + e.message, 'error'); }
  };

  const groups = [
    { title:'CRM', items: CANNED_REPORTS.filter(r => r.group === 'CRM') },
    { title:'Helpdesk', items: CANNED_REPORTS.filter(r => r.group === 'Helpdesk') },
    { title:'My Reports', items: saved },
  ];

  return (
    <div style={{display:'grid',gridTemplateColumns:'230px 1fr',gap:20,alignItems:'start'}}>
      <div className="card" style={{padding:'12px 0'}}>
        {groups.map(g => (
          <div key={g.title}>
            <div style={{fontSize:11,fontWeight:700,letterSpacing:'.06em',textTransform:'uppercase',color:'var(--g400)',padding:'8px 16px 4px'}}>{g.title}</div>
            {g.items.length === 0 && <div style={{padding:'4px 16px',fontSize:12,color:'var(--g400)'}}>None yet — build one in the Builder tab.</div>}
            {g.items.map(r => (
              <div key={r.name + (r.id||'')}
                onClick={() => setActive(r)}
                style={{display:'flex',alignItems:'center',padding:'7px 16px',cursor:'pointer',fontSize:13,fontWeight:600,
                        color: active === r ? 'var(--red)' : 'var(--navy)',
                        background: active === r ? 'var(--off)' : 'transparent',
                        borderLeft: active === r ? '3px solid var(--red)' : '3px solid transparent'}}>
                <span style={{flex:1,minWidth:0,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{r.name}</span>
                {r.id && (
                  <button title="Delete saved report" onClick={e => { e.stopPropagation(); removeSaved(r); }}
                    style={{border:'none',background:'none',cursor:'pointer',color:'var(--g400)',fontSize:13,padding:'0 2px'}}>×</button>
                )}
              </div>
            ))}
          </div>
        ))}
      </div>
      <div>
        <div style={{display:'flex',alignItems:'center',gap:12,marginBottom:10}}>
          <div style={{fontSize:16,fontWeight:800,color:'var(--navy)'}}>{active?.name}</div>
          {active && onEditInBuilder && (
            <button className="btn btn-ghost btn-sm" onClick={() => onEditInBuilder(active)}>
              🛠 Edit in Builder
            </button>
          )}
        </div>
        {active && <ReportRunner key={active.name + (active.id||'')} def={active.def} title={active.name} />}
      </div>
    </div>
  );
}

// ── Report Builder: pick columns / filters / sort / group ──
function ReportBuilder({ user, showToast, seed }) {
  const [sources, setSources] = useState([]);
  const [source, setSource] = useState('tickets');
  const [cols, setCols] = useState({});          // key -> checked
  const [filters, setFilters] = useState([]);    // {col, op, value}
  const [sortCol, setSortCol] = useState('');
  const [sortDir, setSortDir] = useState('asc');
  const [groupBy, setGroupBy] = useState('');
  const [dateCol, setDateCol] = useState('');
  const [runDef, setRunDef] = useState(null);
  const [reportName, setReportName] = useState('');

  useEffect(() => {
    CRM.ReportsAPI.getReportSources().then(s => {
      setSources(s);
      // Seeded from the Library ("Edit in Builder") — preload that definition
      if (seed && s.some(x => x.key === seed.def.source)) { applySeed(s, seed); return; }
      const t = s.find(x => x.key === 'tickets') || s[0];
      if (t) initSource(t);
    }).catch(e => showToast('Failed to load sources: ' + e.message, 'error'));
  }, []);

  const applySeed = (srcs, sd) => {
    const src = srcs.find(x => x.key === sd.def.source);
    if (!src) return;
    setSource(src.key);
    const c = {};
    (sd.def.columns || []).forEach(k => { c[k] = true; });
    setCols(c);
    setFilters((sd.def.filters || []).map(f => ({ ...f })));
    setSortCol(sd.def.sort ? sd.def.sort.col : '');
    setSortDir(sd.def.sort ? sd.def.sort.dir : 'asc');
    setGroupBy(sd.def.groupBy || '');
    setDateCol(sd.def.dateCol || (src.columns.find(x => x.type === 'date') || {}).key || '');
    setRunDef(sd.def);
    setReportName(sd.id ? sd.name : '');   // canned reports save as a NEW name
  };

  const schema = sources.find(s => s.key === source);
  const initSource = (src) => {
    setSource(src.key);
    const def = {};
    src.columns.slice(0, 6).forEach(c => { def[c.key] = true; });
    setCols(def); setFilters([]); setSortCol(''); setGroupBy('');
    setDateCol((src.columns.find(c => c.type === 'date') || {}).key || '');
    setRunDef(null);
  };

  const buildDef = () => ({
    source,
    columns: (schema?.columns || []).filter(c => cols[c.key]).map(c => c.key),
    filters: filters.filter(f => f.col && f.op),
    sort: sortCol ? { col: sortCol, dir: sortDir } : null,
    groupBy: groupBy || null,
    dateCol: dateCol || null,
  });

  const saveAs = async () => {
    const name = (reportName || prompt('Name this report:') || '').trim();
    if (!name) return;
    const d = buildDef();
    if (d.columns.length === 0) return showToast('Pick at least one column before saving.', 'error');
    try {
      const existing = await CRM.ReportsAPI.getReportDefs().catch(() => []);
      const list = Array.isArray(existing) ? existing : [];
      const i = list.findIndex(x => (x.name || '').toLowerCase() === name.toLowerCase());
      if (i >= 0) {
        if (!confirm(`A saved report named "${name}" already exists — overwrite it?`)) return;
        list[i] = { ...list[i], name, def: d };
      } else {
        list.push({ id: 'r' + Math.random().toString(36).slice(2, 10), name, def: d });
      }
      await CRM.ReportsAPI.saveReportDefs(list);
      setReportName(name);
      showToast(`Saved "${name}" — find it under My Reports in the Library.`, 'success');
    } catch (e) { showToast('Save failed: ' + e.message, 'error'); }
  };

  const selCss = { fontSize:12, padding:'5px 8px' };
  const label = t => <div style={{fontSize:11,fontWeight:700,textTransform:'uppercase',letterSpacing:'.05em',color:'var(--g400)',marginBottom:6}}>{t}</div>;

  return (
    <div>
      <div className="card card-pad" style={{marginBottom:16}}>
        <div style={{display:'flex',gap:20,flexWrap:'wrap'}}>
          <div style={{minWidth:160}}>
            {label('Data source')}
            <select className="search-input" style={selCss} value={source}
              onChange={e => { const s = sources.find(x => x.key === e.target.value); if (s) initSource(s); }}>
              {sources.map(s => <option key={s.key} value={s.key}>{s.label}</option>)}
            </select>
          </div>
          <div style={{minWidth:160}}>
            {label('Date column (for range)')}
            <select className="search-input" style={selCss} value={dateCol} onChange={e => setDateCol(e.target.value)}>
              <option value="">— none —</option>
              {(schema?.columns || []).filter(c => c.type === 'date').map(c => <option key={c.key} value={c.key}>{c.label}</option>)}
            </select>
          </div>
          <div style={{minWidth:160}}>
            {label('Group by')}
            <select className="search-input" style={selCss} value={groupBy} onChange={e => setGroupBy(e.target.value)}>
              <option value="">— none (row list) —</option>
              {(schema?.columns || []).map(c => <option key={c.key} value={c.key}>{c.label}</option>)}
            </select>
          </div>
          <div style={{minWidth:220}}>
            {label('Sort')}
            <div style={{display:'flex',gap:6}}>
              <select className="search-input" style={{...selCss,flex:1}} value={sortCol} onChange={e => setSortCol(e.target.value)} disabled={!!groupBy}>
                <option value="">— default —</option>
                {(schema?.columns || []).map(c => <option key={c.key} value={c.key}>{c.label}</option>)}
              </select>
              <select className="search-input" style={selCss} value={sortDir} onChange={e => setSortDir(e.target.value)} disabled={!!groupBy}>
                <option value="asc">▲ asc</option>
                <option value="desc">▼ desc</option>
              </select>
            </div>
          </div>
        </div>

        <div style={{marginTop:16}}>
          {label('Columns')}
          <div style={{display:'flex',flexWrap:'wrap',gap:'6px 14px'}}>
            {(schema?.columns || []).map(c => (
              <label key={c.key} style={{display:'flex',alignItems:'center',gap:5,fontSize:13,color:'var(--navy)',cursor:'pointer'}}>
                <input type="checkbox" checked={!!cols[c.key]}
                  onChange={e => setCols(m => ({ ...m, [c.key]: e.target.checked }))} />
                {c.label}
              </label>
            ))}
          </div>
        </div>

        <div style={{marginTop:16}}>
          {label('Filters')}
          {filters.map((f, i) => (
            <div key={i} style={{display:'flex',gap:6,marginBottom:6,alignItems:'center',flexWrap:'wrap'}}>
              <select className="search-input" style={{...selCss,width:170}} value={f.col}
                onChange={e => setFilters(fs => fs.map((x, j) => j===i ? { ...x, col:e.target.value } : x))}>
                <option value="">— column —</option>
                {(schema?.columns || []).map(c => <option key={c.key} value={c.key}>{c.label}</option>)}
              </select>
              <select className="search-input" style={{...selCss,width:140}} value={f.op}
                onChange={e => setFilters(fs => fs.map((x, j) => j===i ? { ...x, op:e.target.value } : x))}>
                {FILTER_OPS.map(o => <option key={o.id} value={o.id}>{o.label}</option>)}
              </select>
              {!['empty','notempty'].includes(f.op) && (
                <input className="search-input" style={{...selCss,width:170}} placeholder="value" value={f.value || ''}
                  onChange={e => setFilters(fs => fs.map((x, j) => j===i ? { ...x, value:e.target.value } : x))} />
              )}
              <button className="btn btn-ghost btn-xs" onClick={() => setFilters(fs => fs.filter((_, j) => j!==i))}>×</button>
            </div>
          ))}
          <button className="btn btn-ghost btn-sm" onClick={() => setFilters(fs => [...fs, { col:'', op:'contains', value:'' }])}>+ Add filter</button>
        </div>

        <div style={{marginTop:16,display:'flex',gap:8,alignItems:'center',flexWrap:'wrap'}}>
          <button className="btn btn-primary btn-sm" onClick={() => setRunDef(buildDef())}>▶ Run report</button>
          <input className="search-input" style={{width:200,fontSize:12,padding:'5px 8px'}}
            placeholder="Report name…" value={reportName} onChange={e => setReportName(e.target.value)} />
          <button className="btn btn-ghost btn-sm" style={{border:'1px solid var(--g200)'}} onClick={saveAs}>💾 Save report</button>
          <span style={{fontSize:12,color:'var(--g400)'}}>Saved reports appear under My Reports in the Library.</span>
        </div>
      </div>

      {runDef && <ReportRunner key={JSON.stringify(runDef)} def={runDef} title="custom-report" onSaveAs={saveAs} />}
    </div>
  );
}

// ── Overview (the original charts dashboard) ───────────────
function ReportsOverview({ user }) {
  const [pipeline, setPipeline] = useState([]);
  const [leaderboard, setLeaderboard] = useState([]);
  const [forecast, setForecast] = useState({});
  const [leads, setLeads] = useState([]);
  const funnelRef = useRef(null);
  const winLossRef = useRef(null);
  const valueRef = useRef(null);
  const funnelChart = useRef(null);
  const winLossChart = useRef(null);
  const valueChart = useRef(null);

  useEffect(() => {
    const fetchAll = async () => {
      const reqs = [
        CRM.LeadsAPI.getAll(user.role === 'rep' && !user.isAdmin ? { repId: user.id } : {}),
        CRM.ReportsAPI.getPipelineSummary(),
        CRM.ReportsAPI.getForecast(),
      ];
      if (user.isAdmin) reqs.push(CRM.ReportsAPI.getRepLeaderboard());

      const results = await Promise.allSettled(reqs);
      const val = (r) => r.status === 'fulfilled' ? r.value : null;

      if (val(results[0])) setLeads(val(results[0]));
      if (val(results[1])) setPipeline(val(results[1]));
      if (val(results[2])) setForecast(val(results[2]));
      if (user.isAdmin && val(results[3])) setLeaderboard(val(results[3]));

      results.forEach((r, i) => {
        if (r.status === 'rejected') console.error(`Reports request ${i} failed:`, r.reason);
      });
    };
    fetchAll();
  }, []);

  useEffect(() => {
    if (!pipeline.length) return;
    drawCharts();
    return () => {
      funnelChart.current?.destroy();
      winLossChart.current?.destroy();
      valueChart.current?.destroy();
    };
  }, [pipeline, leads]);

  const drawCharts = () => {
    const active = pipeline.filter(s => !['won','lost'].includes(s.id));

    if (funnelRef.current) {
      funnelChart.current?.destroy();
      funnelChart.current = new Chart(funnelRef.current, {
        type: 'bar',
        data: {
          labels: active.map(s => s.label),
          datasets: [{
            data: active.map(s => s.count),
            backgroundColor: active.map(s => s.color + 'CC'),
            borderColor: active.map(s => s.color),
            borderWidth: 1,
            borderRadius: 4,
          }]
        },
        options: {
          indexAxis: 'y',
          plugins: { legend: { display: false } },
          scales: {
            x: { grid: { color: '#F0F2F5' }, ticks: { stepSize: 1, font: { family: 'Inter', size: 11 } } },
            y: { grid: { display: false }, ticks: { font: { family: 'Inter', size: 11 } } }
          },
          responsive: true, maintainAspectRatio: false,
        }
      });
    }

    if (winLossRef.current) {
      winLossChart.current?.destroy();
      const won = leads.filter(l => l.stage === 'won').length;
      const lost = leads.filter(l => l.stage === 'lost').length;
      const active2 = leads.filter(l => !['won','lost'].includes(l.stage)).length;
      winLossChart.current = new Chart(winLossRef.current, {
        type: 'doughnut',
        data: {
          labels: ['Won', 'Lost', 'Active'],
          datasets: [{ data: [won, lost, active2], backgroundColor: ['#10B981','#6B7280','#3B82F6'], borderWidth: 0, hoverOffset: 4 }]
        },
        options: {
          plugins: { legend: { position: 'bottom', labels: { font: { family: 'Inter', size: 11 }, padding: 12 } } },
          responsive: true, maintainAspectRatio: false, cutout: '65%'
        }
      });
    }

    if (valueRef.current) {
      valueChart.current?.destroy();
      valueChart.current = new Chart(valueRef.current, {
        type: 'bar',
        data: {
          labels: pipeline.map(s => s.label.split(' ')[0]),
          datasets: [{
            label: 'Pipeline Value ($)',
            data: pipeline.map(s => s.value),
            backgroundColor: pipeline.map(s => s.color + 'BB'),
            borderColor: pipeline.map(s => s.color),
            borderWidth: 1,
            borderRadius: 4,
          }]
        },
        options: {
          plugins: { legend: { display: false } },
          scales: {
            x: { grid: { display: false }, ticks: { font: { family: 'Inter', size: 10 } } },
            y: { grid: { color: '#F0F2F5' }, ticks: { font: { family: 'Inter', size: 10 }, callback: v => '$'+v.toLocaleString() } }
          },
          responsive: true, maintainAspectRatio: false,
        }
      });
    }
  };

  const fmt = v => '$' + (v||0).toLocaleString();
  const won = leads.filter(l => l.stage === 'won').length;
  const lost = leads.filter(l => l.stage === 'lost').length;
  const total = leads.length;
  const winRate = total ? Math.round(won / total * 100) : 0;
  const proposalSent = leads.filter(l => ['proposal','negotiation','won'].includes(l.stage)).length;
  const proposalConverted = leads.filter(l => l.stage === 'won').length;
  const convRate = proposalSent ? Math.round(proposalConverted / proposalSent * 100) : 0;

  const RANK_COLORS = ['gold', 'silver', 'bronze'];

  const byIndustry = leads.reduce((acc, l) => {
    if (!l.industry) return acc;
    acc[l.industry] = (acc[l.industry] || 0) + 1;
    return acc;
  }, {});
  const topIndustries = Object.entries(byIndustry).sort((a,b) => b[1]-a[1]).slice(0,6);

  const bySource = leads.reduce((acc, l) => {
    if (!l.leadSource) return acc;
    acc[l.leadSource] = (acc[l.leadSource] || 0) + 1;
    return acc;
  }, {});
  const topSources = Object.entries(bySource).sort((a,b) => b[1]-a[1]);

  return (
    <div>
      <div className="stat-grid" style={{gridTemplateColumns:'repeat(5,1fr)'}}>
        <div className="stat-card">
          <div className="stat-label">Total Leads</div>
          <div className="stat-val">{total}</div>
          <div className="stat-sub">All time</div>
        </div>
        <div className="stat-card">
          <div className="stat-label">Win Rate</div>
          <div className="stat-val" style={{color: winRate >= 30 ? 'var(--green)' : 'var(--navy)'}}>{winRate}%</div>
          <div className="stat-sub">{won} won / {lost} lost</div>
        </div>
        <div className="stat-card">
          <div className="stat-label">Pipeline Value</div>
          <div className="stat-val" style={{fontSize:20}}>{fmt(forecast.pipelineValue)}</div>
          <div className="stat-sub">Active deals</div>
        </div>
        <div className="stat-card">
          <div className="stat-label">Weighted Forecast</div>
          <div className="stat-val" style={{fontSize:20}}>{fmt(Math.round(forecast.weightedForecast||0))}</div>
          <div className="stat-sub">Probability-adjusted</div>
        </div>
        <div className="stat-card">
          <div className="stat-label">Proposal Conv.</div>
          <div className="stat-val">{convRate}%</div>
          <div className="stat-sub">{proposalConverted}/{proposalSent} converted</div>
        </div>
      </div>

      <div style={{display:'grid',gridTemplateColumns:'2fr 1fr',gap:20,marginBottom:20}}>
        <div className="card card-pad">
          <div style={{fontWeight:700,fontSize:14,color:'var(--navy)',marginBottom:16}}>Pipeline Funnel — Leads by Stage</div>
          <div className="chart-wrap"><canvas ref={funnelRef} /></div>
        </div>
        <div className="card card-pad">
          <div style={{fontWeight:700,fontSize:14,color:'var(--navy)',marginBottom:16}}>Win / Loss / Active</div>
          <div className="chart-wrap"><canvas ref={winLossRef} /></div>
        </div>
      </div>

      <div style={{marginBottom:20}}>
        <div className="card card-pad">
          <div style={{fontWeight:700,fontSize:14,color:'var(--navy)',marginBottom:16}}>Pipeline Value by Stage</div>
          <div className="chart-wrap"><canvas ref={valueRef} /></div>
        </div>
      </div>

      {user.isAdmin && leaderboard.length > 0 && (
        <div style={{marginBottom:20}}>
          <div style={{fontWeight:700,fontSize:14,color:'var(--navy)',marginBottom:12}}>Rep Leaderboard</div>
          <div style={{display:'flex',flexDirection:'column',gap:10}}>
            {leaderboard.map((entry, i) => (
              <div key={entry.rep.id} className="rep-card">
                <div className={`rep-rank ${RANK_COLORS[i]||''}`}>#{i+1}</div>
                <div style={{width:40,height:40,borderRadius:'50%',background:'var(--navy)',color:'white',display:'flex',alignItems:'center',justifyContent:'center',fontSize:14,fontWeight:700,flexShrink:0}}>
                  {entry.rep.name.charAt(0)}
                </div>
                <div className="rep-info">
                  <div className="rep-name">{entry.rep.name}</div>
                  <div className="rep-stats">{entry.total} leads · {entry.won} won · {entry.pipeline} active · {entry.winRate}% win rate</div>
                </div>
                <div>
                  <div className="rep-revenue">{fmt(entry.revenue)}</div>
                  <div style={{fontSize:11,color:'var(--g400)',textAlign:'right'}}>closed revenue</div>
                </div>
              </div>
            ))}
          </div>
        </div>
      )}

      <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:20,marginBottom:20}}>
        <div className="card card-pad">
          <div style={{fontWeight:700,fontSize:14,color:'var(--navy)',marginBottom:16}}>Leads by Industry</div>
          {topIndustries.length === 0 && <div className="empty">No data</div>}
          {topIndustries.map(([ind, cnt]) => (
            <div key={ind} style={{marginBottom:10}}>
              <div style={{display:'flex',justifyContent:'space-between',marginBottom:4}}>
                <span style={{fontSize:12,fontWeight:600,color:'var(--g600)'}}>{ind}</span>
                <span style={{fontSize:12,fontWeight:700,color:'var(--navy)'}}>{cnt}</span>
              </div>
              <div style={{background:'var(--g100)',borderRadius:4,height:6}}>
                <div style={{background:'var(--navy)',borderRadius:4,height:6,width:`${Math.round(cnt/total*100)}%`}} />
              </div>
            </div>
          ))}
        </div>

        <div className="card card-pad">
          <div style={{fontWeight:700,fontSize:14,color:'var(--navy)',marginBottom:16}}>Leads by Source</div>
          {topSources.length === 0 && <div className="empty">No data</div>}
          {topSources.map(([src, cnt]) => (
            <div key={src} style={{marginBottom:10}}>
              <div style={{display:'flex',justifyContent:'space-between',marginBottom:4}}>
                <span style={{fontSize:12,fontWeight:600,color:'var(--g600)'}}>{src}</span>
                <span style={{fontSize:12,fontWeight:700,color:'var(--navy)'}}>{cnt}</span>
              </div>
              <div style={{background:'var(--g100)',borderRadius:4,height:6}}>
                <div style={{background:'var(--red)',borderRadius:4,height:6,width:`${Math.round(cnt/total*100)}%`}} />
              </div>
            </div>
          ))}
        </div>
      </div>

      <div className="card card-pad" style={{borderLeft:'3px solid var(--green)'}}>
        <div style={{fontWeight:700,fontSize:14,color:'var(--navy)',marginBottom:16}}>Revenue Forecast Summary</div>
        <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:20}}>
          <div>
            <div style={{fontSize:11,fontWeight:700,letterSpacing:'.1em',textTransform:'uppercase',color:'var(--g400)',marginBottom:6}}>Closed Revenue (YTD)</div>
            <div style={{fontSize:28,fontWeight:800,color:'var(--green)'}}>{fmt(forecast.closedRevenue)}</div>
          </div>
          <div>
            <div style={{fontSize:11,fontWeight:700,letterSpacing:'.1em',textTransform:'uppercase',color:'var(--g400)',marginBottom:6}}>Weighted Forecast</div>
            <div style={{fontSize:28,fontWeight:800,color:'var(--navy)'}}>{fmt(Math.round(forecast.weightedForecast||0))}</div>
            <div style={{fontSize:11,color:'var(--g400)'}}>Based on stage probability</div>
          </div>
          <div>
            <div style={{fontSize:11,fontWeight:700,letterSpacing:'.1em',textTransform:'uppercase',color:'var(--g400)',marginBottom:6}}>Lost Revenue</div>
            <div style={{fontSize:28,fontWeight:800,color:'var(--g400)'}}>{fmt(forecast.lostRevenue)}</div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Reports shell with tabs ─────────────────────────────────
function Reports({ user, showToast }) {
  const [tab, setTab] = useState('overview');
  const [builderSeed, setBuilderSeed] = useState(null);
  const toast = showToast || (() => {});
  const editInBuilder = (r) => { setBuilderSeed(r); setTab('builder'); };
  return (
    <div>
      <div style={{display:'flex',gap:4,marginBottom:20,borderBottom:'1px solid var(--g200)'}}>
        {[{id:'overview',label:'📈 Overview'},{id:'library',label:'📚 Report Library'},{id:'builder',label:'🛠 Report Builder'}].map(t => (
          <button key={t.id} onClick={() => setTab(t.id)}
            style={{border:'none',background:'none',cursor:'pointer',fontFamily:'var(--font)',fontSize:14,fontWeight:700,padding:'10px 18px',
                    color: tab===t.id ? 'var(--navy)' : 'var(--g400)',
                    borderBottom: tab===t.id ? '3px solid var(--red)' : '3px solid transparent', marginBottom:-1}}>
            {t.label}
          </button>
        ))}
      </div>
      {tab === 'overview' && <ReportsOverview user={user} />}
      {tab === 'library'  && <ReportLibrary user={user} showToast={toast} onEditInBuilder={editInBuilder} />}
      {tab === 'builder'  && <ReportBuilder key={builderSeed ? builderSeed.name : 'blank'} user={user} showToast={toast} seed={builderSeed} />}
    </div>
  );
}

Object.assign(window, { Reports });
