/* ctor-presets.jsx — пресеты калькулятора: список + drawer-редактор + tree picker */
const { useState: prUseState } = React;
const prUid = window.ConstructorData.uid;
const prCD = window.ConstructorData;

const VIS_META = {
  public:   { label: 'public',   color: '#5aad6e', bg: '#f0fdf4', where: 'Сайт + менеджер' },
  internal: { label: 'internal', color: '#e8793a', bg: '#fff0e6', where: 'Только менеджер/прораб в проекте' },
  hidden:   { label: 'hidden',   color: '#8a817a', bg: '#f0ece5', where: 'Только super (эксперименты)' },
};
const SCOPE_L = { capital: 'Капитальный', cosmetic: 'Косметический' };
const GRADE_L = { economy: 'Эконом', standard: 'Стандарт', business: 'Бизнес', premium: 'Премиум' };
const FLAG_L = {
  hasReplanning: 'Перепланировка', hasHVAC: 'Вентиляция/кондиц.', hasWarmFloor: 'Тёплый пол',
  hasSoundproof: 'Звукоизоляция', hasWindows: 'Окна', engineering: 'Инженерия', soundproofing: 'Шумоизоляция',
};
const ALL_FLAGS = ['hasReplanning', 'hasHVAC', 'hasWarmFloor', 'hasSoundproof', 'hasWindows'];

function VisChip({ v }) {
  const m = VIS_META[v] || VIS_META.internal;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '3px 10px', borderRadius: 980, background: m.bg, color: m.color, fontSize: 11.5, fontWeight: 600 }}>
      <span style={{ width: 6, height: 6, borderRadius: '50%', background: m.color }}></span>{m.label}
    </span>
  );
}
function AxisChip({ children }) {
  return <span style={{ fontSize: 11.5, fontWeight: 500, color: '#6b6259', background: '#f0ece5', padding: '3px 9px', borderRadius: 980, whiteSpace: 'nowrap' }}>{children}</span>;
}

