// ─── Reports & Analytics — dynamic dashboard builder ─────────
// Drag a widget (bar / donut / table) onto the canvas, then pick
// source · dimension · measure. Live from the store, saved locally.

const RPT_KEY = 'deeping_crm_reports_v1';
const RPT_SOURCES = {
  opportunities: { label:'Opportunities', dims:[['stage','Stage'],['owner','Owner'],['type','Typ'],['source','Quelle'],['accountId','Account']], measures:[['count','Anzahl'],['amount','Summe Betrag €'],['avgAmount','Ø Betrag €']] },
  leads:        { label:'Leads',         dims:[['status','Status'],['src','Quelle'],['owner','Owner'],['company','Lead (Name)']], measures:[['count','Anzahl'],['avgScore','Ø Score']] },
  quotes:       { label:'Quotes',        dims:[['status','Status'],['owner','Owner']], measures:[['count','Anzahl'],['total','Summe €'],['avgMargin','Ø Marge %']] },
  activities:   { label:'Activities',    dims:[['kind','Typ'],['owner','Owner'],['done','Status']], measures:[['count','Anzahl']] },
  accounts:     { label:'Accounts',      dims:[['name','Account (Name)'],['tier','Tier'],['owner','Owner'],['health','Health'],['country','Land'],['ind','Branche']], measures:[['count','Anzahl'],['pipeline','Pipeline €'],['revYTD','Umsatz YTD €']] }
};

// Datumsfelder je Quelle für die Zeitachse
const RPT_DATEFIELDS = {
  opportunities: [['createdAt','Erstellt'],['close','Close-Datum']],
  leads: [['createdAt','Erstellt']],
  quotes: [['createdAt','Erstellt'],['validUntil','Gültig bis']],
  activities: [['when','Termin']],
  accounts: [['createdAt','Erstellt']]
};
const RPT_MON = ['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'];
function rptMonthLabel(ym) { const p = ym.split('-'); return RPT_MON[(Number(p[1]) || 1) - 1] + ' ' + p[0].slice(2); }

function rptLabel(source, dim, val) {
  if (val == null || val === '') return '—';
  if (dim === 'owner') return OWNERS[val] || val;
  if (dim === 'stage') return (STAGE_META[val] || {}).label || val;
  if (dim === 'status' && source === 'leads') return (LEAD_STATUS[val] || {}).label || val;
  if (dim === 'status' && source === 'quotes') return (QUOTE_STATUS[val] || {}).label || val;
  if (dim === 'src') return (SRC_META[val] || {}).label || val;
  if (dim === 'kind') return (ACT_KIND[val] || {}).label || val;
  if (dim === 'done') return val ? 'Erledigt' : 'Offen';
  if (dim === 'accountId') { const a = CRMStore.get('accounts', val); return a ? a.name : val; }
  if (dim === 'type') return ({ new:'New Business', renewal:'Renewal', cross:'Cross-sell', up:'Up-sell' })[val] || val;
  return String(val);
}

// Eine Kennzahl über eine Menge von Datensätzen berechnen
function rptMeasure(records, source, measure) {
  let sum = 0, scoreSum = 0, marginSum = 0, rev = 0; const count = records.length;
  records.forEach(r => {
    if (source === 'opportunities') sum += r.amount || 0;
    else if (source === 'quotes') { sum += quoteTotal(r); marginSum += quoteMargin(r); }
    else if (source === 'leads') scoreSum += r.score || 0;
    else if (source === 'accounts') { sum += CRMStore.list('opportunities', o => o.accountId === r.id && !['won','lost'].includes(o.stage)).reduce((s, o) => s + (o.amount || 0), 0); const sp = CRMStore.sapFor(r.id); rev += sp ? sp.revYTD : 0; }
  });
  switch (measure) {
    case 'amount': case 'total': case 'pipeline': return sum;
    case 'revYTD': return rev;
    case 'avgAmount': return count ? Math.round(sum / count) : 0;
    case 'avgScore': return count ? Math.round(scoreSum / count) : 0;
    case 'avgMargin': return count ? Math.round(marginSum / count * 100) : 0;
    default: return count;
  }
}

