// ─── Opportunities — list + CRUD + stage change ──────────────

function blankOpp(accountId) {
  return { name:'', accountId: accountId || '', stage:'qual', amount:0, close:'', prob:20, owner:'JS', type:'new', source:'field', next:'', winProb:null };
}

// Anfrage bewerten — Erfolgswahrscheinlichkeit aus Kunde, Wettbewerb, Volumen, Stage
function evalOpp(o) {
  let score = 40; const notes = [];
  const acc = CRMStore.get('accounts', o.accountId);
  if (acc) {
    if (acc.tier === 'A') { score += 15; notes.push('Key Account (A) · +15'); }
    else if (acc.tier === 'B') { score += 7; notes.push('Account-Tier B · +7'); }
    else { notes.push('Account-Tier C · ±0'); }
    if (acc.health === 'g') { score += 8; notes.push('Gesunde Kundenbeziehung · +8'); }
    else if (acc.health === 'r') { score -= 12; notes.push('Risiko-Account · −12'); }
  }
  if (o.competitor) {
    const hist = CRMStore.list('opportunities', x => x.competitor === o.competitor && (x.stage === 'won' || x.stage === 'lost'));
    const won = hist.filter(x => x.stage === 'won').length, lost = hist.filter(x => x.stage === 'lost').length;
    if (won + lost > 0) { const d = Math.round((won / (won + lost) - 0.5) * 40); score += d; notes.push('Bilanz vs. ' + o.competitor + ' (' + won + '/' + lost + ') · ' + (d >= 0 ? '+' : '') + d); }
    else { score -= 6; notes.push('Wettbewerber ' + o.competitor + ' aktiv · −6'); }
  } else { score += 6; notes.push('Kein Wettbewerber bekannt · +6'); }
  if (o.amount > 250000) { score -= 8; notes.push('Großvolumen (>250k) · −8'); }
  else if (o.amount < 80000 && o.amount > 0) { score += 5; notes.push('Kleinvolumen · +5'); }
  const t = o.type === 'renewal' ? 10 : o.type === 'cross' || o.type === 'up' ? 6 : 0;
  if (t) { score += t; notes.push((o.type === 'renewal' ? 'Renewal' : 'Cross/Up-sell') + ' · +' + t); }
  score += Math.round((CRMStore.STAGE_PROB[o.stage] || 20) / 12); notes.push('Stage-Fortschritt · +' + Math.round((CRMStore.STAGE_PROB[o.stage] || 20) / 12));
  score = Math.max(5, Math.min(95, score));
  return { score, notes };
}

const TYPE_OPTS = [['new','New Business'],['renewal','Renewal'],['cross','Cross-sell'],['up','Up-sell']];
const OPP_SRC_OPTS = [['field','Außendienst'],['snap','snapADDY (Messe)'],['web','Web-Formular'],['ref','Empfehlung'],['cold','Kaltakquise']];

