/* ctor-checklists.jsx — Tab «Чек-листы» (sidebar + builder + executor preview dialog) */
const { useState: clUseState, useEffect: clUseEffect, useRef: clUseRef } = React;
const clCreatePortal = ReactDOM.createPortal;

// Сид и загрузка чек-листов — в constructor-data.js (CD.CHECKLISTS_SEED / loadChecklists / saveChecklists):
// их читают и store при handoff, и карточка исполнителя.
const CL_SEED = window.ConstructorData.CHECKLISTS_SEED;

const loadChecklists = () => window.ConstructorData.loadChecklists();
const saveChecklists = (cls) => window.ConstructorData.saveChecklists(cls);

const TYPE_META = {
  check:       { label:'Чекбокс',           icon:'☑', color:'#e8793a' },
  photo:       { label:'Фото',              icon:'📷', color:'#ec4899' },
  check_photo: { label:'Чекбокс + Фото',    icon:'☑📷', color:'#f97316' },
  number:      { label:'Число',             icon:'#',  color:'#8b5cf6' },
  text:        { label:'Текст',             icon:'T',  color:'#5aad6e' },
};

const ClIconEye = (
  <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
    <circle cx="12" cy="12" r="3" />
  </svg>
);

function TypePicker({ value, onChange }) {
  return (
    <div style={{ display:'flex', gap:5, flexWrap:'wrap' }}>
      {Object.entries(TYPE_META).map(([k, m]) => (
        <button key={k} type="button" onClick={() => onChange(k)} title={m.label} style={{
          padding:'5px 10px', borderRadius:8, fontSize:12, fontWeight:600, cursor:'pointer', fontFamily:'inherit',
          background: value === k ? m.color + '18' : '#f0ece5',
          color: value === k ? m.color : '#8a817a',
          border: value === k ? `1px solid ${m.color}44` : '1px solid transparent',
        }}>{m.icon}</button>
      ))}
    </div>
  );
}

function PhotoSettings({ item, onChange }) {
  if (!['photo','check_photo'].includes(item.type)) return null;
  return (
    <div className="cl-photo-row">
      <span style={{ fontWeight: 600, color: 'var(--text-secondary)' }}>Фото</span>
      <label>
        Мин.
        <input type="number" min={1} max={10} value={item.minPhotos||1} onChange={e=>onChange({...item, minPhotos:+e.target.value})} />
      </label>
      <label>
        Макс.
        <input type="number" min={1} max={10} value={item.maxPhotos||3} onChange={e=>onChange({...item, maxPhotos:+e.target.value})} />
      </label>
      <label style={{ flex: '1 1 140px', minWidth: 120 }}>
        Подсказка
        <input type="text" value={item.photoHint||''} onChange={e=>onChange({...item, photoHint:e.target.value})}
          placeholder="Снимите аналогично схеме" style={{ textAlign: 'left', width: '100%' }} />
      </label>
    </div>
  );
}

function ExecutorPreviewItem({ item, variant }) {
  const isStep = variant === 'step';
  const isPhoto = item.type === 'photo' || item.type === 'check_photo';
  const hasCheck = item.type === 'check' || item.type === 'check_photo';
  const minP = item.minPhotos || 1;
  const maxP = item.maxPhotos || 3;
  return (
    <div className={'cl-executor-item' + (isStep ? ' is-step' : '')}>
      <div className="cl-executor-item-row">
        {hasCheck && <div className="cl-executor-check" aria-hidden="true" />}
        <div style={{ flex:1, minWidth:0 }}>
          <div className="cl-executor-item-label">{item.label || 'Без названия'}</div>
          {item.hint && <div className="cl-executor-item-hint">{item.hint}</div>}
        </div>
        {item.required && <span className="cl-executor-required">обяз.</span>}
      </div>
      {isPhoto && (
        <>
          <div className="cl-executor-photos">
            {Array.from({ length: minP }).map((_, i) => (
              <div key={i} className="cl-executor-photo-slot" aria-hidden="true">
                <span className="cl-executor-photo-slot-label">Фото</span>
              </div>
            ))}
            {minP < maxP && (
              <div className="cl-executor-photo-slot cl-executor-photo-add" aria-hidden="true">
                <span className="cl-executor-photo-slot-label">+</span>
              </div>
            )}
          </div>
          {item.photoHint && <div className="cl-executor-photo-hint">{item.photoHint}</div>}
        </>
      )}
      {item.type === 'number' && (
        <input disabled className="cl-executor-input cl-executor-input-num" placeholder="0" tabIndex={-1} />
      )}
      {item.type === 'text' && (
        <textarea disabled rows={isStep ? 3 : 2} className="cl-executor-input cl-executor-input-text" placeholder="Комментарий…" tabIndex={-1} />
      )}
    </div>
  );
}