function PresetsPanel({ presets, setPresets, catalog }) {
  const [editId, setEditId] = prUseState(null);
  const editing = presets.find((p) => p.id === editId) || null;

  const update = (id, patch) => setPresets((ps) => ps.map((p) => (p.id === id ? { ...p, ...patch } : p)));
  const add = () => {
    const p = {
      id: prUid('preset'), slug: 'new-preset', name: 'Новый пресет', desc: '',
      visibility: 'internal', sortOrder: presets.length + 1, scope: 'capital', grade: 'standard',
      hasDesignProcess: false, requiresDesignPhase: false, durationMul: 1.0, defaultFlags: [], excludeSlugs: [],
      catalogRoot: null, includePhaseIds: null,
    };
    setPresets((ps) => [...ps, p]);
    setEditId(p.id);
  };
  const remove = (id) => { if (confirm('Удалить пресет?')) { setPresets((ps) => ps.filter((p) => p.id !== id)); if (editId === id) setEditId(null); } };
  const duplicate = (id) => {
    const src = presets.find((p) => p.id === id); if (!src) return;
    const clone = prCD.clone(src); clone.id = prUid('preset'); clone.name = src.name + ' (копия)'; clone.slug = src.slug + '-copy'; clone.visibility = 'hidden';
    setPresets((ps) => [...ps, clone]);
  };

  if (!presets.length) {
    return <EmptyState icon="layers" title="Нет пресетов"
      text="Пресеты собирают поддерево каталога в готовый «тип ремонта» для калькулятора. Создайте первый."
      action={<button onClick={add} style={ctorStyles.btnPrimary}>{Icon.plus} Создать пресет</button>} />;
  }

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 18, gap: 16, flexWrap: 'wrap' }}>
        <div>
          <div style={ctorStyles.sectionLabel}>Пресеты калькулятора</div>
          <div style={{ fontSize: 14, color: '#8a817a', marginTop: 6, maxWidth: 620 }}>
            Каждый пресет — это «тип ремонта»: видимость, оси калькулятора и привязка к поддереву каталога. Менеджер не меняет оси — только Super.
          </div>
        </div>
        <button onClick={add} style={ctorStyles.btnPrimary}>{Icon.plus} Пресет</button>
      </div>

      {/* визуальная легенда visibility */}
      <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', marginBottom: 16, padding: '12px 16px', background: '#fff', borderRadius: 12, border: '.5px solid #ece5da' }}>
        {Object.keys(VIS_META).map((k) => (
          <span key={k} style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
            <VisChip v={k} /><span style={{ fontSize: 12.5, color: '#8a817a' }}>{VIS_META[k].where}</span>
          </span>
        ))}
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {presets.slice().sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0)).map((p) => {
          const nodes = prCD.presetNodeCount(p, catalog);
          return (
            <div key={p.id} style={{ ...ctorStyles.card, padding: '16px 20px', display: 'flex', alignItems: 'center', gap: 16, cursor: 'pointer' }}
              onClick={() => setEditId(p.id)}>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
                  <span style={{ fontSize: 16, fontWeight: 600, letterSpacing: '-.015em', color: '#1a1714' }}>{p.name}</span>
                  <VisChip v={p.visibility} />
                  {p.requiresDesignPhase && <span title="Требует фазу дизайна" style={{ fontSize: 11, fontWeight: 600, color: '#7c3aed', background: '#f3eafe', padding: '2px 9px', borderRadius: 980 }}>дизайн-фаза</span>}
                </div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 7, marginTop: 9, flexWrap: 'wrap' }}>
                  <AxisChip>{SCOPE_L[p.scope] || p.scope}</AxisChip>
                  <AxisChip>{GRADE_L[p.grade] || p.grade}</AxisChip>
                  {p.hasDesignProcess && <AxisChip>дизайн-процесс</AxisChip>}
                  <span style={{ fontSize: 12, color: '#bcb3a7' }}>·</span>
                  <span style={{ fontSize: 12.5, color: '#8a817a', fontVariantNumeric: 'tabular-nums' }}>{nodes} узлов из каталога</span>
                </div>
              </div>
              <span style={{ fontSize: 15, fontWeight: 600, color: '#1a1714', fontVariantNumeric: 'tabular-nums', whiteSpace: 'nowrap' }}>×{(+p.durationMul || 1).toFixed(2)}</span>
              <KebabMenu items={[
                { icon: pencilIcon, label: 'Редактировать', onClick: () => setEditId(p.id) },
                { icon: Icon.copy, label: 'Дублировать', onClick: () => duplicate(p.id) },
                { icon: Icon.trash, label: 'Удалить', onClick: () => remove(p.id), danger: true },
              ]} />
            </div>
          );
        })}
      </div>

      {editing && (
        <PresetDrawer preset={editing} catalog={catalog} onChange={(patch) => update(editing.id, patch)} onClose={() => setEditId(null)} />
      )}
    </div>
  );
}

