/* ctor-team-grant.jsx — «Доступ в систему» для профиля штата.
   Профиль каталога = шаблон для сметы. Приглашение создаёт учётную запись
   (AccessStore, remontpro_access_v1) и открывает рабочее пространство роли.
   W1 ACCESS-MODEL: права на разделы = тумблеры зон из window.LK_ZONES
   (генерируется из scripts/lk-pages-config.js — единый источник). */
const { useState: grUseState } = React;

/* какая роль и какое пространство соответствуют типу профиля */
const ROLE_WORKSPACE = {
  manager:     { role: 'Менеджер',      hue: 212, lk: 'lk/manager.html',
    caps: [{ id: 'crm:analytics:read', l: 'CRM-аналитика и дашборды', def: false }, { id: 'leads:claim', l: 'Брать лиды из пула', def: true }] },
  designer:    { role: 'Дизайнер',      hue: 268, lk: 'lk/designer.html',
    caps: [{ id: 'material:approve', l: 'Утверждать материалы', def: true }] },
  architect:   { role: 'Архитектор',    hue: 200, lk: null, caps: [] },
  foreman:     { role: 'Прораб',        hue: 4,   lk: 'lk/foreman.html',
    caps: [{ id: 'team:edit:own', l: 'Менять свою бригаду', def: true }] },
  executor:    { role: 'Исполнитель',   hue: 24,  lk: 'lk/executor.html', caps: [] },
  accountant:  { role: 'Бухгалтер',     hue: 158, lk: 'lk/accountant.html',
    caps: [{ id: 'billing:read', l: 'Платёжные документы', def: true }] },
  procurement: { role: 'Закупщик',      hue: 32,  lk: 'lk/procurement.html', caps: [] },
  people:      { role: 'People Ops',    hue: 288, lk: null, caps: [] }, // кабинет скрыт до HR-контура (волна 1)
  super:       { role: 'Super Admin',   hue: 0,   lk: 'lk/super.html', caps: [] },
};
const GR_STATUS = {
  none:    { l: 'Нет доступа', c: 'var(--text-tertiary)', bg: 'var(--secondary)' },
  invited: { l: 'Приглашён',   c: 'var(--warning-strong)', bg: 'var(--warning-soft)' },
  active:  { l: 'В системе',   c: 'var(--success-strong)', bg: 'var(--success-soft)' },
  paused:  { l: 'Пауза',       c: 'var(--warning-strong)', bg: 'var(--warning-soft)' },
  revoked: { l: 'Отозван',     c: 'var(--destructive)',    bg: 'color-mix(in srgb, var(--destructive) 10%, transparent)' },
};

function grInitials(n) { return (n || '?').split(/\s+/).map((w) => w[0]).slice(0, 2).join('').toUpperCase(); }
function grZonesFor(kind) {
  const z = (window.LK_ZONES || {})[kind];
  return z ? z.zones : null;
}

const GR_IC = {
  send: <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>,
  check: <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>,
  ext: <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>,
  lock: <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>,
};

/* ============ чип статуса + модал ============ */
function WorkspaceAccess({ profile, kind }) {
  const [open, setOpen] = grUseState(false);
  const [rec, setRec] = grUseState(() => window.AccessStore.getAccount(profile.id));
  const status = rec ? rec.status : 'none';
  const s = GR_STATUS[status] || GR_STATUS.none;
  const persist = (patch) => {
    if (patch === null) { window.AccessStore.revoke(profile.id); setRec(window.AccessStore.getAccount(profile.id)); return; }
    setRec(window.AccessStore.upsertAccount(profile.id, patch, rec ? 'grant_updated' : 'granted'));
  };
  return (
    <>
      <button onClick={(e) => { e.stopPropagation(); setOpen(true); }} title="Доступ в рабочее пространство" style={{
        display: 'inline-flex', alignItems: 'center', gap: 6, padding: '3px 10px 3px 8px', borderRadius: 'var(--radius-pill, 9999px)', cursor: 'pointer', fontFamily: 'inherit',
        fontSize: 11.5, fontWeight: 700, color: s.c, background: s.bg,
        border: status === 'none' ? '1px dashed color-mix(in srgb, var(--text-tertiary) 35%, transparent)' : 'none',
      }}>
        <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'currentColor' }} />
        {status === 'none' ? 'Выдать доступ' : s.l}
      </button>
      {open && <WorkspaceModal profile={profile} kind={kind} rec={rec} onPersist={persist} onClose={() => setOpen(false)} />}
    </>
  );
}

