/* AIWine CRM — Groups & Associations (multi-brand winery groups + regional/industry associations) */

/* Normalise an org's contacts → [{id,name,role,email,phone,subscribed}].
   Migrates the legacy single contactName/contactEmail/phone shape so older
   rows keep working until they're re-saved. Exposed on window for campaigns. */
function orgContacts(o) {
  if (!o) return [];
  if (Array.isArray(o.contacts) && o.contacts.length) {
    return o.contacts.map((c, i) => ({
      id: c.id || ('c' + i), name: c.name || '', role: c.role || '',
      email: (c.email || '').trim(), phone: c.phone || '', subscribed: c.subscribed !== false,
    }));
  }
  if (o.contactName || o.contactEmail || o.phone) {
    return [{ id: 'legacy', name: o.contactName || '', role: 'Primary', email: (o.contactEmail || '').trim(), phone: o.phone || '', subscribed: o.subscribed !== false }];
  }
  return [];
}

function Orgs({ country, focusId }) {
  const store = window.UI.useStore();
  const { Badge, CTag, Ic, StatTile, toast } = window.UI;
  const [tab, setTab] = React.useState('group');
  const [q, setQ] = React.useState('');
  const [editing, setEditing] = React.useState(null); // org row or 'new'
  const all = (store.t('orgs') || []);
  const F = (rows) => rows.filter((r) => country === 'ALL' || (r.country || 'NZ') === country);

  React.useEffect(() => {
    if (focusId) { const o = all.find((x) => x.id === focusId); if (o) { setTab(o.type); setEditing(o); } }
  }, [focusId]);

  const needle = q.trim().toLowerCase();
  const rows = F(all).filter((o) => o.type === tab)
    .filter((o) => !needle || (o.name || '').toLowerCase().includes(needle) || (o.region || '').toLowerCase().includes(needle) || orgContacts(o).some((c) => ((c.name || '') + ' ' + (c.email || '')).toLowerCase().includes(needle)))
    .sort((a, b) => (a.name || '').localeCompare(b.name || ''));

  const groups = F(all).filter((o) => o.type === 'group');
  const assocs = F(all).filter((o) => o.type === 'association');
  const memberCount = (o) => store.t('wineries').filter((w) => w.groupId === o.id).length;

  return (
    <div>
      <div className="page-head">
        <div>
          <div className="label" style={{ marginBottom: 6 }}>Multi-brand groups &amp; industry associations</div>
          <h1 className="page-title">Groups &amp; Associations</h1>
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <button className="btn btn-ghost" onClick={() => document.getElementById('org-csv').click()}><Ic name="upload" w={15} /> Import CSV</button>
          <button className="btn btn-primary" onClick={() => setEditing('new')}><Ic name="plus" w={15} /> New {tab === 'group' ? 'group' : 'association'}</button>
        </div>
        <input id="org-csv" type="file" accept=".csv,text/csv" style={{ display: 'none' }} onChange={(e) => importOrgsCsv(e, store, toast)} />
      </div>

      <div className="stat-grid" style={{ marginBottom: 18 }}>
        <StatTile label="Multi-brand groups" num={groups.length} delta={groups.reduce((a, o) => a + memberCount(o), 0) + ' linked wineries'} />
        <StatTile label="Associations" num={assocs.length} delta={new Set(assocs.map((o) => o.region).filter(Boolean)).size + ' regions covered'} />
        <StatTile label="Campaign-reachable" num={F(all).reduce((a, o) => a + orgContacts(o).filter((c) => c.subscribed && c.email).length, 0)} delta="subscribed contacts with an email" />
      </div>

      <window.UI.Tabs value={tab} onChange={setTab} items={[
        { id: 'group', label: 'Multi-brand groups', count: groups.length },
        { id: 'association', label: 'Associations', count: assocs.length },
      ]} />

      <div style={{ display: 'flex', gap: 10, margin: '4px 0 14px' }}>
        <input className="input" style={{ maxWidth: 320 }} placeholder={'Search ' + (tab === 'group' ? 'groups' : 'associations') + '…'} value={q} onChange={(e) => setQ(e.target.value)} />
      </div>

      <div className="tbl-wrap">
        <table className="tbl">
          <thead>
            {tab === 'group'
              ? <tr><th>Group</th><th></th><th>Wineries</th><th>Contacts</th><th>Campaigns</th><th></th></tr>
              : <tr><th>Association</th><th></th><th>Region</th><th>Contacts</th><th>Campaigns</th><th></th></tr>}
          </thead>
          <tbody>
            {rows.map((o) => (
              <tr key={o.id} className="rowlink" onClick={() => setEditing(o)}>
                <td className="main-cell">{o.name}{o.website ? <div className="sub mono" style={{ fontSize: 10.5 }}>{o.website}</div> : null}</td>
                <td><CTag c={o.country || 'NZ'} /></td>
                {tab === 'group'
                  ? <td className="num">{memberCount(o)}</td>
                  : <td style={{ fontSize: 12.5 }}>{o.region || <span style={{ color: 'var(--muted)' }}>—</span>}</td>}
                <td style={{ fontSize: 12.5 }}>{(() => { const cs = orgContacts(o); const p = cs[0]; if (!p) return '—'; return (<React.Fragment>{p.name || p.email || '—'}{cs.length > 1 ? <span className="mono" style={{ fontSize: 10, color: 'var(--muted)' }}> +{cs.length - 1} more</span> : null}{p.email ? <div className="sub mono" style={{ fontSize: 10.5 }}>{p.email}</div> : null}</React.Fragment>); })()}</td>
                <td>{(() => { const r = orgContacts(o).filter((c) => c.subscribed && c.email); return r.length ? <Badge v="active">{r.length} reachable</Badge> : <Badge v="prospect">No email</Badge>; })()}</td>
                <td onClick={(e) => e.stopPropagation()}>
                  <button className="btn btn-ghost btn-sm" onClick={() => setEditing(o)}>Open</button>
                </td>
              </tr>
            ))}
            {rows.length === 0 && <tr><td colSpan="6"><window.UI.Empty msg={tab === 'group' ? 'No multi-brand groups yet — add Foley-style groups here' : 'No associations yet — add regional wine associations here'} /></td></tr>}
          </tbody>
        </table>
      </div>

      {editing && <OrgEditor org={editing === 'new' ? null : editing} defaultType={tab} onClose={() => setEditing(null)} />}
    </div>
  );
}

