const $ = (s, el=document) => el.querySelector(s);
const $$ = (s, el=document) => [...el.querySelectorAll(s)];
const state = { logged:false, tab:'lavado', config:null, pumps:[], reviews:[], dash:null };

async function api(action, data=null, method='POST'){
  let realMethod = method;
  let extraQuery = '';
  if (method.startsWith('GET&')) { realMethod = 'GET'; extraQuery = '&' + method.slice(4); }
  const opts = { method: realMethod, headers:{} };
  let url = `api.php?action=${encodeURIComponent(action)}${extraQuery}`;
  if(data && method==='POST'){ opts.headers['Content-Type']='application/json'; opts.body=JSON.stringify(data); }
  const res = await fetch(url, opts);
  const json = await res.json().catch(()=>({ok:false,error:'Respuesta inválida'}));
  if(!json.ok) throw new Error(json.error || 'Error');
  return json;
}
function toast(msg, ok=true){ const d=document.createElement('div'); d.className=ok?'success':'error'; d.textContent=msg; const host=$('#msgHost')||document.body; host.prepend(d); setTimeout(()=>d.remove(),4500); }
function today(){ return new Date().toISOString().slice(0,10); }
function esc(v){ return String(v??'').replace(/[&<>"]/g, m=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[m])); }
function readFileAsDataURL(file){
  return new Promise((resolve,reject)=>{
    const r=new FileReader();
    r.onerror=reject;
    r.onload=()=>{
      const img=new Image();
      img.onerror=()=>resolve(r.result);
      img.onload=()=>{
        const max=1400;
        let w=img.naturalWidth||img.width, h=img.naturalHeight||img.height;
        const scale=Math.min(1, max/Math.max(w,h));
        w=Math.round(w*scale); h=Math.round(h*scale);
        const c=document.createElement('canvas'); c.width=w; c.height=h;
        const ctx=c.getContext('2d');
        ctx.fillStyle='#fff'; ctx.fillRect(0,0,w,h);
        ctx.drawImage(img,0,0,w,h);
        resolve(c.toDataURL('image/jpeg',0.84));
      };
      img.src=r.result;
    };
    r.readAsDataURL(file);
  });
}

function render(){
  if(!state.logged) return renderLogin();
  $('#app').innerHTML = `
    <header class="topbar"><div class="topbar-inner"><div class="logo"><img src="assets/icons/icon-192.png?v=2.3.0" alt="Revisión Operacional"></div><div class="brand"><div class="eyebrow">Control operacional</div><h1>${esc(state.config?.station_name||'Copec Ogana 20830')}</h1></div><button class="btn secondary" onclick="logout()">Salir</button></div></header>
    <nav class="tabs"><div class="tabs-inner">${[
      ['lavado','Lavado/Aspirado'],['dashboard','Dashboard'],['surtidores','Surtidores'],['generador','Generador'],['historial','Historial'],['config','Configuración']
    ].map(t=>`<button class="tab ${state.tab===t[0]?'active':''}" onclick="setTab('${t[0]}')">${t[1]}</button>`).join('')}</div></nav>
    <main class="wrap"><div id="msgHost"></div><div id="view"></div><div class="footer-space"></div></main>`;
  renderView();
}
function renderLogin(){
  $('#app').innerHTML = `<section class="login"><div class="login-card"><div class="logo"><img src="assets/icons/icon-192.png?v=2.3.0" alt="Revisión Operacional"></div><div class="eyebrow" style="margin-top:16px">Acceso privado</div><h1 class="title">Control Operacional</h1><p class="hint">Ingrese la clave para continuar. Clave inicial: 20830.</p><label class="label">Clave</label><input id="password" class="field" type="password" inputmode="numeric" autocomplete="current-password"><button class="btn full" style="margin-top:14px" onclick="login()">Ingresar</button><div id="loginMsg"></div></div></section>`;
  $('#password').addEventListener('keydown', e=>{ if(e.key==='Enter') login(); });
}
async function login(){ try{ await api('login',{password:$('#password').value}); state.logged=true; await bootstrap(); } catch(e){ $('#loginMsg').innerHTML=`<div class="error">${esc(e.message)}</div>`; } }
async function logout(){ await api('logout',{}).catch(()=>{}); state.logged=false; render(); }
async function bootstrap(){ const r=await api('bootstrap',null,'GET'); state.config=r.config; state.pumps=r.pumps; render(); }
function setTab(t){ state.tab=t; render(); if(t==='historial') loadReviews(); if(t==='dashboard') loadDashboard(); }
function renderView(){
  const map={lavado:renderLavado,dashboard:renderDashboard,surtidores:renderSurtidores,generador:renderGenerador,historial:renderHistorial,config:renderConfig};
  map[state.tab]();
}
function formHeader(title, text){ return `<div class="card"><h2>${title}</h2><p class="muted">${text}</p></div>`; }
function imgInput(id,label,required=true){ return `<label class="label">${label}${required?' *':''}</label><input id="${id}" class="field" type="file" accept="image/*" capture="environment"><div class="photo-preview" id="${id}_preview"></div>`; }
async function bindPreview(id){ const input=$('#'+id); input?.addEventListener('change', async()=>{ const file=input.files[0]; if(!file) return; const data=await readFileAsDataURL(file); $('#'+id+'_preview').innerHTML=`<img src="${data}">`; input.dataset.data=data; }); }

function renderLavado(){
  $('#view').innerHTML = `${formHeader('Revisión lavado y aspirado','Registra numerales, fotos obligatorias, fichas retiradas, incidentes y observaciones.')}
  <div class="card grid two">
    <div><label class="label">Fecha</label><input id="lav_fecha" type="date" class="field" value="${today()}"></div>
    <div><label class="label">Responsable</label><input id="lav_resp" class="field" placeholder="Nombre y apellido"></div>
  </div>
  <div class="card grid two">
    <div><label class="label">Numeral lavado del día *</label><input id="num_lavado" class="field" type="number" min="0" inputmode="numeric">${imgInput('foto_lavado','Foto numeral lavado',true)}</div>
    <div><label class="label">Numeral aspirado del día *</label><input id="num_aspirado" class="field" type="number" min="0" inputmode="numeric">${imgInput('foto_aspirado','Foto numeral aspirado',true)}</div>
  </div>
  <div class="card grid two">
    <div><label class="label">Fichas retiradas lavado</label><input id="fichas_lavado" class="field" type="number" min="0" inputmode="numeric" value="0"></div>
    <div><label class="label">Fichas retiradas aspirado</label><input id="fichas_aspirado" class="field" type="number" min="0" inputmode="numeric" value="0"></div>
  </div>
  <div class="card">
    <h3>Inspección visual</h3>
    ${['Área limpia','Equipos operativos','Mangueras/accesorios en buen estado','Señalética visible','Sin daño visible'].map((x,i)=>`<label class="check"><input type="checkbox" class="visual" value="${esc(x)}"> ${esc(x)}</label>`).join('')}
    <label class="check"><input id="incidente" type="checkbox"> Hay problema presente o incidente</label>
    <label class="label">Observaciones</label><textarea id="lav_obs" class="field" rows="4" placeholder="Detalle si existe observación o incidente"></textarea>
    ${imgInput('foto_obs','Foto adicional de observación',false)}
  </div>
  <div class="card"><h3>Firma responsable</h3><canvas id="sig_lav" class="signature"></canvas><div class="row" style="margin-top:10px"><button class="btn secondary" onclick="clearSignature('sig_lav')">Limpiar firma</button><button class="btn ok" onclick="saveLavado()">Guardar revisión</button></div></div>`;
  bindPreview('foto_lavado'); bindPreview('foto_aspirado'); bindPreview('foto_obs'); setupSignature('sig_lav');
}
async function saveLavado(){
  try{
    const fotoLav=$('#foto_lavado')?.dataset.data, fotoAsp=$('#foto_aspirado')?.dataset.data;
    if(!$('#num_lavado').value || !$('#num_aspirado').value) throw new Error('Debe ingresar numeral lavado y numeral aspirado.');
    if(!fotoLav || !fotoAsp) throw new Error('Debe tomar/subir foto de cada numeral.');
    const data={
      numeral_lavado: Number($('#num_lavado').value), numeral_aspirado:Number($('#num_aspirado').value),
      fichas_lavado:Number($('#fichas_lavado').value||0), fichas_aspirado:Number($('#fichas_aspirado').value||0),
      inspeccion: $$('.visual:checked').map(x=>x.value), incidente: $('#incidente').checked, observaciones: $('#lav_obs').value,
      foto_numeral_lavado: fotoLav, foto_numeral_aspirado: fotoAsp, fotos_observacion: $('#foto_obs')?.dataset.data ? [$('#foto_obs').dataset.data] : []
    };
    const r = await api('save_review',{review_type:'lavado',review_date:$('#lav_fecha').value,responsible_name:$('#lav_resp').value,data,signature_image:getSignature('sig_lav')});
    toast(r.email_sent ? 'Revisión guardada y correo enviado.' : ('Revisión guardada, pero no se pudo enviar correo: ' + (r.email_error || 'revisar SMTP')), !!r.email_sent);
    renderLavado();
  }catch(e){ toast(e.message,false); }
}

function renderDashboard(){ $('#view').innerHTML = `${formHeader('Dashboard lavado y aspirado','El uso real se calcula solo con mínimo dos registros: numeral actual menos numeral anterior.')}<div class="card"><label class="label">Mes</label><div class="row"><input id="dash_month" class="field" type="month" value="${new Date().toISOString().slice(0,7)}"><button class="btn" onclick="loadDashboard()">Actualizar</button></div></div><div id="dashContent" class="grid"></div>`; loadDashboard(); }
async function loadDashboard(){
  if(state.tab!=='dashboard') return;
  const month=$('#dash_month')?.value || new Date().toISOString().slice(0,7);
  try{ state.dash=await api('dashboard_lavado',null,'GET&month='+month); }catch(e){ $('#dashContent').innerHTML=`<div class="error">${esc(e.message)}</div>`; return; }
  const s=state.dash.summary, tr=state.dash.tramos||[], items=state.dash.items||[];
  $('#dashContent').innerHTML = `${s.requiere_minimo_dos_registros?'<div class="alert">Falta información para calcular uso real. Se requieren mínimo 2 días registrados.</div>':''}
  <div class="grid three"><div class="metric"><span class="muted">Uso real total</span><strong>${s.uso_real_total}</strong></div><div class="metric"><span class="muted">Promedio diario</span><strong>${s.promedio_diario}</strong></div><div class="metric"><span class="muted">Proyección mes</span><strong>${s.proyeccion_mes}</strong></div><div class="metric"><span class="muted">Registros</span><strong>${s.registros}</strong></div><div class="metric"><span class="muted">Días calculables</span><strong>${s.dias_calculables}</strong></div><div class="metric"><span class="muted">Incidentes</span><strong>${s.incidentes}</strong></div></div>
  <div class="card"><h3>Tramos calculados</h3><table class="table"><thead><tr><th>Desde</th><th>Hasta</th><th>Lavado</th><th>Aspirado</th><th>Total</th><th>Dif.</th></tr></thead><tbody>${tr.map(t=>`<tr><td>${esc(t.desde)}</td><td>${esc(t.hasta)}</td><td>${t.uso_lavado}</td><td>${t.uso_aspirado}</td><td>${t.uso_total}</td><td><span class="pill ${t.diferencia===0?'ok':(Math.abs(t.diferencia)>5?'bad':'warn')}">${t.diferencia}</span></td></tr>`).join('')||'<tr><td colspan="6">Sin tramos suficientes.</td></tr>'}</tbody></table></div>
  <div class="card"><h3>Últimos numerales</h3><table class="table"><thead><tr><th>Fecha</th><th>Lavado</th><th>Aspirado</th><th>Fotos</th></tr></thead><tbody>${items.slice().reverse().map(i=>`<tr><td>${esc(i.date)}</td><td>${i.lavado}</td><td>${i.aspirado}</td><td>${i.foto_lavado?`<a href="${esc(i.foto_lavado)}" target="_blank">Lavado</a>`:''} ${i.foto_aspirado?`<a href="${esc(i.foto_aspirado)}" target="_blank">Aspirado</a>`:''}</td></tr>`).join('')||'<tr><td colspan="4">Sin registros.</td></tr>'}</tbody></table></div>`;
}
function cleanRut(value){ return String(value||'').replace(/[^0-9kK]/g,'').toUpperCase(); }
function formatRut(value){
  const clean=cleanRut(value);
  if(clean.length<2) return clean;
  const body=clean.slice(0,-1), dv=clean.slice(-1);
  const dotted=body.replace(/\B(?=(\d{3})+(?!\d))/g,'.');
  return `${dotted}-${dv}`;
}
function validRut(value){
  const clean=cleanRut(value);
  if(clean.length<2) return false;
  const body=clean.slice(0,-1), dv=clean.slice(-1);
  if(!/^\d+$/.test(body)) return false;
  let sum=0, multiplier=2;
  for(let i=body.length-1;i>=0;i--){
    sum+=Number(body[i])*multiplier;
    multiplier=multiplier===7?2:multiplier+1;
  }
  const rest=11-(sum%11);
  const expected=rest===11?'0':rest===10?'K':String(rest);
  return dv===expected;
}
function bindRutInput(id){
  const input=$('#'+id);
  input?.addEventListener('input',()=>{ input.value=formatRut(input.value); });
}
function getSurtidoresProgress(){
  const checks=$$('.sur_check');
  const completed=checks.filter(c=>c.checked).length;
  const total=checks.length;
  const percentage=total?Math.round((completed/total)*100):0;
  const pumpTotal=state.pumps.length;
  const pumpCompleted=state.pumps.filter((_,i)=>{
    const items=$$(`.sur_check[data-pump="${i}"]`);
    return items.length>0 && items.every(c=>c.checked);
  }).length;
  return {completed,total,percentage,pumpCompleted,pumpTotal,pending:Math.max(0,total-completed)};
}
function updateSurtidoresProgress(){
  const p=getSurtidoresProgress();
  const bar=$('#sur_progress_bar');
  const text=$('#sur_progress_text');
  const pumps=$('#sur_progress_pumps');
  if(bar){ bar.style.width=`${p.percentage}%`; bar.setAttribute('aria-valuenow',String(p.percentage)); }
  if(text) text.textContent=`${p.completed} de ${p.total} criterios completados (${p.percentage}%)`;
  if(pumps){
    pumps.textContent=`${p.pumpCompleted} de ${p.pumpTotal} surtidores validados completos`;
    pumps.className=`pill ${p.pumpTotal>0 && p.pumpCompleted===p.pumpTotal?'ok':'warn'}`;
  }
  return p;
}

const SURTIDOR_CHECKS_BASE = [
  'Sin fuga visible',
  'Manguera en buen estado',
  'Pistola operativa',
  'Display visible',
  'Botonera operativa',
  'Limpieza adecuada'
];
const SURTIDOR_CHECKS_SEGURIDAD = [
  'El numeral no avanza sin apretar el gatillo',
  'No se excede el monto programado',
  'La pistola corta al soltar el gatillo'
];
const SURTIDOR_CHECKS = [...SURTIDOR_CHECKS_BASE, ...SURTIDOR_CHECKS_SEGURIDAD];

function updatePumpValidation(pumpIdx){
  const checks = $$(`.sur_check[data-pump="${pumpIdx}"]`);
  const complete = checks.length > 0 && checks.every(c=>c.checked);
  const badge = $(`#sur_status_${pumpIdx}`);
  const button = $(`#sur_validate_${pumpIdx}`);
  if(badge){
    badge.className = `pill ${complete?'ok':'warn'}`;
    badge.textContent = complete ? 'Surtidor validado completo' : 'Revisión pendiente';
  }
  if(button){
    button.className = `btn ${complete?'ok':'secondary'} pump-validate-btn`;
    button.textContent = complete ? 'Surtidor validado ✓' : 'Validar surtidor completo';
    button.disabled = complete;
  }
  updateSurtidoresProgress();
  return complete;
}
function validatePump(pumpIdx){
  $$(`.sur_check[data-pump="${pumpIdx}"]`).forEach(c=>{ c.checked=true; });
  updatePumpValidation(pumpIdx);
}
function bindPumpValidation(){
  $$('.sur_check').forEach(c=>c.addEventListener('change',()=>updatePumpValidation(Number(c.dataset.pump))));
  state.pumps.forEach((_,pumpIdx)=>updatePumpValidation(pumpIdx));
  updateSurtidoresProgress();
}

function renderSurtidores(){
  const totalCriteria=state.pumps.reduce((sum,p)=>sum+(Number(p.faces||1)*SURTIDOR_CHECKS.length),0);
  $('#view').innerHTML=`${formHeader('Revisión de surtidores','Registro diario por surtidor y cara. Las casillas marcadas indican funcionamiento correcto.')}
  <div class="card grid three"><div><label class="label">Fecha</label><input id="sur_fecha" type="date" class="field" value="${today()}"></div><div><label class="label">Nombre del revisor *</label><input id="sur_resp" class="field" placeholder="Nombre y apellido" autocomplete="name"></div><div><label class="label">RUT del revisor *</label><input id="sur_rut" class="field" placeholder="12.345.678-9" inputmode="text" autocomplete="off" maxlength="12"></div></div>
  <div class="card progress-card"><div class="progress-head"><div><h3>Avance de la revisión</h3><p id="sur_progress_text" class="muted">0 de ${totalCriteria} criterios completados (0%)</p></div><span id="sur_progress_pumps" class="pill warn">0 de ${state.pumps.length} surtidores validados completos</span></div><div class="progress-track" role="progressbar" aria-label="Avance de revisión" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div id="sur_progress_bar" class="progress-bar" style="width:0%"></div></div></div>
  ${state.pumps.map((p,pumpIdx)=>`<div class="card pump-card">
    <div class="pump-head"><div><h3>${esc(p.name)}</h3><p class="muted">${esc(p.pump_type)} · ${Number(p.faces||1)} cara(s)</p></div><span id="sur_status_${pumpIdx}" class="pill warn">Revisión pendiente</span></div>
    ${Array.from({length:Number(p.faces||1)},(_,faceIdx)=>{
      const face=String.fromCharCode(65+faceIdx);
      const key=`${pumpIdx}_${faceIdx}`;
      return `<section class="pump-face"><h4>Cara ${face}</h4>
        <div class="criteria-title">Estado general</div>
        ${SURTIDOR_CHECKS_BASE.map(c=>`<label class="check"><input type="checkbox" class="sur_check" data-pump="${pumpIdx}" data-key="${key}" value="${esc(c)}"> ${esc(c)}</label>`).join('')}
        <div class="criteria-title safety">Pruebas adicionales de seguridad</div>
        ${SURTIDOR_CHECKS_SEGURIDAD.map(c=>`<label class="check safety-check"><input type="checkbox" class="sur_check" data-pump="${pumpIdx}" data-key="${key}" value="${esc(c)}"> ${esc(c)}</label>`).join('')}
        <label class="label">Observación cara ${face}</label><textarea class="field sur_obs" data-key="${key}" rows="2" placeholder="Registrar falla, anomalía o detalle relevante"></textarea>
      </section>`;
    }).join('')}
    <button id="sur_validate_${pumpIdx}" class="btn secondary pump-validate-btn" onclick="validatePump(${pumpIdx})">Validar surtidor completo</button>
    <p class="muted validation-help">Este botón marca como correctas todas las revisiones de todas las caras del surtidor. Si existe una falla, deje esa casilla sin marcar y detalle la observación.</p>
  </div>`).join('') || '<div class="card alert">No hay surtidores configurados.</div>'}
  <div class="card"><h3>Firma responsable</h3><canvas id="sig_sur" class="signature"></canvas><div class="row" style="margin-top:10px"><button class="btn secondary" onclick="clearSignature('sig_sur')">Limpiar firma</button><button class="btn ok" onclick="saveSurtidores()">Guardar revisión</button></div></div>`;
  setupSignature('sig_sur');
  bindRutInput('sur_rut');
  bindPumpValidation();
}
async function saveSurtidores(){
  try{
    const responsible=$('#sur_resp').value.trim();
    const rut=formatRut($('#sur_rut').value);
    if(!responsible) throw new Error('Debe ingresar el nombre del revisor.');
    if(!rut) throw new Error('Debe ingresar el RUT del revisor.');
    if(!validRut(rut)) throw new Error('El RUT ingresado no es válido.');
    const items=[];
    const pumps=[];
    state.pumps.forEach((p,pumpIdx)=>{
      const faceItems=Array.from({length:Number(p.faces||1)},(_,faceIdx)=>{
        const face=String.fromCharCode(65+faceIdx);
        const key=`${pumpIdx}_${faceIdx}`;
        const checks=$$(`.sur_check[data-key="${key}"]:checked`).map(c=>c.value);
        const item={
          surtidor:p.name,
          cara:face,
          tipo:p.pump_type,
          checks,
          validado_completo:checks.length===SURTIDOR_CHECKS.length,
          observacion:$(`.sur_obs[data-key="${key}"]`)?.value || ''
        };
        items.push(item);
        return item;
      });
      pumps.push({
        surtidor:p.name,
        tipo:p.pump_type,
        caras:faceItems.length,
        validado_completo:faceItems.length>0 && faceItems.every(i=>i.validado_completo)
      });
    });
    const progress=getSurtidoresProgress();
    const incomplete=pumps.filter(p=>!p.validado_completo);
    const statusLine=incomplete.length
      ? `ADVERTENCIA: quedan ${progress.pending} criterio(s) pendiente(s) o no conforme(s).`
      : 'Todos los surtidores están validados completamente.';
    const confirmed=confirm(
      `Confirme el guardado de la revisión\n\n`+
      `Revisor: ${responsible}\n`+
      `RUT: ${rut}\n`+
      `Fecha: ${$('#sur_fecha').value}\n`+
      `Avance: ${progress.completed} de ${progress.total} criterios (${progress.percentage}%)\n`+
      `Surtidores completos: ${progress.pumpCompleted} de ${progress.pumpTotal}\n\n`+
      `${statusLine}\n\n¿Desea guardar esta revisión?`
    );
    if(!confirmed) return;
    const data={
      responsible_rut:rut,
      items,
      pumps,
      progress,
      all_pumps_validated:pumps.length>0 && pumps.every(p=>p.validado_completo),
      required_checks:SURTIDOR_CHECKS
    };
    const r=await api('save_review',{review_type:'surtidores',review_date:$('#sur_fecha').value,responsible_name:responsible,data,signature_image:getSignature('sig_sur')});
    toast(r.email_sent ? 'Revisión guardada y correo enviado.' : ('Revisión guardada, pero no se pudo enviar correo: ' + (r.email_error || 'revisar SMTP')), !!r.email_sent);
    renderSurtidores();
  }catch(e){toast(e.message,false)}
}
function renderGenerador(){ $('#view').innerHTML=`${formHeader('Revisión semanal generador','Registro de respaldo para generador.')}
<div class="card grid two"><div><label class="label">Fecha</label><input id="gen_fecha" type="date" class="field" value="${today()}"></div><div><label class="label">Responsable</label><input id="gen_resp" class="field"></div><div><label class="label">Horómetro</label><input id="gen_horo" class="field"></div><div><label class="label">Minutos de prueba</label><input id="gen_min" class="field" type="number" value="0"></div></div><div class="card">${['Nivel combustible OK','Nivel aceite OK','Batería OK','Tablero sin alarma','Prueba encendido realizada'].map(c=>`<label class="check"><input type="checkbox" class="gen_check" value="${c}"> ${c}</label>`).join('')}<label class="label">Observaciones</label><textarea id="gen_obs" class="field" rows="3"></textarea></div><div class="card"><h3>Firma responsable</h3><canvas id="sig_gen" class="signature"></canvas><div class="row" style="margin-top:10px"><button class="btn secondary" onclick="clearSignature('sig_gen')">Limpiar firma</button><button class="btn ok" onclick="saveGenerador()">Guardar revisión</button></div></div>`; setupSignature('sig_gen'); }
async function saveGenerador(){ try{ const data={horometro:$('#gen_horo').value,minutos:Number($('#gen_min').value||0),checks:$$('.gen_check:checked').map(x=>x.value),observaciones:$('#gen_obs').value}; const r=await api('save_review',{review_type:'generador',review_date:$('#gen_fecha').value,responsible_name:$('#gen_resp').value,data,signature_image:getSignature('sig_gen')}); toast(r.email_sent ? 'Revisión guardada y correo enviado.' : ('Revisión guardada, pero no se pudo enviar correo: ' + (r.email_error || 'revisar SMTP')), !!r.email_sent); renderGenerador(); }catch(e){toast(e.message,false)} }
async function loadReviews(){ if(state.tab!=='historial') return; const r=await api('list_reviews',null,'GET').catch(e=>({reviews:[],error:e.message})); state.reviews=r.reviews||[]; renderHistorial(); }
function renderHistorial(){ $('#view').innerHTML=`${formHeader('Historial','Registros guardados en base de datos MySQL. Cada registro genera PDF y se intenta enviar por correo SMTP.')}${(state.reviews||[]).map(r=>`<div class="card"><div class="row"><div style="flex:1"><h3>${esc(r.review_type)} #${r.id}</h3><p class="muted">${esc(r.review_date)} · ${esc(r.responsible_name)}${r.data?.responsible_rut?' · RUT '+esc(r.data.responsible_rut):''} · ${esc(r.created_at)}</p>${r.review_type==='surtidores'&&r.data?.progress?`<p class="muted">Avance: ${Number(r.data.progress.completed||0)} de ${Number(r.data.progress.total||0)} criterios (${Number(r.data.progress.percentage||0)}%)</p>`:''}<p>${r.email_sent==1?'<span class="pill ok">Correo enviado</span>':'<span class="pill bad">Correo pendiente/error</span>'} ${r.pdf_path?`<a class="pill" href="${esc(r.pdf_path)}" target="_blank">Ver PDF</a>`:''}</p>${r.email_error?`<p class="muted">Error correo: ${esc(r.email_error)}</p>`:''}</div><div><button class="btn secondary" onclick="resendEmail(${r.id})">Reenviar</button></div></div></div>`).join('')||'<div class="card">Sin registros cargados.</div>'}`; }
async function resendEmail(id){ try{ const r=await api('resend_email',{id}); toast(r.email_sent ? 'Correo reenviado correctamente.' : ('No se pudo enviar: ' + (r.email_error || 'revisar SMTP')), !!r.email_sent); await loadReviews(); }catch(e){ toast(e.message,false); } }
function renderConfig(){
  $('#view').innerHTML=`${formHeader('Configuración','Clave, correos y surtidores. Los datos se guardan en MySQL.')}
  <div class="card"><label class="label">Nombre estación</label><input id="cfg_station" class="field" value="${esc(state.config.station_name)}"><label class="label">Correos, separados por coma</label><textarea id="cfg_emails" class="field" rows="3">${esc((state.config.emails||[]).join(', '))}</textarea><label class="label">Nueva clave (opcional)</label><input id="cfg_pass" class="field" type="password" placeholder="Dejar vacío si no cambia"><button class="btn ok" style="margin-top:12px" onclick="saveConfig()">Guardar configuración</button></div>
  <div class="card"><div class="row"><h3 style="flex:1">Surtidores</h3><button class="btn secondary" onclick="addPumpRow()">Agregar</button></div><div id="pumpRows"></div><button class="btn ok" onclick="savePumps()">Guardar surtidores</button></div>`; renderPumpRows();
}
function renderPumpRows(){ $('#pumpRows').innerHTML=state.pumps.map((p,i)=>`<div class="grid three" style="margin-bottom:10px"><input class="field pump-name" data-i="${i}" value="${esc(p.name)}"><input class="field pump-type" data-i="${i}" value="${esc(p.pump_type)}"><select class="field pump-faces" data-i="${i}"><option ${p.faces==1?'selected':''}>1</option><option ${p.faces==2?'selected':''}>2</option><option ${p.faces==3?'selected':''}>3</option><option ${p.faces==4?'selected':''}>4</option></select></div>`).join(''); }
function addPumpRow(){ state.pumps.push({id:0,name:'Surtidor '+(state.pumps.length+1),pump_type:'Multiproducto',faces:2}); renderPumpRows(); }
async function saveConfig(){ try{ const emails=$('#cfg_emails').value.split(',').map(x=>x.trim()).filter(Boolean); await api('save_config',{station_name:$('#cfg_station').value,emails,new_password:$('#cfg_pass').value}); toast('Configuración guardada.'); await bootstrap(); }catch(e){toast(e.message,false)} }
async function savePumps(){ try{ const pumps=state.pumps.map((p,i)=>({id:p.id,name:$(`.pump-name[data-i="${i}"]`).value,pump_type:$(`.pump-type[data-i="${i}"]`).value,faces:Number($(`.pump-faces[data-i="${i}"]`).value)})); await api('save_pumps',{pumps}); toast('Surtidores guardados.'); await bootstrap(); state.tab='config'; render(); }catch(e){toast(e.message,false)} }

const sigs={};
function setupSignature(id){ const c=$('#'+id); if(!c) return; const ctx=c.getContext('2d'); const resize=()=>{ const r=c.getBoundingClientRect(), ratio=window.devicePixelRatio||1; c.width=r.width*ratio; c.height=r.height*ratio; ctx.scale(ratio,ratio); ctx.fillStyle='#fff'; ctx.fillRect(0,0,r.width,r.height); ctx.lineWidth=2; ctx.lineCap='round'; ctx.strokeStyle='#0f172a'; }; resize(); let draw=false,last=null; const point=e=>{const r=c.getBoundingClientRect(),t=e.touches?.[0]||e;return{x:t.clientX-r.left,y:t.clientY-r.top}}; c.onpointerdown=e=>{draw=true;last=point(e);c.setPointerCapture(e.pointerId)}; c.onpointermove=e=>{if(!draw)return;const p=point(e);ctx.beginPath();ctx.moveTo(last.x,last.y);ctx.lineTo(p.x,p.y);ctx.stroke();last=p}; c.onpointerup=()=>{draw=false}; sigs[id]=c; }
function clearSignature(id){ setupSignature(id); }
function getSignature(id){ const c=sigs[id]; return c?c.toDataURL('image/jpeg',0.85):null; }

render();


if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('./service-worker.js?v=2.3.0').catch(() => {});
  });
}