function WorkspaceModal({ profile, kind, rec, onPersist, onClose }) {
  const meta = ROLE_WORKSPACE[kind] || ROLE_WORKSPACE.executor;
  const zoneDict = grZonesFor(kind); /* { zoneId: label } | null (нет ЛК) */
  const [email, setEmail] = grUseState((rec && rec.email) || profile.email || '');
  const [caps, setCaps] = grUseState(() => {
    const init = {}; meta.caps.forEach((c) => { init[c.id] = rec && rec.caps && c.id in rec.caps ? rec.caps[c.id] : c.def; }); return init;
  });
  const [zones, setZones] = grUseState(() => {
    const init = {};
    if (zoneDict) Object.keys(zoneDict).forEach((z) => { init[z] = rec && rec.zones && z in rec.zones ? rec.zones[z] !== false : true; });
    return init;
  });
  const status = rec ? rec.status : 'none';
  const zonesOn = Object.values(zones).filter(Boolean).length;
  const invite = () => onPersist({
    email, status: 'active', caps, zones,
    role: kind, roleLabel: meta.role,
    name: profile.name, phone: profile.phone || null,
    invitedAt: (rec && rec.invitedAt) || new Date().toISOString(),
  });
  const revoke = () => onPersist(null);
  const lkHref = meta.lk ? meta.lk + '?user=' + encodeURIComponent(profile.id) : null;

  return ReactDOM.createPortal((
    <div style={ctorStyles.modalBackdrop} onClick={onClose}>
      <div style={{ ...ctorStyles.modal, width: 'min(500px, 100%)', maxHeight: '86vh', overflowY: 'auto' }} onClick={(e) => e.stopPropagation()}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 18 }}>
          <span style={{ width: 44, height: 44, borderRadius: '50%', background: `hsl(${meta.hue} 52% 46%)`, color: '#fff', fontSize: 15, fontWeight: 700, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>{grInitials(profile.name)}</span>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 17, fontWeight: 800, letterSpacing: '-.02em', color: 'var(--foreground)' }}>{profile.name}</div>
            <div style={{ fontSize: 12.5, color: 'var(--text-tertiary)' }}>Роль в системе: <b style={{ color: 'var(--foreground)' }}>{meta.role}</b></div>
          </div>
          <span style={{ fontSize: 11.5, fontWeight: 700, color: (GR_STATUS[status] || GR_STATUS.none).c, background: (GR_STATUS[status] || GR_STATUS.none).bg, padding: '3px 11px', borderRadius: 'var(--radius-pill, 9999px)' }}>{(GR_STATUS[status] || GR_STATUS.none).l}</span>
        </div>

        {/* email */}
        <label style={{ display: 'block', marginBottom: 16 }}>
          <span style={ctorStyles.fieldLabel}>Email для приглашения</span>
          <input value={email} onChange={(e) => setEmail(e.target.value)} placeholder="name@company.ru" style={{ ...ctorStyles.input, padding: '9px 11px', marginTop: 5 }} />
        </label>

        {/* права на разделы ЛК */}
        {zoneDict ? (
          <>
            <div style={{ ...ctorStyles.sectionLabel, marginBottom: 9 }}>
              Разделы кабинета <span style={{ fontWeight: 600, textTransform: 'none', letterSpacing: 0, color: 'var(--text-tertiary)' }}>· открыто {zonesOn} из {Object.keys(zoneDict).length}</span>
            </div>
            <div style={{ marginBottom: 16, borderRadius: 12, border: '1px solid var(--border-subtle)', overflow: 'hidden' }}>
              {Object.entries(zoneDict).map(([z, label], i, arr) => (
                <label key={z} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '9px 14px', cursor: 'pointer', borderBottom: i < arr.length - 1 ? '1px solid var(--border-subtle)' : 'none', opacity: zones[z] ? 1 : 0.55 }}>
                  <input type="checkbox" checked={!!zones[z]} onChange={(e) => setZones((x) => ({ ...x, [z]: e.target.checked }))} style={{ width: 16, height: 16, accentColor: 'var(--ink)', cursor: 'pointer' }} />
                  <span style={{ flex: 1, fontSize: 13, fontWeight: 600, color: 'var(--foreground)' }}>{label}</span>
                  <code style={{ fontSize: 10.5, color: 'var(--text-tertiary)', fontFamily: 'ui-monospace, monospace' }}>{z}</code>
                </label>
              ))}
            </div>
          </>
        ) : (
          <div style={{ fontSize: 12.5, color: 'var(--text-tertiary)', background: 'var(--secondary)', borderRadius: 10, padding: '10px 14px', marginBottom: 16 }}>
            У роли «{meta.role}» пока нет рабочего пространства — учётная запись создаётся без разделов.
          </div>
        )}

        {/* доп. возможности (caps) */}
        {meta.caps.length > 0 && (
          <div style={{ marginBottom: 20, borderRadius: 12, border: '1px solid var(--border-subtle)', overflow: 'hidden' }}>
            {meta.caps.map((c, i) => (
              <label key={c.id} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '11px 14px', cursor: 'pointer', borderBottom: i < meta.caps.length - 1 ? '1px solid var(--border-subtle)' : 'none' }}>
                <input type="checkbox" checked={!!caps[c.id]} onChange={(e) => setCaps((x) => ({ ...x, [c.id]: e.target.checked }))} style={{ width: 17, height: 17, accentColor: 'var(--ink)', cursor: 'pointer' }} />
                <span style={{ flex: 1 }}>
                  <span style={{ fontSize: 13.5, fontWeight: 600, color: 'var(--foreground)' }}>{c.l}</span>
                  <code style={{ display: 'block', fontSize: 10.5, color: 'var(--text-tertiary)', fontFamily: 'ui-monospace, monospace' }}>{c.id}</code>
                </span>
              </label>
            ))}
          </div>
        )}

        {/* действия */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 4 }}>
          {status === 'active' && lkHref && (
            <a href={lkHref} style={{ ...ctorStyles.btnGhost, textDecoration: 'none' }}>{GR_IC.ext} Открыть ЛК</a>
          )}
          <div style={{ flex: 1 }} />
          {status !== 'none' && status !== 'revoked'
            ? <button onClick={revoke} style={{ ...ctorStyles.btnGhost, color: 'var(--destructive)', borderColor: 'color-mix(in srgb, var(--destructive) 30%, transparent)' }}>{GR_IC.lock} Отозвать доступ</button>
            : <button onClick={onClose} style={ctorStyles.btnGhost}>Отмена</button>}
          <button onClick={invite} disabled={!email.trim()} style={{ ...ctorStyles.btnPrimary, opacity: email.trim() ? 1 : 0.4, cursor: email.trim() ? 'pointer' : 'not-allowed' }}>
            {GR_IC.send}{status === 'active' ? 'Сохранить' : 'Открыть доступ'}
          </button>
        </div>
        {status === 'none' && <div style={{ fontSize: 11.5, color: 'var(--text-tertiary)', marginTop: 12, lineHeight: 1.5 }}>Профиль каталога остаётся шаблоном для сметы. Приглашение создаёт учётную запись; снятые разделы скрываются из sidebar кабинета.</div>}
      </div>
    </div>
  ), document.body);
}

Object.assign(window, { WorkspaceAccess, ROLE_WORKSPACE });