function OppForm({ rec, onClose }) {
  const isNew = !rec.id;
  const [f, setF] = useS(Object.assign(blankOpp(), rec));
  const set = (k, v) => setF(p => ({ ...p, [k]: v }));
  const accounts = CRMStore.list('accounts');
  const canSave = f.name.trim() && f.accountId;

  const setStage = (v) => setF(p => ({ ...p, stage: v, prob: CRMStore.STAGE_PROB[v] }));
  const [evalNotes, setEvalNotes] = useS(null);
  const runEval = () => { const r = evalOpp(f); set('winProb', r.score); setEvalNotes(r.notes); toast('Anfrage bewertet · ' + r.score + '%'); };
  const save = () => {
    if (!canSave) return;
    const payload = Object.assign({}, f, { amount: Number(f.amount) || 0 });
    if (isNew) { CRMStore.create('opportunities', payload); toast('Opportunity angelegt'); }
    else { CRMStore.update('opportunities', rec.id, payload); toast('Opportunity aktualisiert'); }
    onClose();
  };

  return (
    <Modal wide title={isNew ? 'Neue Opportunity' : 'Opportunity bearbeiten'} sub={isNew ? 'Deal in der Pipeline anlegen.' : f.id} onClose={onClose}
      footer={<>
        <span className="cmodal-note">{canSave ? 'Bereit zum Speichern' : 'Name und Account sind erforderlich'}</span>
        <span className="cmodal-foot-right">
          <button className="btn ghost" onClick={onClose}>Abbrechen</button>
          <button className="btn" disabled={!canSave} onClick={save}>{isNew ? 'Opportunity anlegen' : 'Speichern'}</button>
        </span>
      </>}>
      <div className="form-grid">
        <Field label="Name" req full><TextInput value={f.name} onChange={v => set('name', v)} placeholder="z. B. Krause MB — Spindelpaket S-7" /></Field>
        <Field label="Account" req>
          <Select value={f.accountId} onChange={v => set('accountId', v)} options={[['','— wählen —'], ...accounts.map(a => [a.id, a.name])]} />
        </Field>
        <Field label="Typ"><Select value={f.type} onChange={v => set('type', v)} options={TYPE_OPTS} /></Field>
        <Field label="Betrag (€)" req><TextInput value={f.amount} onChange={v => set('amount', v)} type="number" placeholder="z. B. 120000" /></Field>
        <Field label="Stage" hint={'Wahrsch. ' + f.prob + '%'}><Select value={f.stage} onChange={setStage} options={STAGE_OPTS} /></Field>
        <Field label="Erwarteter Abschluss"><TextInput value={f.close} onChange={v => set('close', v)} type="date" /></Field>
        <Field label="Owner"><Select value={f.owner} onChange={v => set('owner', v)} options={OWNER_OPTS} /></Field>
        <Field label="Quelle"><Select value={f.source} onChange={v => set('source', v)} options={OPP_SRC_OPTS} /></Field>
        <Field label="Nächster Schritt" full><TextInput value={f.next} onChange={v => set('next', v)} placeholder="z. B. Technische Demo vereinbaren" /></Field>
      </div>
      <div className="eval-box">
        <button className="btn ghost" onClick={runEval} disabled={!f.accountId} title="Erfolgswahrscheinlichkeit ermitteln">{Icons.target} Anfrage bewerten</button>
        {f.winProb != null && <span className="eval-res">Erfolgswahrscheinlichkeit: <b style={{ color: f.winProb >= 60 ? 'var(--success)' : f.winProb >= 35 ? '#806B3D' : 'var(--danger)' }}>{f.winProb}%</b></span>}
        {evalNotes && <ul className="eval-notes">{evalNotes.map((n, i) => <li key={i}>{n}</li>)}</ul>}
      </div>
      {!isNew && <AttachList refType="opportunity" refId={rec.id} />}
    </Modal>
  );
}

function OppCard({ o, onEdit }) {
  const sm = STAGE_META[o.stage] || STAGE_META.qual;
  const acc = CRMStore.get('accounts', o.accountId);
  return (
    <div className="opp-card" draggable
      onDragStart={e => { e.dataTransfer.setData('text/plain', o.id); e.dataTransfer.effectAllowed = 'move'; e.currentTarget.classList.add('dragging'); }}
      onDragEnd={e => e.currentTarget.classList.remove('dragging')}
      onClick={() => onEdit(o)}>
      <div className="opp-card-top"><span className="oc-id">{o.id}</span><span className="oc-amt">{fmtEUR(o.amount)}</span></div>
      <b>{o.name}</b>
      <span className="oc-acc">{acc ? acc.name : '—'}</span>
      <div className="opp-card-foot"><span className="oc-owner">{o.owner}</span><span className="oc-prob">{o.prob}%</span></div>
    </div>
  );
}

const BOARD_STAGES = ['qual','disc','prop','neg','close','won'];

