/* Vigilo · LTO shared React shell — topbar, role switcher, RBAC gate, scope bar.
   Load via <script type="text/babel" src="_shared/lto-shell.jsx"></script> AFTER
   React + lto-icons.js and BEFORE the page's own babel script. Exports to window. */

const LI = window.LIcons;

const LROLES = {
  posmatrac:  { key: 'posmatrac',  label: 'Posmatrač',  Icon: LI.Eye,    user: { nm: 'Dragan Petrović', sub: 'LTO posmatrač · Voždovac', ini: 'DP' } },
  analiticar: { key: 'analiticar', label: 'Analitičar', Icon: LI.Spark,  user: { nm: 'Marija Ivić',     sub: 'LTO analitičar · Beograd', ini: 'MI' } },
  supervizor: { key: 'supervizor', label: 'Supervizor', Icon: LI.Shield, user: { nm: 'R. Drobac',       sub: 'LTO supervizor · HQ',      ini: 'RD' } },
  pravnik:    { key: 'pravnik',    label: 'Pravnik',    Icon: LI.Scale,  user: { nm: 'Aleksandar Tasić', sub: 'Pravni tim · HQ',         ini: 'AT' } },
};
const ROLE_ORDER = ['posmatrac', 'analiticar', 'supervizor', 'pravnik'];
const ROLE_RANK = { posmatrac: 1, analiticar: 2, supervizor: 3, pravnik: 0 };

// Two-axis case status: LTO lifecycle + (when escalated) legal sub-status.
// Faza procesa → ishod. Razlika: prihvaceno = pravnik preuzeo (početak);
// usvojeno/odbijeno/odbaceno = ishod institucije (kraj). Odbačeno = proceduralno (bez merituma).
const LEGAL_STATUS = {
  prosledjeno: { l: 'Prosleđeno',     cls: 'ls-wait' },
  prihvaceno:  { l: 'Prihvaćeno',     cls: 'ls-ok' },
  odbio:       { l: 'Pravnik odbio',  cls: 'ls-decline' },
  predmet:     { l: 'Predmet u toku', cls: 'ls-active' },
  usvojeno:    { l: 'Usvojeno',       cls: 'ls-done' },
  odbijeno:    { l: 'Odbijeno',       cls: 'ls-no' },
  odbaceno:    { l: 'Odbačeno',       cls: 'ls-dismiss' },
};

function useRole() {
  const [role, setRole] = React.useState(() => {
    try { return localStorage.getItem('vigilo-lto-role') || 'analiticar'; } catch (e) { return 'analiticar'; }
  });
  React.useEffect(() => { try { localStorage.setItem('vigilo-lto-role', role); } catch (e) {} }, [role]);
  return [role, setRole];
}

function RoleSwitch({ role, setRole }) {
  return (
    <div className="role-switch" title="Prototip · promeni rolu da vidiš RBAC">
      <span className="rs-label">Rola</span>
      {ROLE_ORDER.map(k => {
        const R = LROLES[k];
        return (
          <button key={k} className={(role === k ? 'on r-' + k : '')} onClick={() => setRole(k)}>
            <R.Icon/>{R.label}
          </button>
        );
      })}
    </div>
  );
}

function TopBar({ crumbs, role, setRole, children }) {
  const R = LROLES[role];
  return (
    <div className="topbar">
      <div className="breadcrumb">
        {crumbs.map((c, i) => (
          <React.Fragment key={i}>
            {i > 0 && <span className="sep">/</span>}
            <span className={'crumb' + (i === crumbs.length - 1 ? ' current' : '')}>{c}</span>
          </React.Fragment>
        ))}
      </div>
      <div className="top-spacer"/>
      {children}
      <RoleSwitch role={role} setRole={setRole}/>
      <button className="top-icon-btn"><LI.Bell/></button>
      <div className="top-user">
        <div className={'av r-' + role}>{R.user.ini}</div>
        <div className="who"><strong>{R.user.nm}</strong><span>{R.user.sub}</span></div>
      </div>
    </div>
  );
}

/* Region/theme scoping banner shown under topbar */
function ScopeBar({ role, children, end }) {
  const Ico = role === 'supervizor' ? LI.Shield : role === 'pravnik' ? LI.Scale : role === 'analiticar' ? LI.Spark : LI.Eye;
  return (
    <div className={'scope-bar ' + role}>
      <Ico/>
      <span>{children}</span>
      {end && <span className="end">{end}</span>}
    </div>
  );
}

/* Per-user (per-role) read/unread state, persisted. Stored as {role:{id:bool}}.
   isRead(id, defaultRead) · toggle(id, def) · setRead(id,val) · markAll(ids) */
function useReadState(pageKey, role) {
  const storeKey = 'vigilo-read-' + pageKey;
  const [all, setAll] = React.useState(() => { try { return JSON.parse(localStorage.getItem(storeKey) || '{}'); } catch (e) { return {}; } });
  React.useEffect(() => { try { localStorage.setItem(storeKey, JSON.stringify(all)); } catch (e) {} }, [all]);
  const map = all[role] || {};
  const isRead = (id, def) => (map[id] !== undefined ? map[id] : !!def);
  const upd = (fn) => setAll(a => ({ ...a, [role]: fn(a[role] || {}) }));
  const setRead = (id, val) => upd(m => ({ ...m, [id]: val }));
  const toggle = (id, def) => upd(m => ({ ...m, [id]: !(m[id] !== undefined ? m[id] : !!def) }));
  const markAll = (ids) => upd(m => { const n = { ...m }; ids.forEach(i => n[i] = true); return n; });
  return { isRead, setRead, toggle, markAll };
}

/* Seen indicator + manual read/unread toggle. */
function SeenMark({ read, hasUpdate, onToggle }) {
  return (
    <button className={'seen-mark' + (read ? ' read' : '') + (hasUpdate && !read ? ' upd' : '')}
      title={read ? 'Označi kao nepročitano' : 'Označi kao pročitano'}
      onClick={(e) => { e.stopPropagation(); onToggle && onToggle(); }}>
      {hasUpdate && !read ? <span className="seen-upd">novo</span> : <span className="seen-dot"/>}
    </button>
  );
}

/* RBAC gate: shown in place of content when the active role lacks access.
   need = minimum role key; role = current role. */
function Gate({ need, role, title, desc }) {
  const allowed = Array.isArray(need)
    ? need
    : ['posmatrac', 'analiticar', 'supervizor'].filter(k => ROLE_RANK[k] >= ROLE_RANK[need]);
  return (
    <div className="gate">
      <div className="gate-card">
        <div className="ic"><LI.Lock/></div>
        <h2>{title || 'Nemaš pristup ovom prikazu'}</h2>
        <p>{desc}</p>
        <div className="roles-need">
          {allowed.map(k => (
            <span key={k} className="status-pill" style={{ background: 'var(--ink-100)', color: 'var(--ink-700)' }}>{LROLES[k].label}</span>
          ))}
        </div>
      </div>
    </div>
  );
}

function roleAtLeast(role, need) { return ROLE_RANK[role] >= ROLE_RANK[need]; }

Object.assign(window, { LROLES, ROLE_ORDER, ROLE_RANK, LEGAL_STATUS, useRole, RoleSwitch, TopBar, ScopeBar, Gate, roleAtLeast, useReadState, SeenMark });