function ChecklistExecutorStepFlow({ items, title, desc }) {
  const [idx, setIdx] = clUseState(0);
  const total = items.length;
  const current = items[idx];
  const next = items[idx + 1];
  const req = items.filter((i) => i.required).length;

  clUseEffect(() => {
    setIdx(0);
  }, [items.length, title]);

  if (!total) {
    return <div className="cl-executor-empty">Добавьте пункты в шаблон, чтобы увидеть превью</div>;
  }

  const pct = Math.round(((idx + 1) / total) * 100);

  return (
    <div className="cl-executor-phone">
      <div className="cl-executor-phone-notch" aria-hidden="true" />
      <header className="cl-executor-phone-head">
        <div className="cl-executor-phone-head-main">
          <h3 className="cl-executor-phone-title">{title || 'Чек-лист'}</h3>
          {desc && <p className="cl-executor-phone-desc">{desc}</p>}
        </div>
        <div className="cl-executor-step-badge" aria-live="polite">{idx + 1} / {total}</div>
      </header>
      <div className="cl-executor-step-progress" role="progressbar" aria-valuenow={idx + 1} aria-valuemin={1} aria-valuemax={total} aria-label="Прогресс чек-листа">
        <div className="cl-executor-step-progress-fill" style={{ width: pct + '%' }} />
      </div>
      <div className="cl-executor-step-body">
        <ExecutorPreviewItem item={current} variant="step" />
      </div>
      {next && (
        <div className="cl-executor-next-peek" aria-hidden="true">
          <span className="cl-executor-next-peek-label">Следующий пункт</span>
          <div className="cl-executor-next-peek-card">
            <span className="cl-executor-next-peek-title">{next.label || 'Без названия'}</span>
            {next.hint && <span className="cl-executor-next-peek-hint">{next.hint}</span>}
          </div>
        </div>
      )}
      <footer className="cl-executor-step-foot">
        <button type="button" className="cl-executor-step-btn" disabled={idx === 0} onClick={() => setIdx((i) => Math.max(0, i - 1))}>
          Назад
        </button>
        {idx < total - 1
          ? <button type="button" className="cl-executor-step-btn is-primary" onClick={() => setIdx((i) => Math.min(total - 1, i + 1))}>Далее</button>
          : <button type="button" className="cl-executor-step-btn is-primary" disabled tabIndex={-1}>Сдать чек-лист</button>}
      </footer>
      <div className="cl-executor-phone-meta">{req}/{total} обяз.</div>
    </div>
  );
}

function ChecklistExecutorPreviewDialog({ cl, open, onClose }) {
  const dlgRef = clUseRef(null);
  const [viewMode, setViewMode] = clUseState('list');
  const titleId = 'cl-executor-preview-' + (cl?.id || 'draft');

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

  clUseEffect(() => {
    if (open) setViewMode('list');
  }, [open, cl?.id]);

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

  const req = cl.items.filter(i => i.required).length;
  const items = cl.items || [];

  return clCreatePortal(
    <dialog
      ref={dlgRef}
      className="dp-brief-preview-dialog cl-executor-preview-dialog"
      aria-labelledby={titleId}
      onCancel={(e) => { e.preventDefault(); onClose(); }}
      onClose={onClose}
      onClick={(e) => { if (e.target === dlgRef.current) onClose(); }}
    >
      <div className="dp-brief-preview-scroll cl-executor-preview-scroll" onClick={(e) => e.stopPropagation()}>
        <div className="cl-preview-toolbar">
          <div className="cl-preview-mode" role="tablist" aria-label="Режим превью">
            <button type="button" role="tab" aria-selected={viewMode === 'list'} className={'cl-preview-mode-btn' + (viewMode === 'list' ? ' is-on' : '')} onClick={() => setViewMode('list')}>
              Список
            </button>
            <button type="button" role="tab" aria-selected={viewMode === 'step'} className={'cl-preview-mode-btn' + (viewMode === 'step' ? ' is-on' : '')} onClick={() => setViewMode('step')}>
              Пошагово
            </button>
          </div>
          <button type="button" className="dp-brief-preview-close" onClick={onClose} aria-label="Закрыть">
            {Icon.x}
          </button>
        </div>
        {viewMode === 'list'
          ? (
            <article className="cl-executor-sheet cl-executor-sheet--list">
              <header className="cl-executor-sheet-head">
                <h2 id={titleId}>{cl.name || 'Шаблон'}</h2>
                <p className="cl-executor-sheet-meta">
                  {cl.desc ? cl.desc + ' · ' : ''}Чек-лист · вид исполнителя
                </p>
              </header>
              <div className="cl-executor-sheet-body">
                {items.length === 0
                  ? <div className="cl-executor-empty">Добавьте пункты в шаблон, чтобы увидеть превью</div>
                  : items.map(item => <ExecutorPreviewItem key={item.id} item={item} />)}
              </div>
              <footer className="cl-executor-sheet-foot">
                <span className="cl-executor-stats">{req}/{items.length} обяз.</span>
                <button type="button" className="cl-executor-submit" disabled tabIndex={-1}>Сдать чек-лист</button>
              </footer>
            </article>
          )
          : (
            <article className="cl-executor-sheet cl-executor-sheet--step" aria-labelledby={titleId}>
              <h2 id={titleId} className="cl-executor-sr-only">{cl.name || 'Шаблон'} · пошаговый вид</h2>
              <ChecklistExecutorStepFlow items={items} title={cl.name} desc={cl.desc} />
            </article>
          )}
      </div>
    </dialog>,
    document.body
  );
}

