/* global React, Icon, DirChip, Money, Dropdown, Card, Button */
// Schools.ArtemenkoCRM — Заявки с сайта (lead funnel top), redesigned from the real product

const UNIT_LABEL = { зан: '/зан', мес: '/мес', курс: '/курс', разово: '' };

function channelMeta(ch) {
  const all = (window.CRM_DATA && window.CRM_DATA.CONTACT_TYPES) || [];
  return all.find(t => t.value === ch) || { label: 'Контакт', icon: 'at-sign', mono: false };
}

// ---- CSV helpers ----
function leadsToCSV(leads) {
  const head = ['id', 'name', 'contacts', 'goal', 'subject', 'price', 'priceUnit', 'manager', 'date', 'converted'];
  const esc = (v) => {
    const s = v == null ? '' : String(v);
    return /[",\n;]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s;
  };
  const serialiseContacts = (l) => {
    const list = (l.contacts && l.contacts.length) ? l.contacts : (l.contact && l.contact !== '—' ? [{ type: l.channel, value: l.contact }] : []);
    return list.map(c => `${c.type}:${c.value}`).join(' | ');
  };
  const lines = [head.join(',')];
  leads.forEach(l => {
    lines.push([l.id, l.name, serialiseContacts(l), l.goal, ((l.subjects && l.subjects.length) ? l.subjects.join(' | ') : (l.subject || '')), l.price, l.priceUnit, l.manager, l.date, l.converted ? '1' : '0'].map(esc).join(','));
  });
  return lines.join('\n');
}

function parseCSV(text) {
  // minimal CSV parser supporting quoted fields
  const rows = []; let row = []; let cur = ''; let q = false;
  for (let i = 0; i < text.length; i++) {
    const ch = text[i];
    if (q) {
      if (ch === '"' && text[i + 1] === '"') { cur += '"'; i++; }
      else if (ch === '"') q = false;
      else cur += ch;
    } else {
      if (ch === '"') q = true;
      else if (ch === ',') { row.push(cur); cur = ''; }
      else if (ch === '\n' || ch === '\r') { if (cur !== '' || row.length) { row.push(cur); rows.push(row); row = []; cur = ''; } if (ch === '\r' && text[i + 1] === '\n') i++; }
      else cur += ch;
    }
  }
  if (cur !== '' || row.length) { row.push(cur); rows.push(row); }
  return rows;
}

function csvToLeads(text) {
  const rows = parseCSV(text).filter(r => r.length > 1);
  if (!rows.length) return [];
  const head = rows[0].map(h => h.trim().toLowerCase());
  const idx = (k) => head.indexOf(k);
  return rows.slice(1).map((r, n) => {
    const contactsRaw = r[idx('contacts')] || '';
    const contacts = contactsRaw.split('|').map(s => s.trim()).filter(Boolean).map(pair => {
      const k = pair.indexOf(':'); return k === -1 ? { type: 'phone', value: pair } : { type: pair.slice(0, k).trim(), value: pair.slice(k + 1).trim() };
    });
    const first = contacts[0] || { type: 'phone', value: '—' };
    const priceRaw = r[idx('price')];
    return {
      id: parseInt(r[idx('id')], 10) || (Date.now() % 100000) + n,
      name: r[idx('name')] || 'Без имени', contacts, channel: first.type, contact: first.value,
      goal: r[idx('goal')] || '—', subject: r[idx('subject')] || null,
      price: priceRaw ? parseInt(priceRaw, 10) : null, priceUnit: r[idx('priceunit')] || null,
      manager: r[idx('manager')] || null, date: r[idx('date')] || 'импорт',
      converted: ['1', 'true', 'да'].includes((r[idx('converted')] || '').trim().toLowerCase()),
    };
  });
}

function Leads({ onAddLead, onEditLead, onConvert, onDelete, onBulkDelete, onImport, onExport }) {
  const { LEADS, MANAGERS } = window.CRM_DATA;
  const [tab, setTab] = React.useState('open');     // open | converted
  const [qInput, setQInput] = React.useState('');
  const [q, setQ] = React.useState('');
  const [subject, setSubject] = React.useState(null);
  const [manager, setManager] = React.useState(null);
  const [range, setRange] = React.useState(null);   // {start, end} ISO
  const [calOpen, setCalOpen] = React.useState(false);
  const [selected, setSelected] = React.useState([]);
  const fileRef = React.useRef(null);
  const calRef = React.useRef(null);
  const [, force] = React.useReducer(x => x + 1, 0);

  // «Дорогой» поиск: обновляем список с небольшой задержкой после ввода.
  React.useEffect(() => { const t = setTimeout(() => setQ(qInput), 280); return () => clearTimeout(t); }, [qInput]);
  React.useEffect(() => {
    if (!calOpen) return;
    const h = (e) => { if (calRef.current && !calRef.current.contains(e.target)) setCalOpen(false); };
    document.addEventListener('mousedown', h); return () => document.removeEventListener('mousedown', h);
  }, [calOpen]);

  // Parse the mock Russian dates into a comparable yyyy-mm-dd (year 2026).
  const MON_ABBR = { 'янв': 0, 'фев': 1, 'мар': 2, 'апр': 3, 'мая': 4, 'май': 4, 'июн': 5, 'июл': 6, 'авг': 7, 'сен': 8, 'окт': 9, 'ноя': 10, 'дек': 11 };
  const parseLeadDate = (s) => {
    if (!s) return null;
    const low = s.toLowerCase();
    const iso = (y, m, d) => `${y}-${String(m + 1).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
    if (low.includes('сегодня')) return iso(2026, 4, 31);
    if (low.includes('вчера')) return iso(2026, 4, 30);
    const m = low.match(/(\d{1,2})\s+([а-я]+)/);
    if (m && MON_ABBR[m[2].slice(0, 3)] != null) return iso(2026, MON_ABBR[m[2].slice(0, 3)], parseInt(m[1], 10));
    return null;
  };

  const managerOpts = [{ value: null, label: 'Все менеджеры' }, { value: '__none', label: 'Без менеджера' }]
    .concat(MANAGERS.map(m => ({ value: m, label: m })));
  const subjectOpts = [{ value: null, label: 'Все предметы' }]
    .concat((window.CRM_DATA.DIRECTIONS).map(s => ({ value: s, label: s })));

  const rows = LEADS.filter(l => {
    if (tab === 'open' ? l.converted : !l.converted) return false;
    if (q && !(`${l.name} ${l.contact} ${l.goal}`.toLowerCase().includes(q.toLowerCase()))) return false;
    if (subject && !((l.subjects && l.subjects.length ? l.subjects : (l.subject ? [l.subject] : [])).includes(subject))) return false;
    if (manager === '__none' && l.manager) return false;
    if (manager && manager !== '__none' && l.manager !== manager) return false;
    if (range) { const d = parseLeadDate(l.date); if (d && (d < range.start || d > range.end)) return false; }
    return true;
  });

  const fmtRange = (r) => { const f = (s) => { const [y, m, d] = s.split('-'); const MN = ['янв','фев','мар','апр','мая','июн','июл','авг','сен','окт','ноя','дек']; return `${+d} ${MN[+m - 1]}`; }; return f(r.start) + ' – ' + f(r.end); };

  // selection is scoped to the current tab; clear it when tab changes
  React.useEffect(() => { setSelected([]); }, [tab]);
  const visibleIds = rows.map(r => r.id);
  const allSelected = visibleIds.length > 0 && visibleIds.every(id => selected.includes(id));
  const someSelected = selected.length > 0;
  const toggleOne = (id) => setSelected(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);
  const toggleAll = () => setSelected(allSelected ? [] : visibleIds);

  const assignManager = (lead, v) => { lead.manager = v === '__none' ? null : v; force(); };

  const handleExport = () => onExport(rows, tab);
  const handleFile = (e) => { const f = e.target.files && e.target.files[0]; if (f) onImport(f); e.target.value = ''; };

  const th = { textAlign: 'left', fontSize: 11.5, fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: 'var(--text-dim)', padding: '0 18px 13px', whiteSpace: 'nowrap' };
  const td = { padding: '12px 18px', borderTop: '1px solid var(--border)', fontSize: 14, color: 'var(--text)', verticalAlign: 'middle' };
  const dim = { color: 'var(--text-dim)' };
  const cbCol = { width: 40, padding: '0 8px 13px 18px' };
  const cbTd = { padding: '12px 8px 12px 18px', borderTop: '1px solid var(--border)', verticalAlign: 'middle' };

  const Checkbox = ({ checked, onChange, indeterminate }) => (
    <span onClick={(e) => { e.stopPropagation(); onChange(); }}
      onMouseEnter={e => { if (!(checked || indeterminate)) e.currentTarget.style.borderColor = 'var(--brand)'; e.currentTarget.style.boxShadow = '0 0 0 3px var(--brand-soft)'; }}
      onMouseLeave={e => { if (!(checked || indeterminate)) e.currentTarget.style.borderColor = 'var(--border-strong)'; e.currentTarget.style.boxShadow = 'none'; }}
      style={{
      width: 18, height: 18, borderRadius: 4, cursor: 'pointer', flex: 'none', display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      border: '1.5px solid ' + (checked || indeterminate ? 'var(--brand)' : 'var(--border-strong)'),
      background: checked || indeterminate ? 'var(--brand)' : 'var(--bg-card)', color: '#fff',
      transition: 'background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease)',
    }}>
      {checked && <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3.2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12l5 5L20 6"/></svg>}
      {!checked && indeterminate && <span style={{ width: 9, height: 2, background: '#fff', borderRadius: 1 }} />}
    </span>
  );

  return (
    <div style={{ padding: '24px 32px 40px' }}>
      {/* Tabs + toolbar */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 18, flexWrap: 'wrap' }}>
        <div style={{ display: 'inline-flex', background: 'var(--bg-soft)', borderRadius: 'var(--radius-sm)', padding: 3, gap: 2 }}>
          {[{ id: 'open', label: 'Новые' }, { id: 'converted', label: 'Конвертированные' }].map(t => (
            <button key={t.id} onClick={() => setTab(t.id)}
              onMouseEnter={e => { if (tab !== t.id) { e.currentTarget.style.background = 'var(--bg-card)'; e.currentTarget.style.color = 'var(--text-secondary)'; } }}
              onMouseLeave={e => { if (tab !== t.id) { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = 'var(--text-dim)'; } }}
              style={{
              padding: '6px 16px', border: 'none', borderRadius: 5, cursor: 'pointer',
              fontFamily: 'var(--font-sans)', fontSize: 13.5, fontWeight: 600,
              background: tab === t.id ? 'var(--bg-card)' : 'transparent',
              color: tab === t.id ? 'var(--brand-ink)' : 'var(--text-dim)',
              boxShadow: tab === t.id ? 'var(--shadow-xs)' : 'none',
              transition: 'background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease)',
            }}>{t.label}</button>
          ))}
        </div>
        <span style={{ fontSize: 13, color: 'var(--text-dim)' }}>{rows.length} заявок</span>
        <div style={{ flex: 1 }} />
        <Button variant="secondary" icon="download" onClick={handleExport}>Выгрузить базу</Button>
        <Button variant="secondary" icon="upload" onClick={() => fileRef.current && fileRef.current.click()}>Загрузить базу</Button>
        <input ref={fileRef} type="file" accept=".csv,text/csv" onChange={handleFile} style={{ display: 'none' }} />
        <Button icon="add-student" onClick={onAddLead}>Добавить заявку</Button>
      </div>

      {/* Filters */}
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10, marginBottom: 18 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, background: 'var(--bg-card)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)', padding: '8px 12px', width: 220 }}>
          <Icon name="search" size={16} style={{ color: 'var(--text-dim)' }} />
          <input value={qInput} onChange={e => setQInput(e.target.value)} placeholder="Поиск по заявкам…" style={{ border: 'none', outline: 'none', background: 'transparent', flex: 1, fontFamily: 'var(--font-sans)', fontSize: 13.5, color: 'var(--text)' }} />
        </div>
        <Dropdown value={subject} onChange={setSubject} options={subjectOpts} placeholder="Все предметы" width={170} searchable />
        <Dropdown value={manager} onChange={setManager} options={managerOpts} placeholder="Все менеджеры" width={190} searchable />
        <div ref={calRef} style={{ position: 'relative' }}>
          <button onClick={() => setCalOpen(o => !o)}
            onMouseEnter={e => { if (!calOpen && !range) e.currentTarget.style.borderColor = 'var(--border-strong)'; }}
            onMouseLeave={e => { if (!calOpen && !range) e.currentTarget.style.borderColor = 'var(--border)'; }}
            style={{ display: 'inline-flex', alignItems: 'center', gap: 8, padding: '8px 12px', cursor: 'pointer', background: 'var(--bg-card)', border: '1px solid ' + (calOpen || range ? 'var(--brand)' : 'var(--border)'), borderRadius: 'var(--radius-sm)', boxShadow: calOpen ? 'var(--shadow-focus)' : 'none', fontFamily: 'var(--font-sans)', fontSize: 13.5, fontWeight: 500, color: range ? 'var(--text)' : 'var(--text-secondary)', transition: 'border-color var(--dur-fast) var(--ease)', whiteSpace: 'nowrap' }}>
            <Icon name="calendar" size={15} style={{ color: 'var(--text-dim)' }} />{range ? fmtRange(range) : 'Период'}
            {range && <span onClick={(e) => { e.stopPropagation(); setRange(null); }} title="Сбросить" style={{ display: 'inline-flex', color: 'var(--text-dim)', marginLeft: 2 }}><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M9.2 9.2l5.6 5.6M14.8 9.2l-5.6 5.6"/></svg></span>}
          </button>
          {calOpen && <RangeCalendar value={range} onApply={setRange} onClose={() => setCalOpen(false)} />}
        </div>
      </div>

      {/* Bulk action bar */}
      {someSelected && (
        <div className="om-fade-in" style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 14, padding: '10px 16px', background: 'var(--brand-soft)', border: '1px solid #CBD9F0', borderRadius: 'var(--radius-md)' }}>
          <span style={{ fontSize: 13.5, fontWeight: 600, color: 'var(--brand-ink)' }}>Выбрано: {selected.length}</span>
          <div style={{ flex: 1 }} />
          <button onClick={() => setSelected([])}
            onMouseEnter={e => { e.currentTarget.style.background = 'var(--bg-card)'; e.currentTarget.style.color = 'var(--text)'; }}
            onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = 'var(--text-secondary)'; }}
            style={{ border: 'none', background: 'transparent', cursor: 'pointer', color: 'var(--text-secondary)', fontSize: 13, fontWeight: 600, fontFamily: 'var(--font-sans)', padding: '6px 10px', borderRadius: 'var(--radius-sm)', transition: 'background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease)' }}>Снять выделение</button>
          <Button variant="danger" icon="close-tile" onClick={() => onBulkDelete(selected.map(id => LEADS.find(l => l.id === id)).filter(Boolean), tab, () => setSelected([]))}>Удалить выбранные</Button>
        </div>
      )}

      {/* Table */}
      <Card pad={0} style={{ overflow: 'hidden' }}>
        {rows.length > 0 ? (
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', minWidth: 1120 }}>
            <thead><tr>
              <th style={{ ...cbCol, paddingTop: 16 }}><Checkbox checked={allSelected} indeterminate={someSelected && !allSelected} onChange={toggleAll} /></th>
              <th style={{ ...th, paddingTop: 16, width: 44 }}>#</th>
              <th style={{ ...th, paddingTop: 16 }}>Имя</th>
              <th style={{ ...th, paddingTop: 16 }}>Контакт</th>
              <th style={{ ...th, paddingTop: 16 }}>Заметка</th>
              <th style={{ ...th, paddingTop: 16 }}>Предмет</th>
              <th style={{ ...th, paddingTop: 16, textAlign: 'right' }}>Цена</th>
              <th style={{ ...th, paddingTop: 16 }}>Менеджер</th>
              <th style={{ ...th, paddingTop: 16 }}>Дата</th>
              <th style={{ ...th, paddingTop: 16, textAlign: 'right' }}>Действия</th>
            </tr></thead>
            <tbody key={`${tab}|${q}|${subject}|${manager}`}>
              {rows.map((l, ri) => {
                const list = (l.contacts && l.contacts.length) ? l.contacts : (l.contact && l.contact !== '—' ? [{ type: l.channel, value: l.contact }] : []);
                const primaryC = list[0] || { type: l.channel || 'phone', value: '—' };
                const cm = channelMeta(primaryC.type);
                const primary = primaryC.value;
                const extra = Math.max(0, list.length - 1);
                const checked = selected.includes(l.id);
                return (
                <tr key={l.id} className="row-hover om-row-in" style={{ cursor: 'pointer', animationDelay: Math.min(ri * 25, 300) + 'ms', background: checked ? 'var(--bg-soft)' : undefined }} onClick={() => { if (someSelected) toggleOne(l.id); else onEditLead(l); }}>
                  <td style={cbTd} onClick={e => e.stopPropagation()}><Checkbox checked={checked} onChange={() => toggleOne(l.id)} /></td>
                  <td style={{ ...td, ...dim, fontFamily: 'var(--font-mono)', fontSize: 12.5 }}>{l.id}</td>
                  <td style={{ ...td, fontWeight: 600 }}>{l.name}</td>
                  <td style={td}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                      <span style={{ width: 24, height: 24, borderRadius: 6, background: 'var(--bg-soft)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', color: 'var(--text-dim)', flex: 'none' }} title={cm.label}>
                        <Icon name={cm.icon} size={13} />
                      </span>
                      <span style={{ fontFamily: cm.mono ? 'var(--font-mono)' : 'var(--font-sans)', fontSize: cm.mono ? 13 : 14, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 150 }}>{primary}</span>
                      {extra > 0 && <span style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--text-dim)', background: 'var(--bg-soft)', borderRadius: 'var(--radius-pill)', padding: '1px 7px', flex: 'none' }} title={`Ещё ${extra}`}>+{extra}</span>}
                    </div>
                  </td>
                  <td style={{ ...td, ...(l.goal && l.goal !== '—' ? { color: 'var(--text-secondary)' } : dim), fontSize: 13.5, maxWidth: 170, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={l.goal}>{l.goal || '—'}</td>
                  <td style={td}>{(() => { const subs = (l.subjects && l.subjects.length) ? l.subjects : (l.subject ? [l.subject] : []); return subs.length ? <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>{subs.map(s => <DirChip key={s}>{s}</DirChip>)}</div> : <DirChip>{null}</DirChip>; })()}</td>
                  <td style={{ ...td, textAlign: 'right', whiteSpace: 'nowrap' }}>
                    {l.price != null
                      ? <span><Money value={l.price} style={{ fontSize: 14 }} /><span style={{ fontSize: 12, color: 'var(--text-dim)', marginLeft: 2 }}>/зан</span></span>
                      : <span style={dim}>—</span>}
                  </td>
                  <td style={td} onClick={e => e.stopPropagation()}>
                    <Dropdown value={l.manager || '__none'} onChange={v => assignManager(l, v)} searchable
                      options={[{ value: '__none', label: '— назначить —' }].concat(MANAGERS.map(m => ({ value: m, label: m })))} width={168} />
                  </td>
                  <td style={{ ...td, ...dim, fontSize: 13, whiteSpace: 'nowrap' }}>{l.date}</td>
                  <td style={td} onClick={e => e.stopPropagation()}>
                    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: 6 }}>
                      {l.converted
                        ? <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '4px 9px', borderRadius: 'var(--radius-pill)', fontSize: 12, fontWeight: 600, background: 'var(--green-bg)', color: 'var(--green-ink)', whiteSpace: 'nowrap' }}><Icon name="check" size={12} strokeWidth={2.5} />Конвертирован</span>
                        : <button onClick={() => onConvert(l)}
                          onMouseEnter={e => { e.currentTarget.style.background = 'var(--brand)'; e.currentTarget.style.color = '#fff'; }}
                          onMouseLeave={e => { e.currentTarget.style.background = 'var(--brand-soft)'; e.currentTarget.style.color = 'var(--brand-ink)'; }}
                          style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '6px 11px', borderRadius: 'var(--radius-sm)', border: '1px solid var(--brand)', background: 'var(--brand-soft)', color: 'var(--brand-ink)', fontFamily: 'var(--font-sans)', fontSize: 12.5, fontWeight: 600, cursor: 'pointer', whiteSpace: 'nowrap', transition: 'background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease)' }}><Icon name="user-plus" size={13} />В клиента</button>}
                      <button onClick={() => onDelete(l)} title="Удалить заявку" style={{ border: 'none', background: 'none', cursor: 'pointer', color: 'var(--text-dim)', display: 'inline-flex', padding: 5, borderRadius: 6 }}
                        onMouseEnter={e => { e.currentTarget.style.color = 'var(--coral)'; e.currentTarget.style.background = 'var(--coral-bg)'; }}
                        onMouseLeave={e => { e.currentTarget.style.color = 'var(--text-dim)'; e.currentTarget.style.background = 'none'; }}>
                        <Icon name="close-tile" size={17} />
                      </button>
                    </div>
                  </td>
                </tr>
                );
              })}
            </tbody>
          </table>
        </div>
        ) : (
          <div style={{ padding: '48px 24px', textAlign: 'center', color: 'var(--text-dim)', fontSize: 14 }}>
            {tab === 'converted' ? 'Конвертированных заявок пока нет' : 'Новых заявок нет — всё разобрано'}
          </div>
        )}
      </Card>
    </div>
  );
}

Object.assign(window, { Leads, leadsToCSV, csvToLeads });
