/* ctor-packages.jsx — Tab «Пакеты» (пакеты услуг: шаги, разнесённые по фазам ремонта).
   Данные: ConstructorData.loadPackages/savePackages (ctor_packages_v1). Шаг: фаза (цифра 0..N)
   + позиция «в конец фазы / до этапа / после этапа». Калькулятор читает список вживую. */
const { useState: pkUseState } = React;

const PK_ICONS = ['📺', '🪟', '🚽', '🫧', '🔌', '🛁', '🧱', '🪞', '💡', '🔥', '💨', '🎛️', '📦'];
const PK_PALETTE = ['#6366f1', '#e8793a', '#f97316', '#8b5cf6', '#ec4899', '#0ea5e9', '#eab308', '#5aad6e', '#f04e62', '#78716c', '#38bdf8', '#14b8a6'];
const PK_ANCHORS = [{ v: 'end', l: 'в конец фазы' }, { v: 'before', l: 'до этапа…' }, { v: 'after', l: 'после этапа…' }];

function pkNewStep(pkgId, steps) {
  const last = steps[steps.length - 1];
  return { id: pkgId + '-s' + Date.now().toString(36), name: '', role: last ? last.role : null, days: 0.5,
    cost: 5000, margin: 30, tax: 0, costIndex: 5, unitPrice: 6500,
    phase: last ? last.phase : 0, anchor: { mode: 'end', stageId: null }, required: true, checklistId: null, note: '' };
}
function pkNewPackage() {
  const id = 'pkg_' + Date.now().toString(36);
  return { id, name: '', icon: '📦', color: '#6366f1', desc: '', visibility: 'internal', active: true, steps: [pkNewStep(id, [])] };
}
function pkStepErrors(step, catalog) {
  const e = [];
  if (!step.name || !step.name.trim()) e.push('Название шага обязательно');
  const ph = catalog[step.phase];
  if (!ph) e.push('Фазы ' + step.phase + ' нет в каталоге');
  else if (step.anchor && step.anchor.mode !== 'end' && !(ph.stages || []).some((s) => s.id === step.anchor.stageId)) e.push('Выберите этап фазы ' + step.phase);
  return e;
}
function pkPhaseLabel(catalog, idx) { const ph = catalog[idx]; return ph ? ph.name.replace(/^Фаза \d+ · /, '') : '—'; }
function pkAnchorText(catalog, step) {
  if (!step.anchor || step.anchor.mode === 'end') return 'конец фазы';
  const ph = catalog[step.phase];
  const st = ph && (ph.stages || []).find((s) => s.id === step.anchor.stageId);
  return (step.anchor.mode === 'before' ? 'до «' : 'после «') + (st ? st.name : '?') + '»';
}
function pkPlural(n) { return n === 1 ? 'шаг' : n >= 2 && n <= 4 ? 'шага' : 'шагов'; }

/* сегмент цифр фаз 0..N */
function PkPhaseSeg({ value, onChange, catalog }) {
  const bad = !(value >= 0 && value < catalog.length);
  return (
    <div className="pkg-phase-seg" role="group" aria-label="Фаза">
      {catalog.map((ph, i) => <button key={ph.id} type="button" className={value === i ? 'on' : ''} title={ph.name} onClick={() => onChange(i)}>{i}</button>)}
      {bad && <button type="button" className="on bad" title="Фазы нет в каталоге">{value}</button>}
    </div>
  );
}

