/* AIWine CRM — sales pipeline: Kanban board + opportunity editor.
   Opportunities sit on top of wineries (one winery can have a deal). */

const STAGES = [
  { id: 'identified',  label: 'Identified',  prob: 5 },
  { id: 'researching', label: 'Researching', prob: 10 },
  { id: 'contacted',   label: 'Contacted',   prob: 20 },
  { id: 'discovery',   label: 'Discovery',   prob: 35 },
  { id: 'qualified',   label: 'Qualified',   prob: 50 },
  { id: 'proposal',    label: 'Proposal',    prob: 65 },
  { id: 'trial',       label: 'Trial',       prob: 80 },
  { id: 'customer',    label: 'Customer',    prob: 100 },
  { id: 'advocate',    label: 'Advocate',    prob: 100 },
];
const STAGE_BY = Object.fromEntries(STAGES.map((s) => [s.id, s]));
const WON = ['customer', 'advocate'];
const SOURCES = ['', 'directory', 'inbound', 'referral', 'event', 'cold', 'partner'];
const stageLabel = (id) => id === 'lost' ? 'Lost' : (STAGE_BY[id] ? STAGE_BY[id].label : id);

function oppWinery(store, o) { return store.get('wineries', o.wineryId); }

function Pipeline({ country }) {
  const store = window.UI.useStore();
  const { Ic, money, inCountry, rel } = window.UI;
  const [editing, setEditing] = React.useState(null); // opp object or {new:true}
  const [showLost, setShowLost] = React.useState(false);
  const [attnOnly, setAttnOnly] = React.useState(false);
  const [dragId, setDragId] = React.useState(null);

  const opps = store.t('opportunities')
    .map((o) => ({ o, w: oppWinery(store, o) }))
    .filter(({ w }) => w && inCountry(w, country))
    .map(({ o }) => o);

  const open = opps.filter((o) => !WON.includes(o.stage) && o.stage !== 'lost');
  const openValue = open.reduce((s, o) => s + (+o.value || 0), 0);
  const weighted = open.reduce((s, o) => s + (+o.value || 0) * ((o.probability != null ? o.probability : (STAGE_BY[o.stage] || {}).prob || 0) / 100), 0);
  const wonValue = opps.filter((o) => WON.includes(o.stage)).reduce((s, o) => s + (+o.value || 0), 0);
  const cur = country === 'AU' ? 'AU' : 'NZ';

  const move = async (id, stage) => {
    const o = store.get('opportunities', id);
    if (!o || o.stage === stage) return;
    const patch = { stage, updatedAt: new Date().toISOString() };
    if (o.probability == null || o.probability === (STAGE_BY[o.stage] || {}).prob) patch.probability = (STAGE_BY[stage] || { prob: o.probability }).prob;
    await store.update('opportunities', id, patch);
    store.audit('Moved “' + (o.title || 'deal') + '” to ' + stageLabel(stage), 'opportunity');
  };

  const Metric = ({ label, val, sub }) => (
    <div className="stat-tile"><div className="label">{label}</div><div className="num" style={{ fontSize: 26 }}>{val}</div>{sub && <div className="delta" style={{ color: 'var(--muted)' }}>{sub}</div>}</div>
  );

  return (
    <div>
      <div className="page-head">
        <div>
          <div className="label" style={{ marginBottom: 6 }}>{open.length} open · {opps.filter((o) => WON.includes(o.stage)).length} won{opps.filter((o) => o.stage === 'lost').length ? ' · ' + opps.filter((o) => o.stage === 'lost').length + ' lost' : ''}</div>
          <h1 className="page-title">Pipeline</h1>
        </div>
        <button className="btn btn-primary" onClick={() => setEditing({ new: true })}><Ic name="plus" w={15} /> New opportunity</button>
      </div>

      <div className="stat-grid" style={{ marginBottom: 18, gridTemplateColumns: 'repeat(auto-fit, minmax(160px,1fr))' }}>
        <Metric label="Open pipeline" val={money(openValue, cur)} sub={open.length + ' deals'} />
        <Metric label="Weighted forecast" val={money(Math.round(weighted), cur)} sub="value × probability" />
        <Metric label="Won (annual)" val={money(wonValue, cur)} sub={opps.filter((o) => WON.includes(o.stage)).length + ' customers'} />
        <Metric label="Avg deal" val={open.length ? money(Math.round(openValue / open.length), cur) : '—'} sub="open deals" />
      </div>

      <div style={{ display: 'flex', gap: 16, marginBottom: 12, alignItems: 'center' }}>
        <label style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12.5, color: 'var(--ink-soft)' }}>
          <input type="checkbox" checked={showLost} onChange={(e) => setShowLost(e.target.checked)} /> Show lost
        </label>
        <label style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12.5, color: 'var(--ink-soft)' }}>
          <input type="checkbox" checked={attnOnly} onChange={(e) => setAttnOnly(e.target.checked)} /> Needs attention only
        </label>
      </div>

      <div style={{ display: 'flex', gap: 12, overflowX: 'auto', paddingBottom: 16, alignItems: 'flex-start' }}>
        {STAGES.concat(showLost ? [{ id: 'lost', label: 'Lost', prob: 0 }] : []).map((st) => {
          const col = opps.filter((o) => o.stage === st.id).filter((o) => !attnOnly || store.oppHealth(o).attention);
          const sum = col.reduce((s, o) => s + (+o.value || 0), 0);
          return (
            <div key={st.id}
              onDragOver={(e) => { e.preventDefault(); }}
              onDrop={() => { if (dragId) { move(dragId, st.id); setDragId(null); } }}
              style={{ flex: '0 0 230px', width: 230, background: 'var(--card)', border: '1px solid var(--line)', borderRadius: 4, display: 'flex', flexDirection: 'column', minHeight: 120 }}>
              <div style={{ padding: '11px 13px', borderBottom: '1px solid var(--line-soft)', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                <span className="mono" style={{ fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase', color: st.id === 'lost' ? 'var(--muted)' : WON.includes(st.id) ? 'var(--green)' : 'var(--claret)' }}>{st.label}</span>
                <span className="mono" style={{ fontSize: 10, color: 'var(--faint)' }}>{col.length}</span>
              </div>
              {sum > 0 && <div className="mono" style={{ fontSize: 10, color: 'var(--muted)', padding: '6px 13px 0' }}>{money(sum, cur)}</div>}
              <div style={{ padding: 10, display: 'flex', flexDirection: 'column', gap: 8 }}>
                {col.map((o) => {
                  const w = oppWinery(store, o);
                  const h = store.oppHealth(o);
                  const overdue = h.overdue;
                  return (
                    <div key={o.id} draggable onDragStart={() => setDragId(o.id)} onDragEnd={() => setDragId(null)}
                      onClick={() => setEditing(o)}
                      style={{ background: 'var(--card-2)', border: '1px solid ' + (h.attention ? 'var(--claret)' : 'var(--line)'), borderRadius: 3, padding: '10px 11px', cursor: 'pointer', boxShadow: dragId === o.id ? '0 8px 20px rgba(27,20,16,0.18)' : 'none' }}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 6 }}>
                        <div style={{ fontSize: 13, fontWeight: 700, lineHeight: 1.2 }}>{w ? w.name : '—'}</div>
                        {h.cold && <span title={'No activity for ' + h.daysIdle + ' days'} className="mono" style={{ fontSize: 8.5, color: 'var(--brass)', border: '1px solid var(--line)', borderRadius: 3, padding: '1px 4px', whiteSpace: 'nowrap' }}>COLD</span>}
                      </div>
                      {o.title && <div style={{ fontSize: 11.5, color: 'var(--ink-soft)', marginTop: 2 }}>{o.title}</div>}
                      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 7 }}>
                        <span className="mono" style={{ fontSize: 11, color: 'var(--ink)' }}>{o.value ? money(o.value, o.currency === 'AUD' ? 'AU' : 'NZ') : '—'}</span>
                        {w && <span className="mono" style={{ fontSize: 9, color: 'var(--faint)' }}>{w.region}</span>}
                      </div>
                      {o.nextAction && <div style={{ marginTop: 7, paddingTop: 7, borderTop: '1px solid var(--line-soft)', fontSize: 11, color: overdue ? 'var(--claret)' : 'var(--muted)' }}>→ {o.nextAction}{o.nextActionDue ? ' · ' + rel(o.nextActionDue) : ''}</div>}
                    </div>
                  );
                })}
                {col.length === 0 && <div style={{ fontSize: 11, color: 'var(--faint)', textAlign: 'center', padding: '8px 0' }}>—</div>}
              </div>
            </div>
          );
        })}
      </div>

      {editing && <OpportunityEditor opp={editing.new ? null : editing} defaultCountry={cur} onClose={() => setEditing(null)} />}
    </div>
  );
}