function rptAggregate(w) {
  const list = scopeOwner(CRMStore.list(w.source));
  const groups = {};
  list.forEach(r => { const k = rptLabel(w.source, w.dim, r[w.dim]); (groups[k] = groups[k] || []).push(r); });
  return Object.keys(groups).map(k => ({ key: k, value: rptMeasure(groups[k], w.source, w.measure) })).sort((a, b) => b.value - a.value);
}

// Pivot: Zeilen-Dimension × Spalten-Dimension, Kennzahl in den Zellen
function rptPivot(w) {
  const list = scopeOwner(CRMStore.list(w.source));
  const rowSet = {}, colSet = {}, buckets = {};
  list.forEach(r => {
    const rk = rptLabel(w.source, w.dim, r[w.dim]); const ck = rptLabel(w.source, w.dim2, r[w.dim2]);
    rowSet[rk] = 1; colSet[ck] = 1; const key = rk + '\u0000' + ck; (buckets[key] = buckets[key] || []).push(r);
  });
  return { rows: Object.keys(rowSet).sort(), cols: Object.keys(colSet).sort(), val: (rk, ck) => { const b = buckets[rk + '\u0000' + ck]; return b ? rptMeasure(b, w.source, w.measure) : 0; } };
}

function rptFmt(measure, v) {
  if (['amount','total','avgAmount','pipeline','revYTD'].includes(measure)) return fmtEUR(v);
  if (measure === 'avgMargin') return v + '%';
  return String(v);
}

function rptAggregateTime(w) {
  const list = scopeOwner(CRMStore.list(w.source));
  const groups = {};
  list.forEach(r => { const ds = r[w.dateField]; if (!ds) return; const m = String(ds).slice(0, 7); (groups[m] = groups[m] || []).push(r); });
  return Object.keys(groups).sort().map(m => ({ key: rptMonthLabel(m), value: rptMeasure(groups[m], w.source, w.measure) }));
}

const RPT_PALETTE = [['bar','Balken','analytics'],['donut','Donut','target'],['timeline','Zeitachse','route'],['table','Tabelle','quotes']];
const DONUT_COLORS = ['#2A4D74','#3269B4','#5B8AC9','#A7C2E7','#6B7280','#9AA3AE','#C2C8D0','#46586E'];

function rptDefaults(viz) {
  return { id:'w' + Date.now() + Math.floor(Math.random() * 99), viz, title: viz === 'timeline' ? 'Zeitachse' : 'Neues Widget', source:'opportunities', dim:'stage', dim2:'', dateField:'createdAt', measure: viz === 'timeline' ? 'amount' : (viz === 'table' ? 'count' : 'amount'), wide: viz === 'timeline' };
}