/* ---------- CSV import (associations-import.csv / groups-import.csv format) ---------- */
async function importOrgsCsv(e, store, toast) {
  const file = e.target.files && e.target.files[0];
  e.target.value = '';
  if (!file) return;
  const text = (await file.text()).replace(/^\uFEFF/, '');
  /* parse CSV with quoted-field support */
  const rows = [];
  let row = [], cell = '', inQ = false;
  for (let i = 0; i < text.length; i++) {
    const ch = text[i];
    if (inQ) {
      if (ch === '"') { if (text[i + 1] === '"') { cell += '"'; i++; } else inQ = false; }
      else cell += ch;
    } else if (ch === '"') inQ = true;
    else if (ch === ',') { row.push(cell); cell = ''; }
    else if (ch === '\n' || ch === '\r') { if (cell !== '' || row.length) { row.push(cell); rows.push(row); row = []; cell = ''; } if (ch === '\r' && text[i + 1] === '\n') i++; }
    else cell += ch;
  }
  if (cell !== '' || row.length) { row.push(cell); rows.push(row); }
  if (rows.length < 2) { toast('No data rows found in that CSV'); return; }
  const header = rows[0].map((h) => h.trim());
  const need = ['type', 'name'];
  if (!need.every((n) => header.includes(n))) { toast('CSV must have at least "type" and "name" columns'); return; }
  const idx = (n) => header.indexOf(n);
  const existing = new Set((store.t('orgs') || []).map((o) => (o.name || '').trim().toLowerCase()));
  let added = 0, skipped = 0, bad = 0;
  for (const r of rows.slice(1)) {
    const get = (n) => { const i = idx(n); return i >= 0 ? (r[i] || '').trim() : ''; };
    const name = get('name');
    let type = get('type').toLowerCase();
    if (type.startsWith('assoc')) type = 'association'; else if (type) type = 'group';
    if (!name || !type) { bad++; continue; }
    if (existing.has(name.toLowerCase())) { skipped++; continue; }
    existing.add(name.toLowerCase());
    await store.insert('orgs', {
      type, name,
      country: (get('country') || 'NZ').toUpperCase() === 'AU' ? 'AU' : 'NZ',
      region: type === 'association' ? get('region') : '',
      contactName: get('contactName'), contactEmail: get('contactEmail'),
      phone: get('phone'), website: get('website'), notes: get('notes'),
      subscribed: !/^(false|no|0)$/i.test(get('subscribed') || 'TRUE'),
    });
    added++;
  }
  store.audit('Imported ' + added + ' organisations from CSV', 'org');
  toast('Imported ' + added + (skipped ? ' · ' + skipped + ' duplicates skipped' : '') + (bad ? ' · ' + bad + ' rows missing name/type' : ''));
}