function ChecklistEditor({ cl, onChange }) {
  const [previewOpen, setPreviewOpen] = clUseState(false);
  const uid = () => 'i-' + Math.random().toString(36).slice(2,7);
  const setItems = fn => onChange({...cl, items: fn(cl.items)});
  const addItem = () => setItems(items => [...items, { id:uid(), type:'check', label:'', hint:'', required:false }]);
  const delItem = id => setItems(items => items.filter(i => i.id !== id));
  const patchItem = (id, patch) => setItems(items => items.map(i => i.id === id ? {...i,...patch} : i));
  const move = (id, dir) => setItems(items => {
    const idx = items.findIndex(i => i.id === id);
    if (idx < 0) return items;
    const next = [...items];
    const swap = idx+dir;
    if (swap < 0 || swap >= next.length) return items;
    [next[idx], next[swap]] = [next[swap], next[idx]];
    return next;
  });

  const reqCount = cl.items.filter(i => i.required).length;

  return (
    <>
      <div className="cl-editor">
        <div className="cl-editor-head">
          <div className="cl-editor-head-main">
            <input className="cl-editor-title" value={cl.name} onChange={e=>onChange({...cl,name:e.target.value})} placeholder="Название шаблона" />
            <input className="cl-editor-desc" value={cl.desc||''} onChange={e=>onChange({...cl,desc:e.target.value})} placeholder="Описание (когда применять)" />
            <div className="cl-editor-meta">{cl.items.length} пунктов · {reqCount} обяз.</div>
          </div>
          <button type="button" className="dp-brief-preview-open" onClick={() => setPreviewOpen(true)} aria-haspopup="dialog">
            {ClIconEye} Вид исполнителя
          </button>
        </div>
        <div className="cl-editor-list">
          {cl.items.map((item, idx) => (
            <div key={item.id} className="cl-editor-item">
              <div className="cl-editor-item-toolbar">
                <TypePicker value={item.type} onChange={t => patchItem(item.id, {type:t})} />
                <div className="cl-editor-item-toolbar-actions">
                  <button type="button" onClick={() => move(item.id,-1)} disabled={idx===0} style={{...ctorStyles.iconBtnSm, opacity:idx===0?.3:1}} aria-label="Выше">
                    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><polyline points="18 15 12 9 6 15"></polyline></svg>
                  </button>
                  <button type="button" onClick={() => move(item.id,1)} disabled={idx===cl.items.length-1} style={{...ctorStyles.iconBtnSm, opacity:idx===cl.items.length-1?.3:1}} aria-label="Ниже">
                    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><polyline points="6 9 12 15 18 9"></polyline></svg>
                  </button>
                  <button type="button" onClick={() => delItem(item.id)} style={{...ctorStyles.iconBtnSm, color:'#f04e62'}} aria-label="Удалить пункт">{Icon.x}</button>
                </div>
              </div>
              <div className="cl-editor-fields">
                <input value={item.label} onChange={e=>patchItem(item.id,{label:e.target.value})} placeholder="Текст пункта" style={insStyles.field} />
                <input value={item.hint||''} onChange={e=>patchItem(item.id,{hint:e.target.value})} placeholder="Подсказка" style={insStyles.field} />
              </div>
              <label className="cl-editor-required">
                <input type="checkbox" checked={!!item.required} onChange={e=>patchItem(item.id,{required:e.target.checked})} style={{ width:14, height:14, accentColor:'#f04e62' }} />
                <span>Обязательный</span>
              </label>
              <PhotoSettings item={item} onChange={patched => patchItem(item.id, patched)} />
            </div>
          ))}
        </div>
        <div className="cl-editor-foot">
          <button type="button" onClick={addItem} style={{ ...ctorStyles.btnDashed, alignSelf:'flex-start' }}>
            {Icon.plus} Добавить пункт
          </button>
        </div>
      </div>
      <ChecklistExecutorPreviewDialog cl={cl} open={previewOpen} onClose={() => setPreviewOpen(false)} />
    </>
  );
}

