/* ctor-brief-field-presets.jsx — sidebar + dialog «Заготовки полей брифа ДП» · KSH-350 */
const { useState: bpUseState, useEffect: bpUseEffect, useMemo: bpUseMemo, useRef: bpUseRef } = React;
const bpCreatePortal = ReactDOM.createPortal;

const BP_PROPERTY_LABELS = {
  residential: 'Жилая',
  house: 'Дом',
  commercial: 'Коммерция',
};

function BpPropertyChips({ selected, onChange, disabled }) {
  const P = window.BriefFieldPresetsMock;
  const types = P ? P.PROPERTY_TYPES : [];
  const set = new Set(selected || []);
  const toggle = (pt) => {
    if (disabled) return;
    const next = new Set(set);
    if (next.has(pt)) next.delete(pt); else next.add(pt);
    onChange([...next]);
  };
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
      {types.map((pt) => {
        const on = set.has(pt);
        return (
          <button key={pt} type="button" disabled={disabled} onClick={() => toggle(pt)}
            title={on ? 'Убрать тип' : 'Добавить тип · пусто = все типы'}
            style={{
              padding: '6px 11px', borderRadius: 980, font: 'inherit', fontSize: 12.5, fontWeight: 600, cursor: disabled ? 'default' : 'pointer',
              border: '.5px solid ' + (on ? '#e8793a' : '#ece5da'),
              background: on ? '#fff0e6' : '#fff',
              color: on ? '#c2410c' : '#5c5249',
              opacity: disabled ? 0.7 : 1,
            }}>
            {BP_PROPERTY_LABELS[pt] || pt}
          </button>
        );
      })}
      {!set.size && <span style={{ fontSize: 12, color: '#8a817a', alignSelf: 'center' }}>Все типы объекта</span>}
    </div>
  );
}

function BpGroupEditor({ group, onChange, onDelete }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <div>
        <div style={ctorStyles.fieldLabel}>Название группы</div>
        <input className="ctor-input" value={group.title || ''} onChange={(e) => onChange({ ...group, title: e.target.value })}
          style={{ ...ctorStyles.input, marginTop: 6 }} placeholder="Например: Логистика" />
      </div>
      <div>
        <div style={ctorStyles.fieldLabel}>Порядок сортировки</div>
        <input type="number" className="ctor-input" value={group.sortOrder == null ? 0 : group.sortOrder}
          onChange={(e) => onChange({ ...group, sortOrder: +e.target.value })}
          style={{ ...ctorStyles.input, marginTop: 6, width: 96 }} />
      </div>
      <div>
        <div style={ctorStyles.fieldLabel}>Доступна для типов объекта</div>
        <div style={{ marginTop: 8 }}><BpPropertyChips selected={group.propertyTypes} onChange={(pts) => onChange({ ...group, propertyTypes: pts })} /></div>
        <div style={{ fontSize: 11.5, color: '#8a817a', marginTop: 8, lineHeight: 1.45 }}>Пустой набор = все типы. Наследуется заготовками без своих тегов.</div>
      </div>
      <div style={{ paddingTop: 8, borderTop: '.5px solid #f0ece5' }}>
        <button type="button" onClick={onDelete} style={{ ...ctorStyles.btnGhost, color: '#f04e62', borderColor: '#fecaca' }}>{Icon.trash} Удалить группу</button>
      </div>
    </div>
  );
}