/* одна строка шага */
function PkStepRow({ step, idx, total, catalog, roles, checklists, onPatch, onMove, onRemove }) {
  const errs = pkStepErrors(step, catalog);
  const ph = catalog[step.phase];
  const stages = ph ? (ph.stages || []) : [];
  const mode = (step.anchor && step.anchor.mode) || 'end';
  const setPhase = (i) => onPatch({ phase: i, anchor: { mode: 'end', stageId: null } });
  const setMode = (m) => onPatch({ anchor: m === 'end' ? { mode: 'end', stageId: null } : { mode: m, stageId: (step.anchor && step.anchor.stageId) || null } });
  return (
    <div className={'pkg-step' + (errs.length ? ' has-err' : '')}>
      <div className="pkg-step-head">
        <span className="pkg-step-no">{idx + 1}</span>
        <input className="pkg-step-name" value={step.name} placeholder="Название шага (мини-работа)" onChange={(e) => onPatch({ name: e.target.value })} />
        <span className="pkg-step-tools">
          <button type="button" disabled={idx === 0} onClick={() => onMove(-1)} title="Выше">↑</button>
          <button type="button" disabled={idx === total - 1} onClick={() => onMove(1)} title="Ниже">↓</button>
          <button type="button" className="danger" onClick={onRemove} title="Удалить шаг">✕</button>
        </span>
      </div>
      <div className="pkg-step-grid">
        <label><span>Роль</span>
          <select value={step.role || ''} onChange={(e) => onPatch({ role: e.target.value || null })}>
            <option value="">—</option>
            {roles.map((r) => <option key={r.id} value={r.id}>{r.name}</option>)}
          </select>
        </label>
        <label><span>Дни</span><input type="number" min={0.5} step={0.5} value={step.days} onChange={(e) => onPatch({ days: Math.max(0.5, +e.target.value || 0.5) })} /></label>
        <label><span>Себест., ₽</span><input type="number" min={0} step={100} value={step.cost} onChange={(e) => onPatch({ cost: Math.max(0, +e.target.value || 0) })} /></label>
        <label><span>Цена, ₽</span><input type="number" min={0} step={100} value={step.unitPrice} onChange={(e) => onPatch({ unitPrice: Math.max(0, +e.target.value || 0) })} /></label>
      </div>
      <div className="pkg-step-place">
        <div className="pkg-step-phase">
          <span className="pkg-step-lbl">Фаза</span>
          <PkPhaseSeg value={step.phase} onChange={setPhase} catalog={catalog} />
          <span className="pkg-step-phname">{pkPhaseLabel(catalog, step.phase)}</span>
        </div>
        <div className="pkg-step-anchor">
          <span className="pkg-step-lbl">Позиция</span>
          <select value={mode} onChange={(e) => setMode(e.target.value)}>
            {PK_ANCHORS.map((m) => <option key={m.v} value={m.v}>{m.l}</option>)}
          </select>
          {mode !== 'end' && (
            <select value={step.anchor.stageId || ''} onChange={(e) => onPatch({ anchor: { ...step.anchor, stageId: e.target.value || null } })}>
              <option value="">— этап —</option>
              {stages.map((s) => <option key={s.id} value={s.id}>{s.name}</option>)}
            </select>
          )}
        </div>
      </div>
      <div className="pkg-step-flags">
        <label className="pkg-chk" title="Обязательный шаг нельзя выключить в смете, пока включён пакет">
          <input type="checkbox" checked={step.required !== false} onChange={(e) => onPatch({ required: e.target.checked })} /> Обязательный
        </label>
        <label className="pkg-inline"><span>Чек-лист</span>
          <select value={step.checklistId || ''} onChange={(e) => onPatch({ checklistId: e.target.value || null })}>
            <option value="">— нет —</option>
            {checklists.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
          </select>
        </label>
      </div>
      {errs.length > 0 && <div className="pkg-step-err">{errs.join(' · ')}</div>}
    </div>
  );
}

/* раскладка шагов по фазам (read-only превью) */
function PkLayout({ pkg, catalog }) {
  const cols = catalog.map((ph, i) => ({ i, name: pkPhaseLabel(catalog, i), steps: [] }));
  const bad = [];
  pkg.steps.forEach((s, n) => { const c = cols[s.phase]; (c ? c.steps : bad).push({ n: n + 1, s }); });
  return (
    <div className="pkg-layout">
      {cols.map((c) => (
        <div key={c.i} className={'pkg-layout-col' + (c.steps.length ? ' has' : '')}>
          <div className="pkg-layout-head"><b>{c.i}</b><span>{c.name}</span></div>
          {c.steps.map((x) => <div key={x.s.id} className="pkg-layout-dot" style={{ background: pkg.color }} title={x.s.name}>{x.n}<i>{pkAnchorText(catalog, x.s)}</i></div>)}
        </div>
      ))}
      {bad.length > 0 && (
        <div className="pkg-layout-col bad">
          <div className="pkg-layout-head"><b>?</b><span>нет фазы</span></div>
          {bad.map((x) => <div key={x.s.id} className="pkg-layout-dot" title={x.s.name}>{x.n}</div>)}
        </div>
      )}
    </div>
  );
}

/* drawer редактора пакета */
function PackageDrawer({ pkg, catalog, roles, checklists, onSave, onClose }) {
  const [draft, setDraft] = pkUseState(pkg ? JSON.parse(JSON.stringify(pkg)) : pkNewPackage());
  const p = (k, v) => setDraft((d) => ({ ...d, [k]: v }));
  const patchStep = (i, patch) => setDraft((d) => ({ ...d, steps: d.steps.map((s, j) => (j === i ? { ...s, ...patch } : s)) }));
  const moveStep = (i, dir) => setDraft((d) => { const n = [...d.steps]; const j = i + dir; if (j < 0 || j >= n.length) return d; [n[i], n[j]] = [n[j], n[i]]; return { ...d, steps: n }; });
  const removeStep = (i) => setDraft((d) => ({ ...d, steps: d.steps.filter((_, j) => j !== i) }));
  const addStep = () => setDraft((d) => ({ ...d, steps: [...d.steps, pkNewStep(d.id, d.steps)] }));
  const errors = draft.steps.reduce((n, s) => n + pkStepErrors(s, catalog).length, 0) + (draft.name.trim() ? 0 : 1) + (draft.steps.length ? 0 : 1);
  const iconBtn = (on) => ({ width: 36, height: 36, borderRadius: 9, fontSize: 18, border: on ? '2px solid var(--primary)' : '1px solid var(--border-subtle)', background: on ? 'color-mix(in srgb, var(--primary) 10%, var(--card))' : 'transparent', cursor: 'pointer' });
  return (
    <InspectorDrawer title={pkg ? 'Редактировать пакет' : 'Новый пакет'} onClose={onClose} width={620}
      footer={
        <React.Fragment>
          <button type="button" onClick={onClose} style={ctorStyles.btnGhost}>Отмена</button>
          <button type="button" onClick={() => { onSave(draft); onClose(); }} disabled={errors > 0}
            style={{ ...ctorStyles.btnPrimary, opacity: errors > 0 ? 0.45 : 1 }}>Сохранить</button>
        </React.Fragment>
      }>
      <InspectorSection title="Идентификация">
        <FText label="Название" value={draft.name} onChange={(v) => p('name', v)} placeholder="ТВ на стене (65″+, тяжёлый)" />
        <FText label="Описание" value={draft.desc} onChange={(v) => p('desc', v)} placeholder="Закладная, кабели, кронштейн" />
        <div>
          <div style={{ ...insStyles.label, marginBottom: 8 }}>Иконка</div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
            {PK_ICONS.map((ic) => <button key={ic} type="button" onClick={() => p('icon', ic)} style={iconBtn(draft.icon === ic)}>{ic}</button>)}
          </div>
        </div>
        <div>
          <div style={{ ...insStyles.label, marginBottom: 8 }}>Цвет</div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 7 }}>
            {PK_PALETTE.map((c) => <button key={c} type="button" onClick={() => p('color', c)} aria-label={'Цвет ' + c} style={{ width: 28, height: 28, borderRadius: '50%', background: c, border: draft.color === c ? '2.5px solid var(--foreground)' : '2px solid transparent', cursor: 'pointer' }} />)}
          </div>
        </div>
        <div>
          <div style={{ ...insStyles.label, marginBottom: 8 }}>Видимость</div>
          <div className="pkg-seg">
            <button type="button" className={draft.visibility === 'public' ? 'on' : ''} onClick={() => p('visibility', 'public')}>Клиенту</button>
            <button type="button" className={draft.visibility !== 'public' ? 'on' : ''} onClick={() => p('visibility', 'internal')}>Внутренний</button>
          </div>
        </div>
        <FToggle label="Активен" value={draft.active !== false} onChange={(v) => p('active', v)} hint="Неактивный не предлагается в калькуляторе" />
      </InspectorSection>
      <InspectorSection title={'Шаги · ' + draft.steps.length} lead="Каждый шаг — своя мини-работа: фаза (цифра) и позиция внутри фазы">
        {draft.steps.map((s, i) => (
          <PkStepRow key={s.id} step={s} idx={i} total={draft.steps.length} catalog={catalog} roles={roles} checklists={checklists}
            onPatch={(patch) => patchStep(i, patch)} onMove={(dir) => moveStep(i, dir)} onRemove={() => removeStep(i)} />
        ))}
        {!draft.steps.length && <div style={insStyles.hint}>Добавьте хотя бы один шаг</div>}
        <button type="button" className="opt-add-btn" onClick={addStep}>+ Добавить шаг</button>
      </InspectorSection>
      <InspectorSection title="Раскладка по фазам" lead="Куда попадут шаги при добавлении пакета в смету">
        <PkLayout pkg={draft} catalog={catalog} />
      </InspectorSection>
    </InspectorDrawer>
  );
}

