(function(){
const c=()=>window.seniorcareSupabase;
const el=()=>document.getElementById('mainContent');
const fmtDate=v=>v?new Date(v).toLocaleDateString('es-CR',{day:'2-digit',month:'short',year:'numeric'}):'Sin definir';
const fmtDateTime=v=>v?new Date(v).toLocaleString('es-CR'):'Sin definir';
const label=s=>({active:'Activo',grace_period:'En gracia',suspended:'Suspendido',cancelled:'Cancelado'}[s]||'Sin licencia');
const cls=s=>s==='active'?'ok':s==='grace_period'?'warn':'danger';
const icon=name=>(window.svg&&window.svg[name])||'';
const head=(k,t,s)=>window.pageHeader?window.pageHeader(k,t,s):`<h2>${t}</h2>`;
async function load(){
 const [o,l,p,a]=await Promise.all([
  c().from('organizations').select('*').order('created_at',{ascending:false}),
  c().from('licenses').select('*').order('updated_at',{ascending:false}),
  c().from('profiles').select('id,organization_id,full_name,username,role,active,last_seen_at').eq('role','administrator'),
  c().from('activation_codes').select('*').order('created_at',{ascending:false})
 ]);
 for(const r of [o,l,p,a]) if(r.error) throw r.error;
 return {orgs:o.data||[],licenses:l.data||[],admins:p.data||[],codes:a.data||[]};
}
async function audit(action,tableName,recordId,details={}){
 const payload={organization_id:details.organization_id||null,user_id:window.currentUser?.id||null,action,table_name:tableName,record_id:String(recordId||''),details};
 const r=await c().from('audit_logs').insert(payload);
 if(r.error) throw r.error;
 return true;
}
function wire(){
 document.querySelectorAll('[data-go]').forEach(b=>b.onclick=()=>window.go?.(b.dataset.go,{scope:'global'}));
 document.querySelectorAll('[data-back]').forEach(b=>b.onclick=()=>window.goBack?.());
}
function metric(title,value,sub,screen,tone='lilac',ico='report'){return `<button class="supv-metric" data-go="${screen}"><span class="supv-metric-icon ${tone}">${icon(ico)}</span><div><small>${title}</small><strong>${value}</strong><p>${sub}</p></div><b>›</b></button>`}
function quick(screen,title,sub){return `<button data-go="${screen}"><span>${title}</span><small>${sub}</small></button>`}

function escapeHtml(value){return String(value??'').replace(/[&<>"]/g,ch=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[ch]));}
function openDialog(title,body,onSubmit){
 const old=document.getElementById('supvDialog');if(old)old.remove();
 const wrap=document.createElement('div');wrap.id='supvDialog';wrap.className='supv-dialog-backdrop';
 wrap.innerHTML=`<section class="supv-dialog" role="dialog" aria-modal="true"><div class="supv-dialog-head"><div><span>BERNARD HEALTH SENIORCARE</span><h3>${title}</h3></div><button type="button" class="supv-dialog-close" aria-label="Cerrar">×</button></div><form id="supvDialogForm">${body}<div class="form-actions"><button type="button" class="secondary-btn" data-dialog-cancel>Cancelar</button><button type="submit" class="primary-btn">Guardar</button></div></form></section>`;
 document.body.appendChild(wrap);
 const close=()=>wrap.remove();wrap.querySelector('.supv-dialog-close').onclick=close;wrap.querySelector('[data-dialog-cancel]').onclick=close;
 wrap.onclick=e=>{if(e.target===wrap)close();};
 wrap.querySelector('form').onsubmit=async e=>{e.preventDefault();const submit=e.currentTarget.querySelector('[type="submit"]');try{submit.disabled=true;submit.textContent='Procesando…';await onSubmit(new FormData(e.currentTarget));close();}catch(err){window.showToast?.(err?.message||'No se pudo completar la acción.');submit.disabled=false;submit.textContent='Guardar';}};
}
async function createAdminCode(orgId,orgName){
 try{
  const existing=await c().from('activation_codes').select('*').eq('organization_id',orgId).eq('role','administrator').eq('active',true).order('created_at',{ascending:false});
  if(existing.error)throw existing.error;
  const pending=(existing.data||[]).find(x=>Number(x.used_count||0)<Number(x.max_uses||1)&&new Date(x.expires_at)>new Date());
  if(pending){
   openDialog('Acceso ADM pendiente',`<div class="generated-code"><span>CÓDIGO PENDIENTE DE REGISTRO</span><strong>${escapeHtml(pending.code)}</strong><p>Este código todavía no ha sido utilizado. Vence ${fmtDate(pending.expires_at)}.</p></div><div class="confirmation-warning">No se creará otro código mientras este continúe vigente. Puede copiarlo o revocarlo.</div>`,async()=>{});
   const f=document.getElementById('supvDialogForm');
   if(f){
    f.querySelector('.form-actions').innerHTML='<button type="button" class="secondary-btn" data-revoke-code>Revocar código</button><button type="button" class="primary-btn" data-copy-generated>Copiar código</button>';
    f.querySelector('[data-copy-generated]').onclick=async()=>{await navigator.clipboard.writeText(pending.code);window.showToast?.('Código copiado.');};
    f.querySelector('[data-revoke-code]').onclick=async()=>{if(!confirm('¿Revocar este código pendiente?'))return;const r=await c().from('activation_codes').update({active:false}).eq('id',pending.id);if(r.error)return window.showToast?.(r.error.message);try{await audit('activation_code_revoked','activation_codes',pending.id,{organization_id:orgId,code:pending.code});}catch(_e){}document.getElementById('supvDialog')?.remove();window.showToast?.('Código revocado.');window.renderSupervisorOrganizations?.();};
   }
   return;
  }
  openDialog('Crear acceso de administrador',`<div class="dialog-intro"><strong>${escapeHtml(orgName)}</strong><p>El código tendrá una vigencia fija de 7 días y servirá únicamente para activar la cuenta una vez.</p></div><div class="code-validity-note"><strong>Vigencia fija: 7 días</strong><span>Después de registrarse, el administrador conserva su acceso según la licencia contratada.</span></div>`,async ()=>{
    const days=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:7}):await c().rpc('create_activation_code',{p_org_id:orgId,p_role:'administrator',p_days:7});if(r.error)throw r.error;
    const payload=Array.isArray(r.data)?r.data[0]:r.data;
    const code=payload?.code||payload?.result?.code||payload;
    if(!code)throw new Error('Supabase no devolvió el código de activación.');
    window.showToast?.(`Código ${code} creado correctamente.`);
    await audit('activation_code_created','activation_codes',code,{organization_id:orgId,role:'administrator',days});
    openDialog('Código ADM creado',`<div class="generated-code"><span>CÓDIGO PENDIENTE DE REGISTRO</span><strong>${escapeHtml(code)}</strong><p>Vigencia: 7 días. Es de un solo uso y solo activa la cuenta.</p></div>`,async()=>{});
    const f=document.getElementById('supvDialogForm');if(f){f.querySelector('.form-actions').innerHTML='<button type="button" class="primary-btn" data-copy-generated>Copiar código</button>';f.querySelector('[data-copy-generated]').onclick=async()=>{await navigator.clipboard.writeText(code);window.showToast?.('Código copiado.');};}
  });
 }catch(err){window.showToast?.(err?.message||'No se pudo revisar los accesos ADM.');}
}
async function showLicenseEditor(lic,orgName){
 const confirmed=!!lic.payment_confirmed;
 openDialog(confirmed?'Licencia confirmada':'Configurar vigencia de licencia',`<div class="dialog-intro"><strong>${escapeHtml(orgName)}</strong><p>${confirmed?'La vigencia ya fue confirmada con el pago y no puede modificarse durante el período actual.':'Puede ajustar la vigencia antes de confirmar el pago.'}</p></div><div class="form-grid"><label>Duración en días<input name="days" type="number" min="30" max="365" value="${Number(lic.term_days||30)}" ${confirmed?'disabled':''}></label><label>Fecha prevista de vencimiento<input name="renew" type="date" value="${lic.renews_at?(window.BHSC_LOCAL_DATE?window.BHSC_LOCAL_DATE(new Date(lic.renews_at)):new Intl.DateTimeFormat('en-CA',{timeZone:'America/Costa_Rica'}).format(new Date(lic.renews_at))):''}" ${confirmed?'disabled':''}></label><label>Plan<input name="plan" value="${escapeHtml(lic.plan_name||'Mensual')}" ${confirmed?'disabled':''}></label><label>Precio<input name="price" type="number" min="20000" step="1000" value="${Number(lic.price_monthly||20000)}" ${confirmed?'disabled':''}></label></div>${confirmed?'<div class="license-lock-note">Vigencia bloqueada desde la confirmación del pago.</div>':''}`,async fd=>{
   if(confirmed)return;
   const days=Number(fd.get('days'));if(!Number.isInteger(days)||days<30||days>365)throw new Error('La vigencia debe estar entre 30 y 365 días.');
   const renew=String(fd.get('renew')||'');if(!renew)throw new Error('Seleccione la fecha prevista de vencimiento.');
   const args={p_license_id:lic.id,p_term_days:days,p_renews_at:new Date(renew+'T12:00:00').toISOString(),p_plan_name:String(fd.get('plan')||'Mensual'),p_price_monthly:Number(fd.get('price')||0)};const r=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_update_license_draft_v4321','update_license_draft'],args):await c().rpc('update_license_draft',args);if(r.error)throw r.error;
   window.showToast?.('Vigencia preliminar actualizada.');window.renderSupervisorLicenses();
 });
 if(confirmed){const f=document.getElementById('supvDialogForm');if(f)f.querySelector('.form-actions').innerHTML='<button type="button" class="primary-btn" data-dialog-ok>Cerrar</button>';document.querySelector('[data-dialog-ok]')?.addEventListener('click',()=>document.getElementById('supvDialog')?.remove());}
}
async function confirmLicense(lic,orgName){
 if(!lic?.id) return window.showToast?.('No se encontró la licencia seleccionada.');
 openDialog('Confirmar pago y activar vigencia',`<div class="dialog-intro"><strong>${escapeHtml(orgName)}</strong><p>Al confirmar, la vigencia comenzará hoy y quedará bloqueada hasta que finalice el período.</p></div><div class="form-grid"><label class="wide">Días de vigencia<input name="days" type="number" min="30" max="365" value="${Number(lic.term_days||30)}" required></label></div><div class="confirmation-warning">Esta acción inicia el contador regresivo y no permite modificar la fecha durante la vigencia.</div>`,async fd=>{
   const days=Number(fd.get('days'));
   if(!Number.isInteger(days)||days<30||days>365) throw new Error('La vigencia debe estar entre 30 y 365 días.');

   const paymentArgs={p_license_id:lic.id,p_term_days:days};const r=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_confirm_license_payment_v4325','bh_confirm_license_payment_v4321','supervisor_confirm_payment_v2','supervisor_confirm_payment','confirm_license_payment'],paymentArgs):await c().rpc('supervisor_confirm_payment',paymentArgs);
   if(r.error) throw new Error(r.error.message||'No se pudo confirmar el pago.');

   const verify=await c().from('licenses').select('id,organization_id,status,payment_confirmed,starts_at,renews_at,term_days').eq('id',lic.id).single();
   if(verify.error) throw new Error(verify.error.message||'No se pudo verificar la licencia.');
   if(!verify.data?.payment_confirmed || verify.data?.status!=='active' || !verify.data?.renews_at){
     throw new Error('Supabase no confirmó la activación de la licencia.');
   }

   try{await audit('payment_confirmed','licenses',lic.id,{organization_id:lic.organization_id,days});}catch(_e){}
   window.showToast?.(`Pago confirmado. Vigencia activa por ${days} días.`);
   await window.renderSupervisorLicenses?.();
 });
}
window.renderSupervisorHome=async function(){
 const m=el();m.innerHTML='<div class="supv-loading">Cargando panel superior…</div>';
 try{const {orgs,licenses,admins,codes}=await load();const lm=Object.fromEntries(licenses.map(x=>[x.organization_id,x]));const am=Object.fromEntries(admins.map(x=>[x.organization_id,x]));const active=licenses.filter(x=>x.status==='active').length,suspended=licenses.filter(x=>x.status==='suspended').length,grace=licenses.filter(x=>x.status==='grace_period').length,exp=licenses.filter(x=>x.renews_at&&new Date(x.renews_at)>=new Date()&&new Date(x.renews_at)-Date.now()<2592000000).length,pendingAdmins=orgs.filter(o=>!am[o.id]).length,expCodes=codes.filter(x=>x.active&&new Date(x.expires_at)<new Date()).length;
 m.innerHTML=`<section class="admin-welcome supv-welcome"><div><span class="eyebrow">PANEL SUPERVISOR</span><h2>¡Bienvenido, Dr. Abraham Benard!</h2><p>Administre clientes, licencias, administradores, accesos y soporte general de Bernard Health SeniorCare.</p></div><div class="admin-mark">${icon('care')}</div></section>
 <section class="supv-metrics">${metric('Hogares activos',active,'Licencias activas','supervisorOrganizations','lilac','home')}${metric('Licencias por vencer',exp,'Próximos 30 días','supervisorLicenses','amber','calendar')}${metric('Hogares suspendidos',suspended,'Requieren atención','supervisorLicenses','rose','alert')}${metric('Administradores',admins.filter(a=>a.active).length,'Activos en el sistema','supervisorAdmins','lilac','users')}${metric('Sin administrador',pendingAdmins,'Pendientes de configurar','supervisorAdmins','amber','userPlus')}${metric('Códigos vencidos',expCodes,'Revisar accesos','supervisorAlerts','mint','bell')}</section>
 <section class="supv-panel"><h3>Accesos rápidos</h3><div class="supv-quick">${quick('supervisorOrganizations','Organizaciones','Crear y administrar hogares')}${quick('supervisorLicenses','Licencias','Estados, pagos y vencimientos')}${quick('supervisorAdmins','Administradores','Accesos principales')}${quick('supervisorAlerts','Alertas SUPV','Licencias, pagos y accesos')}${quick('supervisorSupport','Centro de soporte','Atención y seguimiento de clientes')}${quick('supervisorMore','Más','Soporte y configuración')}</div></section>
 <section class="supv-panel"><div class="supv-title"><h3>Organizaciones recientes</h3><button data-go="supervisorOrganizations">Ver todas</button></div><div class="supv-table">${orgs.slice(0,5).map(o=>{const l=lm[o.id],a=am[o.id];return `<article><div><strong>${o.name}</strong><small>${a?.full_name||'Administrador pendiente'}</small></div><div><small>Plan</small><strong>${l?.plan_name||'Sin plan'}</strong></div><div><small>Próximo pago</small><strong>${fmtDate(l?.renews_at)}</strong></div><span class="status ${cls(l?.status)}">${label(l?.status)}</span><button class="supv-manage-btn" data-manage-org="${o.id}" aria-label="Gestionar ${o.name}"><span>Ver ficha</span><b>›</b></button></article>`}).join('')||'<p>No hay organizaciones registradas.</p>'}</div></section>`;wire();
 const alertCount=suspended+grace+pendingAdmins+expCodes+exp;const topAlert=document.querySelector('.alerts');if(topAlert){topAlert.innerHTML=`<span class="dot"></span>Alertas activas${alertCount?` (${alertCount})`:''}`;topAlert.classList.toggle('has-alerts',alertCount>0);topAlert.onclick=()=>window.go?.('supervisorAlerts',{scope:'global'});}
 document.querySelectorAll('[data-manage-org]').forEach(b=>b.onclick=()=>{sessionStorage.setItem('seniorcare-selected-org',b.dataset.manageOrg);window.dispatchEvent(new CustomEvent('seniorcare:organization-selected',{detail:{organizationId:b.dataset.manageOrg}}));window.go?.('supervisorOrganizationDetail',{scope:'global'});});
 }catch(e){m.innerHTML=`<div class="empty-state"><strong>No se pudo cargar el panel</strong><span>${e.message}</span></div>`;}
};
window.renderSupervisorOrganizations=async function(){
 const m=el();m.innerHTML=head('GESTIÓN COMERCIAL','Organizaciones','Cree clientes, administre licencias y controle el acceso de cada hogar')+'<div class="supv-loading">Cargando…</div>';
 try{const {orgs,licenses,admins}=await load();const lm=Object.fromEntries(licenses.map(x=>[x.organization_id,x]));const am=Object.fromEntries(admins.map(x=>[x.organization_id,x]));m.innerHTML=head('GESTIÓN COMERCIAL','Organizaciones','Cree clientes, administre licencias y controle el acceso de cada hogar')+`<section class="supv-toolbar"><button class="primary-btn" id="newOrg">+ Nueva organización</button><label class="searchbox">${icon('search')}<input id="orgFind" placeholder="Buscar organización"></label></section><form id="orgForm" class="form-card hidden"><h3>Nueva organización</h3><div 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>Plan<select name="plan"><option>Mensual</option><option>Profesional</option><option>Empresarial</option></select></label><label>Precio mensual<input name="price" type="number" min="20000" step="1000" value="20000"></label><label>Días previstos de vigencia<input name="days" type="number" min="30" max="365" value="30" required></label><label>Fecha prevista de vencimiento<input name="renew" type="date" required></label><label class="wide">Dirección<textarea name="address"></textarea></label></div><div class="form-actions"><button type="button" class="secondary-btn" id="cancelOrg">Cancelar</button><button class="primary-btn" type="submit">Guardar</button></div></form><div class="supv-org-grid">${orgs.map(o=>{const l=lm[o.id],a=am[o.id];return `<article data-org-card><div class="supv-org-head"><div><h3>${o.name}</h3><p>${o.email||'Sin correo'} · ${o.phone||'Sin teléfono'}</p></div><span class="status ${cls(l?.status)}">${label(l?.status)}</span></div><div class="supv-org-data"><span>Administrador<strong>${a?.full_name||'Pendiente'}</strong></span><span>Plan<strong>${l?.plan_name||'Sin plan'}</strong></span><span>Vencimiento<strong>${fmtDate(l?.renews_at)}</strong></span><span>Pago<strong>${l?.payment_confirmed?'Confirmado':'Pendiente'}</strong></span></div><div class="supv-actions"><button class="secondary-btn" data-code="${o.id}" data-name="${o.name}">Crear acceso ADM</button><button class="mini-btn" data-toggle="${o.id}" data-status="${l?.status||'active'}">${l?.status==='suspended'?'Reactivar':'Suspender'}</button></div></article>`}).join('')||'<p>No hay organizaciones.</p>'}</div>`;
 wire();const f=document.getElementById('orgForm');document.getElementById('newOrg').onclick=()=>{f.classList.remove('hidden');f.scrollIntoView({behavior:'smooth'})};document.getElementById('cancelOrg').onclick=()=>f.classList.add('hidden');document.getElementById('orgFind').oninput=e=>document.querySelectorAll('[data-org-card]').forEach(x=>x.style.display=x.textContent.toLowerCase().includes(e.target.value.toLowerCase())?'':'none');
 f.onsubmit=async e=>{e.preventDefault();const submit=f.querySelector('button[type="submit"]');const d=new FormData(f);let createdId=null;try{submit.disabled=true;submit.textContent='Guardando…';const payload={name:String(d.get('name')||'').trim(),legal_name:String(d.get('legal')||'').trim()||null,email:String(d.get('email')||'').trim()||null,phone:String(d.get('phone')||'').trim()||null,address:String(d.get('address')||'').trim()||null,active:true,created_by:window.currentUser?.id||null};if(!payload.name)throw new Error('Escriba el nombre de la organización.');const days=Number(d.get('days'));if(!Number.isInteger(days)||days<30||days>365)throw new Error('La vigencia debe estar entre 30 y 365 días.');const duplicate=await c().from('organizations').select('id,name').ilike('name',payload.name).limit(1);if(duplicate.error)throw duplicate.error;if((duplicate.data||[]).length)throw new Error('Ya existe una organización con ese nombre.');const r=await c().from('organizations').insert(payload).select().single();if(r.error)throw r.error;createdId=r.data.id;const q=await c().from('licenses').insert({organization_id:r.data.id,status:'grace_period',plan_name:String(d.get('plan')||'Mensual'),renews_at:new Date(String(d.get('renew'))+'T12:00:00').toISOString(),term_days:days,payment_confirmed:false,updated_by:window.currentUser?.id||null,price_monthly:Number(d.get('price')||0)}).select().single();if(q.error){await c().from('organizations').delete().eq('id',r.data.id);createdId=null;throw q.error;}const verify=await c().from('organizations').select('id,name').eq('id',r.data.id).single();if(verify.error)throw verify.error;try{await audit('organization_created','organizations',r.data.id,{organization_id:r.data.id,name:r.data.name,plan:q.data.plan_name,days});}catch(_e){}window.showToast?.('Organización creada y verificada correctamente.');f.reset();f.classList.add('hidden');window.go?.('supervisorOrganizations',{scope:'global'},{replace:true});setTimeout(()=>window.renderSupervisorOrganizations?.(),250);}catch(err){window.showToast?.(err?.message||'No se pudo crear la organización.');if(createdId){console.warn('Organización creada parcialmente:',createdId);}submit.disabled=false;submit.textContent='Guardar';}};
 document.querySelectorAll('[data-code]').forEach(b=>b.onclick=()=>createAdminCode(b.dataset.code,b.dataset.name));
 document.querySelectorAll('[data-toggle]').forEach(b=>b.onclick=async()=>{const next=b.dataset.status==='suspended'?'active':'suspended';if(next==='suspended'&&!confirm('¿Suspender esta organización y todos sus accesos?'))return;const r=await c().from('licenses').update({status:next,suspended_at:next==='suspended'?new Date().toISOString():null}).eq('organization_id',b.dataset.toggle);if(r.error)return window.showToast(r.error.message);await audit(next==='suspended'?'license_suspended':'license_reactivated','licenses',b.dataset.toggle,{organization_id:b.dataset.toggle,status:next});window.renderSupervisorOrganizations();});
 }catch(e){m.innerHTML=`<div class="empty-state"><strong>No se pudo cargar</strong><span>${e.message}</span></div>`;}
};
window.renderSupervisorLicenses=async function(){
 const m=el();m.innerHTML=head('CONTROL DE SUSCRIPCIONES','Licencias','Defina la vigencia, confirme el pago y supervise el contador regresivo')+'<div class="supv-loading">Cargando…</div>';
 try{const {orgs,licenses}=await load(),om=Object.fromEntries(orgs.map(o=>[o.id,o]));m.innerHTML=head('CONTROL DE SUSCRIPCIONES','Licencias','Defina la vigencia, confirme el pago y supervise el contador regresivo')+`<section class="license-howto"><div><b>1</b><span><strong>Configure precio y vigencia</strong><small>Indique el monto mensual y la cantidad de días.</small></span></div><div><b>2</b><span><strong>Confirme el pago</strong><small>La licencia se activa y comienza el contador.</small></span></div><div><b>3</b><span><strong>Controle el vencimiento</strong><small>La app mostrará los días restantes.</small></span></div></section><div class="supv-license-grid">${licenses.map(l=>{const days=l.renews_at?Math.max(0,Math.ceil((new Date(l.renews_at)-Date.now())/86400000)):null;return `<article><div class="license-card-top"><span class="status ${cls(l.status)}">${label(l.status)}</span><span class="payment-state ${l.payment_confirmed?'confirmed':'pending'}">${l.payment_confirmed?'Pago confirmado':'Pago pendiente'}</span></div><h3>${om[l.organization_id]?.name||'Organización'}</h3><p>${l.plan_name}</p><div class="license-countdown ${days!==null&&days<=7?'urgent':''}"><small>DÍAS DE VIGENCIA RESTANTES</small><strong>${l.payment_confirmed?(days??0):'—'}</strong><span>${l.payment_confirmed?`Vence ${fmtDate(l.renews_at)}`:'El contador iniciará al confirmar el pago'}</span></div><div class="license-detail"><span>Duración<strong>${l.term_days||30} días</strong></span><span>Precio<strong>${Number(l.price_monthly||0)>0?Number(l.price_monthly).toLocaleString('es-CR',{style:'currency',currency:'CRC'}):'Sin definir'}</strong></span><span>Estado<strong>${l.payment_confirmed?'Bloqueada':'Editable'}</strong></span></div><div class="supv-actions"><button class="secondary-btn" data-edit-license="${l.id}">${l.payment_confirmed?'Ver vigencia':'1. Configurar precio y vigencia'}</button>${!l.payment_confirmed?`<button class="primary-btn" data-confirm-license="${l.id}">2. Confirmar pago</button>`:''}<button class="mini-btn" data-ltoggle="${l.id}" data-org="${l.organization_id}" data-status="${l.status}">${l.status==='suspended'?'Reactivar':'Suspender'}</button></div></article>`}).join('')||'<p>No hay licencias registradas.</p>'}</div>`;wire();
 document.querySelectorAll('[data-edit-license]').forEach(b=>{const lic=licenses.find(x=>x.id===b.dataset.editLicense);b.onclick=()=>showLicenseEditor(lic,om[lic.organization_id]?.name||'Organización');});
 document.querySelectorAll('[data-confirm-license]').forEach(b=>{const lic=licenses.find(x=>x.id===b.dataset.confirmLicense);b.onclick=()=>confirmLicense(lic,om[lic.organization_id]?.name||'Organización');});
 document.querySelectorAll('[data-ltoggle]').forEach(b=>b.onclick=async()=>{const next=b.dataset.status==='suspended'?'active':'suspended';const r=await c().from('licenses').update({status:next,suspended_at:next==='suspended'?new Date().toISOString():null}).eq('id',b.dataset.ltoggle);if(r.error)return window.showToast(r.error.message);await audit(next==='suspended'?'license_suspended':'license_reactivated','licenses',b.dataset.ltoggle,{organization_id:b.dataset.org,status:next});window.renderSupervisorLicenses();});
 }catch(e){m.innerHTML=`<div class="empty-state"><strong>No se pudieron cargar las licencias</strong><span>${e.message}</span></div>`;}
};
window.renderSupervisorAdmins=async function(){
 const m=el();m.innerHTML=head('CONTROL DE ACCESOS','Administradores principales','Cuentas responsables de cada organización')+'<div class="supv-loading">Cargando…</div>';
 try{const {orgs,admins,codes}=await load(),om=Object.fromEntries(orgs.map(o=>[o.id,o]));const pending=codes.filter(x=>['administrator','admin'].includes(String(x.role||'').toLowerCase())&&x.active&&x.used_count<x.max_uses);m.innerHTML=head('CONTROL DE ACCESOS','Administradores principales','Cuentas responsables de cada organización')+`<section class="supv-panel"><h3>Códigos ADM pendientes</h3><div class="access-code-list">${pending.map(x=>`<article class="access-code-card"><div><span>${om[x.organization_id]?.name||'Organización'}</span><strong>${x.code}</strong><small>Vence ${fmtDate(x.expires_at)}</small></div></article>`).join('')||'<p>No hay códigos pendientes.</p>'}</div></section><div class="supv-org-grid">${admins.map(a=>`<article><div class="supv-org-head"><div><h3>${a.full_name}</h3><p>${om[a.organization_id]?.name||'Sin organización'} · ${a.username||'Sin usuario'}</p></div><span class="status ${a.active?'ok':'danger'}">${a.active?'Activo':'Bloqueado'}</span></div><div class="supv-org-data"><span>Último acceso<strong>${fmtDateTime(a.last_seen_at)}</strong></span></div><div class="supv-actions"><button class="secondary-btn" data-atoggle="${a.id}" data-org="${a.organization_id}" data-active="${a.active}">${a.active?'Bloquear':'Reactivar'}</button></div></article>`).join('')||'<p>No hay administradores registrados. Genere un código ADM desde Organizaciones.</p>'}</div>`;wire();document.querySelectorAll('[data-atoggle]').forEach(b=>b.onclick=async()=>{const active=b.dataset.active!=='true';const r=await c().from('profiles').update({active}).eq('id',b.dataset.atoggle);if(r.error)return window.showToast(r.error.message);await audit(active?'administrator_reactivated':'administrator_blocked','profiles',b.dataset.atoggle,{organization_id:b.dataset.org,active});window.renderSupervisorAdmins();});
 }catch(e){m.innerHTML+=`<p>${e.message}</p>`;}
};
window.renderSupervisorAlerts=async function(){
 const m=el();m.innerHTML=head('CENTRO DE ALERTAS SUPV','Alertas comerciales','Licencias, pagos, accesos y configuración de clientes')+'<div class="supv-loading">Cargando…</div>';
 try{const {orgs,licenses,admins,codes}=await load(),am=Object.fromEntries(admins.map(x=>[x.organization_id,x])),om=Object.fromEntries(orgs.map(x=>[x.id,x]));const alerts=[];licenses.forEach(l=>{const days=l.renews_at?Math.ceil((new Date(l.renews_at)-Date.now())/86400000):999;if(l.status==='suspended')alerts.push({level:'high',title:'Organización suspendida',text:om[l.organization_id]?.name||'Organización',screen:'supervisorLicenses'});else if(days<0)alerts.push({level:'high',title:'Pago vencido',text:`${om[l.organization_id]?.name||'Organización'} · ${Math.abs(days)} días de atraso`,screen:'supervisorLicenses'});else if(days<=7)alerts.push({level:'medium',title:'Licencia por vencer',text:`${om[l.organization_id]?.name||'Organización'} · vence en ${days} días`,screen:'supervisorLicenses'});});orgs.filter(o=>!am[o.id]).forEach(o=>alerts.push({level:'medium',title:'Sin administrador principal',text:o.name,screen:'supervisorAdmins'}));codes.filter(x=>x.active&&new Date(x.expires_at)<new Date()&&x.used_count<x.max_uses).forEach(x=>alerts.push({level:'low',title:'Código de acceso vencido',text:`${x.code} · ${om[x.organization_id]?.name||'Organización'}`,screen:'supervisorAdmins'}));m.innerHTML=head('CENTRO DE ALERTAS SUPV','Alertas comerciales','Licencias, pagos, accesos y configuración de clientes')+`<section class="alert-summary"><article class="danger-box"><strong>${alerts.filter(x=>x.level==='high').length}</strong><span>Alta prioridad</span></article><article class="warn-box"><strong>${alerts.filter(x=>x.level==='medium').length}</strong><span>Seguimiento</span></article><article class="ok-box"><strong>${alerts.filter(x=>x.level==='low').length}</strong><span>Informativas</span></article></section><div class="list-stack">${alerts.map(a=>`<article class="data-row"><span class="incident-icon">${icon(a.level==='high'?'alert':'bell')}</span><div class="row-main"><strong>${a.title}</strong><span>${a.text}</span></div><button class="mini-btn" data-go="${a.screen}">Abrir</button></article>`).join('')||'<div class="empty-state"><strong>Sin alertas comerciales</strong><span>Las licencias y accesos están al día.</span></div>'}</div>`;wire();
 }catch(e){m.innerHTML+=`<p>${e.message}</p>`;}
};

window.renderSupervisorPayments=async function(){
 try{
  const {orgs,licenses}=await load();
  const m=el();
  const om=Object.fromEntries(orgs.map(o=>[o.id,o]));
  const pending=licenses.filter(l=>!l.payment_confirmed);
  const confirmed=licenses.filter(l=>l.payment_confirmed);
  const totalConfirmed=confirmed.reduce((s,l)=>s+Number(l.price_monthly||0),0);
  const totalPending=pending.reduce((s,l)=>s+Number(l.price_monthly||0),0);
  const money=n=>new Intl.NumberFormat('es-CR',{style:'currency',currency:'CRC',maximumFractionDigits:0}).format(Number(n||0));
  m.innerHTML=head('CONTROL FINANCIERO','Pagos','Mensualidades, renovaciones y confirmación de vigencias')+`
   <section class="payment-summary-grid">
    <article><span>Pagos confirmados</span><strong>${confirmed.length}</strong><small>${money(totalConfirmed)}</small></article>
    <article><span>Pagos pendientes</span><strong>${pending.length}</strong><small>${money(totalPending)}</small></article>
    <article><span>Organizaciones</span><strong>${orgs.length}</strong><small>Clientes registrados</small></article>
   </section>
   <section class="payment-toolbar"><label class="searchbox">${icon('search')}<input id="paymentSearch" placeholder="Buscar organización o estado"></label></section>
   <div class="payment-card-grid">${licenses.map(l=>{const o=om[l.organization_id];if(!o)return '';const paid=!!l.payment_confirmed;return `
    <article class="payment-card" data-payment-card>
      <div class="payment-card-head"><div><span>${paid?'PAGO CONFIRMADO':'PAGO PENDIENTE'}</span><h3>${escapeHtml(o.name)}</h3><p>${escapeHtml(l.plan_name||'Mensual')}</p></div><span class="status ${paid?'ok':'warn'}">${paid?'Confirmado':'Pendiente'}</span></div>
      <div class="payment-amount"><span>Monto mensual</span><strong>${Number(l.price_monthly||0)>0?money(l.price_monthly):'Sin definir'}</strong></div>
      <div class="payment-meta"><span>Vigencia<strong>${Number(l.term_days||30)} días</strong></span><span>Vencimiento<strong>${fmtDate(l.renews_at)}</strong></span></div>
      <div class="payment-actions">${paid?`<button class="secondary-btn" data-view-payment="${l.id}">Ver vigencia</button>`:`<button class="secondary-btn" data-edit-payment="${l.id}">Editar</button><button class="primary-btn" data-confirm-payment="${l.id}">2. Confirmar pago</button>`}</div>
    </article>`}).join('')||'<div class="empty-state"><strong>No hay pagos registrados</strong><span>Los pagos aparecerán al crear organizaciones y licencias.</span></div>'}</div>`;
  wire();
  document.getElementById('paymentSearch')?.addEventListener('input',e=>document.querySelectorAll('[data-payment-card]').forEach(x=>x.style.display=x.textContent.toLowerCase().includes(e.target.value.toLowerCase())?'':'none'));
  document.querySelectorAll('[data-edit-payment]').forEach(b=>b.onclick=()=>{const l=licenses.find(x=>x.id===b.dataset.editPayment);if(l)showLicenseEditor(l,om[l.organization_id]?.name||'Organización');});
  document.querySelectorAll('[data-view-payment]').forEach(b=>b.onclick=()=>{const l=licenses.find(x=>x.id===b.dataset.viewPayment);if(l)showLicenseEditor(l,om[l.organization_id]?.name||'Organización');});
  document.querySelectorAll('[data-confirm-payment]').forEach(b=>b.onclick=()=>{const l=licenses.find(x=>x.id===b.dataset.confirmPayment);if(l)confirmLicense(l,om[l.organization_id]?.name||'Organización');});
 }catch(e){el().innerHTML=head('CONTROL FINANCIERO','Pagos','Mensualidades y renovaciones')+`<div class="empty-state"><strong>No se pudo cargar Pagos</strong><span>${escapeHtml(e.message)}</span></div>`;}
};
window.renderSupervisorAudit=async function(){
 const m=el();m.innerHTML=head('SEGURIDAD Y TRAZABILIDAD','Auditoría','Registro verificable de acciones realizadas en el sistema')+'<div class="supv-loading">Cargando actividad…</div>';
 try{
  const r=await c().from('audit_logs').select('*').order('created_at',{ascending:false}).limit(150);
  if(r.error)throw r.error;
  const rows=r.data||[];
  const today=new Date().toDateString();
  const todayCount=rows.filter(x=>new Date(x.created_at).toDateString()===today).length;
  const orgActions=rows.filter(x=>x.organization_id).length;
  const securityCount=rows.filter(x=>/blocked|suspended|reactivated|login|access|support/i.test(x.action)).length;
  const actionLabel=a=>({organization_created:'Organización creada',activation_code_created:'Código de acceso creado',license_suspended:'Licencia suspendida',license_reactivated:'Licencia reactivada',payment_registered:'Pago registrado',administrator_blocked:'Administrador bloqueado',administrator_reactivated:'Administrador reactivado',support_mode_opened:'Modo soporte iniciado',audit_test:'Prueba de auditoría',supervisor_login:'Inicio de sesión SUPV'}[a]||String(a||'Evento del sistema').replaceAll('_',' '));
  m.innerHTML=head('SEGURIDAD Y TRAZABILIDAD','Auditoría','Registro verificable de acciones realizadas en el sistema')+`
  <section class="audit-summary-grid">
    <article><span>Eventos registrados</span><strong>${rows.length}</strong><small>Últimos 150 eventos</small></article>
    <article><span>Actividad de hoy</span><strong>${todayCount}</strong><small>Acciones del día</small></article>
    <article><span>Organizaciones afectadas</span><strong>${new Set(rows.map(x=>x.organization_id).filter(Boolean)).size}</strong><small>Clientes distintos</small></article>
    <article><span>Eventos de seguridad</span><strong>${securityCount}</strong><small>Accesos y suspensiones</small></article>
  </section>
  <section class="supv-panel audit-explainer"><div><h3>¿Qué se registra aquí?</h3><p>Solo acciones reales: creación de hogares, licencias, códigos de acceso, bloqueos, pagos y soporte. Un código ADM pendiente no equivale a un administrador registrado.</p></div></section>
  <section class="supv-toolbar audit-toolbar"><label class="searchbox">${icon('search')}<input id="auditFind" placeholder="Buscar acción, tabla o detalle"></label>${rows.length?'<button class="secondary-btn audit-clear-btn" id="auditClearAll">Limpiar historial</button>':''}</section>
  <div class="audit-timeline" id="auditList">${rows.map(x=>`<article data-audit data-audit-id="${x.id}"><div class="audit-dot"></div><div class="audit-body"><div class="audit-title-row"><strong>${actionLabel(x.action)}</strong><time>${fmtDateTime(x.created_at)}</time></div><span>${x.table_name||'Sistema'}${x.organization_id?` · Organización ${String(x.organization_id).slice(0,8)}`:''}</span><small>${Object.entries(x.details||{}).filter(([k])=>k!=='organization_id').map(([k,v])=>`${k}: ${v}`).join(' · ')||'Sin detalles adicionales'}</small></div><button class="audit-delete-btn" type="button" data-delete-audit="${x.id}" aria-label="Eliminar evento">×</button></article>`).join('')||'<div class="empty-state"><strong>Aún no hay eventos reales</strong><span>Las acciones aparecerán aquí al crear organizaciones, accesos, pagos o intervenciones.</span></div>'}</div>`;
  wire();
  document.getElementById('auditFind')?.addEventListener('input',e=>document.querySelectorAll('[data-audit]').forEach(x=>x.style.display=x.textContent.toLowerCase().includes(e.target.value.toLowerCase())?'':'none'));
  document.querySelectorAll('[data-delete-audit]').forEach(btn=>btn.onclick=async()=>{if(!confirm('¿Eliminar este evento de auditoría?'))return;const q=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_delete_audit_log_v4321','supervisor_delete_audit_log'],{p_log_id:Number(btn.dataset.deleteAudit)}):await c().rpc('supervisor_delete_audit_log',{p_log_id:Number(btn.dataset.deleteAudit)});if(q.error){window.showToast?.(q.error.message);return;}window.showToast?.('Evento eliminado.');window.renderSupervisorAudit();});
  document.getElementById('auditClearAll')?.addEventListener('click',async()=>{
    if(!confirm('¿Eliminar todo el historial de auditoría? Esta acción no se puede deshacer.'))return;
    let q=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_clear_audit_logs_v4321','supervisor_clear_audit_logs'],{}):await c().rpc('supervisor_clear_audit_logs');
    if(q.error){
      const rows=await c().from('audit_logs').select('id').order('id',{ascending:true});
      if(rows.error){window.showToast?.(rows.error.message);return;}
      for(const row of rows.data||[]){
        const del=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_delete_audit_log_v4321','supervisor_delete_audit_log'],{p_log_id:Number(row.id)}):await c().rpc('supervisor_delete_audit_log',{p_log_id:Number(row.id)});
        if(del.error){window.showToast?.(del.error.message);return;}
      }
    }
    window.showToast?.('Historial eliminado correctamente.');
    window.renderSupervisorAudit();
  });
  
 }catch(e){m.innerHTML=head('SEGURIDAD Y TRAZABILIDAD','Auditoría','Registro verificable de acciones realizadas en el sistema')+`<div class="empty-state"><strong>No se pudo cargar la auditoría</strong><span>${e.message}</span><small>Revise que el permiso INSERT/SELECT y la política RLS estén instalados.</small></div>`;}
};

window.renderSupervisorOrganizationDetail=async function(){
 const m=el();const id=sessionStorage.getItem('seniorcare-selected-org');
 if(!id){window.go?.('supervisorOrganizations');return;}
 m.innerHTML=head('FICHA DEL CLIENTE','Gestión de organización','Información, licencia, administrador y acciones de soporte')+'<div class="supv-loading">Cargando ficha…</div>';
 try{
  const [o,l,a,codes]=await Promise.all([
   c().from('organizations').select('*').eq('id',id).single(),
   c().from('licenses').select('*').eq('organization_id',id).maybeSingle(),
   c().from('profiles').select('id,full_name,username,active,last_seen_at').eq('organization_id',id).eq('role','administrator').maybeSingle(),
   c().from('activation_codes').select('*').eq('organization_id',id).order('created_at',{ascending:false}).limit(5)
  ]);
  if(o.error)throw o.error;if(l.error)throw l.error;if(a.error)throw a.error;if(codes.error)throw codes.error;
  const org=o.data,lic=l.data,adm=a.data;
  m.innerHTML=head('FICHA DEL CLIENTE',org.name,'Información, licencia, administrador y acciones de soporte')+`
  <section class="org-detail-hero"><div><span>ORGANIZACIÓN</span><h3>${org.name}</h3><p>${org.email||'Sin correo'} · ${org.phone||'Sin teléfono'}</p></div><span class="status ${cls(lic?.status)}">${label(lic?.status)}</span></section>
  <section class="org-detail-grid">
   <article><span>Plan</span><strong>${lic?.plan_name||'Sin plan'}</strong><small>${lic?.price_monthly?`₡${Number(lic.price_monthly).toLocaleString('es-CR')}/mes`:'Precio no definido'}</small></article>
   <article><span>Próxima renovación</span><strong>${fmtDate(lic?.renews_at)}</strong><small>${lic?.status==='suspended'?'Licencia suspendida':'Licencia vigente'}</small></article>
   <article><span>Administrador</span><strong>${adm?.full_name||'Pendiente'}</strong><small>${adm?.active===false?'Cuenta bloqueada':adm?'Cuenta activa':'Sin cuenta creada'}</small></article>
   <article><span>Último acceso</span><strong>${fmtDateTime(adm?.last_seen_at)}</strong><small>Actividad del administrador</small></article>
  </section>
  <section class="supv-panel"><h3>Datos de contacto</h3><div class="detail-grid"><article><span>Razón social</span><strong>${org.legal_name||'No registrada'}</strong></article><article><span>Correo</span><strong>${org.email||'No registrado'}</strong></article><article><span>Teléfono</span><strong>${org.phone||'No registrado'}</strong></article><article class="wide"><span>Dirección</span><strong>${org.address||'No registrada'}</strong></article></div></section>
  <section class="supv-panel"><div class="supv-title"><h3>Accesos recientes</h3></div><div class="access-code-list">${(codes.data||[]).map(x=>`<article class="access-code-card"><div><span>${x.role}</span><strong>${x.code}</strong><small>${Number(x.used_count||0)>=Number(x.max_uses||1)?'Utilizado':(!x.active?'Revocado':(new Date(x.expires_at)<new Date()?'Vencido':'Pendiente de registro'))} · vence ${fmtDate(x.expires_at)}</small></div></article>`).join('')||'<p>No hay códigos generados.</p>'}</div></section>
  <section class="supv-panel"><h3>Acciones</h3><div class="supv-actions detail-actions"><button class="primary-btn" id="openSupport">Abrir centro de soporte</button><button class="secondary-btn" data-go="supervisorAdmins">Administradores</button><button class="secondary-btn" data-go="supervisorLicenses">Licencias</button></div></section>`;
  wire();document.getElementById('openSupport').onclick=()=>{sessionStorage.setItem('seniorcare-support-org',id);window.go?.('supervisorSupport');};
 }catch(e){m.innerHTML=`<div class="empty-state"><strong>No se pudo cargar la organización</strong><span>${e.message}</span></div>`;}
};

window.renderSupervisorSupport=async function(){
 const m=el();const selected=sessionStorage.getItem('seniorcare-support-org');
 m.innerHTML=head('ASISTENCIA TÉCNICA','Centro de soporte','Seleccione una organización y revise su estado sin mezclar información clínica')+'<div class="supv-loading">Cargando clientes…</div>';
 try{
  const {orgs,licenses,admins,codes}=await load();const lm=Object.fromEntries(licenses.map(x=>[x.organization_id,x]));const am=Object.fromEntries(admins.map(x=>[x.organization_id,x]));
  const target=selected?orgs.find(o=>o.id===selected):null;
  if(target){const lic=lm[target.id],adm=am[target.id];m.innerHTML=head('ASISTENCIA TÉCNICA','Soporte: '+target.name,'Diagnóstico y acciones seguras sobre esta organización')+`
   <section class="support-status-card"><div><span>ORGANIZACIÓN EN SOPORTE</span><h3>${target.name}</h3><p>${target.email||'Sin correo'} · ${target.phone||'Sin teléfono'}</p></div><span class="status ${cls(lic?.status)}">${label(lic?.status)}</span></section>
   <section class="support-check-grid">
    <article class="${lic?'ok-check':'bad-check'}"><strong>Licencia</strong><span>${lic?`${label(lic.status)} · ${fmtDate(lic.renews_at)}`:'No encontrada'}</span></article>
    <article class="${adm?'ok-check':'warn-check'}"><strong>Administrador</strong><span>${adm?`${adm.full_name} · ${adm.active?'Activo':'Bloqueado'}`:'Pendiente de registrar'}</span></article>
    <article class="ok-check"><strong>Códigos de acceso</strong><span>${codes.filter(x=>x.organization_id===target.id&&x.active).length} activos</span></article>
    <article class="ok-check"><strong>Conexión</strong><span>Supabase operativo</span></article>
   </section>
   <section class="supv-panel"><h3>Acciones de soporte</h3><div class="support-actions"><button class="primary-btn" id="supportAudit">Registrar intervención</button><button class="secondary-btn" id="supportCode">Crear código ADM</button><button class="secondary-btn" id="supportToggle">${lic?.status==='suspended'?'Reactivar licencia':'Suspender licencia'}</button><button class="secondary-btn" id="leaveSupport">Cerrar soporte</button></div></section>
   <section class="supv-panel support-note"><h3>Alcance del modo soporte</h3><p>Permite revisar licencia, administrador, códigos y conectividad. No abre ni modifica expedientes clínicos del hogar.</p></section>`;
   wire();
   document.getElementById('supportAudit').onclick=async()=>{openDialog('Registrar intervención de soporte',`<div class="dialog-intro"><strong>${escapeHtml(target.name)}</strong><p>Describa brevemente la intervención realizada.</p></div><div class="form-grid"><label class="wide">Detalle de la intervención<textarea name="note" required></textarea></label></div>`,async fd=>{const note=String(fd.get('note')||'').trim();if(!note)throw new Error('Escriba el detalle de la intervención.');const r=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_register_support_intervention_v4321','register_support_intervention'],{p_org_id:target.id,p_note:note}):await c().rpc('register_support_intervention',{p_org_id:target.id,p_note:note});if(r.error)throw r.error;window.showToast?.('Intervención registrada correctamente.');});};
   document.getElementById('supportCode').onclick=()=>createAdminCode(target.id,target.name);
   document.getElementById('supportToggle').onclick=async()=>{const next=lic?.status==='suspended'?'active':'suspended';if(next==='suspended'&&!confirm('¿Suspender esta licencia?'))return;const r=await c().from('licenses').update({status:next,suspended_at:next==='suspended'?new Date().toISOString():null}).eq('organization_id',target.id);if(r.error)return window.showToast?.(r.error.message);try{await audit(next==='suspended'?'license_suspended':'license_reactivated','licenses',target.id,{organization_id:target.id,status:next});}catch(_e){}window.renderSupervisorSupport();};
   document.getElementById('leaveSupport').onclick=()=>{sessionStorage.removeItem('seniorcare-support-org');window.renderSupervisorSupport();};
  }else{
   m.innerHTML=head('ASISTENCIA TÉCNICA','Centro de soporte','Seleccione una organización para revisar su estado')+`<section class="supv-toolbar"><label class="searchbox">${icon('search')}<input id="supportFind" placeholder="Buscar organización"></label></section><div class="support-org-list">${orgs.map(o=>`<button data-support-org="${o.id}"><div><strong>${o.name}</strong><span>${am[o.id]?.full_name||'Administrador pendiente'}</span></div><span class="status ${cls(lm[o.id]?.status)}">${label(lm[o.id]?.status)}</span><b>›</b></button>`).join('')||'<div class="empty-state"><strong>No hay organizaciones</strong><span>Primero registre un cliente.</span></div>'}</div>`;
   document.querySelectorAll('[data-support-org]').forEach(b=>b.onclick=async()=>{sessionStorage.setItem('seniorcare-support-org',b.dataset.supportOrg);try{await audit('support_mode_opened','organizations',b.dataset.supportOrg,{organization_id:b.dataset.supportOrg});}catch(_e){}window.renderSupervisorSupport();});
   document.getElementById('supportFind')?.addEventListener('input',e=>document.querySelectorAll('[data-support-org]').forEach(x=>x.style.display=x.textContent.toLowerCase().includes(e.target.value.toLowerCase())?'':'none'));
  }
 }catch(e){m.innerHTML=`<div class="empty-state"><strong>No se pudo abrir soporte</strong><span>${e.message}</span></div>`;}
};

window.renderSupervisorMore=function(){
 const m=el();m.innerHTML=head('HERRAMIENTAS DEL PROPIETARIO','Más','Soporte, pagos, seguridad y configuración general')+`<div class="more-grid supervisor-more-grid"><button class="module-card" data-go="supervisorAdmins"><span class="quick-icon lilac">${icon('users')}</span><div><strong>Administradores</strong><small>Accesos principales por hogar</small></div><b>›</b></button><button class="module-card" data-go="supervisorAlerts"><span class="quick-icon amber">${icon('bell')}</span><div><strong>Alertas SUPV</strong><small>Licencias, pagos y accesos</small></div><b>›</b></button><button class="module-card" data-go="supervisorLicenses"><span class="quick-icon amber">${icon('calendar')}</span><div><strong>Pagos y mensualidades</strong><small>Renovaciones y suspensión</small></div><b>›</b></button><button class="module-card" data-go="supervisorPayments"><span class="quick-icon mint">${icon('report')}</span><div><strong>Pagos</strong><small>Mensualidades y confirmaciones</small></div><b>›</b></button><button class="module-card" id="supportMode"><span class="quick-icon lilac">${icon('care')}</span><div><strong>Modo soporte</strong><small>Acceso asistido a una organización</small></div><b>›</b></button><button class="module-card" id="profileSupv"><span class="quick-icon blue">${icon('users')}</span><div><strong>Mi perfil SUPV</strong><small>Datos de propietario</small></div><b>›</b></button></div>`;wire();document.getElementById('supportMode').onclick=()=>window.go?.('supervisorSupport',{scope:'global'});document.getElementById('profileSupv').onclick=()=>alert(`Supervisor propietario\n${window.currentUser?.name||''}\n${window.currentUser?.email||''}`);
};
})();

/* V0.7.9 — correcciones funcionales SUPV */
(function(){
  const db=()=>window.seniorcareSupabase;
  const main=()=>document.getElementById('mainContent');
  const esc=v=>String(v??'').replace(/[&<>"']/g,ch=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[ch]));
  const fmt=v=>v?new Date(v).toLocaleDateString('es-CR',{day:'2-digit',month:'short',year:'numeric'}):'Sin definir';
  const fmtDT=v=>v?new Date(v).toLocaleString('es-CR'):'Sin definir';
  const statusLabel=s=>({active:'Activo',grace_period:'Pendiente de pago',suspended:'Suspendido',cancelled:'Cancelado'}[s]||'Sin licencia');
  const statusClass=s=>s==='active'?'ok':s==='grace_period'?'warn':'danger';
  const icon=n=>(window.svg&&window.svg[n])||'';
  const header=(k,t,s)=>window.pageHeader?window.pageHeader(k,t,s):`<h2>${esc(t)}</h2>`;
  const toast=m=>window.showToast?.(m);
  const dismissedKey='seniorcare-supv-dismissed-alerts';
  const seenKey='seniorcare-supv-seen-alerts';
  const getSet=k=>new Set(JSON.parse(localStorage.getItem(k)||'[]'));
  const saveSet=(k,s)=>localStorage.setItem(k,JSON.stringify([...s]));

  async function loadAll(){
    const [o,l,p,a]=await Promise.all([
      db().from('organizations').select('*').order('created_at',{ascending:false}),
      db().from('licenses').select('*').order('updated_at',{ascending:false}),
      db().from('profiles').select('id,organization_id,full_name,username,role,active,last_seen_at').eq('role','administrator'),
      db().from('activation_codes').select('*').order('created_at',{ascending:false})
    ]);
    for(const r of [o,l,p,a]) if(r.error) throw r.error;
    const orgs=o.data||[];
    const validOrgIds=new Set(orgs.map(x=>x.id));
    const licenses=(l.data||[]).filter(x=>validOrgIds.has(x.organization_id));
    const admins=(p.data||[]).filter(x=>validOrgIds.has(x.organization_id));
    const codes=(a.data||[]).filter(x=>validOrgIds.has(x.organization_id));
    return {orgs,licenses,admins,codes};
  }
  function latestPendingCodes(codes){
    const now=Date.now(), map=new Map();
    for(const x of codes){
      if(!['administrator','admin'].includes(String(x.role||'').toLowerCase())||!x.active||Number(x.used_count||0)>=Number(x.max_uses||1)||new Date(x.expires_at).getTime()<=now) continue;
      if(!map.has(x.organization_id)) map.set(x.organization_id,x);
    }
    return [...map.values()];
  }
  function deriveAlerts(data){
    const {orgs,licenses,admins,codes}=data;
    const om=Object.fromEntries(orgs.map(x=>[x.id,x]));
    const am=Object.fromEntries(admins.map(x=>[x.organization_id,x]));
    const alerts=[];
    for(const l of licenses){
      const name=om[l.organization_id]?.name||'Organización';
      const days=l.renews_at?Math.ceil((new Date(l.renews_at)-Date.now())/86400000):null;
      if(l.status==='suspended') alerts.push({key:`license-suspended-${l.id}`,level:'high',title:'Licencia suspendida',text:name,screen:'supervisorLicenses'});
      else if(l.payment_confirmed&&days!==null&&days<0) alerts.push({key:`license-overdue-${l.id}`,level:'high',title:'Licencia vencida',text:`${name} · ${Math.abs(days)} días de atraso`,screen:'supervisorLicenses'});
      else if(l.payment_confirmed&&days!==null&&days<=7) alerts.push({key:`license-expiring-${l.id}-${days}`,level:'medium',title:'Licencia por vencer',text:`${name} · quedan ${Math.max(days,0)} días`,screen:'supervisorLicenses'});
      else if(!l.payment_confirmed) alerts.push({key:`payment-pending-${l.id}`,level:'medium',title:'Pago pendiente de confirmar',text:name,screen:'supervisorLicenses'});
    }
    for(const o of orgs) if(!am[o.id]) alerts.push({key:`admin-missing-${o.id}`,level:'medium',title:'Administrador pendiente',text:o.name,screen:'supervisorAdmins'});
    for(const x of latestPendingCodes(codes)){
      const days=Math.ceil((new Date(x.expires_at)-Date.now())/86400000);
      if(days<=7) alerts.push({key:`code-expiring-${x.id}-${days}`,level:'low',title:'Código ADM por vencer',text:`${x.code} · ${om[x.organization_id]?.name||'Organización'} · ${days} días`,screen:'supervisorAdmins'});
    }
    const dismissed=getSet(dismissedKey);
    return alerts.filter(a=>!dismissed.has(a.key));
  }
  async function refreshTopAlertCount(){
    const btn=document.querySelector('.alerts'); if(!btn||window.currentUser?.role!=='supervisor') return;
    try{
      const alerts=deriveAlerts(await loadAll());
      btn.innerHTML=`<span class="dot"></span>${alerts.length?`Alertas activas (${alerts.length})`:'Sin alertas activas'}`;
      btn.classList.toggle('has-alerts',alerts.length>0);
    }catch(_){btn.innerHTML='<span class="dot"></span>Alertas SUPV';}
  }
  window.updateSupervisorAlertButton=refreshTopAlertCount;

  async function createCode(orgId,orgName){
    const current=latestPendingCodes((await db().from('activation_codes').select('*').eq('organization_id',orgId).eq('role','administrator').order('created_at',{ascending:false})).data||[])[0];
    if(current){
      openDialog('Código ADM pendiente',`<div class="generated-code generated-code-visible"><span>CÓDIGO DE ACCESO DEL ADMINISTRADOR</span><strong>${escapeHtml(current.code)}</strong><p>${escapeHtml(orgName)} · vence ${fmtDate(current.expires_at)}</p></div><div class="confirmation-warning">Este código aún no ha sido utilizado. Compártalo con el administrador del hogar.</div>`,async()=>{});
      const f=document.getElementById('supvDialogForm');
      if(f){
        f.querySelector('.form-actions').innerHTML='<button type="button" class="secondary-btn" data-code-close>Cerrar</button><button type="button" class="primary-btn" data-code-copy>Copiar código</button>';
        f.querySelector('[data-code-close]').onclick=()=>document.getElementById('supvDialog')?.remove();
        f.querySelector('[data-code-copy]').onclick=async()=>{await navigator.clipboard.writeText(current.code).catch(()=>{});toast('Código copiado.');};
      }
      return;
    }
    openDialog('Crear acceso ADM',`<div class="dialog-intro"><strong>${escapeHtml(orgName)}</strong><p>El código sirve únicamente para activar la cuenta del administrador.</p></div><div class="code-validity-note"><strong>Vigencia fija: 7 días</strong><span>Después del registro, la cuenta continúa según la licencia y los módulos contratados.</span></div>`,async()=>{
      let result=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_create_activation_code_v4325','bh_create_activation_code_v4321','supervisor_create_admin_code','create_activation_code'],{p_org_id:orgId,p_role:'administrator',p_days:7}):await db().rpc('create_activation_code',{p_org_id:orgId,p_role:'administrator',p_days:7});
      if(result.error)throw result.error;
      const row=Array.isArray(result.data)?result.data[0]:result.data;
      const code=String(row?.code||row||'');
      if(!code)throw new Error('El código fue creado, pero no pudo mostrarse.');
      openDialog('Código ADM creado',`<div class="generated-code generated-code-visible"><span>CÓDIGO DE ACCESO DEL ADMINISTRADOR</span><strong>${escapeHtml(code)}</strong><p>${escapeHtml(orgName)} · vigencia 7 días</p></div><div class="confirmation-warning">Este código es de un solo uso. Copie o anote el código antes de cerrar.</div>`,async()=>{});
      const f=document.getElementById('supvDialogForm');
      if(f){
        f.querySelector('.form-actions').innerHTML='<button type="button" class="secondary-btn" data-code-close>Cerrar</button><button type="button" class="primary-btn" data-code-copy>Copiar código</button>';
        f.querySelector('[data-code-close]').onclick=()=>document.getElementById('supvDialog')?.remove();
        f.querySelector('[data-code-copy]').onclick=async()=>{await navigator.clipboard.writeText(code).catch(()=>{});toast('Código copiado.');};
      }
      await refreshTopAlertCount();
    });
  }
  window.createCode=createCode;

  async function setLicenseStatus(orgId,next){
    let r=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_set_license_status_v4321','supervisor_set_license_status'],{p_org_id:orgId,p_status:next}):await db().rpc('supervisor_set_license_status',{p_org_id:orgId,p_status:next});
    if(r.error){
      r=await db().from('licenses').update({status:next,suspended_at:next==='suspended'?new Date().toISOString():null,suspension_reason:next==='suspended'?'Suspendida por supervisor':null,updated_at:new Date().toISOString()}).eq('organization_id',orgId).select('id,status').maybeSingle();
    }
    if(r.error){toast(r.error.message);return false;}
    const orgUpdate=await db().from('organizations').update({active:next!=='suspended',updated_at:new Date().toISOString()}).eq('id',orgId);
    if(orgUpdate.error){toast(orgUpdate.error.message);return false;}
    const verify=await db().from('licenses').select('status').eq('organization_id',orgId).maybeSingle();
    if(verify.error){toast(verify.error.message);return false;}
    if(verify.data?.status!==next){toast('La licencia no cambió de estado. Revise la función SQL V0.8.2.');return false;}
    toast(next==='suspended'?'Licencia suspendida correctamente.':'Licencia reactivada correctamente.');
    await refreshTopAlertCount();
    return true;
  }
  function wireBack(defaultScreen='home'){
    document.querySelectorAll('[data-back]').forEach(b=>b.onclick=()=>window.goBack?.());
    document.querySelectorAll('[data-go]').forEach(b=>b.onclick=()=>window.go?.(b.dataset.go,{scope:'global'}));
  }

  window.renderSupervisorHome=async function(){
    const m=main();
    m.innerHTML='<div class="supv-loading">Cargando panel superior…</div>';
    try{
      const data=await loadAll(),{orgs,licenses,admins}=data;
      const am=Object.fromEntries(admins.map(x=>[x.organization_id,x]));
      const active=licenses.filter(x=>x.status==='active').length;
      const suspended=licenses.filter(x=>x.status==='suspended').length;
      const expiring=licenses.filter(x=>x.payment_confirmed&&x.renews_at&&new Date(x.renews_at)>=new Date()&&new Date(x.renews_at)-Date.now()<2592000000).length;
      const pendingAdmins=orgs.filter(o=>!am[o.id]).length;
      const alerts=deriveAlerts(data);
      m.innerHTML=`
      <section class="admin-welcome supv-welcome refined">
        <div><span class="eyebrow">PANEL SUPERVISOR</span><h2>¡Bienvenido, Dr. Abraham Benard!</h2><p>Controle organizaciones, licencias, administradores y soporte desde un solo lugar.</p></div>
        <div class="admin-mark">${icon('care')}</div>
      </section>
      <section class="supv-overview-grid">
        <button class="supv-overview-card tone-purple" data-org-filter="active"><span class="supv-overview-icon">${icon('building')}</span><div><small>Hogares activos</small><strong>${active}</strong><p>Licencias habilitadas</p></div><b>›</b></button>
        <button class="supv-overview-card tone-amber" data-go="supervisorLicenses"><span class="supv-overview-icon">${icon('calendar')}</span><div><small>Por vencer</small><strong>${expiring}</strong><p>Próximos 30 días</p></div><b>›</b></button>
        <button class="supv-overview-card tone-rose" data-org-filter="suspended"><span class="supv-overview-icon">${icon('alert')}</span><div><small>Suspendidos</small><strong>${suspended}</strong><p>Acceso bloqueado</p></div><b>›</b></button>
        <button class="supv-overview-card tone-cyan" data-go="supervisorAdmins"><span class="supv-overview-icon">${icon('users')}</span><div><small>Administradores</small><strong>${admins.filter(a=>a.active).length}</strong><p>Cuentas registradas</p></div><b>›</b></button>
        <button class="supv-overview-card tone-gold" data-go="supervisorAdmins"><span class="supv-overview-icon">${icon('userPlus')}</span><div><small>Sin administrador</small><strong>${pendingAdmins}</strong><p>Pendientes de acceso</p></div><b>›</b></button>
        <button class="supv-overview-card tone-mint" data-go="supervisorAlerts"><span class="supv-overview-icon">${icon('bell')}</span><div><small>Alertas SUPV</small><strong>${alerts.length}</strong><p>Requieren revisión</p></div><b>›</b></button>
      </section>
      <section class="supv-dashboard-section">
        <div class="supv-dashboard-heading"><div><span>GESTIÓN CENTRAL</span><h3>Herramientas del supervisor</h3></div><p>Accesos directos a las funciones principales</p></div>
        <div class="supv-dashboard-menu">
          <button class="supv-dashboard-item tone-purple" data-go="supervisorOrganizations"><span>${icon('building')}</span><div><strong>Organizaciones</strong><small>Crear y administrar hogares</small></div><b>›</b></button>
          <button class="supv-dashboard-item tone-amber" data-go="supervisorLicenses"><span>${icon('calendar')}</span><div><strong>Licencias</strong><small>Pagos, vigencias y estados</small></div><b>›</b></button>
          <button class="supv-dashboard-item tone-cyan" data-go="supervisorAdmins"><span>${icon('users')}</span><div><strong>Administradores</strong><small>Cuentas reales e invitaciones</small></div><b>›</b></button>
          <button class="supv-dashboard-item tone-mint" data-go="supervisorAlerts"><span>${icon('bell')}</span><div><strong>Alertas SUPV</strong><small>Licencias, pagos y accesos</small></div><b>›</b></button>
          <button class="supv-dashboard-item tone-mint" data-go="supervisorSupport"><span>${icon('support')}</span><div><strong>Centro de soporte</strong><small>Atención y seguimiento de clientes</small></div><b>›</b></button>
          <button class="supv-dashboard-item tone-neutral" data-go="supervisorMore"><span>${icon('more')}</span><div><strong>Más herramientas</strong><small>Soporte y configuración</small></div><b>›</b></button>
        </div>
      </section>`;
      wireBack();
      document.querySelectorAll('[data-org-filter]').forEach(b=>b.onclick=()=>{sessionStorage.setItem('seniorcare-org-filter',b.dataset.orgFilter);window.go?.('supervisorOrganizations',{scope:'global'});});
      await refreshTopAlertCount();
    }catch(e){m.innerHTML=`<div class="empty-state"><strong>No se pudo cargar el panel</strong><span>${esc(e.message)}</span></div>`;}
  };

  window.renderSupervisorOrganizations=async function(){
    const m=main(), filter=sessionStorage.getItem('seniorcare-org-filter')||'all';
    m.innerHTML=header('CLIENTES Y RESIDENCIAS','Organizaciones','Cree y administre cada hogar de manera independiente')+'<div class="supv-loading">Cargando…</div>';
    try{
      const {orgs,licenses,admins}=await loadAll();
      const lm=Object.fromEntries(licenses.map(x=>[x.organization_id,x])),am=Object.fromEntries(admins.map(x=>[x.organization_id,x]));
      const visible=orgs.filter(o=>filter==='all'||lm[o.id]?.status===filter);
      m.innerHTML=header('CLIENTES Y RESIDENCIAS','Organizaciones',filter==='all'?'Cree y administre cada hogar de manera independiente':`Filtro activo: ${statusLabel(filter)}`)+`
      <section class="supv-toolbar"><button class="primary-btn" id="newOrg">Nueva organización</button>${filter!=='all'?'<button class="secondary-btn" id="clearOrgFilter">Ver todas</button>':''}</section>
      <form class="form-card hidden" id="orgForm"><div 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>Plan<select name="plan"><option>Mensual</option><option>Trimestral</option><option>Anual</option></select></label><label>Precio mensual<input name="price" type="number" min="20000" step="1000" value="20000"></label><label>Días previstos de vigencia<input name="days" type="number" min="30" max="365" value="30" required></label><label>Fecha prevista de vencimiento<input name="renew" type="date" required></label><label class="wide">Dirección<textarea name="address"></textarea></label></div><div class="form-actions"><button type="button" class="secondary-btn" id="cancelOrg">Cancelar</button><button type="submit" class="primary-btn">Guardar organización</button></div></form>
      <div class="supv-org-grid">${visible.map(o=>{const l=lm[o.id],a=am[o.id];return `<article><div class="supv-org-head"><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)}">${statusLabel(l?.status)}</span></div><div class="supv-org-data"><span>Administrador<strong>${a?.full_name||'Pendiente'}</strong></span><span>Plan<strong>${esc(l?.plan_name||'Sin plan')}</strong></span><span>Vencimiento<strong>${fmt(l?.renews_at)}</strong></span><span>Pago<strong>${l?.payment_confirmed?'Confirmado':'Pendiente'}</strong></span></div><div class="supv-actions"><button class="secondary-btn" data-open-org="${o.id}">Ver ficha</button>${!a?`<button class="secondary-btn" data-code-org="${o.id}" data-org-name="${esc(o.name)}">Crear código ADM</button>`:''}<button class="secondary-btn" data-toggle-org="${o.id}" data-status="${l?.status||''}">${l?.status==='suspended'?'Reactivar':'Suspender'}</button></div></article>`}).join('')||'<div class="empty-state"><strong>No hay organizaciones en este filtro</strong><span>Use “Ver todas” para mostrar todos los clientes.</span></div>'}</div>`;
      wireBack('home');
      document.getElementById('clearOrgFilter')?.addEventListener('click',()=>{sessionStorage.removeItem('seniorcare-org-filter');window.renderSupervisorOrganizations();});
      const form=document.getElementById('orgForm');
      document.getElementById('newOrg').onclick=()=>form.classList.remove('hidden');
      document.getElementById('cancelOrg').onclick=()=>form.classList.add('hidden');
      form.onsubmit=async e=>{e.preventDefault();const btn=form.querySelector('[type="submit"]');if(btn.disabled)return;const fd=new FormData(form);try{btn.disabled=true;btn.textContent='Guardando…';const name=String(fd.get('name')||'').trim();if(!name)throw new Error('Escriba el nombre.');const dup=await db().from('organizations').select('id').ilike('name',name).limit(1);if(dup.error)throw dup.error;if(dup.data?.length)throw new Error('Ya existe una organización con ese nombre.');const org=await db().from('organizations').insert({name,legal_name:String(fd.get('legal')||'').trim()||null,email:String(fd.get('email')||'').trim()||null,phone:String(fd.get('phone')||'').trim()||null,address:String(fd.get('address')||'').trim()||null,active:true,created_by:window.currentUser?.id||null}).select().single();if(org.error)throw org.error;const days=Number(fd.get('days'));const lic=await db().from('licenses').insert({organization_id:org.data.id,status:'grace_period',plan_name:String(fd.get('plan')||'Mensual'),renews_at:new Date(String(fd.get('renew'))+'T12:00:00').toISOString(),term_days:days,payment_confirmed:false,updated_by:window.currentUser?.id||null,price_monthly:Number(fd.get('price')||0)});if(lic.error){await db().from('organizations').delete().eq('id',org.data.id);throw lic.error;}toast('Organización creada correctamente.');form.reset();sessionStorage.removeItem('seniorcare-org-filter');await window.renderSupervisorOrganizations();}catch(err){toast(err.message);}finally{btn.disabled=false;btn.textContent='Guardar organización';}};
      document.querySelectorAll('[data-open-org]').forEach(b=>b.onclick=()=>{sessionStorage.setItem('seniorcare-selected-org',b.dataset.openOrg);window.dispatchEvent(new CustomEvent('seniorcare:organization-selected',{detail:{organizationId:b.dataset.openOrg}}));window.go?.('supervisorOrganizationDetail',{scope:'global'});});
      document.querySelectorAll('[data-code-org]').forEach(b=>b.onclick=()=>createCode(b.dataset.codeOrg,b.dataset.orgName));
      document.querySelectorAll('[data-toggle-org]').forEach(b=>b.onclick=async()=>{const next=b.dataset.status==='suspended'?'active':'suspended';if(next==='suspended'&&!confirm('¿Suspender esta organización y todos sus accesos?'))return;if(await setLicenseStatus(b.dataset.toggleOrg,next))window.renderSupervisorOrganizations();});
    }catch(e){m.innerHTML+=`<div class="empty-state"><strong>Error al cargar</strong><span>${esc(e.message)}</span></div>`;}
  };

  window.renderSupervisorAdmins=async function(){
    const m=main();m.innerHTML=header('CONTROL DE ACCESOS','Administradores principales','Solo cuentas realmente registradas en el sistema')+'<div class="supv-loading">Cargando…</div>';
    try{
      const {orgs,admins,codes}=await loadAll(),om=Object.fromEntries(orgs.map(o=>[o.id,o]));
      const pending=latestPendingCodes(codes);
      m.innerHTML=header('CONTROL DE ACCESOS','Administradores principales','Solo cuentas realmente registradas en el sistema')+`
      <section class="audit-summary-grid"><article><span>Administradores registrados</span><strong>${admins.length}</strong><small>Cuentas reales</small></article><article><span>Activos</span><strong>${admins.filter(a=>a.active).length}</strong><small>Con acceso</small></article><article><span>Bloqueados</span><strong>${admins.filter(a=>!a.active).length}</strong><small>Sin acceso</small></article><article><span>Invitaciones pendientes</span><strong>${pending.length}</strong><small>No son administradores aún</small></article></section>
      <section class="supv-panel"><h3>Administradores registrados</h3><div class="supv-org-grid">${admins.map(a=>`<article><div class="supv-org-head"><div><h3>${esc(a.full_name)}</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></div><div class="supv-org-data"><span>Último acceso<strong>${fmtDT(a.last_seen_at)}</strong></span></div><div class="supv-actions"><button class="secondary-btn" data-admin-toggle="${a.id}" data-org="${a.organization_id}" data-active="${a.active}">${a.active?'Bloquear':'Reactivar'}</button></div></article>`).join('')||'<div class="empty-state"><strong>No hay administradores registrados</strong><span>Los códigos ADM pendientes no cuentan como administradores.</span></div>'}</div></section>
      <section class="supv-panel"><h3>Invitaciones ADM pendientes</h3><div class="access-code-list">${pending.map(x=>`<article class="access-code-card"><div><span>${esc(om[x.organization_id]?.name||'Organización')}</span><strong>${esc(x.code)}</strong><small>Pendiente de registro · vence ${fmt(x.expires_at)}</small></div><button class="mini-btn" data-revoke-code="${x.id}">Revocar</button></article>`).join('')||'<p>No hay invitaciones pendientes.</p>'}</div></section>`;
      wireBack('home');
      document.querySelectorAll('[data-admin-toggle]').forEach(b=>b.onclick=async()=>{const active=b.dataset.active!=='true';const r=await db().from('profiles').update({active}).eq('id',b.dataset.adminToggle);if(r.error)return toast(r.error.message);toast(active?'Administrador reactivado.':'Administrador bloqueado.');window.renderSupervisorAdmins();});
      document.querySelectorAll('[data-revoke-code]').forEach(b=>b.onclick=async()=>{
        if(!confirm('¿Revocar esta invitación?'))return;
        b.disabled=true;
        b.textContent='Revocando…';
        let r=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_revoke_activation_code_v4321','supervisor_revoke_activation_code'],{p_code_id:b.dataset.revokeCode}):await db().rpc('supervisor_revoke_activation_code',{p_code_id:b.dataset.revokeCode});
        if(r.error){
          r=await db().from('activation_codes').update({active:false}).eq('id',b.dataset.revokeCode).select('id,active').maybeSingle();
        }
        if(r.error){b.disabled=false;b.textContent='Revocar';return toast(r.error.message);}
        const card=b.closest('.access-code-card');
        card?.remove();
        toast('Invitación revocada y retirada de la lista.');
        await window.renderSupervisorAdmins();
        await refreshTopAlertCount();
      });
    }catch(e){m.innerHTML+=`<div class="empty-state"><strong>Error</strong><span>${esc(e.message)}</span></div>`;}
  };

  window.renderSupervisorAlerts=async function(){
    const m=main();m.innerHTML=header('CENTRO DE ALERTAS SUPV','Alertas comerciales','Licencias, pagos, accesos y configuración de clientes')+'<div class="supv-loading">Cargando…</div>';
    try{
      const data=await loadAll(),alerts=deriveAlerts(data),seen=getSet(seenKey);
      m.innerHTML=header('CENTRO DE ALERTAS SUPV','Alertas comerciales','Licencias, pagos, accesos y configuración de clientes')+`<section class="alert-summary"><article class="danger-box"><strong>${alerts.filter(x=>x.level==='high').length}</strong><span>Alta prioridad</span></article><article class="warn-box"><strong>${alerts.filter(x=>x.level==='medium').length}</strong><span>Seguimiento</span></article><article class="ok-box"><strong>${alerts.filter(x=>x.level==='low').length}</strong><span>Informativas</span></article></section><div class="list-stack">${alerts.map(a=>`<article class="data-row ${seen.has(a.key)?'resolved-alert':''}"><span class="incident-icon">${icon(a.level==='high'?'alert':'bell')}</span><div class="row-main"><strong>${esc(a.title)}</strong><span>${esc(a.text)}</span><small>${seen.has(a.key)?'Vista':'Nueva'}</small></div><div class="card-actions"><button class="mini-btn" data-alert-open="${a.screen}" data-alert-key="${esc(a.key)}">Abrir</button>${!seen.has(a.key)?`<button class="mini-btn" data-alert-seen="${esc(a.key)}">Marcar vista</button>`:''}<button class="icon-delete" data-alert-dismiss="${esc(a.key)}" aria-label="Eliminar">×</button></div></article>`).join('')||'<div class="empty-state"><strong>Sin alertas comerciales</strong><span>Las licencias y accesos están al día.</span></div>'}</div>`;
      wireBack('home');
      document.querySelectorAll('[data-alert-seen]').forEach(b=>b.onclick=()=>{const s=getSet(seenKey);s.add(b.dataset.alertSeen);saveSet(seenKey,s);window.renderSupervisorAlerts();});
      document.querySelectorAll('[data-alert-dismiss]').forEach(b=>b.onclick=()=>{const s=getSet(dismissedKey);s.add(b.dataset.alertDismiss);saveSet(dismissedKey,s);window.renderSupervisorAlerts();refreshTopAlertCount();});
      document.querySelectorAll('[data-alert-open]').forEach(b=>b.onclick=()=>{const s=getSet(seenKey);s.add(b.dataset.alertKey);saveSet(seenKey,s);window.go?.(b.dataset.alertOpen,{scope:'global'});});
      await refreshTopAlertCount();
    }catch(e){m.innerHTML+=`<div class="empty-state"><strong>Error</strong><span>${esc(e.message)}</span></div>`;}
  };

  const oldSupport=window.renderSupervisorSupport;
  window.renderSupervisorSupport=async function(){
    await oldSupport();
    document.querySelectorAll('[data-back]').forEach(b=>b.onclick=()=>{
      if(sessionStorage.getItem('seniorcare-support-org')){sessionStorage.removeItem('seniorcare-support-org');window.renderSupervisorSupport();}
      else window.go?.('supervisorMore',{scope:'global'});
    });
    const selected=sessionStorage.getItem('seniorcare-support-org');
    if(selected){
      const toggle=document.getElementById('supportToggle');
      if(toggle) toggle.onclick=async()=>{
        const row=await db().from('licenses').select('status').eq('organization_id',selected).maybeSingle();
        if(row.error)return toast(row.error.message);
        const next=row.data?.status==='suspended'?'active':'suspended';
        if(next==='suspended'&&!confirm('¿Suspender esta licencia?'))return;
        if(await setLicenseStatus(selected,next))window.renderSupervisorSupport();
      };
      const code=document.getElementById('supportCode');
      if(code){const org=await db().from('organizations').select('name').eq('id',selected).maybeSingle();code.onclick=()=>createCode(selected,org.data?.name||'Organización');}
    }
  };
})();

/* V0.8.5 — organizaciones editables/eliminables y estados de pago correctos */
(function(){
  const db=()=>window.seniorcareSupabase;
  const main=()=>document.getElementById('mainContent');
  const esc=v=>String(v??'').replace(/[&<>"']/g,ch=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[ch]));
  const toast=m=>window.showToast?.(m);
  const fmt=v=>v?new Date(v).toLocaleDateString('es-CR',{day:'2-digit',month:'short',year:'numeric'}):'Sin definir';
  const header=(k,t,s)=>window.pageHeader?window.pageHeader(k,t,s):`<h2>${esc(t)}</h2>`;
  const icon=n=>(window.svg&&window.svg[n])||'';
  const effectiveStatus=l=>!l?'none':(!l.payment_confirmed?'pending':l.status);
  const statusLabel=l=>({active:'Activo',pending:'Pendiente de pago',grace_period:'En gracia',suspended:'Suspendido',cancelled:'Cancelado',none:'Sin licencia'}[effectiveStatus(l)]||'Sin licencia');
  const statusClass=l=>effectiveStatus(l)==='active'?'ok':effectiveStatus(l)==='pending'||effectiveStatus(l)==='grace_period'?'warn':'danger';
  const wire=()=>{document.querySelectorAll('[data-back]').forEach(b=>b.onclick=()=>window.goBack?.());document.querySelectorAll('[data-go]').forEach(b=>b.onclick=()=>window.go?.(b.dataset.go,{scope:'global'}));};

  async function load(){
    const [orgs,licenses,admins]=await Promise.all([
      db().from('organizations').select('*').order('created_at',{ascending:false}),
      db().from('licenses').select('*').order('updated_at',{ascending:false}),
      db().from('profiles').select('*').eq('role','administrator')
    ]);
    if(orgs.error)throw orgs.error;if(licenses.error)throw licenses.error;if(admins.error)throw admins.error;
    return {orgs:orgs.data||[],licenses:licenses.data||[],admins:admins.data||[]};
  }

  window.renderSupervisorOrganizations=async function(){
    const m=main();
    const filter=sessionStorage.getItem('seniorcare-org-filter')||'all';
    m.innerHTML=header('CLIENTES Y RESIDENCIAS','Organizaciones','Cree, edite y administre cada hogar de manera independiente')+'<div class="supv-loading">Cargando…</div>';
    try{
      const {orgs,licenses,admins}=await load();
      const lm=Object.fromEntries(licenses.map(x=>[x.organization_id,x]));
      const am=Object.fromEntries(admins.map(x=>[x.organization_id,x]));
      const visible=orgs.filter(o=>{
        const s=effectiveStatus(lm[o.id]);
        if(filter==='all')return true;
        if(filter==='active')return s==='active';
        if(filter==='suspended')return s==='suspended';
        if(filter==='pending')return s==='pending';
        return s===filter;
      });
      m.innerHTML=header('CLIENTES Y RESIDENCIAS','Organizaciones',filter==='all'?'Gestión completa de clientes y licencias':'Filtro activo')+`
      <section class="supv-toolbar"><button class="primary-btn" id="newOrg">Nueva organización</button>${filter!=='all'?'<button class="secondary-btn" id="clearOrgFilter">Ver todas</button>':''}</section>
      <form class="form-card hidden" id="orgForm">
        <input type="hidden" name="org_id">
        <div class="form-card-title"><div><span>ORGANIZACIÓN</span><h3 id="orgFormTitle">Nueva organización</h3></div></div>
        <div 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<textarea name="address"></textarea></label>
        </div>
        <div class="form-actions"><button type="button" class="secondary-btn" id="cancelOrg">Cancelar</button><button type="submit" class="primary-btn">Guardar cambios</button></div>
      </form>
      <div class="supv-org-grid polished-org-grid">${visible.map(o=>{const l=lm[o.id],a=am[o.id];return `
        <article class="polished-org-card">
          <div class="supv-org-head"><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)}">${statusLabel(l)}</span></div>
          <div class="supv-org-data"><span>Administrador<strong>${a?.full_name||'Pendiente'}</strong></span><span>Plan<strong>${esc(l?.plan_name||'Sin plan')}</strong></span><span>Vencimiento<strong>${fmt(l?.renews_at)}</strong></span><span>Pago<strong>${l?.payment_confirmed?'Confirmado':'Pendiente'}</strong></span></div>
          <div class="supv-actions org-action-row">
            <button class="secondary-btn" data-open-org="${o.id}">Ver ficha</button>
            <button class="secondary-btn" data-edit-org="${o.id}">Editar</button>
            ${!a?`<button class="secondary-btn" data-code-org="${o.id}" data-org-name="${esc(o.name)}">Crear código ADM</button>`:''}
            <button class="secondary-btn danger-outline" data-delete-org="${o.id}" data-org-name="${esc(o.name)}">Eliminar</button>
          </div>
        </article>`}).join('')||'<div class="empty-state"><strong>No hay organizaciones en este filtro</strong><span>Use “Ver todas” para mostrar todos los clientes.</span></div>'}</div>`;
      wire();
      const form=document.getElementById('orgForm');
      const formTitle=document.getElementById('orgFormTitle');
      const resetForm=()=>{form.reset();form.elements.org_id.value='';formTitle.textContent='Nueva organización';form.classList.add('hidden');};
      document.getElementById('newOrg').onclick=()=>{form.reset();form.elements.org_id.value='';formTitle.textContent='Nueva organización';form.classList.remove('hidden');form.scrollIntoView({behavior:'smooth',block:'start'});};
      document.getElementById('cancelOrg').onclick=resetForm;
      document.getElementById('clearOrgFilter')?.addEventListener('click',()=>{sessionStorage.removeItem('seniorcare-org-filter');window.renderSupervisorOrganizations();});
      document.querySelectorAll('[data-edit-org]').forEach(b=>b.onclick=()=>{const o=orgs.find(x=>x.id===b.dataset.editOrg);if(!o)return;form.elements.org_id.value=o.id;form.elements.name.value=o.name||'';form.elements.legal.value=o.legal_name||'';form.elements.email.value=o.email||'';form.elements.phone.value=o.phone||'';form.elements.address.value=o.address||'';formTitle.textContent='Editar organización';form.classList.remove('hidden');form.scrollIntoView({behavior:'smooth',block:'start'});});
      form.onsubmit=async e=>{e.preventDefault();const btn=form.querySelector('[type="submit"]');const fd=new FormData(form);const id=String(fd.get('org_id')||'');const payload={name:String(fd.get('name')||'').trim(),legal_name:String(fd.get('legal')||'').trim()||null,email:String(fd.get('email')||'').trim()||null,phone:String(fd.get('phone')||'').trim()||null,address:String(fd.get('address')||'').trim()||null,updated_at:new Date().toISOString()};if(!payload.name)return toast('Escriba el nombre de la organización.');try{btn.disabled=true;btn.textContent=id?'Guardando…':'Creando…';if(id){const r=await db().from('organizations').update(payload).eq('id',id).select().single();if(r.error)throw r.error;toast('Organización actualizada correctamente.');}else{const r=await db().from('organizations').insert({...payload,active:false,created_by:window.currentUser?.id||null}).select().single();if(r.error)throw r.error;const lic=await db().from('licenses').insert({organization_id:r.data.id,status:'grace_period',plan_name:'Mensual',term_days:30,payment_confirmed:false,updated_by:window.currentUser?.id||null,price_monthly:20000});if(lic.error){await db().from('organizations').delete().eq('id',r.data.id);throw lic.error;}toast('Organización creada. Permanecerá pendiente hasta confirmar el pago.');}resetForm();await window.renderSupervisorOrganizations();}catch(err){toast(err.message);}finally{btn.disabled=false;btn.textContent='Guardar cambios';}};
      document.querySelectorAll('[data-delete-org]').forEach(b=>b.onclick=async()=>{const id=b.dataset.deleteOrg;const name=b.dataset.orgName;if(am[id])return toast('No puede eliminarse mientras tenga un administrador registrado. Primero bloquee o desvincule esa cuenta.');if(!confirm(`¿Eliminar definitivamente “${name}” y todos sus datos asociados?`))return;const card=b.closest('.polished-org-card');if(card)card.remove();const r=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_delete_organization_complete_v361','supervisor_delete_organization'],{p_org_id:id}):await db().rpc('supervisor_delete_organization',{p_org_id:id});if(r.error){toast(r.error.message);await window.renderSupervisorOrganizations();return;}toast('Organización y licencia eliminadas correctamente.');sessionStorage.removeItem('seniorcare-selected-org');await new Promise(resolve=>setTimeout(resolve,180));await window.renderSupervisorOrganizations();});
      document.querySelectorAll('[data-open-org]').forEach(b=>b.onclick=()=>{sessionStorage.setItem('seniorcare-selected-org',b.dataset.openOrg);window.dispatchEvent(new CustomEvent('seniorcare:organization-selected',{detail:{organizationId:b.dataset.openOrg}}));window.go?.('supervisorOrganizationDetail',{scope:'global'});});
      document.querySelectorAll('[data-code-org]').forEach(b=>b.onclick=()=>window.createCode?window.createCode(b.dataset.codeOrg,b.dataset.orgName):toast('Función de código no disponible.'));
    }catch(e){m.innerHTML+=`<div class="empty-state"><strong>Error al cargar</strong><span>${esc(e.message)}</span></div>`;}
  };

  const oldDetail=window.renderSupervisorOrganizationDetail;
  window.renderSupervisorOrganizationDetail=async function(){
    await oldDetail();
    const id=sessionStorage.getItem('seniorcare-selected-org');
    if(!id)return;
    const actionPanel=[...document.querySelectorAll('.supv-panel')].find(x=>x.querySelector('h3')?.textContent==='Acciones');
    if(actionPanel){const row=actionPanel.querySelector('.supv-actions');if(row){row.insertAdjacentHTML('beforeend','<button class="secondary-btn" id="detailEditOrg">Editar organización</button><button class="secondary-btn danger-outline" id="detailDeleteOrg">Eliminar organización</button>');document.getElementById('detailEditOrg').onclick=()=>window.go?.('supervisorOrganizations',{scope:'global'});document.getElementById('detailDeleteOrg').onclick=async()=>{const adm=await db().from('profiles').select('id').eq('organization_id',id).eq('role','administrator').limit(1);if(adm.error)return toast(adm.error.message);if(adm.data?.length)return toast('No puede eliminarse mientras tenga un administrador registrado.');if(!confirm('¿Eliminar definitivamente esta organización?'))return;const r=window.BHSC_CALL_RPC?await window.BHSC_CALL_RPC(['bh_delete_organization_complete_v361','supervisor_delete_organization'],{p_org_id:id}):await db().rpc('supervisor_delete_organization',{p_org_id:id});if(r.error)return toast(r.error.message);sessionStorage.removeItem('seniorcare-selected-org');toast('Organización y licencia eliminadas.');await new Promise(resolve=>setTimeout(resolve,180));window.go?.('supervisorOrganizations',{scope:'global'});};}}
  };

  const oldHome=window.renderSupervisorHome;
  window.renderSupervisorHome=async function(){
    await oldHome();
    try{
      const {licenses}=await load();
      const active=licenses.filter(x=>x.payment_confirmed&&x.status==='active').length;
      const pending=licenses.filter(x=>!x.payment_confirmed).length;
      const cards=document.querySelectorAll('.supv-overview-card');
      if(cards[0]){cards[0].querySelector('strong').textContent=active;cards[0].querySelector('p').textContent='Pagadas y habilitadas';}
      if(cards[4]){cards[4].querySelector('strong').textContent=pending;cards[4].querySelector('small').textContent='Pagos pendientes';cards[4].querySelector('p').textContent='Sin activar';cards[4].onclick=()=>{sessionStorage.setItem('seniorcare-org-filter','pending');window.go?.('supervisorOrganizations',{scope:'global'});};}
    }catch(_e){}
  };
})();