function ChecklistsPanel({ checklists, setChecklists }) {
  const [activeId, setActiveId] = clUseState(checklists[0]?.id || null);
  const uid = () => 'cl-' + Math.random().toString(36).slice(2,7);
  const active = checklists.find(c => c.id === activeId) || null;

  const update = (updated) => {
    const next = checklists.map(c => c.id === updated.id ? updated : c);
    setChecklists(next); saveChecklists(next);
  };
  const add = () => {
    const nc = { id:uid(), name:'Новый шаблон', desc:'', items:[] };
    const next = [...checklists, nc];
    setChecklists(next); saveChecklists(next);
    setActiveId(nc.id);
  };
  const del = (id) => {
    if (!confirm('Удалить шаблон?')) return;
    const next = checklists.filter(c => c.id !== id);
    setChecklists(next); saveChecklists(next);
    if (activeId === id) setActiveId(next[0]?.id || null);
  };
  const dup = (id) => {
    const src = checklists.find(c => c.id === id);
    if (!src) return;
    const copy = {
      ...src,
      id: uid(),
      name: (src.name || 'Шаблон') + ' (копия)',
      items: src.items.map(i => ({ ...i, id: 'i-' + Math.random().toString(36).slice(2,7) })),
    };
    const next = [...checklists, copy];
    setChecklists(next); saveChecklists(next);
    setActiveId(copy.id);
  };

  const itemCount = (cl) => cl.items.length;
  const reqCount = (cl) => cl.items.filter(i => i.required).length;

  return (
    <div style={{ display:'flex', gap:22, alignItems:'flex-start' }}>
      <div className="dp-briefs-sidebar is-checklists">
        <section className="dp-sidebar-block is-briefs">
          <div className="dp-sidebar-block-head">
            <span className="dp-sidebar-block-title">Чек-листы</span>
            <button type="button" onClick={add} className="dp-sidebar-icon-btn is-create" title="Создать шаблон" aria-label="Создать шаблон">{Icon.plus}</button>
          </div>
          <div className="dp-sidebar-block-scroll" role="list" aria-label="Шаблоны чек-листов">
            {checklists.map(cl => {
              const isActive = cl.id === activeId;
              return (
                <div
                  key={cl.id}
                  onClick={() => setActiveId(cl.id)}
                  className={'dp-sidebar-list-item' + (isActive ? ' is-active' : '')}
                  role="listitem"
                >
                  <div className="dp-sidebar-list-item-main">
                    <div className="dp-sidebar-list-item-title">{cl.name || 'Без названия'}</div>
                    <div className="dp-sidebar-list-item-meta">
                      {itemCount(cl)} пункт. · {reqCount(cl)} обяз.
                    </div>
                  </div>
                  <div className="dp-sidebar-list-item-actions">
                    <button type="button" onClick={(e) => { e.stopPropagation(); dup(cl.id); }} title="Дублировать" className="dp-sidebar-list-icon-btn">{Icon.copy}</button>
                    <button type="button" onClick={(e) => { e.stopPropagation(); del(cl.id); }} title="Удалить" className="dp-sidebar-list-icon-btn is-muted">{Icon.x}</button>
                  </div>
                </div>
              );
            })}
            {!checklists.length && (
              <button type="button" onClick={add} className="dp-sidebar-create-row" aria-label="Создать шаблон">
                {Icon.plus}
              </button>
            )}
          </div>
        </section>
      </div>
      <div style={{ flex:1, minWidth:0 }}>
        {active ? <ChecklistEditor cl={active} onChange={update} /> : (
          <div style={{ padding:'64px 32px', textAlign:'center', color:'#a89e92' }}>
            <div style={{ fontSize:40, marginBottom:12 }}>📋</div>
            <div style={{ fontSize:16, fontWeight:600, marginBottom:6, color:'#6b6259' }}>Выберите шаблон</div>
            <div style={{ fontSize:13.5, maxWidth:360, margin:'0 auto', lineHeight:1.5 }}>Соберите пункты и откройте вид исполнителя, чтобы проверить форму на объекте.</div>
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { ChecklistsPanel, loadChecklists, CL_SEED });