/* панель вкладки */
function PackagesPanel({ packages, setPackages, catalog, roles }) {
  const [editing, setEditing] = pkUseState(null); // null | 'new' | pkg
  const checklists = window.loadChecklists ? window.loadChecklists() : [];
  const save = (pkg) => setPackages((list) => (list.some((x) => x.id === pkg.id) ? list.map((x) => (x.id === pkg.id ? pkg : x)) : [...list, pkg]));
  const toggleActive = (id) => setPackages((list) => list.map((x) => (x.id === id ? { ...x, active: !(x.active !== false) } : x)));
  const duplicate = (pkg) => {
    const id = 'pkg_' + Date.now().toString(36);
    setPackages((list) => [...list, { ...JSON.parse(JSON.stringify(pkg)), id, name: pkg.name + ' (копия)', steps: pkg.steps.map((s, i) => ({ ...s, id: id + '-s' + i })) }]);
  };
  const del = (id) => {
    if (!confirm('Удалить пакет? В уже собранных сметах он останется как архивный.')) return;
    setPackages((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>
      {!packages.length && <div className="pkg-empty">Пакетов нет — создайте первый: услуга клиенту, шаги которой идут в разных фазах.</div>}
      <div className="pkg-grid">
        {packages.map((pkg) => {
          const phases = [...new Set(pkg.steps.map((s) => s.phase))].sort((a, b) => a - b);
          const errs = pkg.steps.reduce((n, s) => n + pkStepErrors(s, catalog).length, 0) + (pkg.name.trim() ? 0 : 1);
          return (
            <div key={pkg.id} className={'pkg-card' + (pkg.active === false ? ' is-off' : '')}>
              <div className="pkg-card-ic" style={{ background: pkg.color }}>{pkg.icon}</div>
              <div className="pkg-card-body">
                <div className="pkg-card-name">{pkg.name || 'Без названия'}</div>
                {pkg.desc && <div className="pkg-card-desc">{pkg.desc}</div>}
                <div className="pkg-card-meta">
                  <span>{pkg.steps.length} {pkPlural(pkg.steps.length)}</span>
                  <span>фазы {phases.join(' · ') || '—'}</span>
                  <span className={'pkg-vis ' + (pkg.visibility === 'public' ? 'pub' : 'int')}>{pkg.visibility === 'public' ? 'Клиенту' : 'Внутренний'}</span>
                  {errs > 0 && <span className="pkg-err-badge" title="Есть ошибки — публикация заблокирована">⚠ {errs}</span>}
                </div>
              </div>
              <div className="pkg-card-tools">
                <OToggle value={pkg.active !== false} onChange={() => toggleActive(pkg.id)} />
                <button type="button" onClick={() => setEditing(pkg)} title="Редактировать">✎</button>
                <button type="button" onClick={() => duplicate(pkg)} title="Дублировать">⧉</button>
                <button type="button" className="danger" onClick={() => del(pkg.id)} title="Удалить">✕</button>
              </div>
            </div>
          );
        })}
      </div>
      {editing && (
        <PackageDrawer pkg={editing === 'new' ? null : editing} catalog={catalog} roles={roles} checklists={checklists}
          onSave={save} onClose={() => setEditing(null)} />
      )}
    </div>
  );
}
window.PackagesPanel = PackagesPanel;