function RptWidget({ w, onChange, onRemove }) {
  const data = w.viz === 'timeline' ? rptAggregateTime(w) : rptAggregate(w);
  const max = Math.max(1, ...data.map(d => d.value));
  const src = RPT_SOURCES[w.source];
  const dims = src.dims, measures = src.measures;
  const set = (k, v) => { const nw = { ...w, [k]: v }; if (k === 'source') { nw.dim = RPT_SOURCES[v].dims[0][0]; nw.measure = RPT_SOURCES[v].measures[0][0]; nw.dateField = (RPT_DATEFIELDS[v] || [['createdAt']])[0][0]; } onChange(nw); };

  // donut geometry
  const total = data.reduce((s, d) => s + d.value, 0) || 1;
  let acc = 0;
  const segs = data.slice(0, 8).map((d, i) => { const a0 = acc / total * 360; acc += d.value; const a1 = acc / total * 360; return { d, a0, a1, c: DONUT_COLORS[i % DONUT_COLORS.length] }; });
  const arc = (cx, cy, r, a0, a1) => { const p = (a) => [cx + r * Math.cos((a - 90) * Math.PI / 180), cy + r * Math.sin((a - 90) * Math.PI / 180)]; const [x0, y0] = p(a0), [x1, y1] = p(a1); const large = a1 - a0 > 180 ? 1 : 0; return `M ${cx} ${cy} L ${x0} ${y0} A ${r} ${r} 0 ${large} 1 ${x1} ${y1} Z`; };

  return (
    <div className={"rpt-widget" + (w.wide ? ' wide' : '')}>
      <div className="rpt-w-hd">
        <input className="rpt-title" value={w.title} onChange={e => set('title', e.target.value)} />
        <button className="rpt-wide" title="Breite umschalten" onClick={() => set('wide', !w.wide)}>{w.wide ? '▣' : '▢'}</button>
        <button className="rpt-rm" title="Entfernen" onClick={onRemove}>✕</button>
      </div>
      <div className="rpt-cfg">
        <select value={w.source} onChange={e => set('source', e.target.value)}>{Object.keys(RPT_SOURCES).map(k => <option key={k} value={k}>{RPT_SOURCES[k].label}</option>)}</select>
        {w.viz === 'timeline'
          ? <select value={w.dateField} onChange={e => set('dateField', e.target.value)}>{(RPT_DATEFIELDS[w.source] || []).map(d => <option key={d[0]} value={d[0]}>nach {d[1]}</option>)}</select>
          : <select value={w.dim} onChange={e => set('dim', e.target.value)}>{dims.map(d => <option key={d[0]} value={d[0]}>nach {d[1]}</option>)}</select>}
        <select value={w.measure} onChange={e => set('measure', e.target.value)}>{(w.viz === 'timeline' ? measures.filter(m => ['count','amount','total','pipeline','revYTD'].includes(m[0])) : measures).map(m => <option key={m[0]} value={m[0]}>{m[1]}</option>)}</select>
        {w.viz === 'table' && <select value={w.dim2 || ''} onChange={e => set('dim2', e.target.value)}>{[['','Spalten: ohne'], ...dims.filter(d => d[0] !== w.dim)].map(d => <option key={d[0]} value={d[0]}>{d[0] ? '× ' + d[1] : d[1]}</option>)}</select>}
      </div>
      <div className="rpt-viz">
        {data.length === 0 ? <div className="rpt-empty">Keine Daten</div> :
          w.viz === 'timeline' ? (
            <div className="rpt-cols">
              {data.map((d, i) => (
                <div key={i} className="rpt-col" title={d.key + ': ' + rptFmt(w.measure, d.value)}>
                  <span className="rpt-col-val">{rptFmt(w.measure, d.value)}</span>
                  <span className="rpt-col-bar" style={{ height: (d.value / max * 100) + '%' }}></span>
                  <span className="rpt-col-lbl">{d.key}</span>
                </div>
              ))}
            </div>
          ) : w.viz === 'bar' ? (
            <div className="rpt-bars">
              {data.slice(0, 10).map((d, i) => (
                <div key={i} className="rpt-bar-row"><span className="rpt-bar-lbl" title={d.key}>{d.key}</span>
                  <span className="rpt-bar-track"><span className="rpt-bar-fill" style={{ width: (d.value / max * 100) + '%' }}></span></span>
                  <span className="rpt-bar-val">{rptFmt(w.measure, d.value)}</span></div>
              ))}
            </div>
          ) : w.viz === 'donut' ? (
            <div className="rpt-donut">
              <svg viewBox="0 0 120 120">
                {segs.map((s, i) => <path key={i} d={arc(60, 60, 56, s.a0, s.a1)} fill={s.c} />)}
                <circle cx="60" cy="60" r="32" fill="var(--surface)" />
              </svg>
              <div className="rpt-legend">{segs.map((s, i) => <div key={i} className="rpt-leg"><span className="rpt-leg-dot" style={{ background: s.c }}></span>{s.d.key}<b>{rptFmt(w.measure, s.d.value)}</b></div>)}</div>
            </div>
          ) : (
            w.dim2 ? (() => { const pv = rptPivot(w); return (
              <div className="lv-scroll"><table className="rpt-table rpt-pivot">
                <thead><tr><th>{(dims.find(d => d[0] === w.dim) || ['',''])[1]}</th>{pv.cols.map(c => <th key={c} className="num">{c}</th>)}</tr></thead>
                <tbody>{pv.rows.map(r => <tr key={r}><td>{r}</td>{pv.cols.map(c => { const v = pv.val(r, c); return <td key={c} className="num">{v ? rptFmt(w.measure, v) : <span style={{ color:'var(--muted-2)' }}>—</span>}</td>; })}</tr>)}</tbody>
              </table></div>
            ); })() : (
            <table className="rpt-table"><tbody>
              {data.map((d, i) => <tr key={i}><td>{d.key}</td><td className="num">{rptFmt(w.measure, d.value)}</td></tr>)}
            </tbody></table>
            )
          )}
      </div>
    </div>
  );
}

