/* ctor-teams.jsx — прорабы и команды (роль → исполнители) */
const { useState: tmUseState } = React;
const tmUid = window.ConstructorData.uid;
function tmInitials(name) { return (name || '?').split(/\s+/).map((w) => w[0]).slice(0, 2).join('').toUpperCase(); }

/* ============ БАЗА ИСПОЛНИТЕЛЕЙ (пул по ролям) ============ */
/* grade: 0–1 → Элита, 2–3 → Профи · load: low|mid|high (текущая загрузка) */
const EXECUTOR_POOL = {
  demolisher:  [{ n:'—', g:1, load:'low' }, { n:'—', g:2, load:'mid' }, { n:'—', g:3, load:'high' }],
  laborer:     [{ n:'—', g:3, load:'mid' }, { n:'—', g:3, load:'low' }, { n:'—', g:2, load:'high' }],
  mason:       [{ n:'—', g:1, load:'low' }, { n:'—', g:2, load:'mid' }],
  electrician: [{ n:'—', g:0, load:'mid' }, { n:'—', g:1, load:'low' }, { n:'—', g:2, load:'high' }],
  lowvolt:     [{ n:'—', g:1, load:'low' }, { n:'—', g:2, load:'mid' }],
  plumber:     [{ n:'—', g:0, load:'mid' }, { n:'—', g:1, load:'low' }, { n:'—', g:2, load:'high' }],
  hvac:        [{ n:'—', g:1, load:'mid' }, { n:'—', g:2, load:'low' }],
  ac_tech:     [{ n:'—', g:1, load:'low' }, { n:'—', g:2, load:'mid' }],
  screeder:    [{ n:'—', g:2, load:'low' }, { n:'—', g:1, load:'mid' }, { n:'—', g:3, load:'high' }],
  plasterer:   [{ n:'—', g:1, load:'mid' }, { n:'—', g:2, load:'low' }],
  waterproofer:[{ n:'—', g:1, load:'low' }, { n:'—', g:2, load:'mid' }],
  tiler:       [{ n:'—', g:0, load:'mid' }, { n:'—', g:1, load:'low' }, { n:'—', g:2, load:'high' }],
  painter:     [{ n:'—', g:2, load:'mid' }, { n:'—', g:1, load:'low' }, { n:'—', g:0, load:'high' }],
  carpenter:   [{ n:'—', g:1, load:'low' }, { n:'—', g:2, load:'mid' }],
  furniture:   [{ n:'—', g:1, load:'mid' }, { n:'—', g:2, load:'low' }],
  cleaner:     [{ n:'—', g:3, load:'low' }, { n:'—', g:3, load:'mid' }],
  designer:    [{ n:'—', g:0, load:'mid' }, { n:'—', g:1, load:'low' }],
  architect:   [{ n:'—', g:0, load:'mid' }],
};
function poolFor(roleId) {
  if (EXECUTOR_POOL[roleId]) return EXECUTOR_POOL[roleId];
  // фолбэк — генерим пару условных исполнителей
  return [{ n:'Исполнитель 1', g:2, load:'low' }, { n:'Исполнитель 2', g:1, load:'mid' }];
}
const LOAD_META = { low:{ c:'#5aad6e', l:'свободен' }, mid:{ c:'#e8a33a', l:'загружен' }, high:{ c:'#f04e62', l:'перегружен' } };
function gradeMeta(g) { return g <= 1 ? { l:'Элита '+g, c:'#7c3aed', bg:'#f3eafe' } : { l:'Профи '+g, c:'#e8793a', bg:'#fff0e6' }; }

function memberMeta(name, roleId) {
  const rec = poolFor(roleId).find((p) => p.n === name);
  return rec ? { grade: rec.g, load: rec.load } : { grade: null, load: null };
}

function buildTeamPreview(team, roles, extraRoles) {
  const items = [];
  const pushRole = (r) => {
    (team[r.id] || []).forEach((name) => {
      const meta = memberMeta(name, r.id);
      items.push({ role: r, name, ...meta });
    });
  };
  roles.forEach(pushRole);
  (extraRoles || []).forEach(pushRole);
  return items;
}

