// Editor Screen — main t-shirt designer

const { useState: usE, useMemo: umE, useRef: urE, useEffect: ueE } = React;

const EDITOR_ZONE_ORDER = ['front', 'back'];

function editorZoneRect(zoneId) {
  return ZONE_RECTS[zoneId];
}

function EditorScreen({ users, customLib, builtinLib, logoGroups, userId, shirtId, shirts, setShirts, onBack, onNextShirt, onPrevShirt, hasNext, hasPrev, showTechFields }) {
  const user = users.find(u => u.id === userId);
  const shirt = shirts[shirtId];
  const [zone, setZone] = usE('front');
  const [selected, setSelected] = usE(null);
  const [snap, setSnap] = usE(true);
  const [showRulers, setShowRulers] = usE(true);
  const [logoSearch, setLogoSearch] = usE('');
  const [showCopyMenu, setShowCopyMenu] = usE(false);
  const [zoom, setZoom] = usE(1);
  const stageScrollRef = urE(null);

  const getZoneDesigns = (zoneId) => shirt.designs?.[zoneId] || [];
  const designs = getZoneDesigns(zone);
  const selDesign = designs.find(d => d.id === selected);
  const activeZone = ZONES.find(z => z.id === zone) || ZONES[0];
  const inkColor = shirt.color === 'white' ? '#0a0a0c' : '#f3f3f1';
  const zoneLimit = ZONE_LIMITS[zone];
  const limitReached = designs.length >= zoneLimit;
  const locked = user.status === 'finished';

  const updateDesigns = (zoneId, newDesigns) => {
    if (locked) return;
    setShirts(prev => ({
      ...prev,
      [shirtId]: {
        ...prev[shirtId],
        designs: { ...prev[shirtId].designs, [zoneId]: newDesigns },
        status: 'in-progress',
      }
    }));
  };
  const applyLogoPolicy = (item, zoneId) => {
    const zoneCfg = ZONES.find(z => z.id === zoneId) || activeZone;
    const policy = getLogoPolicy(item.logoId, customLib, builtinLib);
    let next = { ...item };
    const minWidthMm = Math.max(0, Number(policy.minUserWidthMm || 0) || 0);
    if (minWidthMm > 0) {
      const minPct = (minWidthMm / zoneCfg.printW) * 100;
      if (Number(next.w || 0) < minPct) {
        next.w = minPct;
        next.h = minPct;
      }
    }
    const autoFillBelowMm = Math.max(0, Number(policy.autoContrastBelowMm || 0) || 0);
    const widthMm = (Number(next.w || 0) / 100) * zoneCfg.printW;
    if (autoFillBelowMm > 0 && widthMm < autoFillBelowMm) {
      next.fillMode = 'contrast-fill';
    }
    return next;
  };

  const createDesignItem = (logoId, zoneId, custom = {}) => {
    const aspectRatio = getLogoAspectRatio(logoId, custom.customText, customLib);
    const zoneRect = editorZoneRect(zoneId);
    const policy = getLogoPolicy(logoId, customLib, builtinLib);
    const minWidthPct = policy.minUserWidthMm ? (Number(policy.minUserWidthMm) / (ZONES.find(z => z.id === zoneId)?.printW || 100)) * 100 : 0;
    return applyLogoPolicy(NordicrewGeometry.normalizeItemAspect({
      id: 'd' + Date.now() + Math.floor(Math.random()*1000),
      logoId,
      x: 50, y: 50, w: Math.max(30, minWidthPct), h: Math.max(30, minWidthPct),
      rotation: 0,
      color: inkColor,
      aspectRatio,
      ...custom,
    }, zoneRect, aspectRatio), zoneId);
  };

  const addDesignToZone = (logoId, zoneId, custom = {}) => {
    const zoneDesigns = getZoneDesigns(zoneId);
    if (zoneDesigns.length >= ZONE_LIMITS[zoneId] || locked) return;
    const newItem = createDesignItem(logoId, zoneId, custom);
    updateDesigns(zoneId, [...zoneDesigns, newItem]);
    setZone(zoneId);
    setSelected(newItem.id);
  };

  const addDesign = (logoId, custom = {}) => {
    addDesignToZone(logoId, zone, custom);
  };

  const updateItemInZone = (zoneId, id, next) => {
    updateDesigns(zoneId, getZoneDesigns(zoneId).map(d => d.id === id ? applyLogoPolicy({ ...d, ...next }, zoneId) : d));
  };

  const updateItem = (id, next) => {
    updateItemInZone(zone, id, next);
  };

  const deleteItem = () => {
    if (!selected || locked) return;
    updateDesigns(zone, designs.filter(d => d.id !== selected));
    setSelected(null);
  };

  const handleDeleteKey = (e) => {
    if (locked || !selected || isEditableKeyTarget(e.target)) return;
    if (e.key !== 'Delete' && e.key !== 'Backspace') return;
    e.preventDefault();
    deleteItem();
  };

  const handleLibraryDragStart = (e, logoId, custom = {}) => {
    if (locked) {
      e.preventDefault();
      return;
    }
    setLogoDragData(e, logoId, custom);
  };

  const dropDesignOnZone = (e, zoneId) => {
    e.preventDefault();
    const data = getLogoDragData(e);
    if (!data) return;
    const point = dropEventToZonePct(e, editorZoneRect(zoneId));
    addDesignToZone(data.logoId, zoneId, { ...(data.custom || {}), ...point });
  };

  const moveDesignToZone = (itemId, sourceZoneId, targetZoneId, point, allowFreeSize = false) => {
    if (locked || !targetZoneId || sourceZoneId === targetZoneId) return;
    if ((getZoneDesigns(targetZoneId) || []).length >= ZONE_LIMITS[targetZoneId]) return;
    setShirts(prev => {
      const current = prev[shirtId];
      const sourceItems = current.designs?.[sourceZoneId] || [];
      const item = sourceItems.find(d => d.id === itemId);
      if (!item) return prev;
      const targetItems = current.designs?.[targetZoneId] || [];
      if (targetItems.length >= ZONE_LIMITS[targetZoneId]) return prev;
      const moved = applyLogoPolicy(remapDesignItemToZone(item, sourceZoneId, targetZoneId, point, customLib, allowFreeSize), targetZoneId);
      return {
        ...prev,
        [shirtId]: {
          ...current,
          designs: {
            ...current.designs,
            [sourceZoneId]: sourceItems.filter(d => d.id !== itemId),
            [targetZoneId]: [...targetItems, moved],
          },
          status: 'in-progress',
        },
      };
    });
    setZone(targetZoneId);
    setSelected(itemId);
  };

  const handleDesignMoveEnd = (itemId, sourceZoneId, e) => {
    const targetZoneId = eventTargetZoneId(e);
    if (!targetZoneId || targetZoneId === sourceZoneId || !ZONE_RECTS[targetZoneId]) return;
    moveDesignToZone(itemId, sourceZoneId, targetZoneId, eventToTargetZonePct(e, targetZoneId), e.ctrlKey);
  };

  const clearShirtDesign = () => {
    if (locked) return;
    if (!window.confirm('Очистить весь дизайн этой футболки?')) return;
    setShirts(prev => ({
      ...prev,
      [shirtId]: {
        ...prev[shirtId],
        designs: { front: [], back: [] },
        status: 'empty',
        updatedAt: NordicrewCore.todayIso(),
      },
    }));
    setSelected(null);
  };

  const duplicateSelected = () => {
    if (!selDesign || limitReached || locked) return;
    const aspectRatio = selDesign.aspectRatio || getLogoAspectRatio(selDesign.logoId, selDesign.customText, customLib);
    const copy = NordicrewGeometry.normalizeItemAspect(
      NordicrewCore.cloneDesignItem(selDesign, zone, designs.length),
      editorZoneRect(zone),
      aspectRatio
    );
    updateDesigns(zone, [...designs, applyLogoPolicy(copy, zone)]);
    setSelected(copy.id);
  };

  const invertSelected = () => {
    if (!selDesign) return;
    const c = selDesign.color === '#0a0a0c' ? '#f3f3f1' : '#0a0a0c';
    updateItem(selected, { color: c });
  };

  const toggleFillMode = () => {
    if (!selDesign) return;
    updateItem(selected, { fillMode: selDesign.fillMode === 'contrast-fill' ? 'normal' : 'contrast-fill' });
  };

  const mirrorSelected = (axis) => {
    if (!selDesign) return;
    updateItem(selected, axis === 'y'
      ? { flipY: !selDesign.flipY }
      : { flipX: !selDesign.flipX });
  };

  const setSelColor = (c) => {
    if (!selected) return;
    updateItem(selected, { color: c });
  };

  const finalizeShirt = () => {
    setShirts(prev => ({ ...prev, [shirtId]: { ...prev[shirtId], status: 'done', updatedAt: NordicrewCore.todayIso() } }));
  };

  const copyShirtDesignTo = (targetShirtId) => {
    setShirts(prev => {
      const target = prev[targetShirtId];
      if (!target) return prev;
      return {
        ...prev,
        [targetShirtId]: {
          ...target,
          designs: NordicrewCore.cloneDesignsForShirt(shirt.designs, target.color),
          status: target.status === 'done' ? 'done' : 'in-progress',
        },
      };
    });
    setShowCopyMenu(false);
  };

  const myShirts = user.shirts.map(id => shirts[id]).filter(Boolean);
  const participant = NordicrewCore.participantCode(user, users.findIndex(u => u.id === user.id));
  const activeShirtCode = NordicrewCore.shirtCode(user, Math.max(0, user.shirts.indexOf(shirtId)), users.findIndex(u => u.id === user.id));

  const stickerLibrary = umE(() => [...(builtinLib || BUILT_IN_STICKERS), ...(customLib || [])], [builtinLib, customLib]);
  const filteredLogos = umE(() => {
    if (!logoSearch) return stickerLibrary;
    const q = logoSearch.toLowerCase();
    return stickerLibrary.filter(l => l.name.toLowerCase().includes(q));
  }, [stickerLibrary, logoSearch]);
  const visibleLogoGroups = umE(() => groupLogosByVisual(filteredLogos, logoGroups || VISUAL_GROUPS), [filteredLogos, logoGroups]);

  const allZonesEmpty = ZONES.every(z => (shirt.designs[z.id] || []).length === 0);

  ueE(() => {
    setZone('front');
    setSelected(null);
    setShowCopyMenu(false);
  }, [shirtId]);

  ueE(() => {
    window.addEventListener('keydown', handleDeleteKey);
    return () => window.removeEventListener('keydown', handleDeleteKey);
  }, [handleDeleteKey]);

  const selectInZone = (zoneId, id) => {
    setZone(zoneId);
    setSelected(id);
  };

  const { isPanning, handlers: panHandlers } = usePanScroll({
    scrollRef: stageScrollRef,
    cardSelector: '.editor-view-card',
    onCardActivate: (zoneId) => { setZone(zoneId); setSelected(null); },
  });

  const handleEditorCtrlWheel = React.useCallback((event) => {
    if (!event.ctrlKey) return;
    event.preventDefault();
    setZoom(prev => NordicrewGeometry.clamp(
      Math.round((prev - event.deltaY * 0.001) * 100) / 100,
      0.65,
      3
    ));
  }, []);

  ueE(() => {
    const scrollEl = stageScrollRef.current;
    if (!scrollEl) return;
    scrollEl.addEventListener('wheel', handleEditorCtrlWheel, { passive: false });
    return () => scrollEl.removeEventListener('wheel', handleEditorCtrlWheel);
  }, [handleEditorCtrlWheel]);

  const renderZoneCard = (zoneId) => (
    <ZoneCard
      key={zoneId}
      zoneId={zoneId}
      zoneCfg={ZONES.find(z => z.id === zoneId)}
      designs={getZoneDesigns(zoneId)}
      shirt={shirt}
      selectedId={zone === zoneId ? selected : null}
      snap={snap}
      locked={locked}
      hideZoneOutline={!showRulers}
      customLib={customLib}
      isActive={zone === zoneId}
      zoom={zoom}
      onSelect={(id) => selectInZone(zoneId, id)}
      onChange={(id, patch) => updateItemInZone(zoneId, id, patch)}
      onItemMoveEnd={handleDesignMoveEnd}
      onActivate={(zid) => selectInZone(zid, null)}
      onDragOver={(e) => e.preventDefault()}
      onDrop={(e) => dropDesignOnZone(e, zoneId)}
    />
  );

  return (
    <div className="app-shell editor">
      <TopBar user={user} title={`ФУТБОЛКА · ${shirtColorLabel(shirt.color)} · ${shirt.size}`}
              subtitle={`УЧАСТНИК ${participant} · ФУТБОЛКА ${activeShirtCode}`} onBack={onBack}
              right={
                <div className="editor-nav">
                  <button className="icon-btn" disabled={!hasPrev} onClick={onPrevShirt}>‹</button>
                  <span className="editor-pos">{user.shirts.indexOf(shirtId)+1}/{user.shirts.length}</span>
                  <button className="icon-btn" disabled={!hasNext} onClick={onNextShirt}>›</button>
                </div>
              }/>

      <div className="editor-grid">
        {/* LEFT: Logo library */}
        <div className="panel logo-lib">
          <div className="panel-h">БИБЛИОТЕКА СТИКЕРОВ</div>
          <input className="text-input small" placeholder="Поиск..." value={logoSearch} onChange={e => setLogoSearch(e.target.value)}/>
          <div className="lib-limit">
            <span className="lib-limit-text">
              {limitReached
                ? `${activeZone.viewLabel}: лимит ${zoneLimit} из ${zoneLimit}`
                : `${activeZone.viewLabel}: можно добавить ещё ${zoneLimit - designs.length} из ${zoneLimit}`}
            </span>
          </div>
          <div className="lib-list">
            {visibleLogoGroups.map(group => (
              <div key={group.id} className="lib-group">
                <div className="lib-group-title">{group.name}</div>
                {group.items.map(l => (
                  <button key={l.id} className="lib-item" disabled={locked}
                          draggable={!locked}
                          onDragStart={(e) => handleLibraryDragStart(e, l.id)}
                          onClick={() => addDesign(l.id)}>
                    <div className="lib-item-preview">
                      {l.dataUri || l.inlineMarkup || l.id.startsWith('user-')
                        ? <LogoRender logoId={l.id} color="var(--text)" customLib={customLib}/>
                        : <Sticker src={l.src} color="var(--text)"/>}
                    </div>
                    <div className="lib-item-name">{l.name}</div>
                    <div className="lib-item-add">+</div>
                  </button>
                ))}
              </div>
            ))}
            {filteredLogos.length === 0 && (
              <div className="lib-empty">Ничего не найдено</div>
            )}
          </div>
        </div>

        {/* CENTER: Canvas */}
        <div className="canvas-area">
          <div className="editor-stage-head">
            <div className="active-zone-strip">
              <span>{activeZone.viewLabel}</span>
              <small>{designs.length}/{zoneLimit} · {activeZone.printW}×{activeZone.printH}мм</small>
            </div>
            <label className="zoom-control">
              <span>Масштаб {Math.round(zoom * 100)}%</span>
              <input type="range" min="0.65" max="3" step="0.05" value={zoom}
                     onChange={e => setZoom(parseFloat(e.target.value) || 1)}/>
              <button type="button" className="copy-btn" onClick={() => setZoom(1)}>100%</button>
            </label>
          </div>

          <div className={`stage ${shirt.color}`}>
            <div
              ref={stageScrollRef}
              className={`dual-stage-scroll ${isPanning ? 'panning' : ''}`}
              {...panHandlers}
            >
              <div className="dual-stage-views">
                {EDITOR_ZONE_ORDER.map(renderZoneCard)}
              </div>
            </div>
            <div className="stage-footer">
              <div className="stage-toggle">
            <label><input type="checkbox" checked={snap} onChange={e => setSnap(e.target.checked)}/> Привязка к сетке</label>
                <label><input type="checkbox" checked={showRulers} onChange={e => setShowRulers(e.target.checked)}/> Контуры зон</label>
              </div>
              <div className="stage-info">
                Активная зона: <b>{activeZone.viewLabel} · {activeZone.printW}×{activeZone.printH} мм</b>
              </div>
            </div>
          </div>
        </div>

        {/* RIGHT: Inspector */}
        <div className="panel inspector">
          <div className="panel-h">СВОЙСТВА</div>
          {!selDesign ? (
            <div className="inspector-empty">
              <div className="i-empty-icon">◌</div>
              <div className="i-empty-text">Выберите принт на футболке<br/>или добавьте из библиотеки</div>
            </div>
          ) : (
            <div className="inspector-fields">
              <div className="i-section">
                <div className="panel-h-small">ЭЛЕМЕНТ</div>
                <div className="i-logo-preview" style={{ color: selDesign.color, background: contrastStickerColor(selDesign.color) }}>
                  <div className="i-logo-preview-art" style={{ transform: `scale(${selDesign.flipX ? -1 : 1}, ${selDesign.flipY ? -1 : 1})` }}>
                    <LogoRender logoId={selDesign.logoId} color={selDesign.color} customText={selDesign.customText} customLib={customLib} fillMode={selDesign.fillMode}/>
                  </div>
                </div>
                <div className="i-logo-name">
                  {selDesign.logoId === 'user-text' ? '"' + (selDesign.customText || 'TEXT') + '"' :
                   (stickerLibrary.find(l => l.id === selDesign.logoId)?.name || 'Стикер')}
                </div>
              </div>

              <div className="i-section">
                <div className="panel-h-small">ЦВЕТ ПЕЧАТИ</div>
                <InkSwatchRow value={selDesign.color} onChange={setSelColor}/>
                <button className="btn ghost full small" onClick={invertSelected}>⇄ ИНВЕРТИРОВАТЬ</button>
                <button className={`btn ghost full small ${selDesign.fillMode === 'contrast-fill' ? 'active' : ''}`}
                        onClick={toggleFillMode}
                        title="Добавить контрастную заливку замкнутых контуров">
                  ◩ КОНТРАСТНАЯ ЗАЛИВКА
                </button>
              </div>

              <div className="i-section">
                <div className="panel-h-small">ОПЕРАЦИИ</div>
                <div className="i-actions">
                  <button className={`btn ghost small ${selDesign.flipX ? 'active' : ''}`} onClick={() => mirrorSelected('x')}>⇋ Зеркало X</button>
                  <button className={`btn ghost small ${selDesign.flipY ? 'active' : ''}`} onClick={() => mirrorSelected('y')}>⇵ Зеркало Y</button>
                  <button className="btn ghost small" disabled={limitReached} onClick={duplicateSelected}>⧉ Копия</button>
                </div>
              </div>

              {showTechFields && (
                <div className="i-section">
                  <div className="panel-h-small">ПОЗИЦИЯ И РАЗМЕР</div>
                  <div className="num-grid">
                    <NumField label="X, мм" value={Math.round((selDesign.x/100) * activeZone.printW)}
                              onChange={v => updateItem(selected, { x: NordicrewGeometry.clamp((v / activeZone.printW)*100, 0, 100) })}/>
                    <NumField label="Y, мм" value={Math.round((selDesign.y/100) * activeZone.printH)}
                              onChange={v => updateItem(selected, { y: NordicrewGeometry.clamp((v / activeZone.printH)*100, 0, 100) })}/>
                    <NumField label="W, мм" value={Math.round((selDesign.w/100) * activeZone.printW)}
                              onChange={v => updateItem(selected, { w: NordicrewGeometry.clamp((v / activeZone.printW)*100, 4, 200) })}/>
                    <NumField label="H, мм" value={Math.round((selDesign.h/100) * activeZone.printH)}
                              onChange={v => updateItem(selected, { h: NordicrewGeometry.clamp((v / activeZone.printH)*100, 4, 200) })}/>
                    <NumField label="Поворот°" value={selDesign.rotation || 0}
                              onChange={v => updateItem(selected, { rotation: v })}/>
                  </div>
                </div>
              )}

              <div className="i-section">
                <div className="i-actions">
                  <button className="btn ghost small" onClick={() => updateItem(selected, { x: 50 })}>↔ Центр X</button>
                  <button className="btn ghost small" onClick={() => updateItem(selected, { rotation: 0 })}>↻ Сброс</button>
                  <button className="btn danger small" onClick={deleteItem}>🗑 Удалить</button>
                </div>
              </div>
            </div>
          )}

          <div className="inspector-bottom">
            <div className="i-section">
              <button className="btn danger ghost full small" disabled={locked || allZonesEmpty} onClick={clearShirtDesign}>
                🗑 ОЧИСТИТЬ ФУТБОЛКУ
              </button>
            </div>
            <div className="i-section">
              <div className="panel-h-small">КОПИРОВАТЬ ДИЗАЙН В…</div>
              <button className="btn ghost full small" onClick={() => setShowCopyMenu(s => !s)}>↗ Скопировать всю футболку</button>
              {showCopyMenu && (
                <div className="copy-menu">
                  {myShirts.filter(s => s.id !== shirtId).map(s => (
                    <div key={s.id} className="copy-row">
                      <div className="copy-row-label">
                        <span className="card-color-dot" style={{ background: s.color === 'white' ? '#fff' : '#0a0a0c' }}/>
                        {shirtColorLabel(s.color)} · {s.size}
                      </div>
                      <button className="copy-btn" onClick={() => copyShirtDesignTo(s.id)}>ВЕСЬ ДИЗАЙН →</button>
                    </div>
                  ))}
                </div>
              )}
            </div>

            {shirt.status === 'done' && !locked && (
              <button className="btn ghost full" onClick={() => setShirts(prev => ({ ...prev, [shirtId]: { ...prev[shirtId], status: 'in-progress' } }))}>
                ВЕРНУТЬ В РАБОТУ
              </button>
            )}
            <button className="btn primary full" disabled={allZonesEmpty || shirt.status === 'done' || locked} onClick={finalizeShirt}>
              {shirt.status === 'done' ? '✓ ФУТБОЛКА ГОТОВА' : 'ОТМЕТИТЬ КАК ГОТОВУЮ'}
            </button>
            {hasNext && <button className="btn ghost full" onClick={onNextShirt}>СЛЕДУЮЩАЯ ФУТБОЛКА →</button>}
          </div>
        </div>
      </div>
    </div>
  );
}