// opp = existing row or null (create). wineryId optional preset (from winery profile).
function OpportunityEditor({ opp, wineryId, defaultCountry, onClose }) {
  const store = window.UI.useStore();
  const { Field, toast } = window.UI;
  const editing = !!opp;
  const [f, setF] = React.useState(opp ? { ...opp } : {
    wineryId: wineryId || '', title: '', stage: 'identified', value: '', currency: defaultCountry === 'AU' ? 'AUD' : 'NZD',
    probability: 5, expectedClose: '', source: '', nextAction: '', nextActionDue: '', problems: '', solutions: '', lossReason: '',
    owner: store.user ? store.user.name : '',
  });
  const set = (k) => (e) => setF({ ...f, [k]: e.target.value });
  const wineries = store.t('wineries').slice().sort((a, b) => (a.name || '').localeCompare(b.name || ''));

  const save = async () => {
    if (!f.wineryId) { toast('Pick a winery'); return; }
    const patch = {
      wineryId: f.wineryId, title: f.title, stage: f.stage, value: f.value === '' ? null : Number(f.value), currency: f.currency,
      probability: f.probability === '' ? null : Number(f.probability), expectedClose: f.expectedClose || null,
      source: f.source, nextAction: f.nextAction, nextActionDue: f.nextActionDue || null,
      problems: f.problems, solutions: f.solutions, lossReason: f.stage === 'lost' ? f.lossReason : null,
      owner: f.owner, updatedAt: new Date().toISOString(),
    };
    try {
      if (editing) { await store.update('opportunities', opp.id, patch); store.audit('Updated opportunity', 'opportunity'); }
      else {
        const row = await store.insert('opportunities', patch);
        const w = store.get('wineries', f.wineryId);
        store.audit('Created opportunity for ' + (w ? w.name : ''), 'opportunity');
        store.logActivity('campaign', 'New opportunity: ' + (w ? w.name : '') + (f.value ? ' · ' + f.value : ''), { page: 'pipeline' });
      }
      toast('Saved'); onClose();
    } catch (err) { toast(err.message); }
  };

  return (
    <window.UI.Modal wide title={editing ? 'Edit opportunity' : 'New opportunity'} sub="Sales pipeline" onClose={onClose}
      foot={<React.Fragment>
        {editing && <button className="btn btn-danger btn-sm" style={{ marginRight: 'auto' }} onClick={() => { if (confirm('Delete this opportunity?')) { store.remove('opportunities', opp.id); onClose(); } }}>Delete</button>}
        <button className="btn btn-ghost" onClick={onClose}>Cancel</button>
        <button className="btn btn-primary" onClick={save}>{editing ? 'Save' : 'Create'}</button>
      </React.Fragment>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        {!wineryId && (
          <Field label="Winery">
            <select className="select" value={f.wineryId} onChange={set('wineryId')}>
              <option value="">Select a winery…</option>
              {wineries.map((w) => <option key={w.id} value={w.id}>{w.name} · {w.region}</option>)}
            </select>
          </Field>
        )}
        <Field label="Opportunity (what are you selling?)"><input className="input" value={f.title} onChange={set('title')} placeholder="e.g. AIWine listing + AI Sommelier placement" autoFocus /></Field>
        <div className="grid-2">
          <Field label="Stage">
            <select className="select" value={f.stage} onChange={(e) => { const st = e.target.value; setF({ ...f, stage: st, probability: (STAGE_BY[st] || { prob: f.probability }).prob }); }}>
              {STAGES.map((s) => <option key={s.id} value={s.id}>{s.label}</option>)}
              <option value="lost">Lost</option>
            </select>
          </Field>
          <Field label="Probability (%)"><input className="input" type="number" min="0" max="100" value={f.probability} onChange={set('probability')} /></Field>
        </div>
        <div className="grid-2">
          <Field label="Annual value"><input className="input" type="number" value={f.value} onChange={set('value')} placeholder="e.g. 1200" /></Field>
          <Field label="Expected close"><input className="input" type="date" value={f.expectedClose || ''} onChange={set('expectedClose')} /></Field>
        </div>
        <div className="grid-2">
          <Field label="Source"><select className="select" value={f.source || ''} onChange={set('source')}>{SOURCES.map((s) => <option key={s} value={s}>{s ? s[0].toUpperCase() + s.slice(1) : '—'}</option>)}</select></Field>
          <Field label="Owner"><input className="input" value={f.owner || ''} onChange={set('owner')} /></Field>
        </div>
        <div className="grid-2">
          <Field label="Next action"><input className="input" value={f.nextAction || ''} onChange={set('nextAction')} placeholder="e.g. Book discovery call" /></Field>
          <Field label="Next action due"><input className="input" type="date" value={f.nextActionDue || ''} onChange={set('nextActionDue')} /></Field>
        </div>
        <Field label="Problems identified"><textarea className="input" rows="2" value={f.problems || ''} onChange={set('problems')} placeholder="What pain does this winery have?" /></Field>
        <Field label="Potential solutions"><textarea className="input" rows="2" value={f.solutions || ''} onChange={set('solutions')} placeholder="What AIWine offers them" /></Field>
        {f.stage === 'lost' && <Field label="Loss reason"><input className="input" value={f.lossReason || ''} onChange={set('lossReason')} placeholder="Why was this lost? (learning)" /></Field>}
      </div>
    </window.UI.Modal>
  );
}

Object.assign(window, { Pipeline, OpportunityEditor, STAGES, STAGE_BY, stageLabel, WON_STAGES: WON });