function TeamPreviewStrip({ team, roles, extraRoles, max = 9 }) {
  const items = buildTeamPreview(team, roles, extraRoles);
  if (!items.length) {
    return (
      <div className="team-preview team-preview--empty">
        Команда пуста — раскройте карточку и назначьте исполнителей по trade-ролям
      </div>
    );
  }
  const roleIds = new Set(items.map((it) => it.role.id));
  const vis = items.slice(0, max);
  const rest = items.length - vis.length;
  return (
    <div className="team-preview">
      {vis.map((it) => {
        const gm = it.grade != null ? gradeMeta(it.grade) : null;
        const lm = it.load ? LOAD_META[it.load] : null;
        return (
          <span
            key={it.role.id + '::' + it.name}
            className="team-preview-chip"
            title={[it.role.name, it.name, gm && gm.l, lm && lm.l].filter(Boolean).join(' · ')}
          >
            <span className="team-preview-role" style={{ background: it.role.color }}>{it.role.abbr}</span>
            <span className="team-preview-body">
              <span className="team-preview-trade">{it.role.name}</span>
              <span className="team-preview-name">{it.name}</span>
            </span>
            {gm && <span className="team-preview-grade" style={{ color: gm.c, background: gm.bg }}>{gm.l}</span>}
            {lm && <span className="team-preview-load" style={{ background: lm.c }} title={lm.l} />}
          </span>
        );
      })}
      {rest > 0 && <span className="team-preview-more">+{rest}</span>}
      <span className="team-preview-meta">{items.length} чел. · {roleIds.size} {roleIds.size === 1 ? 'роль' : roleIds.size < 5 ? 'роли' : 'ролей'}</span>
    </div>
  );
}

