'use strict';
/* admin → access section — открыть/закрыть доступ к учебникам и экзаменам
 * для классов и отдельных учеников. Модель allowlist: по умолчанию закрыто,
 * правило ученика важнее правила класса.
 *
 * Два режима:
 *   • «По контенту» — выбрать учебник/экзамен → раздать классам (+ ученики).
 *   • «По классу»   — выбрать класс → отметить доступный ему контент. */
(function () {
  'use strict';
  let inited = false;
  let _catalog = null;   // { textbooks:[], exams:[] }
  let _targets = null;   // { classes:[{id,name,students:[]}], looseStudents:[] }
  let _summary = { totalClasses: 0, textbooks: {}, exams: {} };
  let _mode = 'content'; // 'content' | 'class'

  // content-mode state
  let _selContent = null;           // { type, ref, title }
  let _rules = { classRules: {}, studentRules: {} };
  const _open = new Set();          // развёрнутые классы (показ учеников)

  // class-mode state
  let _selClass = null;             // { id, name }
  let _classOpen = { textbooks: new Set(), exams: new Set() };

  const esc = (s) => (window.LS && LS.esc ? LS.esc(s) : String(s == null ? '' : s));
  const bucket = (type) => (type === 'textbook' ? 'textbooks' : 'exams');
  const keyName = (type) => (type === 'textbook' ? 'slug' : 'exam_key');
  const itemsOf = (type) => (type === 'textbook' ? _catalog.textbooks : _catalog.exams) || [];
  function contentTitle(type, ref) {
    const it = itemsOf(type).find(x => x[keyName(type)] === ref);
    return it ? it.title : ref;
  }

  async function load() {
    const root = document.getElementById('acc-root');
    try {
      [_catalog, _targets, _summary] = await Promise.all([
        LS.accessCatalog(), LS.accessTargets(), LS.accessSummary(),
      ]);
      renderRoot();
    } catch (e) {
      root.innerHTML = `<p style="color:var(--danger);font-size:13px">Ошибка загрузки: ${esc(e.message)}</p>`;
    }
  }

  /* ── каркас: переключатель режимов + две колонки ── */
  function renderRoot() {
    const root = document.getElementById('acc-root');
    const seg = (m, label) =>
      `<button onclick="accMode('${m}')" style="border:1px solid var(--border);
         background:${_mode === m ? 'var(--accent,#4f46e5)' : 'transparent'};color:${_mode === m ? '#fff' : 'var(--text-3)'};
         font-size:13px;padding:6px 16px;cursor:pointer;font-family:inherit;
         ${m === 'content' ? 'border-radius:8px 0 0 8px' : 'border-radius:0 8px 8px 0;border-left:none'}">${label}</button>`;
    root.innerHTML = `
      <div style="margin-bottom:16px;display:inline-flex">
        ${seg('content', 'По контенту')}${seg('class', 'По классу')}
      </div>
      <div class="acc-layout" style="display:flex;gap:20px;align-items:flex-start;flex-wrap:wrap">
        <div class="adm-panel" id="acc-left" style="flex:0 0 290px;max-width:330px;padding:10px"></div>
        <div class="adm-panel" id="acc-right" style="flex:1;min-width:340px;padding:18px"></div>
      </div>`;
    renderLeft();
    renderRight();
  }

  /* ── badge «N/M» ── */
  function badge(open, total) {
    const has = open > 0;
    return `<span style="font-size:11px;font-weight:600;padding:2px 8px;border-radius:20px;
      background:${has ? 'var(--ok-soft,#dcfce7)' : 'var(--border-h,#eee)'};
      color:${has ? 'var(--ok,#16a34a)' : 'var(--muted)'}">${open}/${total}</span>`;
  }

  /* ── ЛЕВАЯ колонка ── */
  function renderLeft() {
    const left = document.getElementById('acc-left');
    if (_mode === 'content') {
      const total = _summary.totalClasses || 0;
      const list = (type, items) => items.map(it => {
        const ref = it[keyName(type)];
        const active = _selContent && _selContent.type === type && _selContent.ref === ref;
        const open = (_summary[bucket(type)] || {})[ref] || 0;
        return `<button class="acc-item${active ? ' active' : ''}" onclick="accSelContent('${type}','${esc(ref)}')"
          style="display:flex;width:100%;align-items:center;justify-content:space-between;gap:8px;text-align:left;border:none;
                 background:${active ? 'var(--accent-soft,#eef2ff)' : 'transparent'};padding:8px 10px;border-radius:8px;
                 cursor:pointer;font-family:inherit;font-size:13.5px;color:var(--text-1);margin-bottom:2px">
          <span style="font-weight:${active ? 600 : 500};overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${esc(it.title)}</span>
          ${badge(open, total)}</button>`;
      }).join('');
      left.innerHTML = `
        <div style="font-weight:600;font-size:13px;color:var(--text-3);padding:6px 8px">Учебники</div>
        ${list('textbook', _catalog.textbooks || []) || empty('Нет учебников')}
        <div style="font-weight:600;font-size:13px;color:var(--text-3);padding:12px 8px 6px">Экзамены</div>
        ${list('exam', _catalog.exams || []) || empty('Нет экзаменов')}`;
    } else {
      const classes = _targets.classes || [];
      left.innerHTML = `
        <div style="font-weight:600;font-size:13px;color:var(--text-3);padding:6px 8px">Классы</div>
        ${classes.length ? classes.map(c => {
          const active = _selClass && _selClass.id === c.id;
          return `<button class="acc-item${active ? ' active' : ''}" onclick="accSelClass(${c.id})"
            style="display:block;width:100%;text-align:left;border:none;background:${active ? 'var(--accent-soft,#eef2ff)' : 'transparent'};
                   padding:8px 10px;border-radius:8px;cursor:pointer;font-family:inherit;font-size:13.5px;color:var(--text-1);margin-bottom:2px">
            <span style="font-weight:${active ? 600 : 500}">${esc(c.name)}</span>
            ${c.teacher_name ? `<span style="color:var(--muted);font-size:12px"> · ${esc(c.teacher_name)}</span>` : ''}</button>`;
        }).join('') : empty('Нет классов')}`;
    }
  }
  const empty = (t) => `<p style="color:var(--muted);font-size:12px;padding:6px 10px">${t}</p>`;

  /* ── ПРАВАЯ колонка ── */
  function renderRight() {
    const right = document.getElementById('acc-right');
    if (_mode === 'content') {
      if (!_selContent) { right.innerHTML = hint('Выберите учебник или экзамен слева, чтобы настроить доступ.'); return; }
      renderContentDetail(right);
    } else {
      if (!_selClass) { right.innerHTML = hint('Выберите класс слева, чтобы открыть ему учебники и экзамены.'); return; }
      renderClassDetail(right);
    }
  }
  const hint = (t) => `<div style="color:var(--muted);font-size:14px">${t}</div>`;

  /* ════════ режим «По контенту» ════════ */
  async function selContent(type, ref) {
    _selContent = { type, ref, title: contentTitle(type, ref) };
    renderLeft();
    const right = document.getElementById('acc-right');
    right.innerHTML = '<p style="color:var(--muted);font-size:13px">Загрузка…</p>';
    try {
      _rules = await LS.accessRules(type, ref);
      renderRight();
    } catch (e) { right.innerHTML = `<p style="color:var(--danger);font-size:13px">Ошибка: ${esc(e.message)}</p>`; }
  }

  function studentTri(uid) {
    const v = _rules.studentRules[uid];
    const state = v === 1 ? 'open' : v === 0 ? 'closed' : 'inherit';
    const btn = (val, label, on) =>
      `<button onclick="accSetStudent(${uid},${val})"
         style="border:1px solid var(--border);background:${on ? 'var(--accent,#4f46e5)' : 'transparent'};
                color:${on ? '#fff' : 'var(--text-3)'};font-size:11.5px;padding:3px 9px;cursor:pointer;font-family:inherit;
                ${val === 'null' ? 'border-radius:7px 0 0 7px' : val === 0 ? 'border-radius:0 7px 7px 0;border-left:none' : 'border-left:none'}">${label}</button>`;
    return `<span style="display:inline-flex">
        ${btn('null', 'Наследовать', state === 'inherit')}${btn(1, 'Открыт', state === 'open')}${btn(0, 'Закрыт', state === 'closed')}</span>`;
  }

  function classRowContent(c) {
    const openToClass = _rules.classRules[c.id] === 1;
    const expanded = _open.has(c.id);
    const students = c.students || [];
    const studentsHtml = expanded ? `
      <div style="padding:6px 0 10px 26px">
        ${students.length ? students.map(s => `
          <div style="display:flex;align-items:center;justify-content:space-between;gap:10px;padding:5px 0;border-top:1px solid var(--border-soft,#f0f0f0)">
            <span style="font-size:13px;color:var(--text-1)">${esc(s.name || s.email)}</span>${studentTri(s.id)}
          </div>`).join('') : '<p style="color:var(--muted);font-size:12px;margin:4px 0">В классе нет учеников</p>'}
      </div>` : '';
    return `
      <div style="border:1px solid var(--border);border-radius:10px;margin-bottom:10px;padding:10px 12px">
        <div style="display:flex;align-items:center;justify-content:space-between;gap:12px">
          <button onclick="accToggleExpand(${c.id})"
            style="border:none;background:transparent;cursor:pointer;font-family:inherit;font-size:14px;font-weight:600;color:var(--text-1);display:flex;align-items:center;gap:6px">
            <span style="display:inline-block;transition:transform .15s;transform:rotate(${expanded ? 90 : 0}deg)">▸</span>
            ${esc(c.name)}${c.teacher_name ? `<span style="font-weight:400;color:var(--muted);font-size:12px">· ${esc(c.teacher_name)}</span>` : ''}
          </button>
          <label style="display:inline-flex;align-items:center;gap:8px;font-size:12.5px;color:var(--text-3);cursor:pointer">
            <span>${openToClass ? 'Открыт' : 'Закрыт'}</span>
            <input type="checkbox" ${openToClass ? 'checked' : ''} onchange="accSetClass(${c.id}, this.checked)">
          </label>
        </div>${studentsHtml}
      </div>`;
  }

  function looseRow(s) {
    const open = _rules.studentRules[s.id] === 1;
    return `
      <div style="display:flex;align-items:center;justify-content:space-between;gap:10px;padding:7px 12px;border:1px solid var(--border);border-radius:9px;margin-bottom:6px">
        <span style="font-size:13px;color:var(--text-1)">${esc(s.name || s.email)} <span style="color:var(--muted);font-size:11.5px">${esc(s.email)}</span></span>
        <label style="display:inline-flex;align-items:center;gap:8px;font-size:12.5px;color:var(--text-3);cursor:pointer">
          <span>${open ? 'Открыт' : 'Закрыт'}</span>
          <input type="checkbox" ${open ? 'checked' : ''} onchange="accSetStudent(${s.id}, this.checked ? 1 : null)">
        </label>
      </div>`;
  }

  function renderContentDetail(right) {
    const classes = _targets.classes || [];
    const loose = _targets.looseStudents || [];
    right.innerHTML = `
      <div style="display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:14px">
        <div style="font-size:16px;font-weight:700;color:var(--text-1)">${esc(_selContent.title)}</div>
        <span class="badge ${_selContent.type === 'exam' ? 'badge-warn' : 'badge-info'}" style="font-size:12px">${_selContent.type === 'exam' ? 'Экзамен' : 'Учебник'}</span>
      </div>
      ${classes.length ? `
        <div style="display:flex;gap:8px;margin-bottom:14px">
          <button class="adm-btn adm-btn-small" onclick="accBulk(1)">Открыть всем классам</button>
          <button class="adm-btn adm-btn-small" style="background:var(--border-h);color:var(--text-3)" onclick="accBulk(0)">Закрыть у всех</button>
        </div>` : ''}
      ${classes.length ? classes.map(classRowContent).join('') : '<p style="color:var(--muted);font-size:13px">Нет классов.</p>'}
      ${loose.length ? `
        <div style="margin-top:18px">
          <div style="font-weight:600;font-size:13px;color:var(--text-3);margin-bottom:8px">Отдельные ученики (без класса)</div>
          ${loose.map(looseRow).join('')}
        </div>` : ''}`;
  }

  /* пересчёт бейджа для текущего контента по отображаемым классам */
  function recountContent() {
    if (!_selContent) return;
    const open = (_targets.classes || []).filter(c => _rules.classRules[c.id] === 1).length;
    _summary[bucket(_selContent.type)][_selContent.ref] = open;
  }

  async function setClass(classId, checked) {
    const allow = checked ? 1 : null;
    try {
      await LS.accessSetRule(_selContent.type, _selContent.ref, 'class', classId, allow);
      if (allow === 1) _rules.classRules[classId] = 1; else delete _rules.classRules[classId];
      recountContent(); renderLeft(); renderRight();
    } catch (e) { LS.toast('Ошибка: ' + e.message, 'error'); renderRight(); }
  }

  async function bulk(allow) {
    const classes = _targets.classes || [];
    try {
      await Promise.all(classes.map(c =>
        LS.accessSetRule(_selContent.type, _selContent.ref, 'class', c.id, allow ? 1 : null)));
      for (const c of classes) { if (allow) _rules.classRules[c.id] = 1; else delete _rules.classRules[c.id]; }
      recountContent(); renderLeft(); renderRight();
      LS.toast(allow ? 'Открыто всем классам' : 'Закрыто у всех классов', 'success');
    } catch (e) { LS.toast('Ошибка: ' + e.message, 'error'); selContent(_selContent.type, _selContent.ref); }
  }

  async function setStudent(uid, allow) {
    if (allow === 'null') allow = null;
    try {
      await LS.accessSetRule(_selContent.type, _selContent.ref, 'student', uid, allow);
      if (allow === 1) _rules.studentRules[uid] = 1;
      else if (allow === 0) _rules.studentRules[uid] = 0;
      else delete _rules.studentRules[uid];
      renderRight();
    } catch (e) { LS.toast('Ошибка: ' + e.message, 'error'); renderRight(); }
  }

  function toggleExpand(classId) {
    if (_open.has(classId)) _open.delete(classId); else _open.add(classId);
    renderRight();
  }

  /* ════════ режим «По классу» ════════ */
  async function selClass(id) {
    const c = (_targets.classes || []).find(x => x.id === id);
    _selClass = { id, name: c ? c.name : ('#' + id) };
    renderLeft();
    const right = document.getElementById('acc-right');
    right.innerHTML = '<p style="color:var(--muted);font-size:13px">Загрузка…</p>';
    try {
      const open = await LS.accessClassOpen(id);
      _classOpen = { textbooks: new Set(open.textbooks || []), exams: new Set(open.exams || []) };
      renderRight();
    } catch (e) { right.innerHTML = `<p style="color:var(--danger);font-size:13px">Ошибка: ${esc(e.message)}</p>`; }
  }

  function classContentRow(type, it) {
    const ref = it[keyName(type)];
    const open = _classOpen[bucket(type)].has(ref);
    return `
      <div style="display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 12px;border:1px solid var(--border);border-radius:9px;margin-bottom:6px">
        <span style="font-size:13.5px;color:var(--text-1)">${esc(it.title)}
          <span class="badge ${type === 'exam' ? 'badge-warn' : 'badge-info'}" style="font-size:10.5px;margin-left:6px">${type === 'exam' ? 'Экзамен' : 'Учебник'}</span></span>
        <label style="display:inline-flex;align-items:center;gap:8px;font-size:12.5px;color:var(--text-3);cursor:pointer">
          <span>${open ? 'Открыт' : 'Закрыт'}</span>
          <input type="checkbox" ${open ? 'checked' : ''} onchange="accClassToggle('${type}','${esc(ref)}', this.checked)">
        </label>
      </div>`;
  }

  function renderClassDetail(right) {
    const tb = _catalog.textbooks || [], ex = _catalog.exams || [];
    right.innerHTML = `
      <div style="font-size:16px;font-weight:700;color:var(--text-1);margin-bottom:14px">Класс «${esc(_selClass.name)}»</div>
      <div style="display:flex;gap:8px;margin-bottom:14px">
        <button class="adm-btn adm-btn-small" onclick="accClassBulk(1)">Открыть весь контент</button>
        <button class="adm-btn adm-btn-small" style="background:var(--border-h);color:var(--text-3)" onclick="accClassBulk(0)">Закрыть весь</button>
      </div>
      <div style="font-weight:600;font-size:13px;color:var(--text-3);margin:4px 0 8px">Учебники</div>
      ${tb.length ? tb.map(it => classContentRow('textbook', it)).join('') : empty('Нет учебников')}
      <div style="font-weight:600;font-size:13px;color:var(--text-3);margin:14px 0 8px">Экзамены</div>
      ${ex.length ? ex.map(it => classContentRow('exam', it)).join('') : empty('Нет экзаменов')}`;
  }

  function bumpSummary(type, ref, delta) {
    const b = _summary[bucket(type)];
    const cur = b[ref] || 0;
    b[ref] = Math.max(0, Math.min(_summary.totalClasses || 0, cur + delta));
  }

  async function classToggle(type, ref, checked) {
    try {
      await LS.accessSetRule(type, ref, 'class', _selClass.id, checked ? 1 : null);
      const set = _classOpen[bucket(type)];
      const was = set.has(ref);
      if (checked) set.add(ref); else set.delete(ref);
      if (checked && !was) bumpSummary(type, ref, +1);
      if (!checked && was) bumpSummary(type, ref, -1);
      renderRight();
    } catch (e) { LS.toast('Ошибка: ' + e.message, 'error'); selClass(_selClass.id); }
  }

  async function classBulk(allow) {
    const all = [...(_catalog.textbooks || []).map(it => ['textbook', it[keyName('textbook')]]),
                 ...(_catalog.exams || []).map(it => ['exam', it[keyName('exam')]])];
    try {
      await Promise.all(all.map(([type, ref]) =>
        LS.accessSetRule(type, ref, 'class', _selClass.id, allow ? 1 : null)));
      for (const [type, ref] of all) {
        const set = _classOpen[bucket(type)];
        const was = set.has(ref);
        if (allow) { set.add(ref); if (!was) bumpSummary(type, ref, +1); }
        else { set.delete(ref); if (was) bumpSummary(type, ref, -1); }
      }
      renderRight();
      LS.toast(allow ? 'Открыт весь контент классу' : 'Закрыт весь контент', 'success');
    } catch (e) { LS.toast('Ошибка: ' + e.message, 'error'); selClass(_selClass.id); }
  }

  /* ── режим ── */
  function setMode(m) {
    if (m === _mode) return;
    _mode = m;
    renderRoot();
  }

  window.accMode         = setMode;
  window.accSelContent   = selContent;
  window.accSetClass     = setClass;
  window.accBulk         = bulk;
  window.accSetStudent   = setStudent;
  window.accToggleExpand = toggleExpand;
  window.accSelClass     = selClass;
  window.accClassToggle  = classToggle;
  window.accClassBulk    = classBulk;

  window.AdminSections = window.AdminSections || {};
  window.AdminSections.access = {
    init: async () => { if (inited) return; inited = true; await load(); },
    reload: load,
  };
})();
