(()=>{
'use strict';
const VERSION='4.3.25';
const MODULES=[
 {key:'doctor',label:'Médico',detail:'Expediente, consultas, indicaciones, recetas y resultados'},
 {key:'nurse',label:'Enfermería',detail:'Signos, curaciones, notas y medicamentos'},
 {key:'assistant',label:'Asistentes',detail:'Cuidados, ingesta e incidentes'},
 {key:'cook',label:'Cocina',detail:'Plan nutricional e ingesta'},
 {key:'security',label:'Seguridad',detail:'Entradas, salidas e incidentes'},
 {key:'cleaning',label:'Miscelánea',detail:'Tareas operativas e incidentes'},
 {key:'maintenance',label:'Mantenimiento',detail:'Tareas, inventario e incidentes'}
];
let channel=null,refreshTimer=null,loadPromise=null,cacheData=null,cacheAt=0,renderBusy=false;
const db=()=>window.seniorcareSupabase;
const root=()=>document.getElementById('mainContent');
const esc=v=>String(v??'').replace(/[&<>'"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#39;','"':'&quot;'}[c]));
const sgIcon=name=>{const p={org:'<path d="M3 21h18M5 21V7l7-4 7 4v14M9 21v-5h6v5M8 10h.01M12 10h.01M16 10h.01M8 13h.01M12 13h.01M16 13h.01"/>',license:'<rect x="3" y="4" width="18" height="16" rx="2"/><path d="M7 8h10M7 12h6M7 16h4"/>',pending:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',blocked:'<path d="M6 10V8a6 6 0 0 1 12 0v2"/><rect x="4" y="10" width="16" height="11" rx="2"/><path d="M12 14v3"/>',money:'<rect x="3" y="6" width="18" height="12" rx="2"/><path d="M7 12h.01M17 12h.01M12 9v6M10 10.5h3a1.5 1.5 0 0 1 0 3h-3"/>',users:'<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8ZM22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/>',audit:'<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2Z"/><path d="M8 7h8M8 11h8M8 15h5"/>',alert:'<path d="M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9M10 21h4"/>',support:'<circle cx="12" cy="12" r="9"/><path d="M12 8v4M12 16h.01"/>',arrow:'<path d="m9 18 6-6-6-6"/>'};return `<svg viewBox="0 0 24 24" aria-hidden="true">${p[name]||p.arrow}</svg>`};
const toast=m=>window.showToast?window.showToast(m):alert(m);
const money=n=>new Intl.NumberFormat('es-CR',{style:'currency',currency:'CRC',maximumFractionDigits:0}).format(Number(n||0));
const fmt=d=>d?new Date(d).toLocaleDateString('es-CR'):'Sin definir';
const fmtDT=d=>d?new Date(d).toLocaleString('es-CR'):'Sin registro';
const roleText=v=>String(v??'').toLowerCase();
const isAdminRole=v=>['admin','administrator'].includes(roleText(v));
const codePayload=data=>{let row=Array.isArray(data)?data[0]:data;if(row&&row.result&&typeof row.result==='object')row=row.result;return row&&typeof row==='object'?row:{};};
const pendingAdminCodes=codes=>(codes||[]).filter(x=>isAdminRole(x.role)&&x.active!==false&&Number(x.used_count||0)<Number(x.max_uses||1)&&(!x.expires_at||new Date(x.expires_at)>new Date())).sort((a,b)=>new Date(b.created_at||0)-new Date(a.created_at||0));
async function copyCode(value){
 const text=String(value||'').trim(); if(!text)return;
 try{await navigator.clipboard.writeText(text);toast('Código copiado.');}
 catch(_){const area=document.createElement('textarea');area.value=text;area.style.position='fixed';area.style.opacity='0';document.body.appendChild(area);area.select();document.execCommand('copy');area.remove();toast('Código copiado.');}
}
function codeCard(x,orgName){return `<article class="access-code-card" data-admin-code-card="${esc(x.id||'')}"><div><span>${esc(orgName||'Organización')}</span><strong>${esc(x.code||'')}</strong><small>Disponible · vence ${fmt(x.expires_at)}</small></div><div class="card-actions"><button type="button" class="mini-btn" data-copy-admin-code="${esc(x.code||'')}">Copiar</button><button type="button" class="mini-btn" data-revoke-admin-code="${esc(x.id||'')}">Revocar</button></div></article>`;}
const isSup=()=>String(window.currentUser?.role||'').toLowerCase()==='supervisor';
const page=(eyebrow,title,text,backScreen='home')=>`<section class="page-head supervisor-page-head">${backScreen?`<button class="back-btn supervisor-back-btn" data-go="${backScreen}" aria-label="Volver">‹<span>Volver</span></button>`:''}<div><span>${eyebrow}</span><h2>${title}</h2><p>${text}</p></div></section>`;
const status=l=>!l?'Pendiente':l.status==='suspended'?'Suspendida':l.payment_confirmed&&l.status==='active'?'Activa':l.status==='cancelled'?'Cancelada':'Pendiente';
const statusClass=l=>status(l)==='Activa'?'ok':status(l)==='Suspendida'||status(l)==='Cancelada'?'danger':'warn';
const selectedOrg=()=>sessionStorage.getItem('seniorcare-selected-org');
function navigate(screen){
 if(!isSup())return;
 window.activeScreen=screen;
 const map={home:window.renderSupervisorHome,supervisorOrganizations:window.renderSupervisorOrganizations,supervisorOrganizationDetail:window.renderSupervisorOrganizationDetail,supervisorLicenses:window.renderSupervisorLicenses,supervisorPayments:window.renderSupervisorPayments,supervisorAdmins:window.renderSupervisorAdmins,supervisorAudit:window.renderSupervisorAudit,supervisorAlerts:window.renderSupervisorAlerts,supervisorSupport:window.renderSupervisorSupport,supervisorMore:window.renderSupervisorMore};
 const fn=map[screen];
 if(typeof fn==='function') fn();
 try{window.setActiveNav?.(screen==='supervisorOrganizations'?'supervisorOrganizations':screen==='supervisorLicenses'||screen==='supervisorPayments'?'supervisorLicenses':screen==='supervisorMore'?'supervisorMore':'home')}catch(_){ }
}
async function loadAll(force=false){
 const now=Date.now();
 if(!force&&cacheData&&(now-cacheAt)<12000)return cacheData;
 if(loadPromise)return loadPromise;
 loadPromise=(async()=>{
  const codePromise=(async()=>{
   if(window.BHSC_CALL_RPC){
    const rpc=await window.BHSC_CALL_RPC(['bh_list_admin_activation_codes_v4321'],{});
    if(!rpc.error){const payload=codePayload(rpc.data);return {data:Array.isArray(payload)?payload:(Array.isArray(rpc.data)?rpc.data:[]),error:null};}
    if(!window.BHSC_RPC_FUNCTION_MISSING?.(rpc.error))return rpc;
   }
   return db().from('activation_codes').select('id,organization_id,code,role,expires_at,max_uses,used_count,active,created_at').order('created_at',{ascending:false}).limit(250);
  })();
  const [o,l,p,m,a,codes]=await Promise.all([
   db().from('organizations').select('*').order('created_at',{ascending:false}),
   db().from('licenses').select('*'),
   db().from('profiles').select('id,organization_id,full_name,username,role,active,last_seen_at').eq('role','administrator'),
   db().from('organization_module_subscriptions').select('*'),
   db().from('audit_logs').select('*').order('created_at',{ascending:false}).limit(120),
   codePromise
  ]);
  for(const r of [o,l,p,m,a,codes]) if(r?.error) throw r.error;
  const codeRows=Array.isArray(codes?.data)?codes.data:[];
  cacheData={orgs:o.data||[],licenses:l.data||[],admins:p.data||[],modules:m.data||[],audit:a.data||[],codes:codeRows};
  cacheAt=Date.now();
  return cacheData;
 })();
 try{return await loadPromise}finally{loadPromise=null}
}

function invalidateCache(){cacheData=null;cacheAt=0}
async function audit(orgId,action,details={}){
 const result=await db().from('audit_logs').insert({organization_id:orgId||null,user_id:window.currentUser?.id||null,action,table_name:'supervisor_global_v4325',record_id:orgId||null,details});
 if(result.error)throw result.error;
 invalidateCache();
}
function wireRealtime(){
 if(!isSup()||channel)return;
 channel=db().channel('seniorcare-supervisor-global-v354')
  .on('postgres_changes',{event:'*',schema:'public',table:'organizations'},scheduleRefresh)
  .on('postgres_changes',{event:'*',schema:'public',table:'licenses'},scheduleRefresh)
  .on('postgres_changes',{event:'*',schema:'public',table:'profiles'},scheduleRefresh)
  .on('postgres_changes',{event:'*',schema:'public',table:'organization_module_subscriptions'},scheduleRefresh)
  .on('postgres_changes',{event:'*',schema:'public',table:'audit_logs'},scheduleRefresh)
  .on('postgres_changes',{event:'*',schema:'public',table:'activation_codes'},scheduleRefresh)
  .subscribe();
}
function scheduleRefresh(){
 invalidateCache();
 clearTimeout(refreshTimer); refreshTimer=setTimeout(()=>{
  const active=document.activeElement;
  if(active&&/^(INPUT|TEXTAREA|SELECT)$/.test(active.tagName))return;
  const s=String(window.activeScreen||'');
  const fn={home:window.renderSupervisorHome,supervisorOrganizations:window.renderSupervisorOrganizations,supervisorOrganizationDetail:window.renderSupervisorOrganizationDetail,supervisorLicenses:window.renderSupervisorLicenses,supervisorAdmins:window.renderSupervisorAdmins,supervisorPayments:window.renderSupervisorPayments,supervisorAudit:window.renderSupervisorAudit,supervisorAlerts:window.renderSupervisorAlerts,supervisorSupport:window.renderSupervisorSupport}[s];
  if(isSup()&&typeof fn==='function'&&!renderBusy) fn();
 },900);
}
async function setOrgStatus(orgId,next){
 const lic=await db().from('licenses').select('*').eq('organization_id',orgId).maybeSingle(); if(lic.error)throw lic.error;
 const active=next==='active';
 // La suspensión institucional se controla en organización/licencia.
 // No se modifica profiles.active para conservar los bloqueos individuales.
 const lr=await db().from('licenses').update({status:next,suspended_at:active?null:new Date().toISOString(),suspension_reason:active?null:'Suspendida por Supervisor',updated_by:window.currentUser?.id||null,updated_at:new Date().toISOString()}).eq('organization_id',orgId); if(lr.error)throw lr.error;
 const or=await db().from('organizations').update({active,updated_at:new Date().toISOString()}).eq('id',orgId); if(or.error)throw or.error;
 await audit(orgId,active?'organization_reactivated':'organization_suspended',{license_id:lic.data?.id,scope:'organization',profiles_preserved:true});
}
async function createAdminCode(orgId){
 const safeDays=7;
 const r=window.BHSC_CALL_RPC
  ?await window.BHSC_CALL_RPC(['bh_create_activation_code_v4325','bh_create_activation_code_v4321','create_activation_code'],{p_org_id:orgId,p_role:'administrator',p_days:safeDays})
  :await db().rpc('create_activation_code',{p_org_id:orgId,p_role:'administrator',p_days:safeDays});
 if(r.error)throw r.error;
 const row=codePayload(r.data),code=String(row.code||'').trim();
 if(!code)throw new Error('Supabase no devolvió el código ADM. Ejecute el SQL V4.3.21 y vuelva a intentarlo.');
 invalidateCache();
 await audit(orgId,'administrator_code_created',{code_id:row.id||null,expires_at:row.expires_at||null,reused:row.reused===true});
 toast(row.reused?'Código ADM vigente recuperado.':'Código ADM creado correctamente.');
 return {...row,code,organization_id:row.organization_id||orgId,role:row.role||'administrator'};
}
async function revokeAdminCode(codeId){
 if(!codeId)throw new Error('Código no válido.');
 const r=window.BHSC_CALL_RPC
  ?await window.BHSC_CALL_RPC(['bh_revoke_activation_code_v4321','supervisor_revoke_activation_code'],{p_code_id:codeId})
  :await db().rpc('supervisor_revoke_activation_code',{p_code_id:codeId});
 if(r.error)throw r.error;
 invalidateCache();
 return true;
}
function wireAdminCodeActions(container,refresh){
 container.querySelectorAll('[data-copy-admin-code]').forEach(b=>b.onclick=()=>copyCode(b.dataset.copyAdminCode));
 container.querySelectorAll('[data-revoke-admin-code]').forEach(b=>b.onclick=async()=>{if(!confirm('¿Revocar este código ADM?'))return;try{b.disabled=true;await revokeAdminCode(b.dataset.revokeAdminCode);toast('Código ADM revocado.');await refresh();}catch(e){toast(e.message||'No se pudo revocar el código.');}finally{b.disabled=false;}});
}

window.renderSupervisorHome=async function(){
 if(!isSup())return; wireRealtime(); const r=root(); r.innerHTML=page('CONTROL GENERAL','Panel Supervisor','Licencias, organizaciones, módulos, pagos y accesos',null)+`<section class="sg-welcome"><div><span>BIENVENIDO</span><h3>${esc(window.currentUser?.name||window.currentUser?.full_name||'Supervisor')}</h3><p>Control general de licencias, residencias y accesos de la plataforma.</p></div><span class="sg-welcome-icon">${sgIcon('support')}</span></section>`;
 try{const d=await loadAll(); const active=d.licenses.filter(x=>status(x)==='Activa').length,susp=d.licenses.filter(x=>status(x)==='Suspendida').length,pending=d.licenses.filter(x=>status(x)==='Pendiente').length,total=(d.orgs.length*20000)+d.modules.filter(x=>x.enabled).reduce((sum,item)=>sum+Math.max(0,Number(item.monthly_price??10000)||0),0);
 r.insertAdjacentHTML('beforeend',`<section class="supervisor-global-kpis supervisor-kpis-pro"><article class="sg-kpi sg-kpi-purple"><span class="sg-kpi-icon">${sgIcon('org')}</span><div><span>Organizaciones</span><strong>${d.orgs.length}</strong><small>Residencias registradas</small></div></article><article class="sg-kpi sg-kpi-green"><span class="sg-kpi-icon">${sgIcon('license')}</span><div><span>Licencias activas</span><strong>${active}</strong><small>Centros operativos</small></div></article><article class="sg-kpi sg-kpi-amber"><span class="sg-kpi-icon">${sgIcon('pending')}</span><div><span>Pendientes</span><strong>${pending}</strong><small>Pago o activación</small></div></article><article class="sg-kpi sg-kpi-red"><span class="sg-kpi-icon">${sgIcon('blocked')}</span><div><span>Suspendidas</span><strong>${susp}</strong><small>Acceso bloqueado</small></div></article><article class="sg-kpi sg-kpi-blue"><span class="sg-kpi-icon">${sgIcon('money')}</span><div><span>Facturación mensual</span><strong>${money(total)}</strong><small>Paneles y módulos contratados</small></div></article></section><section class="sg-command-section"><div class="sg-section-heading"><div><span>CENTRO DE CONTROL</span><h3>Gestión de la plataforma</h3><p>Administre licencias, organizaciones, accesos y trazabilidad.</p></div></div><div class="supervisor-global-menu supervisor-menu-pro"><button data-go="supervisorOrganizations"><span class="sg-menu-icon purple">${sgIcon('org')}</span><div><strong>Organizaciones</strong><small>Crear, editar y abrir expedientes</small></div><span class="sg-menu-arrow">${sgIcon('arrow')}</span></button><button data-go="supervisorLicenses"><span class="sg-menu-icon green">${sgIcon('license')}</span><div><strong>Licencias y pagos</strong><small>Activar, renovar o suspender</small></div><span class="sg-menu-arrow">${sgIcon('arrow')}</span></button><button data-go="supervisorAdmins"><span class="sg-menu-icon blue">${sgIcon('users')}</span><div><strong>Administradores</strong><small>Gestionar accesos principales</small></div><span class="sg-menu-arrow">${sgIcon('arrow')}</span></button><button data-go="supervisorAudit"><span class="sg-menu-icon amber">${sgIcon('audit')}</span><div><strong>Auditoría</strong><small>Consultar el historial de acciones</small></div><span class="sg-menu-arrow">${sgIcon('arrow')}</span></button></div></section>`);
 }catch(e){r.insertAdjacentHTML('beforeend',`<div class="empty-state"><strong>No se pudo cargar Supervisor</strong><span>${esc(e.message)}</span></div>`);} };
window.renderSupervisorOrganizations=async function(){
 if(!isSup())return; wireRealtime(); const r=root(); r.innerHTML=page('CLIENTES','Organizaciones','Hogares autorizados para operar en SeniorCare','home');
 try{
  const d=await loadAll(true),lm=Object.fromEntries(d.licenses.map(x=>[x.organization_id,x])),am=d.admins.reduce((m,x)=>((m[x.organization_id]??=[]).push(x),m),{}),mm=d.modules.reduce((m,x)=>((m[x.organization_id]??=[]).push(x),m),{}),pending=pendingAdminCodes(d.codes),cm=pending.reduce((m,x)=>{if(!m[x.organization_id])m[x.organization_id]=x;return m;},{});
  r.insertAdjacentHTML('beforeend',`<section class="supervisor-create-card"><h3>Nueva organización</h3><form id="sgOrgForm" class="form-grid"><label>Nombre<input name="name" required></label><label>Razón social<input name="legal"></label><label>Correo<input name="email" type="email"></label><label>Teléfono<input name="phone"></label><label class="wide">Dirección<input name="address"></label><div class="form-actions wide"><button class="primary-btn">Crear organización</button></div></form></section><div class="supervisor-org-list">${d.orgs.map(o=>{const l=lm[o.id],mods=(mm[o.id]||[]).filter(x=>x.enabled),total=20000+mods.reduce((sum,item)=>sum+Math.max(0,Number(item.monthly_price??10000)||0),0),code=cm[o.id];return `<article class="supervisor-org-card"><div><h3>${esc(o.name)}</h3><p>${esc(o.email||'Sin correo')} · ${esc(o.phone||'Sin teléfono')}</p></div><span class="status ${statusClass(l)}">${status(l)}</span><div class="supervisor-org-meta"><span>Administradores<strong>${(am[o.id]||[]).length||'Pendiente'}</strong></span><span>Módulos<strong>${mods.length}</strong></span><span>Factura mensual<strong>${money(total)}</strong></span><span>Renovación<strong>${fmt(l?.renews_at)}</strong></span></div>${code?`<div class="generated-code generated-code-visible"><span>CÓDIGO ADM DISPONIBLE</span><strong>${esc(code.code)}</strong><p>Vence ${fmt(code.expires_at)}</p><div class="card-actions"><button type="button" class="mini-btn" data-copy-admin-code="${esc(code.code)}">Copiar código</button><button type="button" class="mini-btn" data-revoke-admin-code="${esc(code.id)}">Revocar</button></div></div>`:''}<div class="supervisor-org-actions"><button class="secondary-btn" data-sg-open="${o.id}">Abrir expediente</button><button class="secondary-btn" data-sg-code="${o.id}">${code?'Mostrar / recuperar código ADM':'Crear código ADM'}</button><button class="${status(l)==='Suspendida'?'primary-btn':'mini-btn'}" data-sg-toggle="${o.id}" data-next="${status(l)==='Suspendida'?'active':'suspended'}">${status(l)==='Suspendida'?'Reactivar':'Suspender'}</button></div></article>`}).join('')||'<div class="empty-state">No hay organizaciones.</div>'}</div>`);
  document.getElementById('sgOrgForm').onsubmit=async e=>{e.preventDefault();const f=new FormData(e.currentTarget),btn=e.currentTarget.querySelector('button');try{btn.disabled=true;const org=await db().from('organizations').insert({name:String(f.get('name')).trim(),legal_name:String(f.get('legal')||'').trim()||null,email:String(f.get('email')||'').trim()||null,phone:String(f.get('phone')||'').trim()||null,address:String(f.get('address')||'').trim()||null,active:false,created_by:window.currentUser?.id||null}).select().single();if(org.error)throw org.error;const lic=await db().from('licenses').insert({organization_id:org.data.id,status:'grace_period',plan_name:'Mensual',term_days:30,payment_confirmed:false,price_monthly:20000,updated_by:window.currentUser?.id||null});if(lic.error){await db().from('organizations').delete().eq('id',org.data.id);throw lic.error;}await audit(org.data.id,'organization_created',{name:org.data.name});toast('Organización creada.');await window.renderSupervisorOrganizations();}catch(x){toast(x.message)}finally{btn.disabled=false}};
  r.querySelectorAll('[data-sg-open]').forEach(b=>b.onclick=()=>{sessionStorage.setItem('seniorcare-selected-org',b.dataset.sgOpen);window.go?.('supervisorOrganizationDetail',{scope:'global'})});
  r.querySelectorAll('[data-sg-code]').forEach(b=>b.onclick=async()=>{try{b.disabled=true;await createAdminCode(b.dataset.sgCode);await window.renderSupervisorOrganizations();}catch(e){toast(e.message)}finally{b.disabled=false}});
  r.querySelectorAll('[data-sg-toggle]').forEach(b=>b.onclick=async()=>{if(b.dataset.next==='suspended'&&!confirm('¿Suspender la organización y bloquear todos sus accesos?'))return;try{await setOrgStatus(b.dataset.sgToggle,b.dataset.next);toast(b.dataset.next==='active'?'Organización reactivada.':'Organización suspendida.');await window.renderSupervisorOrganizations()}catch(e){toast(e.message)}});
  wireAdminCodeActions(r,window.renderSupervisorOrganizations);
 }catch(e){r.insertAdjacentHTML('beforeend',`<div class="empty-state">${esc(e.message)}</div>`);} };

window.renderSupervisorOrganizationDetail=async function(){
 if(!isSup())return; wireRealtime(); const orgId=selectedOrg(),r=root(); if(!orgId){window.go?.('supervisorOrganizations');return;} r.innerHTML=page('EXPEDIENTE COMERCIAL','Organización','Licencia, administrador y módulos contratados','supervisorOrganizations');
 try{const d=await loadAll(),o=d.orgs.find(x=>x.id===orgId),l=d.licenses.find(x=>x.organization_id===orgId),admins=d.admins.filter(x=>x.organization_id===orgId),a=admins[0],map=Object.fromEntries(d.modules.filter(x=>x.organization_id===orgId).map(x=>[x.module_key,x]));if(!o)throw new Error('Organización no encontrada.');
 r.insertAdjacentHTML('beforeend',`<section class="supervisor-detail-head"><div><h3>${esc(o.name)}</h3><p>${esc(o.legal_name||'')} ${o.email?'· '+esc(o.email):''}</p></div><span class="status ${statusClass(l)}">${status(l)}</span></section><section class="supervisor-detail-grid"><article><span>Administradores</span><strong>${admins.length||'Pendiente'}</strong><small>${admins.length?`${admins.filter(x=>x.active!==false).length} activos · ${admins.filter(x=>x.active===false).length} bloqueados`:'Sin registrar'}</small></article><article><span>Plan</span><strong>${esc(l?.plan_name||'Mensual')}</strong><small>${l?.term_days||30} días</small></article><article><span>Renovación</span><strong>${fmt(l?.renews_at)}</strong><small>${l?.payment_confirmed?'Pago confirmado':'Pago pendiente'}</small></article><article><span>Estado</span><strong>${status(l)}</strong><small>${esc(l?.suspension_reason||'Sin observaciones')}</small></article></section><section class="supervisor-module-panel"><div class="supervisor-module-head"><div><span>PAQUETE COMERCIAL</span><h3>Módulos habilitados</h3><p>Cada módulo tiene precio mensual independiente.</p></div><strong id="sgModuleTotal"></strong></div><div class="supervisor-module-grid">${MODULES.map(m=>{const x=map[m.key];return `<article data-sg-module="${m.key}"><label><input type="checkbox" ${x?.enabled?'checked':''}><div><strong>${m.label}</strong><small>${m.detail}</small></div></label><input class="sg-price" type="number" min="0" step="1000" value="${Math.max(0,Number(x?.monthly_price??10000)||0)}"></article>`}).join('')}</div><div class="form-actions"><button class="primary-btn" id="sgSaveModules">Guardar paquete</button></div></section><section class="supervisor-detail-actions"><button class="secondary-btn" id="sgCreateAdmin">Crear código ADM</button><button class="secondary-btn" data-go="supervisorLicenses">Gestionar licencia</button><button class="mini-btn" id="sgSuspendOrg">${status(l)==='Suspendida'?'Reactivar organización':'Suspender organización'}</button></section>`);
 const modulePrice=c=>{const input=c.querySelector('.sg-price'),raw=String(input?.value??'').trim(),value=raw===''?10000:Number(raw);return Number.isFinite(value)?Math.max(0,Math.round(value)):10000};const updateTotal=()=>{const total=20000+[...r.querySelectorAll('[data-sg-module]')].reduce((s,c)=>s+(c.querySelector('input[type=checkbox]').checked?modulePrice(c):0),0);document.getElementById('sgModuleTotal').textContent=money(total)};r.querySelectorAll('[data-sg-module] input').forEach(i=>i.oninput=updateTotal);updateTotal();
 document.getElementById('sgSaveModules').onclick=async()=>{const btn=document.getElementById('sgSaveModules');try{btn.disabled=true;const rows=[...r.querySelectorAll('[data-sg-module]')].map(c=>({organization_id:orgId,module_key:c.dataset.sgModule,enabled:c.querySelector('input[type=checkbox]').checked,monthly_price:modulePrice(c),currency:'CRC',updated_at:new Date().toISOString(),updated_by:window.currentUser?.id||null}));const payload=rows.map(x=>({module_key:x.module_key,enabled:x.enabled,monthly_price:x.monthly_price,currency:'CRC'}));let q=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_save_module_contract_v4331','bh_save_module_contract_v4330','bh_save_module_contract_v4328','bh_save_module_contract_v4327','bh_save_module_contract_v4325'],{p_org_id:orgId,p_modules:payload}):null;if(!q||q.error&&window.BHSC_RPC_FUNCTION_MISSING?.(q.error))q=await db().from('organization_module_subscriptions').upsert(rows,{onConflict:'organization_id,module_key'});if(q?.error)throw q.error;await audit(orgId,'module_package_updated_v4331',{modules:payload,admin_base_price:20000,default_module_price:10000});toast('Contrato actualizado.');updateTotal()}catch(e){const msg=String(e?.message||'');toast(/organization_module_subscriptions_module_key_check|violates check constraint/i.test(msg)?'Ejecute el SQL V4.3.31 en Supabase y vuelva a guardar.':msg)}finally{btn.disabled=false}};
 document.getElementById('sgCreateAdmin')?.addEventListener('click',async()=>{try{await createAdminCode(orgId)}catch(e){toast(e.message)}});
 document.getElementById('sgSuspendOrg').onclick=async()=>{const next=status(l)==='Suspendida'?'active':'suspended';if(next==='suspended'&&!confirm('¿Suspender organización y accesos?'))return;try{await setOrgStatus(orgId,next);toast(next==='active'?'Organización reactivada.':'Organización suspendida.');await window.renderSupervisorOrganizationDetail()}catch(e){toast(e.message)}};
 }catch(e){r.insertAdjacentHTML('beforeend',`<div class="empty-state">${esc(e.message)}</div>`);} };
window.renderSupervisorLicenses=async function(){
 if(!isSup())return; wireRealtime(); const r=root();r.innerHTML=page('CONTROL COMERCIAL','Licencias y pagos','Confirmación, renovación, suspensión y monto mensual','home');
 try{const d=await loadAll(),om=Object.fromEntries(d.orgs.map(x=>[x.id,x]));r.insertAdjacentHTML('beforeend',`<div class="supervisor-license-list">${d.licenses.map(l=>`<article><div><h3>${esc(om[l.organization_id]?.name||'Organización')}</h3><p>${status(l)} · renueva ${fmt(l.renews_at)}</p></div><div class="supervisor-license-fields"><label>Precio mensual<input type="number" min="20000" step="1000" data-sg-price-license="${l.id}" value="${Number(l.price_monthly||0)}"></label><label>Vigencia<input type="number" min="30" max="365" data-sg-days-license="${l.id}" value="${Number(l.term_days||30)}"></label></div><div class="supervisor-org-actions"><button class="secondary-btn" data-sg-save-license="${l.id}">Guardar precio y vigencia</button>${!l.payment_confirmed?`<button class="primary-btn" data-sg-confirm="${l.id}">Confirmar pago</button>`:`<button class="secondary-btn" data-sg-renew="${l.id}">Renovar licencia</button>`}<button class="mini-btn" data-sg-license-toggle="${l.organization_id}" data-next="${l.status==='suspended'?'active':'suspended'}">${l.status==='suspended'?'Reactivar':'Suspender'}</button></div></article>`).join('')}</div>`);
 r.querySelectorAll('[data-sg-save-license]').forEach(b=>b.onclick=async()=>{const id=b.dataset.sgSaveLicense,days=Number(r.querySelector(`[data-sg-days-license="${id}"]`).value||30),price=Number(r.querySelector(`[data-sg-price-license="${id}"]`).value||0);try{b.disabled=true;let q=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_update_license_draft_v4321','update_license_draft'],{p_license_id:id,p_term_days:days,p_renews_at:new Date(Date.now()+days*86400000).toISOString(),p_plan_name:'Mensual',p_price_monthly:price}):await db().rpc('update_license_draft',{p_license_id:id,p_term_days:days,p_renews_at:new Date(Date.now()+days*86400000).toISOString(),p_plan_name:'Mensual',p_price_monthly:price});if(q.error){q=await db().from('licenses').update({term_days:days,price_monthly:price,updated_at:new Date().toISOString(),updated_by:window.currentUser?.id||null}).eq('id',id)}if(q.error)throw q.error;const lic=d.licenses.find(x=>x.id===id);await audit(lic?.organization_id,'license_price_updated',{days,price});invalidateCache();toast('Precio y vigencia guardados.')}catch(e){toast(e.message)}finally{b.disabled=false}});
 r.querySelectorAll('[data-sg-confirm],[data-sg-renew]').forEach(b=>b.onclick=async()=>{const id=b.dataset.sgConfirm||b.dataset.sgRenew,days=Number(r.querySelector(`[data-sg-days-license="${id}"]`).value||30),price=Number(r.querySelector(`[data-sg-price-license="${id}"]`).value||0);try{const draft=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_update_license_draft_v4321','update_license_draft'],{p_license_id:id,p_term_days:days,p_renews_at:new Date(Date.now()+days*86400000).toISOString(),p_plan_name:'Mensual',p_price_monthly:price}):await db().rpc('update_license_draft',{p_license_id:id,p_term_days:days,p_renews_at:new Date(Date.now()+days*86400000).toISOString(),p_plan_name:'Mensual',p_price_monthly:price});if(draft.error&&!/confirmada|bloqueada/i.test(draft.error.message))throw draft.error;let q=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_confirm_license_payment_v4331','bh_confirm_license_payment_v4330','bh_confirm_license_payment_v4329','bh_confirm_license_payment_v4325','bh_confirm_license_payment_v4321','supervisor_confirm_payment_v2','confirm_license_payment','supervisor_confirm_payment'],{p_license_id:id,p_term_days:days}):await db().rpc('supervisor_confirm_payment_v2',{p_license_id:id,p_term_days:days});if(q.error)throw q.error;const lic=d.licenses.find(x=>x.id===id);await audit(lic?.organization_id,'license_payment_confirmed',{days,price});toast('Pago confirmado y licencia activa.');await window.renderSupervisorLicenses()}catch(e){toast(e.message)}});
 r.querySelectorAll('[data-sg-license-toggle]').forEach(b=>b.onclick=async()=>{try{await setOrgStatus(b.dataset.sgLicenseToggle,b.dataset.next);await window.renderSupervisorLicenses()}catch(e){toast(e.message)}});
 }catch(e){r.insertAdjacentHTML('beforeend',`<div class="empty-state">${esc(e.message)}</div>`);} };
window.renderSupervisorPayments=window.renderSupervisorLicenses;
window.renderSupervisorAdmins=async function(){
 if(!isSup())return;wireRealtime();const r=root();r.innerHTML=page('ACCESOS','Administradores','Códigos ADM y cuentas administrativas por organización','supervisorMore');
 try{
  const d=await loadAll(true),om=Object.fromEntries(d.orgs.map(x=>[x.id,x])),pending=pendingAdminCodes(d.codes);
  r.insertAdjacentHTML('beforeend',`<section class="supervisor-create-card sg-admin-create"><div><span>NUEVO ACCESO</span><h3>Crear administrador</h3><p>Genere un código ADM. El código permanecerá visible aquí hasta que sea usado, revocado o venza.</p></div><form id="sgAdminCreateForm" class="form-grid"><label>Organización<select name="org" required><option value="">Seleccione una organización</option>${d.orgs.map(o=>`<option value="${o.id}">${esc(o.name)}</option>`).join('')}</select></label><div class="code-validity-note"><strong>Vigencia fija: 7 días</strong><span>Solo activa la cuenta; no limita el acceso después del registro.</span></div><div class="form-actions wide"><button class="primary-btn">Generar código de administrador</button></div></form></section><section class="history-card"><div class="sg-section-heading"><div><span>INVITACIONES ACTIVAS</span><h3>Códigos ADM disponibles</h3><p>Puede copiarlos nuevamente mientras sigan vigentes.</p></div><strong>${pending.length}</strong></div><div class="access-code-list" id="sgPendingAdminCodes">${pending.map(x=>codeCard(x,om[x.organization_id]?.name)).join('')||'<div class="empty-state"><strong>No hay códigos ADM pendientes</strong><span>Genere uno seleccionando la organización.</span></div>'}</div></section><section class="history-card"><div class="sg-section-heading"><div><span>CUENTAS REGISTRADAS</span><h3>Administradores</h3><p>Estas cuentas ya completaron su inscripción.</p></div><strong>${d.admins.length}</strong></div><div class="supervisor-admin-list">${d.admins.map(a=>`<article><div><h3>${esc(a.full_name||'Administrador')}</h3><p>${esc(om[a.organization_id]?.name||'Sin organización')} · ${esc(a.username||'Sin usuario')}</p></div><span class="status ${a.active?'ok':'danger'}">${a.active?'Activo':'Bloqueado'}</span><small>Último acceso: ${fmtDT(a.last_seen_at)}</small><button class="${a.active?'mini-btn':'primary-btn'}" data-sg-admin="${a.id}" data-org="${a.organization_id}" data-active="${a.active}">${a.active?'Bloquear':'Reactivar'}</button></article>`).join('')||'<div class="empty-state">No hay administradores registrados.</div>'}</div></section>`);
  document.getElementById('sgAdminCreateForm')?.addEventListener('submit',async e=>{e.preventDefault();const fd=new FormData(e.currentTarget),orgId=String(fd.get('org')||'');if(!orgId){toast('Seleccione una organización.');return;}const btn=e.currentTarget.querySelector('button');try{btn.disabled=true;btn.textContent='Generando…';await createAdminCode(orgId);invalidateCache();await window.renderSupervisorAdmins();}catch(x){toast(x.message)}finally{btn.disabled=false;btn.textContent='Generar código de administrador';}});
  r.querySelectorAll('[data-sg-admin]').forEach(b=>b.onclick=async()=>{const active=b.dataset.active!=='true';try{b.disabled=true;const rpc=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_set_profile_active_v4321'],{p_target:b.dataset.sgAdmin,p_active:active}):null;let q=rpc;if(!rpc||rpc.error&&window.BHSC_RPC_FUNCTION_MISSING?.(rpc.error))q=await db().from('profiles').update({active,updated_at:new Date().toISOString()}).eq('id',b.dataset.sgAdmin);if(q?.error)throw q.error;await audit(b.dataset.org,active?'administrator_reactivated':'administrator_blocked',{profile_id:b.dataset.sgAdmin});toast(active?'Administrador reactivado.':'Administrador bloqueado.');await window.renderSupervisorAdmins()}catch(e){toast(e.message)}finally{b.disabled=false}});
  wireAdminCodeActions(r,window.renderSupervisorAdmins);
 }catch(e){r.insertAdjacentHTML('beforeend',`<div class="empty-state">${esc(e.message)}</div>`);} };

window.renderSupervisorAudit=async function(){
 if(!isSup())return;wireRealtime();const r=root();r.innerHTML=page('TRAZABILIDAD','Auditoría','Acciones realizadas por Supervisor y usuarios','supervisorMore');try{const d=await loadAll(),om=Object.fromEntries(d.orgs.map(x=>[x.id,x])),label=a=>({administrator_login:'Entrada del administrador',supervisor_login:'Entrada del supervisor',administrator_blocked:'Administrador bloqueado',administrator_reactivated:'Administrador reactivado'}[a]||String(a||'Acción').replaceAll('_',' '));r.insertAdjacentHTML('beforeend',`<div class="supervisor-audit-list">${d.audit.map(x=>`<article><div><strong>${esc(label(x.action))}</strong><span>${esc(om[x.organization_id]?.name||'Global')}</span></div><small>${fmtDT(x.created_at)}</small><p>${esc(JSON.stringify(x.details||{}))}</p></article>`).join('')||'<div class="empty-state">Sin registros.</div>'}</div>`)}catch(e){r.insertAdjacentHTML('beforeend',`<div class="empty-state">${esc(e.message)}</div>`);} };
window.renderSupervisorAlerts=async function(){if(!isSup())return;wireRealtime();const r=root();r.innerHTML=page('SEGUIMIENTO','Alertas comerciales','Licencias vencidas, pagos pendientes y cuentas suspendidas','supervisorMore');try{const d=await loadAll(),om=Object.fromEntries(d.orgs.map(x=>[x.id,x])),items=[];d.licenses.forEach(l=>{const name=om[l.organization_id]?.name||'Organización';if(!l.payment_confirmed)items.push(['Pago pendiente',name,'warn']);if(l.status==='suspended')items.push(['Licencia suspendida',name,'danger']);if(l.renews_at&&new Date(l.renews_at)<new Date())items.push(['Licencia vencida',name,'danger'])});r.insertAdjacentHTML('beforeend',`<div class="supervisor-alert-list">${items.map(x=>`<article><span class="status ${x[2]}">${x[0]}</span><strong>${esc(x[1])}</strong></article>`).join('')||'<div class="empty-state">No hay alertas comerciales.</div>'}</div>`)}catch(e){r.insertAdjacentHTML('beforeend',`<div class="empty-state">${esc(e.message)}</div>`);} };
window.renderSupervisorSupport=async function(){if(!isSup())return;const r=root();r.innerHTML=page('SOPORTE','Intervenciones','Registrar asistencia técnica a una organización','supervisorMore');try{const d=await loadAll();r.insertAdjacentHTML('beforeend',`<form id="sgSupportForm" class="form-card form-grid"><label>Organización<select name="org">${d.orgs.map(o=>`<option value="${o.id}">${esc(o.name)}</option>`).join('')}</select></label><label class="wide">Detalle<textarea name="note" rows="5" required></textarea></label><div class="form-actions wide"><button class="primary-btn">Registrar intervención</button></div></form>`);document.getElementById('sgSupportForm').onsubmit=async e=>{e.preventDefault();const f=new FormData(e.currentTarget);try{let q=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_register_support_intervention_v4321','register_support_intervention'],{p_org_id:f.get('org'),p_note:String(f.get('note')).trim()}):await db().rpc('register_support_intervention',{p_org_id:f.get('org'),p_note:String(f.get('note')).trim()});if(q.error){await audit(f.get('org'),'support_intervention',{note:String(f.get('note')).trim()})}toast('Intervención registrada.');e.currentTarget.reset()}catch(x){toast(x.message)}}}catch(e){r.insertAdjacentHTML('beforeend',`<div class="empty-state">${esc(e.message)}</div>`);} };
window.renderSupervisorMore=function(){const r=root();r.innerHTML=page('SUPERVISOR','Más herramientas','Administradores, auditoría, alertas y soporte','home')+`<section class="supervisor-global-menu supervisor-menu-pro"><button data-go="supervisorAdmins"><span class="sg-menu-icon blue">${sgIcon('users')}</span><div><strong>Administradores</strong><small>Bloquear o reactivar cuentas</small></div><span class="sg-menu-arrow">${sgIcon('arrow')}</span></button><button data-go="supervisorAudit"><span class="sg-menu-icon amber">${sgIcon('audit')}</span><div><strong>Auditoría</strong><small>Revisar acciones del sistema</small></div><span class="sg-menu-arrow">${sgIcon('arrow')}</span></button><button data-go="supervisorAlerts"><span class="sg-menu-icon red">${sgIcon('alert')}</span><div><strong>Alertas</strong><small>Vencimientos y pagos pendientes</small></div><span class="sg-menu-arrow">${sgIcon('arrow')}</span></button><button data-go="supervisorSupport"><span class="sg-menu-icon green">${sgIcon('support')}</span><div><strong>Soporte</strong><small>Registrar intervenciones técnicas</small></div><span class="sg-menu-arrow">${sgIcon('arrow')}</span></button></section>`};
document.addEventListener('click',e=>{
 if(!isSup())return;
 const go=e.target.closest('[data-go]');
 if(go){const screen=go.dataset.go;if(screen&&['home','supervisorOrganizations','supervisorOrganizationDetail','supervisorLicenses','supervisorPayments','supervisorAdmins','supervisorAudit','supervisorAlerts','supervisorSupport','supervisorMore'].includes(screen)){e.preventDefault();e.stopImmediatePropagation();navigate(screen);return;}}
},true);
window.__supervisorGlobalActive=true;
window.addEventListener('seniorcare:session-ready',wireRealtime);
setTimeout(()=>{if(isSup())wireRealtime()},1200);
console.info(`Supervisor Global ${VERSION} listo`);
})();
