/* ctor-intake-rules.jsx — Tab «Заготовки по анкете»: ответ анкеты сделки (prefs.tech) или чип брифа ДП сам
   приносит в смету этапы каталога + пакеты смежных работ (правило матчится по source, см. lk/calc2-intake-rules.js).
   Данные: ConstructorData.loadIntakeRules/saveIntakeRules (ctor_intake_rules_v1). Каркас и стили — как
   constructor/ctor-packages.jsx (карточки-правила + drawer-редактор), переиспользует его pkPhaseLabel(). */
const { useState: irUseState } = React;

function irNewRule() {
  const id = 'ir_' + Date.now().toString(36);
  return { id, key: id, label: '', source: [], stages: [], packages: [], active: true };
}
function irSlug(s) {
  return (s || '').toLowerCase().trim().replace(/[^a-zа-яё0-9]+/gi, '_').replace(/^_+|_+$/g, '').slice(0, 24) || 'rule';
}
function irRuleErrors(rule) {
  const e = [];
  if (!rule.label || !rule.label.trim()) e.push('Название обязательно');
  if (!rule.source.length) e.push('Нужен хотя бы один источник-ответ');
  if (!rule.stages.length && !rule.packages.length) e.push('Нужен хотя бы один этап или пакет');
  return e;
}

/* toggle-чип: подсвечивается через ui-chips.css .chip--control[data-active] */
function IrChip({ active, onClick, children, title }) {
  return (
    <button type="button" className="chip chip--control" data-active={active ? 'true' : 'false'} onClick={onClick} title={title}>
      {children}
    </button>
  );
}

/* источники-ответы: список читаемых чипов (tech:<key> / brief:<чип>) + добавление свободным текстом */
function IrSourceEditor({ value, onChange }) {
  const [text, setText] = irUseState('');
  const add = () => {
    const v = text.trim();
    if (!v || value.indexOf(v) >= 0) { setText(''); return; }
    onChange([...value, v]);
    setText('');
  };
  const remove = (s) => onChange(value.filter((x) => x !== s));
  return (
    <div>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 8 }}>
        {value.map((s) => (
          <span key={s} className="chip chip--data">
            {s}
            <button type="button" onClick={() => remove(s)} aria-label={'Убрать ' + s}
              style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'inherit', padding: 0, marginLeft: 2, fontSize: 11, lineHeight: 1, opacity: .7 }}>✕</button>
          </span>
        ))}
        {!value.length && <span style={insStyles.hint}>Источников нет — добавьте tech:&lt;ключ&gt; или brief:&lt;чип&gt;</span>}
      </div>
      <div style={{ display: 'flex', gap: 6 }}>
        <input value={text} onChange={(e) => setText(e.target.value)} placeholder="tech:vent или brief:Приточная вентиляция"
          onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); add(); } }}
          style={{ ...insStyles.field, flex: 1 }} />
        <button type="button" className="opt-add-btn" onClick={add}>+ Добавить</button>
      </div>
    </div>
  );
}

/* мультивыбор этапов каталога, сгруппированные по фазам (та же структура, что и якорь шага пакета) */
function IrStagesEditor({ value, onChange, catalog }) {
  const toggle = (id) => onChange(value.indexOf(id) >= 0 ? value.filter((x) => x !== id) : [...value, id]);
  const phasesWithStages = (catalog || []).map((ph, i) => ({ ph, i })).filter((x) => (x.ph.stages || []).length);
  if (!phasesWithStages.length) return <div style={insStyles.hint}>В каталоге нет этапов.</div>;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
      {phasesWithStages.map(({ ph, i }) => (
        <div key={ph.id}>
          <div style={{ ...insStyles.hint, marginBottom: 5, fontWeight: 700 }}>{i} · {pkPhaseLabel(catalog, i)}</div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
            {(ph.stages || []).map((st) => <IrChip key={st.id} active={value.indexOf(st.id) >= 0} onClick={() => toggle(st.id)}>{st.name}</IrChip>)}
          </div>
        </div>
      ))}
    </div>
  );
}

/* мультивыбор пакетов смежных работ (ctor-packages.jsx / loadPackages) */
function IrPackagesEditor({ value, onChange, packages }) {
  const toggle = (id) => onChange(value.indexOf(id) >= 0 ? value.filter((x) => x !== id) : [...value, id]);
  if (!packages.length) return <div style={insStyles.hint}>Пакетов пока нет — создайте во вкладке «Пакеты».</div>;
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
      {packages.map((pkg) => (
        <IrChip key={pkg.id} active={value.indexOf(pkg.id) >= 0} onClick={() => toggle(pkg.id)} title={pkg.desc || ''}>
          <span aria-hidden="true">{pkg.icon}</span> {pkg.name || 'Без названия'}
        </IrChip>
      ))}
    </div>
  );
}