function OppBoard({ rows, onEdit }) {
  const [over, setOver] = useS(null);
  const drop = (stage) => (e) => {
    e.preventDefault();
    const id = e.dataTransfer.getData('text/plain');
    setOver(null);
    const o = CRMStore.get('opportunities', id);
    if (o && o.stage !== stage) { CRMStore.update('opportunities', id, { stage, prob: CRMStore.STAGE_PROB[stage] }); toast('→ ' + STAGE_META[stage].label); }
  };
  return (
    <div className="opp-board">
      {BOARD_STAGES.map(st => {
        const col = rows.filter(o => o.stage === st);
        const sum = col.reduce((s, o) => s + (o.amount || 0), 0);
        return (
          <div key={st} className={"opp-col" + (over === st ? ' over' : '')}
            onDragOver={e => { e.preventDefault(); setOver(st); }}
            onDragLeave={() => setOver(o => o === st ? null : o)}
            onDrop={drop(st)}>
            <div className="opp-col-hd">
              <span className={"stage-pill " + STAGE_META[st].cls}><span className="dot"></span>{STAGE_META[st].label}</span>
              <span className="opp-col-meta">{col.length} · {fmtEUR(sum)}</span>
            </div>
            <div className="opp-col-body">
              {col.map(o => <OppCard key={o.id} o={o} onEdit={onEdit} />)}
              {col.length === 0 && <div className="opp-col-empty">hierher ziehen</div>}
            </div>
          </div>
        );
      })}
    </div>
  );
}