function NumField({ label, value, onChange }) {
  const [draft, setDraft] = usE(String(value ?? 0));
  const [editing, setEditing] = usE(false);

  ueE(() => {
    if (!editing) setDraft(String(value ?? 0));
  }, [value, editing]);

  const commit = () => {
    setEditing(false);
    const normalized = String(draft).replace(',', '.').trim();
    if (normalized === '' || normalized === '-' || normalized === '.') {
      setDraft(String(value ?? 0));
      return;
    }
    const next = Number.parseFloat(normalized);
    if (!Number.isFinite(next)) {
      setDraft(String(value ?? 0));
      return;
    }
    onChange(next);
  };

  const cancel = () => {
    setEditing(false);
    setDraft(String(value ?? 0));
  };

  return (
    <label className="num-field">
      <span>{label}</span>
      <input
        type="text"
        inputMode="decimal"
        value={editing ? draft : value}
        onFocus={() => {
          setEditing(true);
          setDraft(String(value ?? 0));
        }}
        onChange={e => setDraft(e.target.value)}
        onBlur={commit}
        onKeyDown={e => {
          if (e.key === 'Enter') {
            e.preventDefault();
            e.currentTarget.blur();
          }
          if (e.key === 'Escape') {
            e.preventDefault();
            cancel();
          }
        }}
      />
    </label>
  );
}

Object.assign(window, { EditorScreen, NumField });