/* drawer редактора правила */
function IntakeRuleDrawer({ rule, catalog, packages, onSave, onClose }) {
  const [draft, setDraft] = irUseState(rule ? JSON.parse(JSON.stringify(rule)) : irNewRule());
  const p = (k, v) => setDraft((d) => ({ ...d, [k]: v }));
  const errors = irRuleErrors(draft);
  return (
    <InspectorDrawer title={rule ? 'Редактировать правило' : 'Новое правило'} onClose={onClose} width={620}
      footer={
        <React.Fragment>
          <button type="button" onClick={onClose} style={ctorStyles.btnGhost}>Отмена</button>
          <button type="button" onClick={() => { onSave({ ...draft, key: draft.key || irSlug(draft.label) }); onClose(); }} disabled={errors.length > 0}
            style={{ ...ctorStyles.btnPrimary, opacity: errors.length > 0 ? 0.45 : 1 }}>Сохранить</button>
        </React.Fragment>
      }>
      <InspectorSection title="Правило">
        <FText label="Название" value={draft.label} onChange={(v) => p('label', v)} placeholder="Приточная вентиляция" />
        <FToggle label="Активно" value={draft.active !== false} onChange={(v) => p('active', v)} hint="Неактивное правило не применяется в мастере сметы" />
      </InspectorSection>
      <InspectorSection title="Источники" lead="Ответ анкеты сделки (tech:<ключ> из prefs.tech) или чип брифа ДП (brief:<текст чипа>)">
        <IrSourceEditor value={draft.source} onChange={(v) => p('source', v)} />
      </InspectorSection>
      <InspectorSection title={'Этапы каталога · ' + draft.stages.length} lead="Что включится в смету, когда правило сработает">
        <IrStagesEditor value={draft.stages} onChange={(v) => p('stages', v)} catalog={catalog} />
      </InspectorSection>
      <InspectorSection title={'Пакеты смежных работ · ' + draft.packages.length}>
        <IrPackagesEditor value={draft.packages} onChange={(v) => p('packages', v)} packages={packages} />
      </InspectorSection>
      {errors.length > 0 && <div style={{ color: 'var(--destructive)', fontSize: 12.5 }}>{errors.join(' · ')}</div>}
    </InspectorDrawer>
  );
}

/* панель вкладки */
function IntakeRulesPanel({ rules, setRules, catalog, packages, focusId }) {
  const [editing, setEditing] = irUseState(null); // null | 'new' | rule
  const [flashId, setFlashId] = irUseState(null); // подсветка карточки, найденной глобальным поиском
  React.useEffect(() => {
    if (!focusId) return;
    const el = document.getElementById('ir-card-' + focusId);
    if (el) el.scrollIntoView({ behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth', block: 'center' });
    setFlashId(focusId);
    const t = setTimeout(() => setFlashId(null), 1800);
    return () => clearTimeout(t);
  }, [focusId]);
  const save = (rule) => setRules((list) => (list.some((x) => x.id === rule.id) ? list.map((x) => (x.id === rule.id ? rule : x)) : [...list, rule]));
  const toggleActive = (id) => setRules((list) => list.map((x) => (x.id === id ? { ...x, active: !(x.active !== false) } : x)));
  const del = (id) => {
    if (!confirm('Удалить правило? Уже применённые этапы и пакеты в собранных сметах останутся.')) return;
    setRules((list) => list.filter((x) => x.id !== id));
  };
  return (
    <div className="opt-panel">
      <header className="opt-toolbar">
        <div>
          <h2 className="opt-heading">Заготовки по анкете</h2>
          <p className="opt-lead">Ответ анкеты сделки (техника) или чип брифа ДП сам приносит в смету нужные этапы и пакеты смежных работ.</p>
        </div>
        <button type="button" className="opt-add-btn" onClick={() => setEditing('new')}>+ Новое правило</button>
      </header>
      {!rules.length && <div className="pkg-empty">Правил нет — создайте первое: ответ анкеты → этапы и пакеты.</div>}
      <div className="pkg-grid">
        {rules.map((rule) => {
          const errs = irRuleErrors(rule);
          return (
            <div key={rule.id} id={'ir-card-' + rule.id} className={'pkg-card' + (rule.active === false ? ' is-off' : '')}
              style={flashId === rule.id ? { boxShadow: '0 0 0 3px var(--primary)', borderRadius: 14 } : undefined}>
              <div className="pkg-card-ic" style={{ background: 'var(--secondary)' }}>🧭</div>
              <div className="pkg-card-body">
                <div className="pkg-card-name">{rule.label || 'Без названия'}</div>
                <div className="pkg-card-desc">{(rule.source || []).join(' · ') || '— источников нет —'}</div>
                <div className="pkg-card-meta">
                  <span>{(rule.stages || []).length} этап.</span>
                  <span>{(rule.packages || []).length} пак.</span>
                  {errs.length > 0 && <span className="pkg-err-badge" title={errs.join(' · ')}>⚠ {errs.length}</span>}
                </div>
              </div>
              <div className="pkg-card-tools">
                <OToggle value={rule.active !== false} onChange={() => toggleActive(rule.id)} />
                <button type="button" onClick={() => setEditing(rule)} title="Редактировать">✎</button>
                <button type="button" className="danger" onClick={() => del(rule.id)} title="Удалить">✕</button>
              </div>
            </div>
          );
        })}
      </div>
      {editing && (
        <IntakeRuleDrawer rule={editing === 'new' ? null : editing} catalog={catalog} packages={packages}
          onSave={save} onClose={() => setEditing(null)} />
      )}
    </div>
  );
}
window.IntakeRulesPanel = IntakeRulesPanel;
