/* ctor-access-center.jsx — W3 ACCESS-MODEL: живой центр управления правами.
   Данные: window.AccessStore (remontpro_access_v1) + window.LK_ZONES.
   Отвечает на: кто в системе · кто что видит · кто чем пользуется · кто что менял. */
const { useState: lacUseState } = React;

function lacAgo(iso) {
  if (!iso) return 'ни разу';
  const m = Math.round((Date.now() - new Date(iso).getTime()) / 60000);
  if (m < 1) return 'только что';
  if (m < 60) return m + ' мин назад';
  const h = Math.round(m / 60);
  if (h < 24) return h + ' ч назад';
  return Math.round(h / 24) + ' дн назад';
}
const LAC_STATUS = {
  active:  { l: 'В системе', cls: 'chip chip--required' },
  invited: { l: 'Приглашён', cls: 'chip chip--conditional' },
  paused:  { l: 'Пауза',     cls: 'chip chip--conditional' },
  revoked: { l: 'Отозван',   cls: 'chip chip--data' },
};
const LAC_AUDIT_L = {
  granted: 'Выдан доступ', grant_updated: 'Права обновлены', revoked: 'Доступ отозван',
  zone_on: 'Раздел открыт', zone_off: 'Раздел закрыт', profile_updated: 'Профиль обновлён',
  migrated_legacy: 'Миграция грантов', paused: 'Пауза', resumed: 'Возобновлён',
};

function LacKpi({ v, l, warn }) {
  return (
    <div style={{ ...ctorStyles.card, padding: '14px 18px', minWidth: 132 }}>
      <div style={{ fontSize: 24, fontWeight: 800, fontVariantNumeric: 'tabular-nums', color: warn ? 'var(--warning-strong)' : 'var(--foreground)' }}>{v}</div>
      <div style={{ fontSize: 11.5, color: 'var(--text-tertiary)', fontWeight: 600 }}>{l}</div>
    </div>
  );
}