/* ---------- editor drawer ---------- */
function OrgEditor({ org, defaultType, onClose }) {
  const store = window.UI.useStore();
  const { Field, Seg, Ic, toast } = window.UI;
  const isNew = !org;
  const [f, setF] = React.useState(() => {
    const base = org || { type: defaultType || 'group', name: '', country: 'NZ', region: '', website: '', notes: '', subscribed: true };
    return { ...base, contacts: orgContacts(org) };
  });
  const cid = () => 'c' + Math.random().toString(36).slice(2, 9);
  const addContact = () => setF((p) => ({ ...p, contacts: [...(p.contacts || []), { id: cid(), name: '', role: '', email: '', phone: '', subscribed: true }] }));
  const setContact = (id, k, v) => setF((p) => ({ ...p, contacts: (p.contacts || []).map((c) => c.id === id ? { ...c, [k]: v } : c) }));
  const rmContact = (id) => setF((p) => ({ ...p, contacts: (p.contacts || []).filter((c) => c.id !== id) }));
  const [wq, setWq] = React.useState('');
  const set = (k, v) => setF({ ...f, [k]: v });

  const regions = React.useMemo(() => Array.from(new Set(store.t('wineries').map((w) => w.region).filter(Boolean))).sort(), [store]);
  const members = !isNew && f.type === 'group' ? store.t('wineries').filter((w) => w.groupId === org.id) : [];
  const wNeedle = wq.trim().toLowerCase();
  const candidates = wNeedle.length < 2 ? [] : store.t('wineries')
    .filter((w) => !w.groupId && (w.name || '').toLowerCase().includes(wNeedle)).slice(0, 6);

  const save = async () => {
    if (!f.name.trim()) { toast('Give it a name first'); return; }
    const contacts = (f.contacts || [])
      .map((c) => ({ id: c.id || cid(), name: (c.name || '').trim(), role: (c.role || '').trim(), email: (c.email || '').trim(), phone: (c.phone || '').trim(), subscribed: c.subscribed !== false }))
      .filter((c) => c.name || c.email || c.phone);
    const primary = contacts[0] || {};
    const row = {
      ...f, name: f.name.trim(), region: f.type === 'association' ? f.region : '',
      contacts,
      contactName: primary.name || '', contactEmail: primary.email || '', phone: primary.phone || '',
      subscribed: contacts.some((c) => c.subscribed),
    };
    try {
      if (isNew) {
        const r = await store.insert('orgs', row);
        store.audit('Added ' + (f.type === 'group' ? 'group' : 'association') + ' ' + r.name, 'org');
        toast(f.type === 'group' ? 'Group added — reopen it to link wineries' : 'Association added');
      } else {
        await store.update('orgs', org.id, row);
        store.audit('Updated ' + row.name, 'org');
        toast('Saved');
      }
    } catch (err) { toast(err.message || 'Could not save'); return; }
    onClose();
  };
  const remove = async () => {
    if (!confirm('Delete "' + org.name + '"? Linked wineries are kept (just unlinked).')) return;
    try {
      for (const w of store.t('wineries').filter((x) => x.groupId === org.id)) await store.update('wineries', w.id, { groupId: null });
      await store.remove('orgs', org.id);
    } catch (err) { toast(err.message || 'Could not delete'); return; }
    store.audit('Deleted ' + org.name, 'org');
    toast('Deleted'); onClose();
  };
  const link = async (w) => { try { await store.update('wineries', w.id, { groupId: org.id }); } catch (err) { toast(err.message || 'Could not link'); return; } setWq(''); toast(w.name + ' linked'); };
  const unlink = async (w) => { try { await store.update('wineries', w.id, { groupId: null }); } catch (err) { toast(err.message || 'Could not unlink'); return; } toast(w.name + ' unlinked'); };

  return (
    <window.UI.Drawer title={isNew ? ('New ' + (f.type === 'group' ? 'multi-brand group' : 'association')) : f.name}
      sub={f.type === 'group' ? 'Multi-brand group' : 'Industry association'} onClose={onClose}
      foot={<React.Fragment>
        {!isNew && <button className="btn btn-ghost" style={{ color: 'var(--claret)' }} onClick={remove}>Delete</button>}
        <div style={{ flex: 1 }}></div>
        <button className="btn btn-ghost" onClick={onClose}>Cancel</button>
        <button className="btn btn-primary" onClick={save}>{isNew ? 'Add' : 'Save'}</button>
      </React.Fragment>}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        {isNew && (
          <Field label="Type">
            <Seg options={[{ value: 'group', label: 'Multi-brand group' }, { value: 'association', label: 'Association' }]} value={f.type} onChange={(v) => set('type', v)} />
          </Field>
        )}
        <Field label="Name"><input className="input" value={f.name} onChange={(e) => set('name', e.target.value)} placeholder={f.type === 'group' ? 'e.g. Foley Wines NZ' : 'e.g. Wairarapa Winegrowers'} autoFocus={isNew} /></Field>
        <div className="grid-2" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <Field label="Market">
            <Seg mono options={[{ value: 'NZ', label: 'NZ' }, { value: 'AU', label: 'AU' }]} value={f.country || 'NZ'} onChange={(v) => set('country', v)} />
          </Field>
          {f.type === 'association' && (
            <Field label="Linked region">
              <select className="select" value={f.region || ''} onChange={(e) => set('region', e.target.value)}>
                <option value="">— No region —</option>
                {regions.map((r) => <option key={r} value={r}>{r}</option>)}
              </select>
            </Field>
          )}
        </div>
        <Field label="Website"><input className="input" value={f.website || ''} onChange={(e) => set('website', e.target.value)} placeholder="https://…" /></Field>

        <div className="card card-pad" style={{ background: 'var(--card-2)' }}>
          <div style={{ display: 'flex', alignItems: 'center', marginBottom: 10 }}>
            <div className="label" style={{ flex: 1 }}>Contacts · {(f.contacts || []).length}</div>
            <button className="btn btn-ghost btn-sm" onClick={addContact}><Ic name="plus" w={13} /> Add contact</button>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {(f.contacts || []).map((c, i) => (
              <div key={c.id} style={{ border: '1px solid var(--line-soft)', borderRadius: 10, padding: '11px 12px', background: 'var(--card)' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 }}>
                  <span className="mono" style={{ fontSize: 10, color: 'var(--muted)', flex: 1 }}>Contact {i + 1}{i === 0 ? ' · primary' : ''}</span>
                  <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11.5, color: 'var(--muted)', cursor: 'pointer' }} title="Include this contact when emailing this organisation">
                    <input type="checkbox" checked={c.subscribed !== false} onChange={(e) => setContact(c.id, 'subscribed', e.target.checked)} /> Emailable
                  </label>
                  <button className="btn-quiet" title="Remove contact" onClick={() => rmContact(c.id)}><Ic name="x" w={14} /></button>
                </div>
                <div className="grid-2" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
                  <input className="input" placeholder="Name" value={c.name || ''} onChange={(e) => setContact(c.id, 'name', e.target.value)} />
                  <input className="input" placeholder="Role / title" value={c.role || ''} onChange={(e) => setContact(c.id, 'role', e.target.value)} />
                  <input className="input" type="email" placeholder="Email" value={c.email || ''} onChange={(e) => setContact(c.id, 'email', e.target.value)} />
                  <input className="input" placeholder="Phone" value={c.phone || ''} onChange={(e) => setContact(c.id, 'phone', e.target.value)} />
                </div>
              </div>
            ))}
            {(f.contacts || []).length === 0 && <div style={{ fontSize: 12.5, color: 'var(--muted)' }}>No contacts yet — add one so you can email this {f.type === 'group' ? 'group' : 'association'}.</div>}
          </div>
          <div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 10 }}>Each “emailable” contact is reached individually in campaigns that target {f.type === 'group' ? 'groups' : 'associations'}.</div>
        </div>

        <Field label="Notes"><textarea className="input" rows="3" value={f.notes || ''} onChange={(e) => set('notes', e.target.value)}></textarea></Field>

        {!isNew && f.type === 'group' && (
          <div className="card card-pad" style={{ background: 'var(--card-2)' }}>
            <div className="label" style={{ marginBottom: 10 }}>Linked wineries · {members.length}</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginBottom: 10 }}>
              {members.map((w) => (
                <div key={w.id} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '7px 10px', background: 'var(--card)', border: '1px solid var(--line-soft)', borderRadius: 8 }}>
                  <span style={{ flex: 1, fontWeight: 600, fontSize: 13, cursor: 'pointer' }} onClick={() => { onClose(); window.go('wineries', w.id); }}>{w.name}</span>
                  <span className="mono" style={{ fontSize: 10, color: 'var(--muted)' }}>{w.region}</span>
                  <button className="btn-quiet" title="Unlink" onClick={() => unlink(w)}><Ic name="x" w={14} /></button>
                </div>
              ))}
              {members.length === 0 && <div style={{ fontSize: 12.5, color: 'var(--muted)' }}>No wineries linked yet — search below to add the group's brands.</div>}
            </div>
            <input className="input" placeholder="Search wineries to link…" value={wq} onChange={(e) => setWq(e.target.value)} />
            {candidates.length > 0 && (
              <div style={{ marginTop: 6, border: '1px solid var(--line-soft)', borderRadius: 8, overflow: 'hidden' }}>
                {candidates.map((w) => (
                  <button key={w.id} className="btn-quiet" style={{ display: 'flex', width: '100%', justifyContent: 'space-between', padding: '8px 12px', borderBottom: '1px solid var(--line-soft)' }} onClick={() => link(w)}>
                    <span style={{ fontWeight: 600, fontSize: 13 }}>{w.name}</span>
                    <span className="mono" style={{ fontSize: 10, color: 'var(--muted)' }}>{w.region} · link</span>
                  </button>
                ))}
              </div>
            )}
            {wNeedle.length >= 2 && candidates.length === 0 && <div style={{ fontSize: 11.5, color: 'var(--muted)', marginTop: 6 }}>No unlinked wineries match — a winery can only belong to one group.</div>}
          </div>
        )}
        {isNew && f.type === 'group' && <div style={{ fontSize: 12, color: 'var(--muted)' }}>Save the group first, then reopen it to link its wineries.</div>}
      </div>
    </window.UI.Drawer>
  );
}

Object.assign(window, { Orgs, OrgEditor, orgContacts });