function TeamsPanel({ foremen, setForemen, roles, catalog, hideHeader }) {
  const [openId, setOpenId] = tmUseState(foremen[0] ? foremen[0].id : null);

  // роли, реально используемые в каталоге (их и нужно покрыть команде)
  // менеджер/дизайнер/архитектор НЕ входят в бригаду прораба (ТЗ §4.5)
  const FOREMAN_CREW_EXCLUDE = new Set(['pm', 'designer', 'architect']);
  const usedRoleIds = new Set();
  catalog.forEach((ph) => ph.stages.forEach((st) => st.tasks.forEach((tk) => {
    if (tk.role && !FOREMAN_CREW_EXCLUDE.has(tk.role)) usedRoleIds.add(tk.role);
    (tk.sub || []).forEach((su) => { if (su.role && !FOREMAN_CREW_EXCLUDE.has(su.role)) usedRoleIds.add(su.role); });
  })));
  const usedRoles = roles.filter((r) => usedRoleIds.has(r.id));

  const update = (id, patch) => setForemen((fs) => fs.map((f) => (f.id === id ? { ...f, ...patch } : f)));
  const updateTeam = (id, roleId, names) => setForemen((fs) => fs.map((f) => (f.id === id ? { ...f, team: { ...f.team, [roleId]: names } } : f)));
  const add = () => {
    const f = { id: tmUid('frm'), name: 'Новый прораб', brigade: 'Бригада', phone: '', durationMul: 1.0, note: '', team: {} };
    setForemen((fs) => [...fs, f]);
    setOpenId(f.id);
  };
  const remove = (id) => { if (confirm('Удалить прораба и его команду?')) setForemen((fs) => fs.filter((f) => f.id !== id)); };

  const coverage = (f) => {
    const covered = usedRoles.filter((r) => (f.team[r.id] || []).length > 0).length;
    return { covered, total: usedRoles.length };
  };

  return (
    <div>
      {!hideHeader && (
      <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: 600 }}>
            Прораб заранее закрепляет исполнителей за ролями. При выборе прораба в калькуляторе система автоматически назначает их на задачи по совпадению роли — с возможностью ручной правки в смете.
          </div>
        </div>
        <button onClick={add} style={ctorStyles.btnPrimary}>{Icon.plus} Прораб</button>
      </div>
      )}

      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        {foremen.map((f) => {
          const open = openId === f.id;
          const cov = coverage(f);
          const full = cov.covered === cov.total && cov.total > 0;
          const extraRoles = roles.filter((r) => !usedRoleIds.has(r.id) && (f.team[r.id] || []).length > 0);
          return (
            <div key={f.id} style={{ ...ctorStyles.card, padding: 0, overflow: 'hidden' }}>
              {/* HEAD */}
              <div style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '16px 20px', cursor: 'pointer' }}
                onClick={() => setOpenId(open ? null : f.id)}>
                <span style={{ width: 44, height: 44, borderRadius: '50%', background: '#1a1714', color: '#fff', fontSize: 16, fontWeight: 600, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                  {f.name.split(' ').map((w) => w[0]).slice(0, 2).join('')}
                </span>
                <div style={{ flex: 1, minWidth: 0 }} onClick={(e) => e.stopPropagation()}>
                  <InlineInput value={f.name} onCommit={(v) => update(f.id, { name: v || 'Прораб' })}
                    style={{ fontSize: 17, fontWeight: 600, letterSpacing: '-.015em', color: '#1a1714', width: '100%' }} />
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 1 }}>
                    <InlineInput value={f.brigade} onCommit={(v) => update(f.id, { brigade: v })}
                      style={{ fontSize: 13, color: '#8a817a', width: 'auto', minWidth: 80 }} />
                    {f.phone && <span style={{ fontSize: 13, color: '#bcb3a7' }}>· {f.phone}</span>}
                  </div>
                  <TeamPreviewStrip team={f.team} roles={usedRoles} extraRoles={extraRoles} />
                </div>
                {/* coverage */}
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }} onClick={(e) => e.stopPropagation()}>
                  <span title="Множитель сроков бригады" style={{ ...ctorStyles.numField, padding: '4px 10px 4px 6px' }}>
                    <span style={{ fontSize: 11, color: '#8a817a', fontWeight: 500 }}>×</span>
                    <input type="number" min={0.5} max={2} step={0.05} value={f.durationMul}
                      onChange={(e) => update(f.id, { durationMul: Math.max(0.5, +e.target.value || 1) })}
                      style={{ ...ctorStyles.numInput, width: 42, textAlign: 'left' }} />
                  </span>
                </div>
                <span style={{
                  fontSize: 12, fontWeight: 600, padding: '4px 11px', borderRadius: 980, whiteSpace: 'nowrap',
                  background: full ? '#f0fdf4' : '#fffbeb', color: full ? '#5aad6e' : '#92620a',
                }}>
                  {full ? '✓ команда укомплектована' : `${cov.covered}/${cov.total} ролей`}
                </span>
                <KebabMenu items={[
                  { icon: Icon.trash, label: 'Удалить прораба', onClick: () => remove(f.id), danger: true },
                ]} />
                <span style={{ ...ctorStyles.iconBtn, color: '#bcb3a7', transform: open ? 'rotate(90deg)' : 'none', transition: 'transform .15s' }}>{Icon.chevron}</span>
              </div>

              {/* BODY */}
              {open && (
                <div style={{ borderTop: '.5px solid #f0ece5', padding: '16px 20px 20px', background: '#fcfcfd' }}>
                  <div style={{ display: 'flex', gap: 10, marginBottom: 18, flexWrap: 'wrap' }}>
                    <label style={{ display: 'flex', flexDirection: 'column', gap: 4, flex: 1, minWidth: 200 }}>
                      <span style={ctorStyles.fieldLabel}>Телефон</span>
                      <InlineInput value={f.phone} onCommit={(v) => update(f.id, { phone: v })} placeholder="+7 ..."
                        style={{ ...ctorStyles.input, padding: '8px 10px' }} />
                    </label>
                    <label style={{ display: 'flex', flexDirection: 'column', gap: 4, flex: 2, minWidth: 240 }}>
                      <span style={ctorStyles.fieldLabel}>Заметка</span>
                      <InlineInput value={f.note} onCommit={(v) => update(f.id, { note: v })} placeholder="Специализация бригады"
                        style={{ ...ctorStyles.input, padding: '8px 10px' }} />
                    </label>
                  </div>

                  <div style={{ ...ctorStyles.sectionLabel, marginBottom: 12 }}>Состав команды по ролям</div>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                    {usedRoles.map((r) => (
                      <TeamRow key={r.id} role={r} names={f.team[r.id] || []} onChange={(names) => updateTeam(f.id, r.id, names)} />
                    ))}
                    {usedRoles.length === 0 && (
                      <div style={{ fontSize: 13, color: '#8a817a' }}>В каталоге пока нет задач с ролями.</div>
                    )}
                  </div>

                  {/* Прочие роли вне каталога, но заполненные */}
                  {extraRoles.length > 0 && (
                      <div style={{ marginTop: 14 }}>
                        <div style={{ ...ctorStyles.sectionLabel, marginBottom: 10, color: '#bcb3a7' }}>Прочие роли</div>
                        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                          {extraRoles.map((r) => <TeamRow key={r.id} role={r} names={f.team[r.id] || []} onChange={(names) => updateTeam(f.id, r.id, names)} />)}
                        </div>
                      </div>
                    )}
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* TeamRow — роль + чипы исполнителей + dropdown выбора из базы */
function TeamRow({ role, names, onChange }) {
  const [open, setOpen] = tmUseState(false);
  const [q, setQ] = tmUseState('');
  const wrapRef = React.useRef(null);
  const removeName = (n) => onChange(names.filter((x) => x !== n));
  const addName = (n) => { if (!names.includes(n)) onChange([...names, n]); setQ(''); setOpen(false); };

  const pool = poolFor(role.id);
  const filtered = pool.filter((p) => p.n.toLowerCase().includes(q.toLowerCase()));

  React.useEffect(() => {
    if (!open) return;
    const onDown = (e) => { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false); };
    const onKey = (e) => { if (e.key === 'Escape') setOpen(false); };
    document.addEventListener('mousedown', onDown);
    document.addEventListener('keydown', onKey);
    return () => { document.removeEventListener('mousedown', onDown); document.removeEventListener('keydown', onKey); };
  }, [open]);

  return (
    <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12, padding: '8px 0', borderBottom: '.5px solid #f3f3f6' }}>
      <div style={{ width: 178, flexShrink: 0, paddingTop: 4 }}>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 7 }}>
          <span style={{ width: 22, height: 22, borderRadius: '50%', background: role.color, color: '#fff', fontSize: 9.5, fontWeight: 700, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{role.abbr}</span>
          <span style={{ fontSize: 13.5, fontWeight: 500, color: '#1a1714' }}>{role.name}</span>
        </span>
      </div>
      <div style={{ flex: 1, display: 'flex', flexWrap: 'wrap', gap: 6, alignItems: 'center' }}>
        {names.map((n) => {
          const rec = pool.find((p) => p.n === n);
          const gm = rec ? gradeMeta(rec.g) : null;
          return (
            <span key={n} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '4px 6px 4px 7px', borderRadius: 980, background: '#fff', border: '.5px solid #e4ddd2', fontSize: 13, color: '#1a1714', boxShadow: '0 1px 2px rgba(0,0,0,.03)' }}>
              <span style={{ width: 20, height: 20, borderRadius: '50%', background: role.color, color: '#fff', fontSize: 8.5, fontWeight: 700, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>{tmInitials(n)}</span>
              <span style={{ display: 'flex', flexDirection: 'column', gap: 1, lineHeight: 1.2 }}>
                <span style={{ fontSize: 10, fontWeight: 700, color: role.color, letterSpacing: '.02em' }}>{role.abbr} · {role.name}</span>
                <span>{n}</span>
              </span>
              {gm && <span style={{ fontSize: 10, fontWeight: 700, color: gm.c, background: gm.bg, padding: '1px 6px', borderRadius: 999 }}>{gm.l}</span>}
              {rec && <span title={LOAD_META[rec.load].l} style={{ width: 7, height: 7, borderRadius: '50%', background: LOAD_META[rec.load].c, flexShrink: 0 }}></span>}
              <button onClick={() => removeName(n)} style={{ ...ctorStyles.iconBtnSm, width: 18, height: 18, color: '#bcb3a7' }} title="Убрать">{Icon.x}</button>
            </span>
          );
        })}
        {/* dropdown trigger */}
        <div ref={wrapRef} style={{ position: 'relative' }}>
          <button onClick={() => setOpen((o) => !o)} style={{
            display: 'inline-flex', alignItems: 'center', gap: 5, padding: '5px 11px 5px 9px', borderRadius: 980,
            background: open ? '#fff0e6' : '#f0ece5', border: '.5px solid ' + (open ? '#e8793a40' : 'transparent'),
            color: open ? '#e8793a' : '#6b6259', fontSize: 12.5, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit', transition: 'all .12s',
          }}>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
            {names.length ? 'ещё' : 'исполнитель'}
          </button>
          {open && (
            <div style={{
              position: 'absolute', top: 'calc(100% + 6px)', left: 0, width: 300, zIndex: 60,
              background: '#fff', borderRadius: 14, border: '.5px solid #e4ddd2', boxShadow: '0 14px 40px rgba(0,0,0,.16)',
              overflow: 'hidden', animation: 'popIn .13s cubic-bezier(.32,.72,0,1)',
            }}>
              <div style={{ padding: '10px 12px', borderBottom: '.5px solid #f0ece5' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 7, marginBottom: 2 }}>
                  <span style={{ width: 18, height: 18, borderRadius: '50%', background: role.color, color: '#fff', fontSize: 8, fontWeight: 700, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{role.abbr}</span>
                  <span style={{ fontSize: 12, fontWeight: 700, color: '#1a1714' }}>{role.name}</span>
                  <span style={{ fontSize: 11, color: '#a89e92', marginLeft: 'auto' }}>{filtered.length} в базе</span>
                </div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 7, background: '#f0ece5', borderRadius: 9, padding: '6px 10px', marginTop: 6 }}>
                  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#8a817a" strokeWidth="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
                  <input autoFocus value={q} onChange={(e) => setQ(e.target.value)} placeholder="Поиск по имени"
                    style={{ border: 'none', outline: 'none', background: 'transparent', fontFamily: 'inherit', fontSize: 12.5, flex: 1, color: '#1a1714' }} />
                </div>
              </div>
              <div style={{ maxHeight: 248, overflowY: 'auto', padding: 5 }}>
                {filtered.map((p) => {
                  const added = names.includes(p.n);
                  const gm = gradeMeta(p.g);
                  return (
                    <button key={p.n} onClick={() => !added && addName(p.n)} disabled={added} style={{
                      width: '100%', display: 'flex', alignItems: 'center', gap: 10, padding: '8px 9px', borderRadius: 9, border: 'none',
                      background: 'transparent', cursor: added ? 'default' : 'pointer', fontFamily: 'inherit', textAlign: 'left', opacity: added ? 0.5 : 1,
                    }}
                    onMouseEnter={(e) => { if (!added) e.currentTarget.style.background = '#fff7f0'; }}
                    onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}>
                      <span style={{ width: 28, height: 28, borderRadius: '50%', background: role.color, color: '#fff', fontSize: 10, fontWeight: 700, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>{tmInitials(p.n)}</span>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontSize: 13, fontWeight: 500, color: '#1a1714' }}>{p.n}</div>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 2 }}>
                          <span style={{ fontSize: 10.5, fontWeight: 700, color: gm.c, background: gm.bg, padding: '1px 7px', borderRadius: 980 }}>{gm.l}</span>
                          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, fontSize: 11, color: '#8a817a' }}>
                            <span style={{ width: 6, height: 6, borderRadius: '50%', background: LOAD_META[p.load].c }}></span>{LOAD_META[p.load].l}
                          </span>
                        </div>
                      </div>
                      {added
                        ? <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#5aad6e" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>
                        : <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#bcb3a7" strokeWidth="2.4" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>}
                    </button>
                  );
                })}
                {filtered.length === 0 && (
                  <div style={{ padding: '20px 12px', textAlign: 'center', color: '#a89e92', fontSize: 12.5 }}>Никто не найден</div>
                )}
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { TeamsPanel, EXECUTOR_POOL });