function LiveAccessCenter() {
  const [tick, setTick] = lacUseState(0);
  const refresh = () => setTick((t) => t + 1);
  const store = window.AccessStore.load();
  const zonesAll = window.LK_ZONES || {};
  const accounts = Object.values(store.accounts || {});
  const activity = store.activity || [];
  const audit = store.audit || [];

  const byStatus = (s) => accounts.filter((a) => a.status === s).length;
  const active7d = new Set(activity.filter((e) => Date.now() - new Date(e.at).getTime() < 7 * 864e5).map((e) => e.acc)).size;
  const restricted = accounts.filter((a) => a.zones && Object.values(a.zones).some((v) => v === false));

  /* матрица роль×зона: allowed / total активных аккаунтов роли */
  const roles = [...new Set(accounts.filter((a) => a.status === 'active').map((a) => a.role))].filter((r) => zonesAll[r]);

  /* обратный вид */
  const [qRole, setQRole] = lacUseState('');
  const [qZone, setQZone] = lacUseState('');
  const reverse = qRole && qZone
    ? accounts.filter((a) => a.role === qRole && a.status === 'active' && window.AccessStore.zoneAllowed(a, qZone))
    : null;

  /* использование зон */
  const zoneUse = {};
  activity.forEach((e) => { zoneUse[e.zone] = (zoneUse[e.zone] || 0) + 1; });
  const topZones = Object.entries(zoneUse).sort((a, b) => b[1] - a[1]).slice(0, 6);

  const quick = (a, patch, type) => { window.AccessStore.upsertAccount(a.profileId, patch, type); refresh(); };

  return (
    <div style={{ marginBottom: 34 }}>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 10, marginBottom: 14 }}>
        <div style={ctorStyles.sectionLabel}>Учётные записи и права · живые данные</div>
        <span style={{ fontSize: 11.5, color: 'var(--text-tertiary)' }}>remontpro_access_v1 · обновлено сейчас</span>
      </div>

      {/* KPI */}
      <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginBottom: 20 }}>
        <LacKpi v={byStatus('active')} l="в системе" />
        <LacKpi v={byStatus('invited')} l="приглашены" warn={byStatus('invited') > 0} />
        <LacKpi v={byStatus('paused') + byStatus('revoked')} l="пауза / отозваны" />
        <LacKpi v={active7d} l="активны за 7 дней" />
        <LacKpi v={restricted.length} l="с ограничениями разделов" warn={restricted.length > 0} />
      </div>

      {accounts.length === 0 && (
        <div style={{ ...ctorStyles.card, padding: '18px 20px', fontSize: 13.5, color: 'var(--text-tertiary)' }}>
          Учётных записей пока нет. Выдайте доступ из подвкладки «Команда (штат)» — кнопка в строке профиля.
        </div>
      )}

      {accounts.length > 0 && (
        <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.45fr) minmax(320px, 1fr)', gap: 22, alignItems: 'start' }}>
          {/* аккаунты */}
          <div style={ctorStyles.card}>
            <div style={{ ...ctorStyles.sectionLabel, marginBottom: 10 }}>Аккаунты · {accounts.length}</div>
            {accounts.map((a, i) => {
              const zd = (zonesAll[a.role] || {}).zones || {};
              const total = Object.keys(zd).length;
              const open = Object.keys(zd).filter((z) => window.AccessStore.zoneAllowed(a, z)).length;
              const st = LAC_STATUS[a.status] || LAC_STATUS.invited;
              const seen = window.AccessStore.lastSeen(a.profileId);
              return (
                <div key={a.profileId} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 2px', borderBottom: i < accounts.length - 1 ? '1px solid var(--border-subtle)' : 'none' }}>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 13.5, fontWeight: 700, color: 'var(--foreground)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{a.name || a.email || a.profileId}</div>
                    <div style={{ fontSize: 11.5, color: 'var(--text-tertiary)' }}>{a.roleLabel || a.role} · {a.status === 'active' ? (total ? `разделы ${open}/${total}` : 'без разделов') : '—'} · был(а) {lacAgo(seen)}</div>
                  </div>
                  <span className={st.cls}>{a.status === 'active' && <span className="chip-dot"></span>}{st.l}</span>
                  {a.status === 'active' && total > 0 && (
                    <a className="chip chip--control" target="_blank" rel="noopener"
                      title={'Открыть кабинет глазами: ' + (a.name || a.email) + ' — применяются его права, баннер superView, только чтение'}
                      href={'lk/' + a.role + '-' + ((zonesAll[a.role] || {}).defaultZone || 'soon') + '.html?user=' + encodeURIComponent(a.profileId) + '&superView=1&name=' + encodeURIComponent(a.name || a.email || a.profileId)}>
                      ЛК от имени
                    </a>
                  )}
                  {a.status === 'active' && <button className="chip chip--control" onClick={() => quick(a, { status: 'paused' }, 'paused')}>пауза</button>}
                  {a.status === 'paused' && <button className="chip chip--control" onClick={() => quick(a, { status: 'active' }, 'resumed')}>вернуть</button>}
                  {a.status !== 'revoked' && <button className="chip chip--ghost" onClick={() => { window.AccessStore.revoke(a.profileId); refresh(); }}>отозвать</button>}
                </div>
              );
            })}
            {restricted.length > 0 && (
              <div style={{ marginTop: 12, fontSize: 11.5, color: 'var(--warning-strong)' }}>
                Ограничения разделов: {restricted.map((a) => a.name || a.profileId).join(', ')} — детально в «Штат» → «Выдать доступ».
              </div>
            )}
          </div>

          {/* правая колонка: матрица + обратный вид + активность + аудит */}
          <div style={{ display: 'grid', gap: 16 }}>
            {roles.length > 0 && (
              <div style={ctorStyles.card}>
                <div style={{ ...ctorStyles.sectionLabel, marginBottom: 10 }}>Матрица роль × раздел</div>
                {roles.map((r) => {
                  const zd = (zonesAll[r] || {}).zones || {};
                  const accs = accounts.filter((a) => a.role === r && a.status === 'active');
                  return (
                    <div key={r} style={{ marginBottom: 10 }}>
                      <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--foreground)', marginBottom: 5 }}>{(accs[0] && accs[0].roleLabel) || r} · {accs.length}</div>
                      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5 }}>
                        {Object.entries(zd).map(([z, label]) => {
                          const ok = accs.filter((a) => window.AccessStore.zoneAllowed(a, z)).length;
                          const all = ok === accs.length;
                          return <span key={z} className={'chip ' + (all ? 'chip--data' : 'chip--conditional')} title={label + ': открыто у ' + ok + ' из ' + accs.length}>{label} {ok}/{accs.length}</span>;
                        })}
                      </div>
                    </div>
                  );
                })}
              </div>
            )}

            <div style={ctorStyles.card}>
              <div style={{ ...ctorStyles.sectionLabel, marginBottom: 10 }}>Кто видит раздел</div>
              <div style={{ display: 'flex', gap: 8, marginBottom: 10 }}>
                <select value={qRole} onChange={(e) => { setQRole(e.target.value); setQZone(''); }} style={{ ...ctorStyles.input, padding: '7px 10px', fontSize: 13 }}>
                  <option value="">роль…</option>
                  {Object.keys(zonesAll).map((r) => <option key={r} value={r}>{r}</option>)}
                </select>
                <select value={qZone} onChange={(e) => setQZone(e.target.value)} disabled={!qRole} style={{ ...ctorStyles.input, padding: '7px 10px', fontSize: 13 }}>
                  <option value="">раздел…</option>
                  {qRole && Object.entries((zonesAll[qRole] || {}).zones || {}).map(([z, l]) => <option key={z} value={z}>{l}</option>)}
                </select>
              </div>
              {reverse && (reverse.length
                ? reverse.map((a) => <div key={a.profileId} style={{ fontSize: 13, fontWeight: 600, color: 'var(--foreground)', padding: '4px 0' }}>{a.name || a.email}</div>)
                : <div style={{ fontSize: 12.5, color: 'var(--text-tertiary)' }}>Никто из активных аккаунтов роли.</div>)}
            </div>

            <div style={ctorStyles.card}>
              <div style={{ ...ctorStyles.sectionLabel, marginBottom: 10 }}>Активность · {activity.length} событий</div>
              {topZones.length ? (
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5, marginBottom: 10 }}>
                  {topZones.map(([z, n]) => <span key={z} className="chip chip--data">{z} · {n}</span>)}
                </div>
              ) : <div style={{ fontSize: 12.5, color: 'var(--text-tertiary)', marginBottom: 8 }}>Пока пусто — события появляются, когда сотрудник открывает разделы своего ЛК (вход по ссылке с <code>?user=</code>).</div>}
              {activity.slice(-5).reverse().map((e, i) => {
                const a = store.accounts[e.acc];
                return <div key={i} style={{ fontSize: 12, color: 'var(--text-secondary)', padding: '3px 0' }}>{(a && (a.name || a.email)) || e.acc} → <b>{e.zone}</b> · {lacAgo(e.at)}</div>;
              })}
            </div>

            <div style={ctorStyles.card}>
              <div style={{ ...ctorStyles.sectionLabel, marginBottom: 10 }}>Аудит прав · живой</div>
              {audit.slice(-7).reverse().map((e, i) => {
                const a = e.acc ? store.accounts[e.acc] : null;
                return (
                  <div key={i} style={{ fontSize: 12, color: 'var(--text-secondary)', padding: '4px 0', borderBottom: i < Math.min(audit.length, 7) - 1 ? '1px solid var(--border-subtle)' : 'none' }}>
                    <b style={{ color: 'var(--foreground)' }}>{LAC_AUDIT_L[e.t] || e.t}</b>
                    {a ? ' · ' + (a.name || a.email || e.acc) : ''}{e.zone ? ' · ' + e.zone : ''} · {lacAgo(e.at)}
                  </div>
                );
              })}
              {!audit.length && <div style={{ fontSize: 12.5, color: 'var(--text-tertiary)' }}>Записей пока нет.</div>}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { LiveAccessCenter });
