/* Bernard Health SeniorCare V4.3.1 — módulo médico clínico simplificado */
(function(){
'use strict';
const db=()=>window.seniorcareSupabase, u=()=>window.currentUser||{}, org=()=>u().organizationId||u().organization_id;
const role=()=>String(u().role||'');
const esc=v=>String(v??'').replace(/[&<>"']/g,m=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m]));
const allowed=()=>['doctor','admin','administrator','nurse','supervisor'].includes(role());
const doctorWrite=()=>['doctor','admin','administrator'].includes(role());
const orderWork=()=>['doctor','admin','administrator','nurse'].includes(role());
let residents=[],histories=[],consults=[],orders=[],results=[],prescriptions=[],documents=[];
const header=(e,t,s)=>window.pageHeader?.(e,t,s)||`<h2>${esc(t)}</h2>`;
const empty=t=>window.empty?.(t)||`<p>${esc(t)}</p>`;
const toast=t=>window.showToast?.(t);
const nowLocal=()=>{const d=new Date();d.setMinutes(d.getMinutes()-d.getTimezoneOffset());return d.toISOString().slice(0,16)};
const missingTable=e=>{const m=String(e?.message||'').toLowerCase();return e?.code==='PGRST205'||m.includes('could not find the table')||m.includes('schema cache')};
async function safe(q,{optional=false}={}){const r=await q;if(r.error){if(optional&&missingTable(r.error))return {data:[],missing:true};throw r.error}return {data:r.data||[],missing:false}}
const residentKey=r=>String(r?.resident_key??r?.data?.resident_key??r?.id??r?.data?.id??'').trim();
const residentName=r=>r?.full_name||r?.resident_name||r?.data?.name||r?.data?.full_name||'Residente';
async function load(){
 if(!db()||!org()||!allowed())return;
 // Se consulta la fila completa y se ordena en el cliente. Esto mantiene compatibilidad
 // con instalaciones donde full_name o resident_name todavía no existen como columnas.
 const rr=await safe(db().from('seniorcare_residents').select('*').eq('organization_id',org()).eq('active',true));
 residents=(rr.data||[]).map(r=>({...r,resident_key:residentKey(r)})).filter(r=>r.resident_key).sort((a,b)=>residentName(a).localeCompare(residentName(b),'es',{sensitivity:'base'}));
 const qs=await Promise.all([
  safe(db().from('seniorcare_medical_histories').select('*').eq('organization_id',org()).eq('active',true),{optional:true}),
  safe(db().from('seniorcare_medical_consultations').select('*').eq('organization_id',org()).eq('active',true).order('created_at',{ascending:false}),{optional:true}),
  safe(db().from('seniorcare_medical_orders').select('*').eq('organization_id',org()).eq('active',true).order('created_at',{ascending:false}),{optional:true}),
  safe(db().from('seniorcare_medical_results').select('*').eq('organization_id',org()).eq('active',true).order('created_at',{ascending:false}),{optional:true}),
  safe(db().from('seniorcare_medical_prescriptions').select('*').eq('organization_id',org()).eq('active',true).order('issued_at',{ascending:false}),{optional:true}),
  safe(db().from('seniorcare_medical_documents').select('*').eq('organization_id',org()).eq('active',true).order('created_at',{ascending:false}),{optional:true})
 ]);
 [histories,consults,orders,results,prescriptions,documents]=qs.map(x=>x.data);
 window.BHSC_MEDICAL_MISSING_TABLES=qs.map((x,i)=>x.missing?['seniorcare_medical_histories','seniorcare_medical_consultations','seniorcare_medical_orders','seniorcare_medical_results','seniorcare_medical_prescriptions','seniorcare_medical_documents'][i]:null).filter(Boolean);
}
async function ready(){try{await load();return true}catch(e){toast(e.message||'No se pudo cargar el módulo médico.');return false}}
const rn=k=>{const r=residents.find(x=>String(x.resident_key)===String(k));return residentName(r)};
const opts=()=>residents.length?residents.map(r=>`<option value="${esc(r.resident_key)}">${esc(residentName(r))} · ${esc(r.room||r.data?.room||'Sin habitación')}</option>`).join(''):'<option value="">No hay residentes activos</option>';
const fmt=d=>d?new Date(d).toLocaleString('es-CR'):'—';
const stat=s=>`<span class="med-status ${String(s||'').toLowerCase().replace(/\s+/g,'-')}">${esc(s||'Pendiente')}</span>`;
function printDoc(title,body){const w=open('','_blank');if(!w)return toast('El navegador bloqueó la ventana de impresión.');w.document.write(`<!doctype html><html><head><meta charset="utf-8"><title>${esc(title)}</title><style>body{font-family:Arial,sans-serif;color:#17324d;margin:34px}header{border-bottom:3px solid #177f75;padding-bottom:14px;margin-bottom:24px}h1{margin:0;font-size:24px}h2{font-size:18px;margin:24px 0 8px}.meta{color:#52697d;font-size:12px}.box{border:1px solid #d9e3ea;border-radius:10px;padding:14px;margin:10px 0;white-space:pre-wrap}.foot{margin-top:40px;border-top:1px solid #ccd7df;padding-top:12px;font-size:11px;color:#607385}@media print{button{display:none}}</style></head><body><header><h1>Bernard Health SeniorCare</h1><div class="meta">${esc(title)} · ${new Date().toLocaleString('es-CR')}</div></header>${body}<div class="foot">Documento clínico confidencial. Generado por Bernard Health SeniorCare.</div><script>onload=()=>setTimeout(()=>print(),250)<\/script></body></html>`);w.document.close()}
async function registerDoc(type,residentKey,title,payload){const row={organization_id:org(),resident_key:residentKey,document_type:type,title,document_data:payload,created_by:u().id,created_by_name:u().name||u().email,status:'Emitido',active:true,updated_at:new Date().toISOString()};const {error}=await db().from('seniorcare_medical_documents').insert(row);if(error)throw error}
window.renderMedicalDashboard=async()=>{if(!await ready())return;const pend=orders.filter(x=>!['Completada','Suspendida'].includes(x.status)).length;window.main.innerHTML=header('MÓDULO MÉDICO','Centro clínico','Historia clínica, consulta, indicaciones, recetas y documentos')+`<section class="med-hero"><div><span>EXPEDIENTE CLÍNICO</span><h2>Atención médica clara y organizada</h2><p>Acceso rápido a antecedentes, consulta, órdenes y documentación.</p></div><div class="med-hero-count"><b>${residents.length}</b><small>residentes activos</small></div></section><section class="medical-summary-grid"><article><span>Historias clínicas</span><strong>${histories.length}</strong></article><article><span>Consultas</span><strong>${consults.length}</strong></article><article><span>Indicaciones pendientes</span><strong>${pend}</strong></article><article><span>Documentos</span><strong>${documents.length}</strong></article></section><div class="module-grid medical-module-grid">
<button class="module-card" data-go="medicalHistory"><span class="quick-icon mint">HC</span><div><strong>Historia clínica</strong><small>Antecedentes esenciales del residente</small></div><b>›</b></button>
<button class="module-card" data-go="medicalConsultation"><span class="quick-icon blue">CM</span><div><strong>Consulta médica</strong><small>Evaluación, examen y plan</small></div><b>›</b></button>
<button class="module-card" data-go="medicalOrders"><span class="quick-icon amber">IM</span><div><strong>Indicaciones médicas</strong><small>Visibles para Enfermería y Administración</small></div><b>›</b></button>
<button class="module-card" data-go="medicalPrescriptions"><span class="quick-icon lilac">Rx</span><div><strong>Recetas</strong><small>Prescripción y PDF</small></div><b>›</b></button>
<button class="module-card" data-go="medicalDocuments"><span class="quick-icon blue">PDF</span><div><strong>Documentos médicos</strong><small>Consultar, imprimir y compartir</small></div><b>›</b></button></div>`;window.bindActions?.()};
window.renderMedicalHistory=async()=>{if(!await ready())return;window.main.innerHTML=header('EXPEDIENTE','Historia clínica','Antecedentes esenciales, simples y editables')+`${doctorWrite()?`<form id="medHistoryForm" class="form-card med-premium-form"><div class="form-grid"><label>Residente<select name="resident_key" required>${opts()}</select></label><label class="wide">Motivo de consulta habitual / razón de valoración<textarea name="chief_complaint"></textarea></label><label class="wide">Antecedentes personales patológicos<textarea name="personal_history" placeholder="Hipertensión, diabetes, EPOC, demencia…"></textarea></label><label class="wide">Antecedentes personales no patológicos<textarea name="non_pathological_history" placeholder="Hábitos, alimentación, sueño, movilidad, eliminación…"></textarea></label><label class="wide">Antecedentes quirúrgicos<textarea name="surgical_history"></textarea></label><label class="wide">Alergias a medicamentos<textarea name="drug_allergies" placeholder="Medicamento y tipo de reacción. Escriba Niega si no existen."></textarea></label><label class="wide">Medicamentos actuales<textarea name="current_medications"></textarea></label><label class="wide">Observaciones generales<textarea name="general_notes"></textarea></label></div><div class="form-actions"><button class="primary-btn">Guardar historia clínica</button></div></form>`:''}<section class="history-card"><h3>Historias registradas</h3>${histories.length?histories.map(h=>`<article class="medical-record-card"><div><strong>${esc(rn(h.resident_key))}</strong><span>Alergias: ${esc(h.drug_allergies||'No registradas')}</span><small>Actualizada ${fmt(h.updated_at)}</small></div><div class="card-actions"><button class="mini-btn" data-history-edit="${h.id}">Editar</button><button class="mini-btn" data-history-print="${h.id}">PDF</button></div></article>`).join(''):empty('No hay historias clínicas registradas.')}</section>`;
const f=document.getElementById('medHistoryForm');f?.elements.resident_key.addEventListener('change',()=>fillHistory(f));fillHistory(f);f?.addEventListener('submit',saveHistory);document.querySelectorAll('[data-history-edit]').forEach(b=>b.onclick=()=>{f.elements.resident_key.value=histories.find(x=>x.id===b.dataset.historyEdit)?.resident_key||'';fillHistory(f);f.scrollIntoView({behavior:'smooth'})});document.querySelectorAll('[data-history-print]').forEach(b=>b.onclick=()=>{const h=histories.find(x=>x.id===b.dataset.historyPrint);printDoc('Historia clínica',`<h2>${esc(rn(h.resident_key))}</h2>${[['Motivo',h.chief_complaint],['Antecedentes personales',h.personal_history],['No patológicos',h.non_pathological_history],['Quirúrgicos',h.surgical_history],['Alergias',h.drug_allergies],['Medicamentos actuales',h.current_medications],['Observaciones',h.general_notes]].map(x=>`<h2>${x[0]}</h2><div class="box">${esc(x[1]||'Sin registro')}</div>`).join('')}`)})};
function fillHistory(f){if(!f)return;const h=histories.find(x=>String(x.resident_key)===String(f.elements.resident_key.value));['chief_complaint','personal_history','non_pathological_history','surgical_history','drug_allergies','current_medications','general_notes'].forEach(k=>f.elements[k].value=h?.[k]||'');f.dataset.id=h?.id||''}
async function saveHistory(e){e.preventDefault();const f=e.currentTarget,fd=new FormData(f),p={organization_id:org(),resident_key:String(fd.get('resident_key')),chief_complaint:String(fd.get('chief_complaint')||''),personal_history:String(fd.get('personal_history')||''),non_pathological_history:String(fd.get('non_pathological_history')||''),surgical_history:String(fd.get('surgical_history')||''),drug_allergies:String(fd.get('drug_allergies')||''),current_medications:String(fd.get('current_medications')||''),general_notes:String(fd.get('general_notes')||''),updated_by:u().id,updated_by_name:u().name||u().email,updated_at:new Date().toISOString(),active:true};let q=f.dataset.id?db().from('seniorcare_medical_histories').update(p).eq('id',f.dataset.id):db().from('seniorcare_medical_histories').insert(p);const {error}=await q;if(error){if(missingTable(error))return toast('Falta activar el almacenamiento del Resumen clínico en Supabase.');return toast(error.message)}toast('Resumen clínico guardado.');window.renderMedicalHistory()}
const examFields={systems:['Estado general','Cabeza y cuello','Cardiovascular','Respiratorio','Abdomen','Genitourinario','Musculoesquelético','Neurológico','Piel'],anatomical:['Cabeza','Cuello','Tórax','Abdomen','Pelvis','Extremidades','Columna','Piel']};
function examUI(model){if(model==='free')return `<label class="wide">Examen físico libre<textarea name="exam_free" rows="7"></textarea></label>`;return examFields[model].map((n,i)=>`<div class="exam-row"><strong>${n}</strong><select name="exam_state_${i}"><option>Normal</option><option>Alterado</option><option>No evaluado</option></select><input name="exam_note_${i}" placeholder="Hallazgos u observaciones"></div>`).join('')}
function consultationVitalsUI(){return `<fieldset class="wide med-vitals-block"><legend>Signos vitales</legend><div class="form-grid med-vitals-grid"><label>Presión arterial<input name="vital_bp" placeholder="120/80 mmHg"></label><label>Frecuencia cardiaca<input name="vital_hr" placeholder="72 lpm"></label><label>Frecuencia respiratoria<input name="vital_rr" placeholder="18 rpm"></label><label>Temperatura<input name="vital_temp" placeholder="36.5 °C"></label><label>Saturación O₂<input name="vital_spo2" placeholder="98 %"></label><label>Glucemia<input name="vital_glucose" placeholder="Opcional"></label></div></fieldset>`}
function consultMeta(c){const d=c?.exam_data||{};return {vitals:d.vital_signs||{},observations:d.observations||''}}
function vitalText(c){const v=consultMeta(c).vitals||{};const labels={bp:'Presión arterial',hr:'Frecuencia cardiaca',rr:'Frecuencia respiratoria',temp:'Temperatura',spo2:'Saturación O₂',glucose:'Glucemia'};const lines=Object.entries(labels).filter(([k])=>v[k]).map(([k,l])=>`${l}: ${v[k]}`);return lines.length?lines.join('\n'):'Sin registro'}
window.renderMedicalConsultation=async()=>{if(!await ready())return;window.main.innerHTML=header('ATENCIÓN MÉDICA','Consulta médica','Evaluación clínica ordenada y práctica')+`${doctorWrite()?`<form id="medicalConsultForm" class="form-card med-premium-form"><div class="form-grid"><label>Residente<select name="resident_key" required>${opts()}</select></label><label>Fecha y hora<input type="datetime-local" name="consultation_date" value="${nowLocal()}" required></label><label class="wide">Motivo de consulta<textarea name="reason" required></textarea></label>${consultationVitalsUI()}<label>Modelo de examen físico<select name="exam_model"><option value="systems">Por aparatos y sistemas</option><option value="anatomical">Por zonas anatómicas</option><option value="free">Texto libre</option></select></label><div class="wide med-exam-builder" id="examBuilder">${examUI('systems')}</div><label class="wide">Diagnósticos<textarea name="diagnosis" required></textarea></label><label class="wide">Tratamiento<textarea name="plan" required></textarea></label><label class="wide">Observaciones<textarea name="observations"></textarea></label><label>Próxima consulta<input type="date" name="follow_up_date"></label></div><div class="form-actions"><button class="primary-btn">Guardar consulta</button></div></form>`:''}<section class="history-card"><h3>Consultas registradas</h3>${consults.length?consults.map(c=>`<article class="medical-record-card"><div><strong>${esc(rn(c.resident_key))}</strong><span>${esc(c.diagnosis||'Sin diagnóstico')}</span><small>${fmt(c.consultation_date)} · ${esc(c.doctor_name||'Médico')}</small></div><div class="card-actions"><button class="mini-btn" data-consult-print="${c.id}">PDF</button><button class="mini-btn" data-consult-send="${c.id}">Enviar a Administración</button></div></article>`).join(''):empty('Sin consultas registradas.')}</section>`;const f=document.getElementById('medicalConsultForm');f?.elements.exam_model.addEventListener('change',e=>document.getElementById('examBuilder').innerHTML=examUI(e.target.value));f?.addEventListener('submit',saveConsult);document.querySelectorAll('[data-consult-print]').forEach(b=>b.onclick=()=>{const c=consults.find(x=>x.id===b.dataset.consultPrint),m=consultMeta(c);printDoc('Consulta médica',`<h2>${esc(rn(c.resident_key))}</h2><h2>Motivo de consulta</h2><div class="box">${esc(c.reason)}</div><h2>Signos vitales</h2><div class="box">${esc(vitalText(c))}</div><h2>Examen físico</h2><div class="box">${esc(c.physical_exam||'Sin registro')}</div><h2>Diagnósticos</h2><div class="box">${esc(c.diagnosis)}</div><h2>Tratamiento</h2><div class="box">${esc(c.plan)}</div><h2>Observaciones</h2><div class="box">${esc(m.observations||'Sin observaciones')}</div><h2>Próxima consulta</h2><div class="box">${esc(c.follow_up_date||'No indicada')}</div>`)});document.querySelectorAll('[data-consult-send]').forEach(b=>b.onclick=async()=>{const c=consults.find(x=>x.id===b.dataset.consultSend);if(!c)return;try{await registerDoc('Resumen de consulta',c.resident_key,`Resumen de consulta · ${rn(c.resident_key)}`,{consultation_id:c.id,reason:c.reason,vital_signs:c.exam_data?.vital_signs||{},physical_exam:c.physical_exam,diagnosis:c.diagnosis,treatment:c.plan,observations:consultMeta(c).observations||'',follow_up_date:c.follow_up_date,sent_to_admin:true,sent_at:new Date().toISOString()});toast('Resumen enviado a Administración y guardado en Documentos médicos.')}catch(err){toast(err.message||'No se pudo enviar el resumen.')}});};
async function saveConsult(e){e.preventDefault();const f=e.currentTarget,fd=new FormData(f),model=String(fd.get('exam_model')),findings={};let text='';if(model==='free')text=String(fd.get('exam_free')||'');else examFields[model].forEach((n,i)=>{const state=String(fd.get('exam_state_'+i)||''),note=String(fd.get('exam_note_'+i)||'');findings[n]={state,note};text+=`${n}: ${state}${note?' — '+note:''}\n`});const vital_signs={bp:String(fd.get('vital_bp')||''),hr:String(fd.get('vital_hr')||''),rr:String(fd.get('vital_rr')||''),temp:String(fd.get('vital_temp')||''),spo2:String(fd.get('vital_spo2')||''),glucose:String(fd.get('vital_glucose')||'')};const exam_data={findings,vital_signs,observations:String(fd.get('observations')||'')};const p={organization_id:org(),resident_key:String(fd.get('resident_key')),consultation_date:String(fd.get('consultation_date')),reason:String(fd.get('reason')),history:'',physical_exam:text.trim(),exam_model:model,exam_data,diagnosis:String(fd.get('diagnosis')),plan:String(fd.get('plan')),follow_up_date:fd.get('follow_up_date')||null,doctor_id:u().id,doctor_name:u().name||u().email,active:true,updated_at:new Date().toISOString()};const {data:r,error}=await db().from('seniorcare_medical_consultations').insert(p).select().single();if(error)return toast(error.message);await registerDoc('Consulta médica',p.resident_key,`Consulta médica · ${rn(p.resident_key)}`,{consultation_id:r.id});toast('Consulta médica guardada.');window.renderMedicalConsultation()}
window.renderMedicalOrders=async()=>{if(!await ready())return;window.main.innerHTML=header('INDICACIONES MÉDICAS','Órdenes e indicaciones','Médico emite; Enfermería y Administración reciben y controlan')+`${doctorWrite()?`<form id="medicalOrderForm" class="form-card med-premium-form"><div class="form-grid"><label>Residente<select name="resident_key" required>${opts()}</select></label><label>Tipo<select name="order_type"><option>Medicamento</option><option>Control de signos</option><option>Curación</option><option>Dieta</option><option>Laboratorio</option><option>Imagen</option><option>Interconsulta</option><option>Terapia</option><option>Cuidado especial</option><option>Traslado</option><option>Otra</option></select></label><label>Prioridad<select name="priority"><option>Normal</option><option>Preferente</option><option>Urgente</option></select></label><label>Fecha límite<input type="date" name="due_date"></label><label class="wide">Indicación<textarea name="detail" required></textarea></label></div><div class="form-actions"><button class="primary-btn">Emitir indicación</button></div></form>`:''}<section class="history-card"><h3>Indicaciones</h3>${orders.length?orders.map(o=>`<article class="medical-record-card"><div><strong>${esc(rn(o.resident_key))} · ${esc(o.order_type)}</strong><span>${esc(o.detail)}</span><small>${esc(o.priority)} · ${fmt(o.created_at)} · ${esc(o.doctor_name||'Médico')}</small></div><div class="card-actions">${stat(o.status)}${orderWork()&&!['Completada','Suspendida'].includes(o.status)?`<button class="mini-btn" data-order-status="${o.id}" data-next="${o.status==='Pendiente'?'Leída':o.status==='Leída'?'En ejecución':'Completada'}">${o.status==='Pendiente'?'Marcar leída':o.status==='Leída'?'Iniciar':'Completar'}</button>`:''}<button class="mini-btn" data-order-print="${o.id}">PDF</button></div></article>`).join(''):empty('No hay indicaciones médicas.')}</section>`;document.getElementById('medicalOrderForm')?.addEventListener('submit',saveOrder);document.querySelectorAll('[data-order-status]').forEach(b=>b.onclick=async()=>{const {error}=await db().from('seniorcare_medical_orders').update({status:b.dataset.next,acknowledged_by:u().id,acknowledged_by_name:u().name||u().email,acknowledged_at:new Date().toISOString(),updated_at:new Date().toISOString()}).eq('id',b.dataset.orderStatus);if(error)return toast(error.message);toast('Indicación actualizada.');window.renderMedicalOrders()});document.querySelectorAll('[data-order-print]').forEach(b=>b.onclick=()=>{const o=orders.find(x=>x.id===b.dataset.orderPrint);printDoc('Indicación médica',`<h2>${esc(rn(o.resident_key))}</h2><div class="box"><b>${esc(o.order_type)} · ${esc(o.priority)}</b><br><br>${esc(o.detail)}</div><p>Médico: ${esc(o.doctor_name||'')}</p>`)})};
async function saveOrder(e){e.preventDefault();const fd=new FormData(e.currentTarget),p={organization_id:org(),resident_key:String(fd.get('resident_key')),order_type:String(fd.get('order_type')),detail:String(fd.get('detail')),priority:String(fd.get('priority')),due_date:fd.get('due_date')||null,status:'Pendiente',doctor_id:u().id,doctor_name:u().name||u().email,active:true,updated_at:new Date().toISOString()};const {data:r,error}=await db().from('seniorcare_medical_orders').insert(p).select().single();if(error)return toast(error.message);await registerDoc('Indicación médica',p.resident_key,`Indicación · ${rn(p.resident_key)}`,{order_id:r.id});const alertResult=await db().from('seniorcare_alerts').insert({organization_id:org(),alert_key:'medical-order:'+r.id,source_key:'medical-order:'+r.id,title:`Nueva indicación médica · ${rn(p.resident_key)}`,detail:p.detail,priority:p.priority==='Urgente'?'Critical':'Pending',status:'Nueva',alert_type:'medical_order',resident_key:p.resident_key,target_screen:'medicalOrders',active:true,data:{order_id:r.id,category:'resident'}});if(alertResult.error){toast('La indicación se guardó, pero la alerta no pudo crearse: '+alertResult.error.message);return;}toast('Indicación emitida para Enfermería y Administración.');window.renderMedicalOrders()}
window.renderMedicalPrescriptions=async()=>{if(!await ready())return;window.main.innerHTML=header('PRESCRIPCIÓN','Recetas médicas','Recetas claras, registradas y listas para PDF')+`${doctorWrite()?`<form id="prescriptionForm" class="form-card med-premium-form"><div class="form-grid"><label>Residente<select name="resident_key" required>${opts()}</select></label><label>Medicamento<input name="medication" required></label><label>Concentración<input name="strength"></label><label>Dosis<input name="dose" required></label><label>Vía<select name="route"><option>Oral</option><option>Subcutánea</option><option>Intramuscular</option><option>Intravenosa</option><option>Tópica</option><option>Inhalada</option><option>Otra</option></select></label><label>Frecuencia<input name="frequency" required></label><label>Duración<input name="duration"></label><label>Cantidad<input name="quantity"></label><label class="wide">Indicaciones especiales<textarea name="instructions"></textarea></label></div><div class="form-actions"><button class="primary-btn">Emitir receta</button></div></form>`:''}<section class="history-card"><h3>Recetas emitidas</h3>${prescriptions.length?prescriptions.map(p=>`<article class="medical-record-card"><div><strong>${esc(rn(p.resident_key))} · ${esc(p.medication)}</strong><span>${esc([p.strength,p.dose,p.route,p.frequency,p.duration].filter(Boolean).join(' · '))}</span><small>${fmt(p.issued_at)} · ${esc(p.doctor_name||'Médico')}</small></div><div class="card-actions">${stat(p.status)}<button class="mini-btn" data-rx-print="${p.id}">PDF</button></div></article>`).join(''):empty('No hay recetas emitidas.')}</section>`;document.getElementById('prescriptionForm')?.addEventListener('submit',saveRx);document.querySelectorAll('[data-rx-print]').forEach(b=>b.onclick=()=>printRx(prescriptions.find(x=>x.id===b.dataset.rxPrint)))};
async function saveRx(e){e.preventDefault();const fd=new FormData(e.currentTarget),p={organization_id:org(),resident_key:String(fd.get('resident_key')),medication:String(fd.get('medication')),strength:String(fd.get('strength')||''),dose:String(fd.get('dose')),route:String(fd.get('route')),frequency:String(fd.get('frequency')),duration:String(fd.get('duration')||''),quantity:String(fd.get('quantity')||''),instructions:String(fd.get('instructions')||''),doctor_id:u().id,doctor_name:u().name||u().email,status:'Vigente',issued_at:new Date().toISOString(),active:true,updated_at:new Date().toISOString()};const {data:r,error}=await db().from('seniorcare_medical_prescriptions').insert(p).select().single();if(error)return toast(error.message);await registerDoc('Receta médica',p.resident_key,`Receta · ${rn(p.resident_key)}`,{prescription_id:r.id});toast('Receta emitida y registrada.');window.renderMedicalPrescriptions()}
function printRx(p){printDoc('Receta médica',`<h2>Paciente: ${esc(rn(p.resident_key))}</h2><div class="box"><b>${esc(p.medication)} ${esc(p.strength||'')}</b><br>Dosis: ${esc(p.dose)}<br>Vía: ${esc(p.route)}<br>Frecuencia: ${esc(p.frequency)}<br>Duración: ${esc(p.duration||'Según indicación')}<br>Cantidad: ${esc(p.quantity||'—')}<br><br>${esc(p.instructions||'')}</div><p>Médico: ${esc(p.doctor_name||'')}</p>`) }
window.renderMedicalStudies=async()=>{if(!await ready())return;const studyOrders=orders.filter(o=>['Laboratorio','Imagen'].includes(o.order_type));window.main.innerHTML=header('EXÁMENES Y ESTUDIOS','Solicitudes diagnósticas','Laboratorios e imágenes enviados a Enfermería y Administración')+`${doctorWrite()?`<form id="medicalStudyForm" class="form-card med-premium-form"><div class="form-grid"><label>Residente<select name="resident_key" required>${opts()}</select></label><label>Tipo<select name="order_type"><option>Laboratorio</option><option>Imagen</option></select></label><label>Prioridad<select name="priority"><option>Normal</option><option>Preferente</option><option>Urgente</option></select></label><label>Fecha límite<input type="date" name="due_date"></label><label class="wide">Examen o estudio solicitado<input name="study_name" required placeholder="Ej.: Hemograma completo, ultrasonido abdominal"></label><label class="wide">Indicación clínica<textarea name="clinical_note" placeholder="Motivo o sospecha clínica"></textarea></label></div><div class="form-actions"><button class="primary-btn">Enviar solicitud</button></div></form>`:''}<section class="history-card"><h3>Solicitudes emitidas</h3>${studyOrders.length?studyOrders.map(o=>`<article class="medical-record-card"><div><strong>${esc(rn(o.resident_key))} · ${esc(o.order_type)}</strong><span>${esc(o.detail)}</span><small>${esc(o.priority)} · ${fmt(o.created_at)} · ${esc(o.status||'Pendiente')}</small></div><div class="card-actions">${stat(o.status)}<button class="mini-btn" data-study-print="${o.id}">PDF</button></div></article>`).join(''):empty('No hay solicitudes de exámenes o imágenes.')}</section>`;document.getElementById('medicalStudyForm')?.addEventListener('submit',async e=>{e.preventDefault();const fd=new FormData(e.currentTarget),name=String(fd.get('study_name')),note=String(fd.get('clinical_note')||''),detail=note?`${name}
Indicación clínica: ${note}`:name;const p={organization_id:org(),resident_key:String(fd.get('resident_key')),order_type:String(fd.get('order_type')),priority:String(fd.get('priority')),due_date:fd.get('due_date')||null,detail,status:'Pendiente',doctor_id:u().id,doctor_name:u().name||u().email,active:true,updated_at:new Date().toISOString()};const {data:r,error}=await db().from('seniorcare_medical_orders').insert(p).select().single();if(error)return toast(error.message);await registerDoc('Solicitud de estudio',p.resident_key,`${p.order_type} · ${name}`,{order_id:r.id,study_name:name,clinical_note:note,priority:p.priority,due_date:p.due_date});toast('Solicitud enviada a Enfermería y Administración.');window.renderMedicalStudies()});document.querySelectorAll('[data-study-print]').forEach(b=>b.onclick=()=>{const o=studyOrders.find(x=>x.id===b.dataset.studyPrint);printDoc('Solicitud de examen o estudio',`<h2>${esc(rn(o.resident_key))}</h2><div class="box"><b>${esc(o.order_type)} · ${esc(o.priority)}</b><br><br>${esc(o.detail)}</div><p>Médico: ${esc(o.doctor_name||'')}</p>`)})};
window.renderMedicalResults=async()=>{if(!await ready())return;window.main.innerHTML=header('RESULTADOS','Resultados clínicos','Registro e interpretación médica')+`${doctorWrite()?`<form id="medicalResultForm" class="form-card"><div class="form-grid"><label>Residente<select name="resident_key" required>${opts()}</select></label><label>Tipo<select name="result_type"><option>Laboratorio</option><option>Imagen</option><option>Interconsulta</option><option>Otro</option></select></label><label>Fecha<input type="date" name="result_date" value="${(window.BHSC_LOCAL_DATE?window.BHSC_LOCAL_DATE():new Intl.DateTimeFormat('en-CA',{timeZone:'America/Costa_Rica'}).format(new Date()))}" required></label><label>Estado<select name="status"><option>Pendiente</option><option>Revisado</option><option>Requiere seguimiento</option></select></label><label class="wide">Resultado<textarea name="summary" required></textarea></label><label class="wide">Interpretación médica<textarea name="interpretation"></textarea></label></div><div class="form-actions"><button class="primary-btn">Guardar resultado</button></div></form>`:''}<section class="history-card"><h3>Resultados</h3>${results.length?results.map(r=>`<article class="medical-record-card"><div><strong>${esc(rn(r.resident_key))} · ${esc(r.result_type)}</strong><span>${esc(r.summary)}</span><small>${esc(r.result_date)}</small></div>${stat(r.status)}</article>`).join(''):empty('Sin resultados.')}</section>`;document.getElementById('medicalResultForm')?.addEventListener('submit',async e=>{e.preventDefault();const fd=new FormData(e.currentTarget),p={organization_id:org(),resident_key:String(fd.get('resident_key')),result_type:String(fd.get('result_type')),result_date:String(fd.get('result_date')),status:String(fd.get('status')),summary:String(fd.get('summary')),interpretation:String(fd.get('interpretation')||''),reviewed_by:u().id,reviewed_by_name:u().name||u().email,active:true,updated_at:new Date().toISOString()};const {error}=await db().from('seniorcare_medical_results').insert(p);if(error)return toast(error.message);toast('Resultado guardado.');window.renderMedicalResults()})};
window.renderMedicalAssessments=async()=>{if(!await ready())return;window.main.innerHTML=header('VALORACIÓN','Valoración geriátrica','Registro complementario')+`<form id="assessForm" class="form-card"><div class="form-grid"><label>Residente<select name="resident_key">${opts()}</select></label><label>Tipo<select name="assessment_type"><option>Barthel</option><option>Lawton y Brody</option><option>Riesgo de caídas</option><option>Braden / Norton</option><option>Nutricional</option><option>Cognitiva</option><option>Estado de ánimo</option></select></label><label>Puntaje<input type="number" step="0.1" name="score"></label><label class="wide">Conclusión<textarea name="conclusion" required></textarea></label></div><div class="form-actions"><button class="primary-btn">Guardar valoración</button></div></form>`};
window.renderMedicalDocuments=async()=>{if(!await ready())return;window.main.innerHTML=header('ARCHIVO MÉDICO','Documentos médicos','Administración y médico pueden consultar e imprimir')+`<section class="med-doc-toolbar"><input id="medDocSearch" placeholder="Buscar residente o documento"><select id="medDocType"><option value="">Todos los documentos</option>${[...new Set(documents.map(d=>d.document_type))].map(t=>`<option>${esc(t)}</option>`).join('')}</select></section><section id="medDocList" class="history-card"></section>`;const draw=()=>{const q=(document.getElementById('medDocSearch').value||'').toLowerCase(),t=document.getElementById('medDocType').value;const list=documents.filter(d=>(!t||d.document_type===t)&&(`${d.title} ${rn(d.resident_key)}`).toLowerCase().includes(q));document.getElementById('medDocList').innerHTML=`<h3>Documentos (${list.length})</h3>${list.length?list.map(d=>`<article class="medical-record-card"><div><strong>${esc(d.title)}</strong><span>${esc(rn(d.resident_key))} · ${esc(d.document_type)}</span><small>${fmt(d.created_at)} · ${esc(d.created_by_name||'')}</small></div><div class="card-actions"><button class="mini-btn" data-doc-open="${d.id}">Abrir / PDF</button></div></article>`).join(''):empty('No hay documentos.')}`;document.querySelectorAll('[data-doc-open]').forEach(b=>b.onclick=()=>openStoredDoc(documents.find(x=>x.id===b.dataset.docOpen)))};draw();document.getElementById('medDocSearch').oninput=draw;document.getElementById('medDocType').onchange=draw};
function openStoredDoc(d){const data=d.document_data||{};let body=`<h2>${esc(rn(d.resident_key))}</h2><div class="box">${esc(d.title)}</div>`;const c=consults.find(x=>x.id===data.consultation_id),o=orders.find(x=>x.id===data.order_id),p=prescriptions.find(x=>x.id===data.prescription_id);if(c){const m=consultMeta(c);body+=`<h2>Motivo de consulta</h2><div class="box">${esc(c.reason)}</div><h2>Signos vitales</h2><div class="box">${esc(vitalText(c))}</div><h2>Examen físico</h2><div class="box">${esc(c.physical_exam||'Sin registro')}</div><h2>Diagnósticos</h2><div class="box">${esc(c.diagnosis)}</div><h2>Tratamiento</h2><div class="box">${esc(c.plan)}</div><h2>Observaciones</h2><div class="box">${esc(m.observations||'Sin observaciones')}</div><h2>Próxima consulta</h2><div class="box">${esc(c.follow_up_date||'No indicada')}</div>`;}if(o)body+=`<div class="box"><b>${esc(o.order_type)}</b><br>${esc(o.detail)}</div>`;if(p)return printRx(p);printDoc(d.title,body)}
addEventListener('seniorcare:user-ready',()=>{if(role()==='doctor')setTimeout(()=>window.go?.('medicalDashboard',{scope:'global'},{replace:true}),250)});
})();