function BpPresetEditor({ preset, groups, onChange, onDelete, onDuplicate }) {
  const FieldEditor = window.MsFieldEditor;
  const uid = () => 'f-' + Math.random().toString(36).slice(2, 7);
  const setFields = (fn) => onChange({ ...preset, fields: fn(preset.fields || []) });
  const patchField = (id, p) => setFields((fields) => fields.map((f) => (f.id === id ? { ...f, ...p } : f)));
  const delField = (id) => setFields((fields) => fields.filter((f) => f.id !== id));
  const moveField = (id, dir) => setFields((fields) => {
    const idx = fields.findIndex((f) => f.id === id);
    if (idx < 0) return fields;
    const next = [...fields];
    const swap = idx + dir;
    if (swap < 0 || swap >= next.length) return fields;
    [next[idx], next[swap]] = [next[swap], next[idx]];
    return next;
  });
  const addField = () => setFields((fields) => [...fields, { id: uid(), type: 'text', label: '', required: false }]);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        <label style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
          <span style={ctorStyles.fieldLabel}>Заголовок блока</span>
          <input className="ctor-input" value={preset.title || ''} onChange={(e) => onChange({ ...preset, title: e.target.value })} style={ctorStyles.input} />
        </label>
        <label style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
          <span style={ctorStyles.fieldLabel}>Группа</span>
          <select className="ctor-input" value={preset.groupId || ''} onChange={(e) => onChange({ ...preset, groupId: e.target.value })} style={ctorStyles.input}>
            {(groups || []).map((g) => <option key={g.id} value={g.id}>{g.title}</option>)}
            <option value="_ungrouped">Без группы</option>
          </select>
        </label>
      </div>
      <label style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
        <span style={ctorStyles.fieldLabel}>Подсказка под заголовком</span>
        <input className="ctor-input" value={preset.hint || ''} onChange={(e) => onChange({ ...preset, hint: e.target.value })} style={ctorStyles.input} placeholder="Необязательно" />
      </label>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 14, alignItems: 'center' }}>
        <label style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, cursor: 'pointer' }}>
          <input type="checkbox" checked={preset.active !== false} onChange={(e) => onChange({ ...preset, active: e.target.checked })} />
          Активна · показывать в picker
        </label>
      </div>
      <div>
        <div style={ctorStyles.fieldLabel}>Типы объекта (override группы)</div>
        <div style={{ marginTop: 8 }}><BpPropertyChips selected={preset.propertyTypes} onChange={(pts) => onChange({ ...preset, propertyTypes: pts })} /></div>
      </div>
      <div>
        <div style={{ ...ctorStyles.fieldLabel, marginBottom: 10 }}>Поля заготовки · {(preset.fields || []).length}</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {(preset.fields || []).map((f, idx) => FieldEditor ? (
            <FieldEditor key={f.id} field={f} idx={idx} total={(preset.fields || []).length}
              onPatch={patchField} onDelete={delField} onMove={moveField} />
          ) : (
            <div key={f.id} style={{ padding: 12, background: '#fff', borderRadius: 10, border: '.5px solid #ece5da', fontSize: 13 }}>{f.label || f.id} · {f.type}</div>
          ))}
        </div>
        <button type="button" onClick={addField} style={{ ...ctorStyles.btnDashed, marginTop: 10, fontSize: 12.5 }}>{Icon.plus} Добавить поле</button>
      </div>
      <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', paddingTop: 8, borderTop: '.5px solid #f0ece5' }}>
        <button type="button" onClick={onDuplicate} style={ctorStyles.btnGhost}>{Icon.copy} Дублировать</button>
        <button type="button" onClick={onDelete} style={{ ...ctorStyles.btnGhost, color: '#f04e62', borderColor: '#fecaca' }}>{Icon.trash} Удалить заготовку</button>
      </div>
    </div>
  );
}