function OppsView({ focusRec, clearFocus }) {
  const [q, setQ] = useS('');
  const [tab, setTab] = useS('open');
  const [mode, setMode] = useS('list');
  const [edit, setEdit] = useS(null);
  const [del, setDel] = useS(null);
  const [lossOpp, setLossOpp] = useS(null);
  const [sort, setSort] = useS({ key:'', dir:1 });

  // external trigger (e.g. "new opp for account", or open specific opp)
  useE(() => {
    if (focusRec) { setEdit(focusRec); clearFocus(); }
  }, [focusRec]);

  const all = scopeOwner(CRMStore.list('opportunities'));
  const open = all.filter(o => !['won','lost'].includes(o.stage));
  const tabs = [['open','Offen',open.length],['all','Alle',all.length],['won','Gewonnen',all.filter(o => o.stage === 'won').length]];
  let rows = all;
  if (tab === 'open') rows = open;
  if (tab === 'won') rows = all.filter(o => o.stage === 'won');
  if (q.trim()) { const s = q.toLowerCase(); rows = rows.filter(o => o.name.toLowerCase().includes(s)); }

  const accName = (id) => { const a = CRMStore.get('accounts', id); return a ? a.name : '—'; };
  const total = rows.reduce((s, o) => s + (o.amount || 0), 0);
  const sortVal = (o, k) => k === 'account' ? accName(o.accountId).toLowerCase() : k === 'name' ? o.name.toLowerCase() : k === 'stage' ? (CRMStore.STAGE_PROB[o.stage] || 0) : k === 'amount' ? (o.amount || 0) : k === 'close' ? (o.close || '') : k === 'prob' ? (o.prob || 0) : k === 'winProb' ? (o.winProb == null ? -1 : o.winProb) : 0;
  if (sort.key) rows = rows.slice().sort((a, b) => { const va = sortVal(a, sort.key), vb = sortVal(b, sort.key); return (va < vb ? -1 : va > vb ? 1 : 0) * sort.dir; });
  const Th = ({ k, label, cls }) => <th className={cls} onClick={() => setSort(s => s.key === k ? { key:k, dir:-s.dir } : { key:k, dir:1 })} style={{ cursor:'pointer', whiteSpace:'nowrap' }}>{label}{sort.key === k ? (sort.dir === 1 ? ' ▲' : ' ▼') : ''}</th>;

  const quickStage = (o, v) => { if (v === 'lost') { setLossOpp(o); return; } CRMStore.update('opportunities', o.id, { stage: v, prob: CRMStore.STAGE_PROB[v] }); toast('Stage → ' + (STAGE_META[v] ? STAGE_META[v].label : v)); };

  return (
    <div className="page">
      <div className="page-title-row">
        <div>
          <h1 className="page-title">Opportunities</h1>
          <p className="page-sub">Die Pipeline von der Qualifizierung bis zum Abschluss. Stage direkt in der Liste ändern — Summen aktualisieren sich live.</p>
        </div>
        <button className="btn" onClick={() => setEdit(blankOpp())}>{Icons.plus} Neue Opportunity</button>
      </div>

      <Toolbar q={q} onQ={setQ} placeholder="Opportunities durchsuchen …" tabs={mode === 'list' ? tabs : null} tab={tab} onTab={setTab}
        right={<div className="view-toggle">
          <button className={"vt" + (mode === 'list' ? ' active' : '')} onClick={() => setMode('list')}>Liste</button>
          <button className={"vt" + (mode === 'board' ? ' active' : '')} onClick={() => setMode('board')}>Board</button>
        </div>} />

      {mode === 'board' ? (
        <OppBoard rows={all.filter(o => o.stage !== 'lost' && (!q.trim() || o.name.toLowerCase().includes(q.toLowerCase())))} onEdit={setEdit} />
      ) : (
      <div className="lv-card">
        <div className="lv-card-hd"><h3>{tab === 'won' ? 'Gewonnene Deals' : tab === 'all' ? 'Alle Opportunities' : 'Offene Pipeline'}</h3><span className="sub">{rows.length} Deals · {fmtEUR(total)} gesamt</span></div>
        {rows.length === 0 ? (
          <div className="empty">Keine Opportunities. <a onClick={() => setEdit(blankOpp())}>Erste Opportunity anlegen →</a></div>
        ) : (
        <div className="lv-scroll">
        <table className="tbl">
          <thead><tr><Th k="name" label="Opportunity" /><Th k="account" label="Account" /><Th k="stage" label="Stage" /><Th k="amount" label="Betrag" cls="num" /><Th k="close" label="Close" /><Th k="prob" label="Gate" cls="num" /><Th k="winProb" label="Erfolg" cls="num" /><th className="num">Aktion</th></tr></thead>
          <tbody>
            {rows.map(o => {
              const sm = STAGE_META[o.stage] || STAGE_META.qual;
              return (
                <tr key={o.id} data-kiki-id={o.id} data-kiki-label={o.name} data-kiki-kind="Opportunity" {...attachDropProps('opportunity', o.id)}>
                  <td className="name"><b>{o.name}</b><span className="sub">{o.id}{o.next ? ' · ' + o.next : ''}</span></td>
                  <td>{accName(o.accountId)}</td>
                  <td onClick={e => e.stopPropagation()}>
                    <select className="stage-select" value={o.stage} onChange={e => quickStage(o, e.target.value)}>
                      {STAGE_OPTS.map(s => <option key={s[0]} value={s[0]}>{STAGE_META[s[0]].label}</option>)}
                    </select>
                  </td>
                  <td className="num" style={{fontWeight:600}}>{fmtEUR(o.amount)}</td>
                  <td style={{fontFamily:'var(--font-mono)', fontSize:11.5, color:'var(--muted)'}}>{o.close || '—'}</td>
                  <td className="num">{o.prob}%</td>
                  <td className="num">{o.winProb == null ? <span style={{color:'var(--muted-2)', fontFamily:'var(--font-mono)', fontSize:11}}>—</span> : <span style={{fontFamily:'var(--font-mono)', fontWeight:600, color: o.winProb >= 60 ? 'var(--success)' : o.winProb >= 35 ? '#806B3D' : 'var(--danger)'}}>{o.winProb}%</span>}</td>
                  <td className="num">
                    <div className="row-actions">
                      {!['won','lost'].includes(o.stage) && <button className="ra" title="Verloren melden" onClick={() => setLossOpp(o)}>Verloren</button>}
                      <button className="ra icon" title="Bearbeiten" onClick={() => setEdit(o)}>{Icons.edit || '✎'}</button>
                      <button className="ra icon danger" title="Löschen" onClick={() => setDel(o)}>{Icons.trash || '🗑'}</button>
                    </div>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
        </div>
        )}
      </div>
      )}

      {edit && <OppForm rec={edit} onClose={() => setEdit(null)} />}
      {lossOpp && <LossForm opp={lossOpp} onClose={() => setLossOpp(null)} />}
      {del && <Confirm danger text={'Opportunity „' + del.name + '" löschen?'} confirmLabel="Löschen"
        onConfirm={() => { CRMStore.remove('opportunities', del.id); toast('Opportunity gelöscht'); setDel(null); }}
        onCancel={() => setDel(null)} />}
    </div>
  );
}