function ReportsView() {
  useStore();
  const [widgets, setWidgets] = useS(() => { try { return JSON.parse(localStorage.getItem(RPT_KEY) || 'null') || []; } catch (e) { return []; } });
  const save = (ws) => { setWidgets(ws); try { localStorage.setItem(RPT_KEY, JSON.stringify(ws)); } catch (e) {} };
  const add = (viz) => save([...widgets, rptDefaults(viz)]);
  const change = (id, nw) => save(widgets.map(w => w.id === id ? nw : w));
  const remove = (id) => save(widgets.filter(w => w.id !== id));
  const [over, setOver] = useS(false);

  return (
    <div className="page">
      <div className="page-title-row">
        <div>
          <h1 className="page-title">Reports &amp; Analytics</h1>
          <p className="page-sub">Eigenes Dashboard bauen: Widget vom Rand aufs Canvas ziehen, dann Quelle, Dimension und Kennzahl wählen. Alles live aus den Daten.</p>
        </div>
        {widgets.length > 0 && <button className="btn ghost" onClick={() => save([])}>Alle entfernen</button>}
      </div>

      <div className="rpt-layout">
        <aside className="rpt-palette">
          <div className="rpt-pal-hd">Widgets</div>
          {RPT_PALETTE.map(p => (
            <div key={p[0]} className="rpt-pal-item" draggable
              onDragStart={e => { e.dataTransfer.setData('text/plain', p[0]); e.dataTransfer.effectAllowed = 'copy'; }}
              onClick={() => add(p[0])}>
              <span className="rpt-pal-ic">{Icons[p[2]]}</span>{p[1]}
            </div>
          ))}
          <div className="rpt-pal-hint">Ziehen oder klicken zum Hinzufügen</div>
        </aside>

        <section className={"rpt-canvas" + (over ? ' over' : '')}
          onDragOver={e => { e.preventDefault(); setOver(true); }}
          onDragLeave={() => setOver(false)}
          onDrop={e => { e.preventDefault(); setOver(false); const v = e.dataTransfer.getData('text/plain'); if (['bar','donut','table','timeline'].includes(v)) add(v); }}>
          {widgets.length === 0 ? (
            <div className="rpt-canvas-empty">{Icons.analytics}<b>Leeres Dashboard</b><span>Ziehen Sie ein Widget aus der Leiste hierher — oder klicken Sie es an.</span></div>
          ) : (
            <div className="rpt-grid">
              {widgets.map(w => <RptWidget key={w.id} w={w} onChange={nw => change(w.id, nw)} onRemove={() => remove(w.id)} />)}
            </div>
          )}
        </section>
      </div>
    </div>
  );
}