function BriefPresetEditorDialog({ open, kind, itemId, groups, presets, onClose, onReload, onOpenEditor }) {
  const P = window.BriefFieldPresetsMock;
  const dlgRef = bpUseRef(null);
  const titleId = 'bp-editor-title';

  const selectedGroup = kind === 'group' && itemId ? groups.find((g) => g.id === itemId) : null;
  const selectedPreset = kind === 'preset' && itemId ? presets.find((p) => p.id === itemId) : null;

  bpUseEffect(() => {
    const dlg = dlgRef.current;
    if (!dlg) return;
    if (open) {
      if (!dlg.open) dlg.showModal();
    } else if (dlg.open) {
      dlg.close();
    }
  }, [open]);

  const saveGroup = (patch) => {
    P.upsertGroup(patch);
    onReload();
  };

  const savePreset = (patch) => {
    P.upsertPreset(patch);
    onReload();
  };

  const delGroup = () => {
    if (!selectedGroup) return;
    const cnt = presets.filter((p) => p.groupId === selectedGroup.id).length;
    const msg = cnt ? 'Переместить ' + cnt + ' заготовок в «Без группы»?' : 'Удалить группу?';
    if (!confirm(msg)) return;
    P.deleteGroup(selectedGroup.id);
    onReload();
    onClose();
  };

  const delPreset = () => {
    if (!selectedPreset || !confirm('Удалить заготовку «' + selectedPreset.title + '»?')) return;
    P.deletePreset(selectedPreset.id);
    onReload();
    onClose();
  };

  const dupPreset = () => {
    if (!selectedPreset) return;
    const copy = P.duplicatePreset(selectedPreset.id);
    onReload();
    if (copy && onOpenEditor) onOpenEditor('preset', copy.id);
  };

  if (typeof document === 'undefined' || !open) return null;

  const dialogTitle = selectedPreset
    ? 'Заготовка · ' + (selectedPreset.title || 'без названия')
    : selectedGroup
      ? 'Группа · ' + (selectedGroup.title || 'без названия')
      : 'Редактор';

  return bpCreatePortal(
    <dialog
      ref={dlgRef}
      className="bp-editor-dialog"
      aria-labelledby={titleId}
      onCancel={(e) => { e.preventDefault(); onClose(); }}
      onClose={onClose}
      onClick={(e) => { if (e.target === dlgRef.current) onClose(); }}
    >
      <div className="bp-editor-panel" onClick={(e) => e.stopPropagation()}>
        <header className="bp-editor-head">
          <div>
            <h2 id={titleId} className="bp-editor-title">{dialogTitle}</h2>
            <p className="bp-editor-sub">Изменения сохраняются сразу · linked-брифы подхватят правки</p>
          </div>
          <button type="button" className="bp-editor-close" onClick={onClose} aria-label="Закрыть">{Icon.x}</button>
        </header>
        <div className="bp-editor-body">
          {selectedPreset ? (
            <BpPresetEditor preset={selectedPreset} groups={groups} onChange={savePreset} onDelete={delPreset} onDuplicate={dupPreset} />
          ) : selectedGroup ? (
            <>
              <BpGroupEditor group={selectedGroup} onChange={saveGroup} onDelete={delGroup} />
              <button type="button" onClick={() => {
                const pr = P.upsertPreset({
                  id: P.uid('preset'),
                  groupId: selectedGroup.id,
                  title: 'Новая заготовка',
                  hint: '',
                  propertyTypes: [],
                  active: true,
                  fields: [{ id: 'f-' + Math.random().toString(36).slice(2, 7), type: 'text', label: 'Поле', required: false }],
                });
                onReload();
                if (onOpenEditor) onOpenEditor('preset', pr.id);
              }} style={{ ...ctorStyles.btnDashed, marginTop: 16, fontSize: 12.5 }}>{Icon.plus} Заготовка в группе</button>
            </>
          ) : (
            <div style={{ padding: '32px 16px', textAlign: 'center', color: '#a89e92' }}>Элемент не найден</div>
          )}
        </div>
      </div>
    </dialog>,
    document.body
  );
}