/* ---------- Drawer редактора ---------- */
function PresetDrawer({ preset, catalog, onChange, onClose }) {
  const p = preset;
  const excludeSet = new Set(p.excludeSlugs || []);
  const includePhases = p.includePhaseIds; // null = все
  const nodes = prCD.presetNodeCount(p, catalog);

  const togglePhase = (phId) => {
    let inc = includePhases ? [...includePhases] : catalog.map((x) => x.id);
    if (inc.includes(phId)) inc = inc.filter((x) => x !== phId); else inc.push(phId);
    onChange({ includePhaseIds: inc.length === catalog.length ? null : inc });
  };
  const toggleStage = (slug) => {
    const ex = new Set(p.excludeSlugs || []);
    if (ex.has(slug)) ex.delete(slug); else ex.add(slug);
    onChange({ excludeSlugs: [...ex] });
  };
  const toggleFlag = (f) => {
    const cur = new Set(p.defaultFlags || []);
    if (cur.has(f)) cur.delete(f); else cur.add(f);
    onChange({ defaultFlags: [...cur] });
  };
  const phaseIncluded = (phId) => !includePhases || includePhases.includes(phId);

  return (
    <InspectorDrawer
      title="Редактор пресета"
      badges={<VisChip v={p.visibility} />}
      onClose={onClose}
      width={560}
    >
      <InspectorSection title="Идентификация">
        <FText label="Название" value={p.name} onChange={(v) => onChange({ name: v })} />
        <InspectorFieldGrid cols={2}>
          <FText label="Slug" value={p.slug} onChange={(v) => onChange({ slug: v })} mono />
          <FNum label="Порядок" value={p.sortOrder} onChange={(v) => onChange({ sortOrder: v })} />
        </InspectorFieldGrid>
        <FText label="Описание" value={p.desc} onChange={(v) => onChange({ desc: v })} multiline placeholder="Что это за тип ремонта" />
        <FSeg label="Видимость" value={p.visibility} onChange={(v) => onChange({ visibility: v })}
          options={[{ v: 'public', l: 'public', color: '#5aad6e' }, { v: 'internal', l: 'internal', color: '#e8793a' }, { v: 'hidden', l: 'hidden' }]} />
        <div style={insStyles.hint}>{VIS_META[p.visibility].where}</div>
      </InspectorSection>

      <InspectorSection title="Оси калькулятора" lead="Только super-admin">
        <FSeg label="Объём (scope)" value={p.scope} onChange={(v) => onChange({ scope: v })}
          options={[{ v: 'capital', l: 'Капитальный' }, { v: 'cosmetic', l: 'Косметический' }]} />
        <FSeg label="Класс (grade)" value={p.grade} onChange={(v) => onChange({ grade: v })}
          options={[{ v: 'economy', l: 'Эконом' }, { v: 'standard', l: 'Стандарт' }, { v: 'business', l: 'Бизнес' }, { v: 'premium', l: 'Премиум' }]} />
        <FToggle label="hasDesignProcess" value={p.hasDesignProcess} onChange={(v) => onChange({ hasDesignProcess: v })} hint="Включает дизайн-процесс в расчёт" />
      </InspectorSection>

      <InspectorSection title="Флаги и множитель">
        <FToggle label="requiresDesignPhase" value={p.requiresDesignPhase} onChange={(v) => onChange({ requiresDesignPhase: v })} />
        <div>
          <div style={{ ...insStyles.label, marginBottom: 7 }}>Флаги по умолчанию</div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
            {ALL_FLAGS.map((f) => {
              const on = (p.defaultFlags || []).includes(f);
              return (
                <button key={f} type="button" onClick={() => toggleFlag(f)} style={{
                  padding: '5px 11px', borderRadius: 980, border: '1px solid ' + (on ? 'color-mix(in srgb, var(--primary) 25%, var(--border-subtle))' : 'var(--border-subtle)'),
                  background: on ? 'color-mix(in srgb, var(--primary) 10%, var(--card))' : 'var(--secondary)', color: on ? 'var(--primary)' : 'var(--text-secondary)', fontSize: 12, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit',
                }}>{FLAG_L[f] || f}</button>
              );
            })}
          </div>
        </div>
        <FNum label="durationMultiplier" value={p.durationMul} onChange={(v) => onChange({ durationMul: v })} suffix="×" step={0.05} min={0.1} />
        <ExcludeTags value={p.excludeSlugs || []} onChange={(v) => onChange({ excludeSlugs: v })} />
      </InspectorSection>

      <InspectorSection title={'Привязка к каталогу · ' + nodes + ' узлов'} full>
        <div className="ins-picker-list" style={{ maxHeight: 280 }}>
          {catalog.map((ph) => {
            const phOn = phaseIncluded(ph.id);
            return (
              <div key={ph.id} style={{ padding: '2px 0' }}>
                <label className="ins-picker-row" style={{ cursor: 'pointer' }}>
                  <Check on={phOn} onClick={() => togglePhase(ph.id)} />
                  <span style={{ fontSize: 13.5, fontWeight: 600, color: phOn ? 'var(--foreground)' : 'var(--text-tertiary)' }}>{ph.name}</span>
                </label>
                {phOn && (
                  <div style={{ paddingLeft: 30 }}>
                    {ph.stages.map((st) => {
                      const stOn = !excludeSet.has(st.id) && !excludeSet.has(st.slug);
                      return (
                        <label key={st.id} className="ins-picker-row" style={{ cursor: 'pointer', padding: '4px 10px' }}>
                          <Check on={stOn} small onClick={() => toggleStage(st.id)} color={st.color} />
                          <span style={{ width: 8, height: 8, borderRadius: '50%', background: st.color, opacity: stOn ? 1 : 0.3, flexShrink: 0 }} aria-hidden="true"></span>
                          <span style={{ fontSize: 12.5, color: stOn ? 'var(--text-secondary)' : 'var(--text-tertiary)', textDecoration: stOn ? 'none' : 'line-through' }}>{st.name}</span>
                        </label>
                      );
                    })}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </InspectorSection>

      <InspectorSection title="Превью на калькуляторе" full>
        <div style={{ fontSize: 12, color: 'var(--text-secondary)', marginBottom: 10 }}>
          {p.visibility === 'public' ? 'На публичном /calculator клиент увидит карточку:' : p.visibility === 'internal' ? 'В калькуляторе проекта менеджер увидит:' : 'Скрытый пресет на калькуляторе не показывается.'}
        </div>
        <div style={{ display: 'inline-flex', flexDirection: 'column', gap: 8, padding: '14px 16px', borderRadius: 14, border: '1.5px solid ' + (p.visibility === 'hidden' ? 'var(--border-subtle)' : 'var(--primary)'), background: p.visibility === 'hidden' ? 'var(--secondary)' : 'color-mix(in srgb, var(--primary) 6%, var(--card))', minWidth: 220, opacity: p.visibility === 'hidden' ? 0.6 : 1 }}>
          <span style={{ fontSize: 15, fontWeight: 600, color: 'var(--foreground)' }}>{p.name}</span>
          <span style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            <AxisChip>{SCOPE_L[p.scope]}</AxisChip><AxisChip>{GRADE_L[p.grade]}</AxisChip>
          </span>
          <span style={{ fontSize: 12, color: 'var(--text-secondary)' }}>множитель сроков ×{(+p.durationMul || 1).toFixed(2)}</span>
        </div>
      </InspectorSection>
    </InspectorDrawer>
  );
}

/* checkbox */
function Check({ on, onClick, small, color }) {
  return (
    <span onClick={(e) => { e.preventDefault(); onClick(); }} style={{
      width: small ? 16 : 18, height: small ? 16 : 18, borderRadius: 5, flexShrink: 0, cursor: 'pointer',
      border: on ? 'none' : '1.5px solid #d4d4d8', background: on ? (color || '#e8793a') : '#fff',
      display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'all .12s',
    }}>
      {on && <svg width={small ? 10 : 12} height={small ? 10 : 12} viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>}
    </span>
  );
}

/* multi-tag input для excludeSlugs */
function ExcludeTags({ value, onChange }) {
  const [draft, setDraft] = prUseState('');
  const addTag = () => { const v = draft.trim(); if (!v) return; if (!value.includes(v)) onChange([...value, v]); setDraft(''); };
  return (
    <div>
      <div style={{ ...insStyles.label, marginBottom: 7 }}>excludeSlugs</div>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, alignItems: 'center', background: '#f0ece5', border: '.5px solid #e4ddd2', borderRadius: 10, padding: '7px 9px' }}>
        {value.map((s) => (
          <span key={s} style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '3px 5px 3px 9px', borderRadius: 980, background: '#fff', border: '.5px solid #e4ddd2', fontSize: 12, ...insStyles.mono, color: '#6b6259' }}>
            {s}<button onClick={() => onChange(value.filter((x) => x !== s))} style={{ ...ctorStyles.iconBtnSm, width: 16, height: 16, color: '#bcb3a7' }}>{Icon.x}</button>
          </span>
        ))}
        <input value={draft} onChange={(e) => setDraft(e.target.value)}
          onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addTag(); } }} onBlur={addTag}
          placeholder={value.length ? '+ slug' : 'demo_floor_covers, screed …'}
          style={{ border: 'none', outline: 'none', background: 'transparent', fontFamily: 'inherit', fontSize: 12.5, color: '#1a1714', padding: '3px 4px', minWidth: 120, flex: 1 }} />
      </div>
    </div>
  );
}

Object.assign(window, { PresetsPanel, VIS_META, Check });