function BriefPresetsSidebarBlock() {
  const P = window.BriefFieldPresetsMock;
  const [groups, setGroups] = bpUseState(() => (P ? P.listGroups() : []));
  const [presets, setPresets] = bpUseState(() => (P ? P.listPresets() : []));
  const [editor, setEditor] = bpUseState(null);

  const reload = () => {
    if (!P) return;
    setGroups(P.listGroups());
    setPresets(P.listPresets());
  };

  bpUseEffect(() => {
    reload();
    const h = () => reload();
    window.addEventListener('remontpro:brief-field-presets-updated', h);
    return () => window.removeEventListener('remontpro:brief-field-presets-updated', h);
  }, []);

  const openEditor = (kind, id) => setEditor({ kind, id });
  const closeEditor = () => setEditor(null);

  const treeGroups = bpUseMemo(() => {
    if (!P) return [];
    const gList = [...groups];
    const ungrouped = presets.filter((p) => p.groupId === P.UNGROUPED || !groups.find((g) => g.id === p.groupId));
    if (ungrouped.length) {
      gList.push({ id: P.UNGROUPED, title: 'Без группы', sortOrder: 9999, propertyTypes: [] });
    }
    return gList.sort((a, b) => a.sortOrder - b.sortOrder || a.title.localeCompare(b.title, 'ru'));
  }, [groups, presets, P]);

  const addGroup = () => {
    const g = P.upsertGroup({ id: P.uid('grp'), title: 'Новая группа', sortOrder: (groups.length + 1) * 10, propertyTypes: [] });
    reload();
    openEditor('group', g.id);
  };

  const addPreset = () => {
    const gid = (groups[0] && groups[0].id) || P.UNGROUPED;
    const pr = P.upsertPreset({
      id: P.uid('preset'),
      groupId: gid,
      title: 'Новая заготовка',
      hint: '',
      propertyTypes: [],
      active: true,
      fields: [{ id: 'f-' + Math.random().toString(36).slice(2, 7), type: 'text', label: 'Поле', required: false }],
    });
    reload();
    openEditor('preset', pr.id);
  };

  const resetSeed = () => {
    if (!confirm('Сбросить библиотеку заготовок к заводским пресетам?')) return;
    P.resetSeed();
    reload();
    closeEditor();
  };

  if (!P) {
    return (
      <section className="dp-sidebar-block is-presets">
        <div className="dp-sidebar-block-head">
          <span className="dp-sidebar-block-title">Заготовки</span>
        </div>
        <div className="dp-sidebar-block-scroll">
          <div style={{ padding: 16, fontSize: 12, color: '#a89e92' }}>Mock не загружен</div>
        </div>
      </section>
    );
  }

  return (
    <>
      <section className="dp-sidebar-block is-presets">
        <div className="dp-sidebar-block-head">
          <span className="dp-sidebar-block-title">Заготовки</span>
          <div className="dp-sidebar-block-actions">
            <button type="button" onClick={resetSeed} className="dp-sidebar-icon-btn" title="Сбросить к seed" aria-label="Сбросить к seed">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>
            </button>
            <button type="button" onClick={addGroup} className="dp-sidebar-icon-btn" title="Создать группу" aria-label="Создать группу">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" aria-hidden="true"><path d="M3 7v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-5l-2-2H5a2 2 0 0 0-2 2z"/><path d="M12 11v6M9 14h6"/></svg>
            </button>
            <button type="button" onClick={addPreset} className="dp-sidebar-icon-btn is-create" title="Создать заготовку" aria-label="Создать заготовку">{Icon.plus}</button>
          </div>
        </div>
        <div className="dp-sidebar-block-scroll is-presets-tree" role="list" aria-label="Заготовки полей">
          {treeGroups.map((g) => {
            const gPresets = presets.filter((p) => p.groupId === g.id || (g.id === P.UNGROUPED && (p.groupId === P.UNGROUPED || !groups.find((gg) => gg.id === p.groupId))));
            return (
              <div key={g.id} className="bp-sidebar-group">
                <button type="button" className="bp-sidebar-group-btn" onClick={() => openEditor('group', g.id)} title={'Редактировать группу «' + g.title + '»'}>
                  <span className="bp-sidebar-group-leading" aria-hidden="true">
                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75"><path d="M3 7v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-5l-2-2H5a2 2 0 0 0-2 2z"/></svg>
                  </span>
                  <span className="bp-sidebar-group-title">{g.title}</span>
                  <span className="bp-sidebar-meta">{gPresets.length}</span>
                </button>
                {gPresets.length > 0 && (
                  <ul className="bp-sidebar-preset-list">
                    {gPresets.map((p) => (
                      <li key={p.id}>
                        <button type="button" className="bp-sidebar-preset-btn" onClick={() => openEditor('preset', p.id)}>
                          <span className="bp-sidebar-preset-dot" aria-hidden="true" />
                          <span className={'bp-sidebar-preset-title' + (p.active === false ? ' is-off' : '')}>{p.title}</span>
                          <span className="bp-sidebar-meta">{(p.fields || []).length} пол.</span>
                        </button>
                      </li>
                    ))}
                  </ul>
                )}
              </div>
            );
          })}
          {!treeGroups.length && (
            <button type="button" onClick={addGroup} className="dp-sidebar-create-row" aria-label="Создать группу">
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" aria-hidden="true"><path d="M3 7v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-5l-2-2H5a2 2 0 0 0-2 2z"/><path d="M12 11v6M9 14h6"/></svg>
            </button>
          )}
        </div>
      </section>

      <BriefPresetEditorDialog
        open={!!editor}
        kind={editor && editor.kind}
        itemId={editor && editor.id}
        groups={groups}
        presets={presets}
        onClose={closeEditor}
        onReload={reload}
        onOpenEditor={openEditor}
      />
    </>
  );
}

Object.assign(window, { BriefPresetsSidebarBlock, BriefPresetEditorDialog, BriefFieldPresetsPanel: BriefPresetsSidebarBlock });
