// EUTPeru — Ventas: Cotizaciones + Precios Especiales
const { useState, useRef } = React;
const G = window.C;
const { T, Modal, FInput, FSelect, FTextarea, Row, Btn, Table, Card, Tabs, PageHeader, StatusBadge, DaysBadge, CreditBadge, Tag, KPICard, fmtS, creditFactor } = window;

// ── Quote PDF Preview (fullscreen modal) ─────────────────────
function QuotePDF({ quote, onClose, contacts }) {
  const client = (contacts||[]).find(c=>c.id===quote.clientId)||{name:quote.client,ruc:'',attn:''};
  const cond = quote.credit===0?'Contado':`${quote.credit} días`;

  const [downloading, setDownloading] = useState(false);

  const downloadPDF = async () => {
    setDownloading(true);
    try {
      const token = localStorage.getItem('eutToken');
      const res = await fetch(`/api/quotes/${quote.id}/pdf`, {
        headers: { Authorization: `Bearer ${token}` }
      });
      if (!res.ok) throw new Error('Error generando PDF');
      const blob = await res.blob();
      const blobUrl = URL.createObjectURL(new Blob([blob], { type: 'application/pdf' }));
      const link = document.createElement('a');
      link.href = blobUrl;
      link.download = `${quote.id}.pdf`;
      link.target = '_blank';
      document.body.appendChild(link);
      link.click();
      setTimeout(() => {
        document.body.removeChild(link);
        URL.revokeObjectURL(blobUrl);
      }, 1000);
    } catch {
      alert('Error al generar el PDF. Intenta de nuevo.');
    } finally {
      setDownloading(false);
    }
  };

  return (
    <div style={{position:'fixed',inset:0,background:'#000000e0',zIndex:1000,display:'flex',flexDirection:'column'}} onClick={onClose}>
      <div style={{height:50,background:G.card,borderBottom:`1px solid ${G.border}`,display:'flex',alignItems:'center',padding:'0 20px',gap:12,flexShrink:0}} onClick={e=>e.stopPropagation()}>
        <span style={{fontFamily:"'Barlow Condensed',sans-serif",fontSize:16,fontWeight:700,color:G.text,flex:1}}>Cotización — {quote.id}</span>
        <Btn onClick={downloadPDF} disabled={downloading} title="iPhone: toca Compartir → Guardar en Archivos">{downloading?'Generando...':'⬇ Descargar PDF'}</Btn>
        <button onClick={onClose} style={{background:'none',border:'none',color:G.textSec,fontSize:18,cursor:'pointer',padding:'4px 8px'}}>✕</button>
      </div>
      <div style={{flex:1,overflow:'auto',padding:32,display:'flex',justifyContent:'center'}} onClick={e=>e.stopPropagation()}>
        <div id="cot-print-area" style={{background:'#fff',color:'#111',width:794,minHeight:1123,padding:'24px 32px',fontFamily:'Arial,sans-serif',fontSize:11,lineHeight:1.4,boxShadow:'0 8px 40px #00000060'}}>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',marginBottom:12,paddingBottom:8,borderBottom:'3px solid #6DBF2E',pageBreakInside:'avoid',breakInside:'avoid'}}>
            <div>
              <div style={{fontWeight:800,fontSize:18,color:'#1a1a1a',letterSpacing:1}}>EUTPERU</div>
              <div style={{fontSize:9,color:'#4A8A1F',fontWeight:700,letterSpacing:0.5,marginTop:2}}>EQUIPOS E IMPLEMENTOS DE SEGURIDAD</div>
            </div>
            <div style={{textAlign:'right',fontSize:10}}>
              <div style={{fontWeight:700,fontSize:12,marginBottom:2}}>E.U.T. PERÚ EIRL</div>
              <div>RUC: 20611733985</div>
              <div>Tel/WhatsApp: +51 986 401 657</div>
              <div>eutperu@gmail.com | logistica@eutperu.com</div>
            </div>
          </div>
          <div style={{textAlign:'center',marginBottom:8}}>
            <div style={{fontSize:14,fontWeight:700,color:'#1a1a1a',letterSpacing:2,textTransform:'uppercase'}}>COTIZACIÓN N° {quote.num||quote.id}</div>
          </div>
          <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:10,marginBottom:10,pageBreakInside:'avoid',breakInside:'avoid'}}>
            <div style={{border:'1px solid #ddd',borderRadius:4,padding:'6px 10px'}}>
              <div style={{fontWeight:700,color:'#6DBF2E',fontSize:10,marginBottom:4,textTransform:'uppercase',letterSpacing:0.5}}>Cliente</div>
              <div><b>Razón Social:</b> {client.name}</div>
              <div><b>RUC:</b> {client.ruc||'—'}</div>
              <div><b>Atención:</b> {client.attn||'—'}</div>
              {client.direccion && <div><b>Dirección:</b> {client.direccion}</div>}
            </div>
            <div style={{border:'1px solid #ddd',borderRadius:4,padding:'6px 10px'}}>
              <div style={{fontWeight:700,color:'#6DBF2E',fontSize:10,marginBottom:4,textTransform:'uppercase',letterSpacing:0.5}}>Cotización</div>
              <div><b>N°:</b> {quote.id}</div>
              <div><b>Fecha:</b> {quote.date}</div>
              <div><b>Condición de Pago:</b> {cond}</div>
              <div><b>Tiempo de Entrega:</b> 24 hrs de recibida OC</div>
            </div>
          </div>
          <table style={{width:'100%',borderCollapse:'collapse',marginBottom:8}}>
            <thead>
              <tr style={{background:'#6DBF2E',color:'#fff'}}>
                {['ITEM','DESCRIPCIÓN','U.M.','CANTIDAD','PRECIO UNI.','TOTAL'].map(h=>(
                  <th key={h} style={{padding:'5px 8px',textAlign:h==='ITEM'||h==='U.M.'||h==='CANTIDAD'?'center':'left',fontSize:10,fontWeight:700,letterSpacing:0.5}}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {(quote.items||[]).map((item,i)=>(
                <tr key={i} style={{background:i%2===0?'#f9f9f9':'#fff',borderBottom:'1px solid #e0e0e0'}}>
                  <td style={{padding:'4px 8px',textAlign:'center'}}>{i+1}</td>
                  <td style={{padding:'4px 8px'}}>{item.name}</td>
                  <td style={{padding:'4px 8px',textAlign:'center'}}>{item.um}</td>
                  <td style={{padding:'4px 8px',textAlign:'center'}}>{item.qty}</td>
                  <td style={{padding:'4px 8px',textAlign:'right'}}>S/ {Number(item.unit).toFixed(2)}</td>
                  <td style={{padding:'4px 8px',textAlign:'right',fontWeight:600}}>S/ {Number(item.total).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g,',')}</td>
                </tr>
              ))}
            </tbody>
          </table>
          <div style={{display:'flex',justifyContent:'flex-end',marginBottom:10,pageBreakInside:'avoid',breakInside:'avoid'}}>
            <table style={{width:240}}>
              <tbody>
                <tr><td style={{padding:'3px 8px',color:'#555'}}>SUBTOTAL (sin IGV)</td><td style={{padding:'3px 8px',textAlign:'right',fontWeight:600}}>{fmtS(quote.subtotal)}</td></tr>
                <tr><td style={{padding:'3px 8px',color:'#555'}}>I.G.V. (18%)</td><td style={{padding:'3px 8px',textAlign:'right'}}>{fmtS(quote.igv)}</td></tr>
                <tr style={{background:'#6DBF2E',color:'#fff'}}>
                  <td style={{padding:'4px 8px',fontWeight:700,borderRadius:'4px 0 0 4px'}}>TOTAL</td>
                  <td style={{padding:'4px 8px',textAlign:'right',fontWeight:700,fontSize:13,borderRadius:'0 4px 4px 0'}}>{fmtS(quote.total)}</td>
                </tr>
              </tbody>
            </table>
          </div>
          <div style={{borderTop:'2px solid #6DBF2E',paddingTop:8,fontSize:10,color:'#666',pageBreakInside:'avoid',breakInside:'avoid'}}>
            <b>LOS PRECIOS ESTÁN EN SOLES (S/)</b> e incluyen IGV 18%.<br/>
            Entrega: 24 horas hábiles después de recibida la Orden de Compra. Si la OC es recibida el viernes, la entrega se programa para el lunes siguiente.<br/>
            Vigencia: 5 días hábiles desde la fecha de emisión.
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Accept OC modal ───────────────────────────────────────────
function AcceptOCModal({ quote, onSave, onClose, requestMode=false }) {
  const [ocNum, setOcNum] = useState('');
  const [ocDate, setOcDate] = useState('');
  const [delivDate, setDelivDate] = useState('');
  const [saving, setSaving] = useState(false);

  const calcDelivery = (d) => {
    if(!d) return;
    const dt = new Date(d);
    const day = dt.getDay();
    const add = day===5?3:day===6?2:1;
    dt.setDate(dt.getDate()+add);
    const dd = String(dt.getDate()).padStart(2,'0');
    const mm = String(dt.getMonth()+1).padStart(2,'0');
    setDelivDate(`${dd}/${mm}/${dt.getFullYear()}`);
    setOcDate(d.split('-').reverse().join('/'));
  };

  const save = async () => {
    if(!ocNum) return;
    setSaving(true);
    try {
      console.log('[AcceptOC] Enviando OC:', quote.id, {ocNum, ocDate, deliveryDate: delivDate});
      const res = requestMode
        ? await window.api('/operation-requests', {
            method: 'POST',
            body: JSON.stringify({ quoteId: quote.id, type: 'confirm_oc', payload: { ocNum, ocDate, deliveryDate: delivDate } })
          })
        : await window.api(`/quotes/${quote.id}/accept`, {
            method: 'PUT',
            body: JSON.stringify({ ocNum, ocDate, deliveryDate: delivDate })
          });
      console.log('[AcceptOC] Respuesta status:', res?.status, 'ok:', res?.ok);
      if (res && res.ok) {
        const updated = await res.json();
        if (requestMode) {
          alert('Solicitud enviada para confirmar la OC.');
        } else {
          console.log('[AcceptOC] Quote actualizada:', updated.id, 'status:', updated.status);
          onSave(updated);
          if (window.refreshDashboard) window.refreshDashboard();
        }
        onClose();
      } else if (res) {
        const err = await res.json().catch(() => ({}));
        console.error('[AcceptOC] Error:', err);
        alert(err.error || `Error al registrar OC (código ${res.status}). Revisa la consola.`);
      }
    } finally { setSaving(false); }
  };

  return (
    <Modal title="Registrar Orden de Compra Aceptada" onClose={onClose} width={480}>
      <FInput label="N° de Orden de Compra *" value={ocNum} onChange={e=>setOcNum(e.target.value)} placeholder="Ej: OC-2026-0041"/>
      <FInput label="Fecha de recepción OC" type="date" onChange={e=>calcDelivery(e.target.value)} note="El sistema calculará la fecha de entrega automáticamente (regla días hábiles)."/>
      {delivDate && (
        <div style={{background:G.bg,border:`1px solid ${G.accent}44`,borderRadius:6,padding:'10px 14px',marginBottom:12}}>
          <div style={{fontSize:12,color:G.textSec,marginBottom:4}}>Cálculo automático:</div>
          <div style={{display:'flex',gap:20}}>
            <div><div style={{...T.sm}}>Fecha entrega estimada</div><div style={{color:G.accent,fontWeight:700}}>{delivDate}</div></div>
            <div><div style={{...T.sm}}>Vencimiento pago ({quote.credit===0?'Contado':`${quote.credit}d`})</div><div style={{color:G.warning,fontWeight:700}}>{quote.credit===0?delivDate:'calculado'}</div></div>
          </div>
        </div>
      )}
      <FInput label="Ajustar fecha de entrega (opcional)" value={delivDate} onChange={e=>setDelivDate(e.target.value)} placeholder="DD/MM/YYYY"/>
      <div style={{display:'flex',justifyContent:'flex-end',gap:8,marginTop:8}}>
        <Btn variant="secondary" onClick={onClose}>Cancelar</Btn>
        <Btn onClick={save} disabled={saving||!ocNum}>{saving?'Guardando…':requestMode?'Enviar solicitud':'Confirmar Aceptación'}</Btn>
      </div>
    </Modal>
  );
}

// ── New Quote Wizard ──────────────────────────────────────────
function NewQuoteWizard({ contacts, setContacts, products, specialPrices, onSave, onClose, initialQuote, currentUser }) {
  const [step, setStep] = useState(initialQuote ? 2 : 1);
  const [clientId, setClientId] = useState(initialQuote ? String(initialQuote.clientId) : '');
  const [newClient, setNewClient] = useState({name:'',ruc:'',attn:'',phone:'',email:''});
  const [isNew, setIsNew] = useState(false);
  const [credit, setCredit] = useState(initialQuote ? initialQuote.credit : 0);
  const [lines, setLines] = useState(initialQuote ? initialQuote.items.map(item=>{
    const prod = (products||[]).find(p=>p.id===item.pid);
    return {pid:item.pid, name:item.name, um:item.um, qty:item.qty,
      unit:item.unit, base:item.unit, special:item.special, total:item.total, buyPrice:+(prod?.buy||0)};
  }) : []);
  const [search, setSearch] = useState('');
  const [saving, setSaving] = useState(false);
  const todayISO = new Date().toISOString().slice(0,10);
  const [quoteDate,     setQuoteDate]     = useState(todayISO);
  const [initialStatus, setInitialStatus] = useState('vigente');
  const [histOcNum,     setHistOcNum]     = useState('');
  const [histOcDate,    setHistOcDate]    = useState('');
  const [histDelivDate, setHistDelivDate] = useState('');
  const [histInvoice,   setHistInvoice]   = useState('');
  const isHistPast = quoteDate < todayISO;
  const isHistOp   = isHistPast && initialStatus !== 'vigente';
  const inputSt    = {background:G.bg,border:`1px solid ${G.border}`,borderRadius:5,color:G.text,padding:'7px 12px',fontSize:13,outline:'none',fontFamily:"'Inter',sans-serif"};

  const isAdminUser = currentUser?.role === 'Administrador';
  const canCotizarTodos        = isAdminUser || !!currentUser?.perms?.cotizarTodos;
  const canOtorgarCredito      = isAdminUser || !!currentUser?.perms?.otorgarCredito;
  const canAjustarPrecio       = isAdminUser || !!currentUser?.perms?.ajustarPrecio;
  const canEditarFechaCotiz    = isAdminUser || !!currentUser?.perms?.editarFechaCotizacion;
  const clients = (contacts||[]).filter(c =>
    c.type==='cliente' && (canCotizarTodos || c.ownerId===currentUser?.id)
  );
  const selClient = clients.find(c=>c.id===+clientId);
  const f = creditFactor(+credit);

  const clientCreditMax = selClient!=null ? (selClient.credit??0) : 120;
  const allCreditOpts = [
    {value:0,  label:'Contado (precio base)'},
    {value:30, label:'30 días (+5%)'},
    {value:60, label:'60 días (+10%)'},
    {value:90, label:'90 días (+15%)'},
    {value:120,label:'120 días (+20%)'},
  ];
  const creditOpts = canOtorgarCredito
    ? allCreditOpts
    : allCreditOpts.filter(o=>+o.value<=clientCreditMax);

  React.useEffect(()=>{
    if(!initialQuote && clientId){
      const c=(contacts||[]).find(cl=>cl.type==='cliente'&&cl.id===+clientId);
      if(c!=null) setCredit(c.credit??0);
    }
  },[clientId]);

  const filteredProds = (products||[]).filter(p=>(p.name||'').toLowerCase().includes(search.toLowerCase())||(p.brand||'').toLowerCase().includes(search.toLowerCase()));

  const getPrice = (p) => {
    const sp = (specialPrices||[]).find(x=>x.productId===p.id && x.clientId===+clientId);
    return {base: sp?sp.special:p.sell, special:!!sp, isSpecial:!!sp};
  };

  const addProduct = (p) => {
    if(lines.find(l=>l.pid===p.id)) return;
    const {base,isSpecial} = getPrice(p);
    const unit = isSpecial ? +base.toFixed(2) : +(base*f).toFixed(2);
    setLines(ls=>[...ls,{pid:p.id,name:p.name,um:p.um,qty:1,unit,base,special:isSpecial,total:unit,buyPrice:+(p.buy||0)}]);
    setSearch('');
  };

  const setLineQty = (pid,qty) => setLines(ls=>ls.map(l=>l.pid!==pid?l:{...l,qty:+qty,total:+(l.unit*(+qty)).toFixed(2)}));
  const setLineUnit = (pid,newUnit) => setLines(ls=>ls.map(l=>{
    if(l.pid!==pid) return l;
    const parsed = +newUnit;
    const minPrice = l.buyPrice||0;
    const clamped = (minPrice>0 && parsed<minPrice) ? minPrice : parsed;
    return {...l,unit:clamped,rawUnit:undefined,total:+(clamped*l.qty).toFixed(2),special:false};
  }));
  const setLineRaw = (pid,raw) => setLines(ls=>ls.map(l=>{
    if(l.pid!==pid) return l;
    const parsed = parseFloat(raw)||0;
    return {...l,rawUnit:raw,total:+(parsed*l.qty).toFixed(2)};
  }));
  const removeL = (pid) => setLines(ls=>ls.filter(l=>l.pid!==pid));

  const subtotal = lines.reduce((s,l)=>s+l.total,0);
  const igv = +(subtotal*0.18).toFixed(2);
  const total = +(subtotal+igv).toFixed(2);

  const next = () => setStep(s=>s+1);
  const back = () => setStep(s=>s-1);

  const save = async () => {
    setSaving(true);
    try {
      let cid = +clientId;
      if (isNew) {
        if (!newClient.name) return;
        const cr = await window.api('/contacts', {
          method: 'POST',
          body: JSON.stringify({
            type:'cliente', name:newClient.name, ruc:newClient.ruc||'',
            credit:+credit, email:newClient.email||'', phone:newClient.phone||'',
            attn:newClient.attn||'', direccion:'', note:''
          })
        });
        if (!cr || !cr.ok) return;
        const contact = await cr.json();
        if (setContacts) setContacts(cs=>[...cs,contact]);
        cid = contact.id;
      }
      if (!cid) return;
      if (isHistOp && !histOcNum) return;
      const res = await window.api('/quotes', {
        method: 'POST',
        body: JSON.stringify({
          clientId:cid, credit:+credit,
          subtotal:+subtotal.toFixed(2), igv, total,
          quoteDate: canEditarFechaCotiz ? quoteDate : undefined,
          items: lines.map(l=>({pid:l.pid,name:l.name,um:l.um,qty:l.qty,unit:l.unit,total:l.total,special:!!l.special})),
          initialStatus: isHistPast ? initialStatus : undefined,
          ocNum:       isHistOp ? histOcNum       : undefined,
          ocDate:      isHistOp ? histOcDate       : undefined,
          deliveryDate:isHistOp ? histDelivDate    : undefined,
          invoice:     initialStatus==='entregada' ? histInvoice : undefined,
        })
      });
      if (res && res.ok) {
        const q = await res.json();
        onSave(q);
        onClose();
      }
    } finally { setSaving(false); }
  };

  const steps = ['Cliente','Condiciones','Productos','Resumen'];

  return (
    <Modal title={initialQuote ? `Re-cotizar — ${initialQuote.id}` : 'Nueva Cotización'} onClose={onClose} width={700}>
      {/* Stepper */}
      <div style={{display:'flex',gap:0,marginBottom:22}}>
        {steps.map((s,i)=>(
          <div key={s} style={{display:'flex',alignItems:'center',flex:1}}>
            <div style={{display:'flex',alignItems:'center',gap:6}}>
              <div style={{width:22,height:22,borderRadius:'50%',background:step>i+1?G.accent:step===i+1?G.accent+'44':G.card2,border:`1px solid ${step>=i+1?G.accent:G.border}`,display:'flex',alignItems:'center',justifyContent:'center',fontSize:10,fontWeight:700,color:step>i+1?'#000':step===i+1?G.accent:G.textSec}}>{step>i+1?'✓':i+1}</div>
              <span style={{fontSize:11,color:step===i+1?G.accent:G.textSec,fontWeight:step===i+1?600:400}}>{s}</span>
            </div>
            {i<steps.length-1 && <div style={{flex:1,height:1,background:step>i+1?G.accent:G.border,margin:'0 8px'}}/>}
          </div>
        ))}
      </div>

      {step===1 && (
        <div>
          <div style={{display:'flex',gap:8,marginBottom:14}}>
            <Btn sm variant={!isNew?'primary':'ghost'} onClick={()=>setIsNew(false)}>Cliente existente</Btn>
            <Btn sm variant={isNew?'primary':'ghost'} onClick={()=>setIsNew(true)}>+ Crear nuevo</Btn>
          </div>
          {!isNew ? (
            <div>
              <FSelect label="Seleccionar cliente *" value={clientId} onChange={e=>setClientId(e.target.value)} options={[{value:'',label:'Seleccionar…'},...clients.map(c=>({value:c.id,label:`${c.name} — RUC ${c.ruc}`}))]}/>
              {selClient && (
                <div style={{background:G.bg,border:`1px solid ${G.border}`,borderRadius:6,padding:'10px 14px'}}>
                  <div style={{display:'flex',gap:16,flexWrap:'wrap'}}>
                    <div><div style={{...T.sm}}>RUC</div><div style={{fontSize:12,color:G.text}}>{selClient.ruc}</div></div>
                    <div><div style={{...T.sm}}>Atención</div><div style={{fontSize:12,color:G.text}}>{selClient.attn}</div></div>
                    <div><div style={{...T.sm}}>Crédito habitual</div><div><CreditBadge days={selClient.credit}/></div></div>
                    {selClient.hasSpecial && <div style={{display:'flex',alignItems:'center'}}><Tag label="⭐ Tiene precios especiales" color={G.warning}/></div>}
                  </div>
                </div>
              )}
            </div>
          ) : (
            <div>
              <Row><FInput label="Razón Social *" value={newClient.name} onChange={e=>setNewClient(n=>({...n,name:e.target.value}))}/><FInput label="RUC" value={newClient.ruc} onChange={e=>setNewClient(n=>({...n,ruc:e.target.value}))}/></Row>
              <Row><FInput label="Contacto (Atención)" value={newClient.attn} onChange={e=>setNewClient(n=>({...n,attn:e.target.value}))}/><FInput label="Teléfono" value={newClient.phone} onChange={e=>setNewClient(n=>({...n,phone:e.target.value}))}/></Row>
              <FInput label="Email" type="email" value={newClient.email} onChange={e=>setNewClient(n=>({...n,email:e.target.value}))}/>
            </div>
          )}
        </div>
      )}

      {step===2 && (
        <div>
          <FSelect label="Plazo de crédito *" value={credit} onChange={e=>setCredit(e.target.value)}
            options={creditOpts}
            disabled={!canOtorgarCredito && clientCreditMax===0}/>
          {canEditarFechaCotiz && (
            <div style={{marginBottom:14}}>
              <div style={{fontSize:11,color:G.textSec,marginBottom:4,textTransform:'uppercase',letterSpacing:0.5}}>Fecha de cotización</div>
              <input type="date" value={quoteDate} onChange={e=>{setQuoteDate(e.target.value);setInitialStatus('vigente');setHistOcNum('');setHistOcDate('');setHistDelivDate('');setHistInvoice('');}} max={todayISO}
                style={inputSt}/>
              {quoteDate !== todayISO && (
                <span style={{marginLeft:10,fontSize:11,color:G.warning}}>⚠ Fecha retroactiva — se registrará en ese mes</span>
              )}
            </div>
          )}
          {isHistPast && (
            <div style={{border:`1px solid ${G.border}`,borderRadius:6,padding:'12px 14px',marginBottom:14,background:G.bg}}>
              <div style={{fontSize:11,fontWeight:700,color:G.text,marginBottom:10,textTransform:'uppercase',letterSpacing:0.5}}>Estado inicial (historial)</div>
              <div style={{display:'flex',gap:8,marginBottom:isHistOp?12:0,flexWrap:'wrap'}}>
                {[['vigente','Vigente'],['aceptada','Aceptada'],['entregada','Entregada']].map(([v,l])=>(
                  <button key={v} onClick={()=>setInitialStatus(v)} style={{padding:'6px 16px',borderRadius:5,border:`1px solid ${initialStatus===v?G.accent:G.border}`,background:initialStatus===v?G.accent+'22':'transparent',color:initialStatus===v?G.accent:G.textSec,fontSize:12,fontWeight:initialStatus===v?700:400,cursor:'pointer'}}>{l}</button>
                ))}
              </div>
              {isHistOp && (
                <div>
                  <FInput label="N° de OC *" value={histOcNum} onChange={e=>setHistOcNum(e.target.value)} placeholder="Ej: OC-2026-001"/>
                  <Row>
                    <div>
                      <div style={{fontSize:11,color:G.textSec,marginBottom:4,textTransform:'uppercase',letterSpacing:0.5}}>Fecha de OC</div>
                      <input type="date" value={histOcDate} onChange={e=>setHistOcDate(e.target.value)} max={todayISO} style={inputSt}/>
                    </div>
                    <div>
                      <div style={{fontSize:11,color:G.textSec,marginBottom:4,textTransform:'uppercase',letterSpacing:0.5}}>Fecha de entrega</div>
                      <input type="date" value={histDelivDate} onChange={e=>setHistDelivDate(e.target.value)} max={todayISO} style={inputSt}/>
                    </div>
                  </Row>
                  {initialStatus==='entregada' && (
                    <FInput label="N° Factura (opcional)" value={histInvoice} onChange={e=>setHistInvoice(e.target.value)} placeholder="Ej: F001-00001" style={{marginTop:8}}/>
                  )}
                </div>
              )}
            </div>
          )}
          {!canOtorgarCredito && selClient && (
            <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:10,fontSize:12,color:G.textSec,flexWrap:'wrap'}}>
              <span>Crédito asignado al cliente:</span>
              <CreditBadge days={clientCreditMax}/>
              {clientCreditMax===0 && <span style={{color:G.warning,fontSize:11}}>(no se puede aumentar sin permiso)</span>}
            </div>
          )}
          <div style={{background:G.bg,border:`1px solid ${G.border}`,borderRadius:6,padding:'12px 16px'}}>
            <div style={{fontSize:12,color:G.textSec,marginBottom:10}}>Impacto en precios con plazo seleccionado:</div>
            <div style={{display:'flex',gap:24,flexWrap:'wrap'}}>
              {creditOpts.map(o=>(
                <div key={o.value} style={{textAlign:'center'}}>
                  <div style={{fontSize:10,color:+o.value===+credit?G.accent:G.textSec,fontWeight:+o.value===+credit?700:400}}>{+o.value===0?'Contado':`${o.value}d`}</div>
                  <div style={{fontSize:13,color:+o.value===+credit?G.accent:G.textSec,fontWeight:+o.value===+credit?700:400}}>+{((creditFactor(+o.value)-1)*100).toFixed(0)}%</div>
                </div>
              ))}
            </div>
          </div>
        </div>
      )}

      {step===3 && (
        <div>
          <input value={search} onChange={e=>setSearch(e.target.value)} placeholder="Buscar y agregar producto…" style={{background:G.bg,border:`1px solid ${G.border}`,borderRadius:5,color:G.text,padding:'7px 12px',fontSize:13,width:'100%',outline:'none',fontFamily:"'Inter',sans-serif",boxSizing:'border-box',marginBottom:8}}/>
          {search && (
            <div style={{background:G.bg,border:`1px solid ${G.border}`,borderRadius:6,marginBottom:10,maxHeight:140,overflowY:'auto'}}>
              {filteredProds.slice(0,6).map(p=>{
                const {base,isSpecial}=getPrice(p);
                const unit=isSpecial ? +base.toFixed(2) : +(base*f).toFixed(2);
                return (
                  <div key={p.id} onClick={()=>addProduct(p)} style={{display:'flex',justifyContent:'space-between',alignItems:'center',padding:'7px 12px',cursor:'pointer',borderBottom:`1px solid ${G.border}22`}} onMouseEnter={e=>e.currentTarget.style.background=G.card2} onMouseLeave={e=>e.currentTarget.style.background='transparent'}>
                    <div>
                      <div style={{fontSize:12,color:G.text}}>{p.name}</div>
                      <div style={{fontSize:10,color:G.textSec}}>{p.brand} · {p.um}</div>
                    </div>
                    <div style={{textAlign:'right'}}>
                      <div style={{color:G.accent,fontWeight:600,fontSize:12}}>{fmtS(unit)}</div>
                      {isSpecial && <Tag label="⭐ Esp." color={G.warning}/>}
                    </div>
                  </div>
                );
              })}
              {filteredProds.length===0 && <div style={{padding:12,color:G.textSec,fontSize:12}}>Sin resultados</div>}
            </div>
          )}
          {lines.length>0 && (
            <table style={{width:'100%',borderCollapse:'collapse'}}>
              <thead><tr>
                {['ITEM','DESCRIPCIÓN','U.M.','CANT.','P.UNIT.','TOTAL',''].map(h=><th key={h} style={{padding:'5px 8px',textAlign:'left',fontSize:9,color:G.textSec,fontWeight:700,textTransform:'uppercase',borderBottom:`1px solid ${G.border}`}}>{h}</th>)}
              </tr></thead>
              <tbody>
                {lines.map((l,i)=>(
                  <tr key={l.pid}>
                    <td style={{padding:'6px 8px',fontSize:12,color:G.textSec}}>{i+1}</td>
                    <td style={{padding:'6px 8px',fontSize:12,color:G.text}}>{l.name.length>36?l.name.substring(0,36)+'…':l.name}{l.special && <Tag label="⭐" color={G.warning}/>}</td>
                    <td style={{padding:'6px 8px',fontSize:11,color:G.textSec}}>{l.um}</td>
                    <td style={{padding:'6px 8px'}}><input type="number" min={1} value={l.qty} onChange={e=>setLineQty(l.pid,e.target.value)} style={{width:50,background:G.bg,border:`1px solid ${G.border}`,borderRadius:4,color:G.text,padding:'3px 6px',fontSize:12,textAlign:'center'}}/></td>
                    <td style={{padding:'6px 8px'}}>
                      {canAjustarPrecio
                        ? <input type="number" min={l.buyPrice||0} step="0.01" value={l.rawUnit!==undefined?l.rawUnit:l.unit}
                            onChange={e=>setLineRaw(l.pid,e.target.value)}
                            onBlur={e=>setLineUnit(l.pid,e.target.value)}
                            style={{width:72,background:G.bg,border:`1px solid ${G.accent}55`,borderRadius:4,color:G.accent,padding:'3px 6px',fontSize:12,fontWeight:600}}
                            title={l.buyPrice>0?`Precio mín. costo: S/ ${l.buyPrice.toFixed(2)}`:'Editar precio unitario'}/>
                        : <span style={{color:G.accent,fontWeight:600,fontSize:12}}>{fmtS(l.unit)}</span>
                      }
                    </td>
                    <td style={{padding:'6px 8px',fontSize:12,fontWeight:700,color:G.text}}>{fmtS(l.total)}</td>
                    <td style={{padding:'6px 8px'}}><button onClick={()=>removeL(l.pid)} style={{background:'none',border:'none',color:G.error,cursor:'pointer',fontSize:13}}>✕</button></td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
          {lines.length===0 && <div style={{color:G.textSec,fontSize:12,textAlign:'center',padding:20}}>Busca y agrega productos usando el campo de arriba</div>}
        </div>
      )}

      {step===4 && (
        <div>
          <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12,marginBottom:14}}>
            <div style={{background:G.bg,border:`1px solid ${G.border}`,borderRadius:6,padding:'10px 14px'}}>
              <div style={{...T.sm,marginBottom:6}}>Cliente</div>
              <div style={{fontSize:13,fontWeight:600,color:G.text}}>{isNew?newClient.name:selClient?.name}</div>
              <div style={{fontSize:11,color:G.textSec}}>RUC: {isNew?newClient.ruc:selClient?.ruc}</div>
            </div>
            <div style={{background:G.bg,border:`1px solid ${G.border}`,borderRadius:6,padding:'10px 14px'}}>
              <div style={{...T.sm,marginBottom:6}}>Condición</div>
              <CreditBadge days={+credit}/>
              <div style={{fontSize:11,color:G.textSec,marginTop:4}}>Recargo: +{((creditFactor(+credit)-1)*100).toFixed(0)}% sobre precio base</div>
            </div>
          </div>
          <table style={{width:'100%',borderCollapse:'collapse',marginBottom:12}}>
            <thead><tr style={{background:G.card2}}>
              {['#','DESCRIPCIÓN','U.M.','CANT.','P.UNIT.','TOTAL'].map(h=><th key={h} style={{padding:'7px 10px',textAlign:'left',fontSize:10,color:G.textSec,fontWeight:700,textTransform:'uppercase'}}>{h}</th>)}
            </tr></thead>
            <tbody>
              {lines.map((l,i)=>(
                <tr key={l.pid} style={{borderBottom:`1px solid ${G.border}22`}}>
                  <td style={{padding:'6px 10px',fontSize:12,color:G.textSec}}>{i+1}</td>
                  <td style={{padding:'6px 10px',fontSize:12,color:G.text}}>{l.name}{l.special&&<Tag label="⭐" color={G.warning}/>}</td>
                  <td style={{padding:'6px 10px',fontSize:11,color:G.textSec}}>{l.um}</td>
                  <td style={{padding:'6px 10px',fontSize:12}}>{l.qty}</td>
                  <td style={{padding:'6px 10px',fontSize:12,color:G.accent,fontWeight:600}}>{fmtS(l.unit)}</td>
                  <td style={{padding:'6px 10px',fontSize:12,fontWeight:700}}>{fmtS(l.total)}</td>
                </tr>
              ))}
            </tbody>
          </table>
          <div style={{display:'flex',justifyContent:'flex-end'}}>
            <div style={{width:240}}>
              {[['SUBTOTAL',fmtS(subtotal)],['IGV (18%)',fmtS(igv)]].map(([k,v])=>(
                <div key={k} style={{display:'flex',justifyContent:'space-between',padding:'5px 12px',borderBottom:`1px solid ${G.border}`}}>
                  <span style={{fontSize:12,color:G.textSec}}>{k}</span><span style={{fontSize:12,color:G.text}}>{v}</span>
                </div>
              ))}
              <div style={{display:'flex',justifyContent:'space-between',padding:'8px 12px',background:G.accentDark+'33',borderRadius:4,marginTop:4}}>
                <span style={{fontWeight:700,color:G.text}}>TOTAL</span><span style={{fontWeight:700,color:G.accent,fontSize:16}}>{fmtS(total)}</span>
              </div>
            </div>
          </div>
          {isHistOp && (
            <div style={{marginTop:10,padding:'10px 14px',background:G.warning+'18',border:`1px solid ${G.warning}44`,borderRadius:6,fontSize:11,color:G.warning}}>
              ⚠ Se registrará como <b style={{textTransform:'capitalize'}}>{initialStatus}</b>
              {initialStatus==='entregada' && ' — el stock se descontará automáticamente'}
              {histOcNum && <> · OC: <b>{histOcNum}</b></>}
              {histInvoice && <> · Factura: <b>{histInvoice}</b></>}
            </div>
          )}
          {!isHistOp && (
            <div style={{marginTop:14,padding:'10px 14px',background:G.bg,border:`1px solid ${G.border}`,borderRadius:6,fontSize:11,color:G.textSec}}>
              LOS PRECIOS ESTÁN EN SOLES (S/) — Vigencia: 5 días hábiles — Entrega: 24 hrs de recibida OC
            </div>
          )}
        </div>
      )}

      <div style={{display:'flex',justifyContent:'space-between',marginTop:20}}>
        <Btn variant="secondary" onClick={step===1?onClose:back}>{step===1?'Cancelar':'← Atrás'}</Btn>
        <div style={{display:'flex',gap:8}}>
          {step===4 && <Btn variant="ghost" onClick={save} disabled={saving}>{saving?'Guardando…':'💾 Solo Guardar'}</Btn>}
          {step<4 ? <Btn onClick={next} disabled={(step===1&&!isNew&&!clientId)||(step===2&&isHistOp&&!histOcNum)}>Siguiente →</Btn>
                  : <Btn onClick={save} disabled={saving}>{saving?'Guardando…':'✅ Guardar y Generar PDF'}</Btn>}
        </div>
      </div>
    </Modal>
  );
}

// ── ELIMINAR COTIZACIÓN — Modal de 3 pasos ────────────────────
function DeleteQuoteModal({ quote, onClose, onDeleted }) {
  const [step, setStep] = useState(1);
  const [revertStock, setRevertStock] = useState(null);
  const [reason, setReason] = useState('');
  const [saving, setSaving] = useState(false);

  const needsStockStep = !!quote.stockConfirmed;
  const hasInvoice = !!quote.invoice;

  const goNext = () => setStep(needsStockStep ? 2 : 3);

  const confirm = async () => {
    if (!reason.trim() || saving) return;
    setSaving(true);
    try {
      const res = await window.api(`/quotes/${quote.id}`, {
        method: 'DELETE',
        body: JSON.stringify({ reason: reason.trim(), revertStock: revertStock === true }),
      });
      if (res && res.ok) {
        onDeleted(quote.id, revertStock === true, reason.trim());
      } else {
        const err = await res?.json().catch(() => ({}));
        alert(err?.error || 'Error al eliminar la cotización');
      }
    } finally { setSaving(false); }
  };

  return (
    <div style={{position:'fixed',inset:0,background:'#000000d0',zIndex:1200,display:'flex',alignItems:'center',justifyContent:'center',padding:20}} onClick={onClose}>
      <div style={{background:G.card2,border:`1px solid ${G.border}`,borderRadius:10,width:'100%',maxWidth:500,boxShadow:'0 20px 60px #00000080'}} onClick={e=>e.stopPropagation()}>
        {/* Header */}
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',padding:'14px 22px',borderBottom:`1px solid ${G.border}`}}>
          <div>
            <div style={{fontFamily:"'Barlow Condensed',sans-serif",fontSize:20,fontWeight:700,color:G.error}}>ELIMINAR COTIZACIÓN</div>
            <div style={{fontSize:11,color:G.textSec}}>
              {step===1 && 'Paso 1 de ' + (needsStockStep?3:2) + ' — Confirmar eliminación'}
              {step===2 && 'Paso 2 de 3 — Stock en almacén'}
              {step===3 && `Paso ${needsStockStep?3:2} de ${needsStockStep?3:2} — Motivo`}
            </div>
          </div>
          <button onClick={onClose} style={{background:'none',border:'none',color:G.textSec,fontSize:18,cursor:'pointer',lineHeight:1,padding:4}}>✕</button>
        </div>

        <div style={{padding:'20px 22px'}}>
          {/* Step 1: Confirmation */}
          {step===1 && (
            <>
              <div style={{background:G.bg,border:`1px solid ${G.border}`,borderRadius:8,padding:'12px 16px',marginBottom:14}}>
                {[
                  ['N° Cotización', quote.id,    G.accent],
                  ['Cliente',       quote.client, G.text],
                  ['Monto',         fmtS(quote.total), G.accent],
                  ['Fecha',         quote.date,   null],
                  ['Estado',        (quote.status||'').charAt(0).toUpperCase()+(quote.status||'').slice(1), null],
                  hasInvoice ? ['Factura SUNAT', quote.invoice, '#29B6F6'] : null,
                ].filter(Boolean).map(([l,v,c])=>(
                  <div key={l} style={{display:'flex',justifyContent:'space-between',padding:'5px 0',borderBottom:`1px solid ${G.border}22`}}>
                    <span style={{fontSize:12,color:G.textSec}}>{l}</span>
                    <span style={{fontSize:12,fontWeight:600,color:c||G.text}}>{v}</span>
                  </div>
                ))}
              </div>
              {hasInvoice && (
                <div style={{background:G.warning+'22',border:`1px solid ${G.warning}44`,borderRadius:6,padding:'10px 14px',marginBottom:14,fontSize:12,color:G.warning}}>
                  ⚠️ Esta cotización tiene factura electrónica emitida. Recuerda anularla manualmente en SUNAT / Nubefact antes de proceder.
                </div>
              )}
              <div style={{background:G.error+'11',border:`1px solid ${G.error}33`,borderRadius:6,padding:'8px 12px',fontSize:12,color:G.textSec,marginBottom:16}}>
                Esta acción es <b style={{color:G.error}}>irreversible</b>. La cotización y sus ítems serán eliminados permanentemente.
              </div>
              <div style={{display:'flex',justifyContent:'flex-end',gap:8}}>
                <Btn variant="secondary" onClick={onClose}>Cancelar</Btn>
                <Btn variant="danger" onClick={goNext}>Continuar →</Btn>
              </div>
            </>
          )}

          {/* Step 2: Stock (only when stockConfirmed) */}
          {step===2 && (
            <>
              <div style={{background:G.bg,border:`1px solid ${G.border}`,borderRadius:8,padding:'20px 16px',marginBottom:16,textAlign:'center'}}>
                <div style={{fontSize:28,marginBottom:10}}>📦</div>
                <div style={{fontSize:14,fontWeight:600,color:G.text,marginBottom:6}}>¿Devolver stock al almacén?</div>
                <div style={{fontSize:12,color:G.textSec,maxWidth:340,margin:'0 auto'}}>
                  Esta cotización descontó stock de los productos. ¿Deseas revertir el inventario?
                </div>
              </div>
              <div style={{display:'flex',gap:10,marginBottom:4}}>
                <button onClick={()=>{setRevertStock(true);setStep(3);}} style={{flex:1,background:G.accent+'22',border:`1px solid ${G.accent}44`,color:G.accent,padding:'12px',borderRadius:6,fontSize:13,fontWeight:700,cursor:'pointer'}}>
                  ✅ Sí, devolver stock
                </button>
                <button onClick={()=>{setRevertStock(false);setStep(3);}} style={{flex:1,background:G.card,border:`1px solid ${G.border}`,color:G.textSec,padding:'12px',borderRadius:6,fontSize:13,fontWeight:600,cursor:'pointer'}}>
                  No, mantener
                </button>
              </div>
            </>
          )}

          {/* Step 3: Reason */}
          {step===3 && (
            <>
              {needsStockStep && (
                <div style={{background:G.bg,border:`1px solid ${G.border}`,borderRadius:6,padding:'8px 12px',fontSize:12,color:G.textSec,marginBottom:14}}>
                  Stock: {revertStock
                    ? <b style={{color:G.accent}}>✅ Se devolverá al almacén</b>
                    : <b style={{color:G.textSec}}>No se revertirá</b>}
                </div>
              )}
              <div style={{marginBottom:16}}>
                <div style={{fontSize:11,color:G.textSec,marginBottom:5}}>Motivo de eliminación <b style={{color:G.error}}>*</b></div>
                <textarea
                  autoFocus
                  value={reason}
                  onChange={e=>setReason(e.target.value)}
                  rows={3}
                  placeholder="Ej: Error en cotización, duplicado, solicitud del cliente…"
                  style={{width:'100%',background:G.bg,border:`1px solid ${reason.trim()?G.accent:G.border}`,borderRadius:5,color:G.text,padding:'8px 11px',fontSize:13,resize:'vertical',outline:'none',fontFamily:"'Inter',sans-serif",boxSizing:'border-box'}}
                />
                {!reason.trim() && <div style={{fontSize:11,color:G.error,marginTop:3}}>Campo obligatorio — no puede quedar vacío</div>}
              </div>
              <div style={{display:'flex',justifyContent:'flex-end',gap:8}}>
                <Btn variant="secondary" onClick={onClose}>Cancelar</Btn>
                <Btn variant="danger" onClick={confirm} disabled={!reason.trim()||saving}>
                  {saving ? 'Eliminando…' : '🗑️ Confirmar eliminación'}
                </Btn>
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

// ── COTIZACIONES ──────────────────────────────────────────────
function Cotizaciones({ quotes, setQuotes, contacts, setContacts, products, specialPrices, logActivity, currentUser }) {
  const [showNew, setShowNew] = useState(false);
  const [viewPDF, setViewPDF] = useState(null);
  const [viewNota, setViewNota] = useState(null);
  const [acceptOC, setAcceptOC] = useState(null);
  const [filter, setFilter] = useState('todos');
  const [rejectQ, setRejectQ] = useState(null);
  const [rejectReason, setRejectReason] = useState('');
  const [rejecting, setRejecting] = useState(false);
  const [recotizarQ, setRecotizarQ] = useState(null);
  const [deliverModal, setDeliverModal] = useState(null);
  const [requestAcceptOC, setRequestAcceptOC] = useState(null);
  const [requestDeliver, setRequestDeliver] = useState(false);
  const [deliverSerie, setDeliverSerie] = useState('F001');
  const [deliverNum, setDeliverNum] = useState('');
  const [searchInvoice, setSearchInvoice] = useState('');
  const [searchClient,  setSearchClient]  = useState('');
  const [deleteModal,   setDeleteModal]   = useState(null);
  const [stockLoading,  setStockLoading]  = useState(new Set());

  const isAdmin          = currentUser?.role === 'Administrador';
  const canSeeAll        = isAdmin || !!currentUser?.perms?.cotizaciones;
  const canCreate        = isAdmin || !!currentUser?.perms?.crearCotizacion;
  const canConfirmOC     = isAdmin || !!currentUser?.perms?.confirmarOC;
  const canDeliver       = isAdmin || !!currentUser?.perms?.entregar;
  const canConfirmStock  = isAdmin || !!currentUser?.perms?.almacen || !!currentUser?.perms?.entregar;
  const canDelete        = isAdmin || !!currentUser?.perms?.eliminarFacturas || !!currentUser?.perms?.eliminarOC || !!currentUser?.perms?.eliminarCotizaciones;

  const baseQuotes = canSeeAll
    ? (quotes||[])
    : (quotes||[]).filter(q => q.createdBy === currentUser?.username);

  const filters = ['todos','vigente','aceptada','entregada','rechazada','vencida'];
  const filtered = baseQuotes
    .filter(q=>filter==='todos'||q.status===filter)
    .filter(q=>!searchInvoice||(q.invoice||'').toLowerCase().includes(searchInvoice.toLowerCase()))
    .filter(q=>!searchClient||(q.client||'').toLowerCase().includes(searchClient.toLowerCase()));

  const replaceQuote = (updated) => setQuotes(qs=>qs.map(q=>q.id===updated.id?updated:q));

  const addQuote = (q) => {
    setQuotes(qs=>[q,...qs]);
    if(logActivity) logActivity('Creó cotización','Cotizaciones',`${q.id} para ${q.client} — ${window.fmtS(q.total)}`);
  };

  const deliver = (q, asRequest=false) => { setDeliverModal(q); setDeliverNum(''); setDeliverSerie('F001'); setRequestDeliver(asRequest); };

  const doDeliver = async () => {
    if (!deliverModal || !deliverNum.trim()) return;
    const invoice = `${deliverSerie}-${deliverNum.trim()}`;
    const res = requestDeliver
      ? await window.api('/operation-requests', {method:'POST', body:JSON.stringify({quoteId:deliverModal.id,type:'deliver_invoice',payload:{invoice}})})
      : await window.api(`/quotes/${deliverModal.id}/deliver`, {method:'PUT', body:JSON.stringify({invoice})});
    if (res && res.ok) {
      if (requestDeliver) {
        alert('Solicitud enviada para entregar y facturar.');
      } else {
        const updated = await res.json();
        replaceQuote(updated);
        if(logActivity) logActivity('Entregó pedido','Cotizaciones',`Cotización ${deliverModal.id} — Factura ${invoice}`);
      }
    }
    setDeliverModal(null); setDeliverNum(''); setRequestDeliver(false);
  };

  const confirmStock = async (q) => {
    if (stockLoading.has(q.id)) return;
    setStockLoading(s => new Set([...s, q.id]));
    try {
      const res = await window.api(`/quotes/${q.id}/confirm-stock`, {method:'PUT'});
      if (res && res.ok) {
        const updated = await res.json();
        replaceQuote(updated);
        if(logActivity) logActivity('Desconto stock','Cotizaciones',`Stock descontado para ${q.id}`);
      } else if (res) {
        const err = await res.json().catch(()=>({}));
        alert(err.error || 'Error al descontar stock');
      }
    } finally {
      setStockLoading(s => { const ns = new Set(s); ns.delete(q.id); return ns; });
    }
  };

  const reject = async () => {
    if (!rejectQ || !rejectReason.trim()) return;
    setRejecting(true);
    try {
      const res = await window.api(`/quotes/${rejectQ.id}`, {
        method:'PUT',
        body: JSON.stringify({status:'rechazada', rejectionReason: rejectReason.trim()})
      });
      if (res && res.ok) {
        const updated = await res.json();
        replaceQuote(updated);
        if(logActivity) logActivity('Rechazó cotización','Cotizaciones',`${rejectQ.id} — ${rejectReason.trim()}`);
        setRejectQ(null); setRejectReason('');
      }
    } finally { setRejecting(false); }
  };

  const cols = [
    {key:'id',label:'N° Cotización',w:140,render:q=><span style={{color:G.accent,fontWeight:600,cursor:'pointer'}} onClick={()=>setViewPDF(q)}>{q.id}</span>},
    {key:'date',label:'Fecha',w:100},
    {key:'client',label:'Cliente',render:q=><span style={{fontWeight:500}}>{q.client}</span>},
    {key:'credit',label:'Plazo',w:90,render:q=><CreditBadge days={q.credit}/>},
    {key:'total',label:'Total',w:120,render:q=><span style={{fontWeight:700,color:G.accent}}>{fmtS(q.total)}</span>},
    {key:'status',label:'Estado',w:130,render:q=>(
      <div>
        <StatusBadge status={q.status}/>
        {q.rejectionReason && <div style={{fontSize:10,color:G.textSec,marginTop:2,maxWidth:120,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}} title={q.rejectionReason}>{q.rejectionReason}</div>}
      </div>
    )},
    {key:'vigencia',label:'Vigencia',w:80,render:q=>(q.status==='vigente'?<DaysBadge days={q.daysLeft}/>:<span style={{color:G.textSec,fontSize:11}}>—</span>)},
    {key:'invoice',label:'Factura',w:110,render:q=>(q.invoice?<span style={{color:'#29B6F6',fontSize:11,fontWeight:600}}>{q.invoice}</span>:<span style={{color:G.textSec,fontSize:11}}>—</span>)},
    {key:'actions',label:'',render:q=>(
      <div style={{display:'flex',gap:4,flexWrap:'wrap',justifyContent:'flex-end'}}>
        <Btn sm variant="ghost" onClick={e=>{e.stopPropagation();setViewPDF(q);}}>📄</Btn>
        {(q.status==='aceptada'||q.status==='entregada') && <Btn sm variant="ghost" onClick={e=>{e.stopPropagation();setViewNota(q);}}>📋</Btn>}
        {q.status==='vigente' && (canConfirmOC
          ? <Btn sm variant="accent" onClick={e=>{e.stopPropagation();setAcceptOC(q);}}>✓ OC</Btn>
          : <Btn sm variant="ghost" onClick={e=>{e.stopPropagation();setRequestAcceptOC(q);}}>Solicitar OC</Btn>)}
        {q.status==='aceptada' && !q.stockConfirmed && canConfirmStock && <Btn sm variant="ghost" disabled={stockLoading.has(q.id)} onClick={e=>{e.stopPropagation();confirmStock(q);}} title="Descontar stock del almacén">{stockLoading.has(q.id)?'⏳':'📦 Stock'}</Btn>}
        {q.status==='aceptada' && q.stockConfirmed && <span style={{fontSize:10,color:G.accent,padding:'2px 6px',background:G.accent+'11',borderRadius:3}}>✓ Stock</span>}
        {q.status==='aceptada' && (canDeliver
          ? <Btn sm variant="primary" onClick={e=>{e.stopPropagation();deliver(q);}}>📦 Entregar</Btn>
          : <Btn sm variant="ghost" onClick={e=>{e.stopPropagation();deliver(q,true);}}>Solicitar factura</Btn>)}
        {(q.status==='vigente'||q.status==='aceptada') && (isAdmin||q.createdBy===currentUser?.username) && <Btn sm variant="danger" onClick={e=>{e.stopPropagation();setRejectQ(q);setRejectReason('');}}>✕ Rechazar</Btn>}
        {q.status==='rechazada' && canCreate && <Btn sm variant="ghost" onClick={e=>{e.stopPropagation();setRecotizarQ(q);}}>↻ Re-cotizar</Btn>}
        {canDelete && <Btn sm variant="danger" style={{padding:'3px 7px',opacity:0.75}} onClick={e=>{e.stopPropagation();setDeleteModal(q);}}>🗑️</Btn>}
      </div>
    )},
  ];


  return (
    <div>
      <PageHeader title="COTIZACIONES" subtitle={`${filtered.length} cotizaciones`} action={canCreate && <Btn onClick={()=>setShowNew(true)}>+ Nueva Cotización</Btn>}/>
      <div style={{display:'flex',gap:8,marginBottom:12,flexWrap:'wrap',alignItems:'center'}}>
        <div style={{display:'flex',gap:6,flexWrap:'wrap',flex:1}}>
          {filters.map(f=>(
            <button key={f} onClick={()=>setFilter(f)} style={{background:filter===f?G.accent+'22':G.card2,border:`1px solid ${filter===f?G.accent:G.border}`,color:filter===f?G.accent:G.textSec,padding:'5px 12px',borderRadius:4,fontSize:12,fontWeight:600,cursor:'pointer',textTransform:'capitalize'}}>
              {f==='todos'?'Todos':f.charAt(0).toUpperCase()+f.slice(1)}
            </button>
          ))}
        </div>
        <div style={{display:'flex',alignItems:'center',gap:6,flexShrink:0}}>
          <span style={{fontSize:11,color:G.textSec}}>👤 Cliente:</span>
          <input value={searchClient} onChange={e=>setSearchClient(e.target.value)} placeholder="Buscar cliente…" style={{background:G.card2,border:`1px solid ${searchClient?G.accent:G.border}`,borderRadius:5,color:G.text,padding:'5px 10px',fontSize:12,outline:'none',width:150}}/>
          {searchClient && <button onClick={()=>setSearchClient('')} style={{background:'none',border:'none',color:G.textSec,cursor:'pointer',fontSize:13,padding:'0 2px'}}>✕</button>}
        </div>
        <div style={{display:'flex',alignItems:'center',gap:6,flexShrink:0}}>
          <span style={{fontSize:11,color:G.textSec}}>🔍 N° Factura:</span>
          <input value={searchInvoice} onChange={e=>setSearchInvoice(e.target.value)} placeholder="F001-00001" style={{background:G.card2,border:`1px solid ${searchInvoice?G.accent:G.border}`,borderRadius:5,color:G.text,padding:'5px 10px',fontSize:12,outline:'none',width:130}}/>
          {searchInvoice && <button onClick={()=>setSearchInvoice('')} style={{background:'none',border:'none',color:G.textSec,cursor:'pointer',fontSize:13,padding:'0 2px'}}>✕</button>}
        </div>
      </div>
      <Card noPad>
        <Table cols={cols} rows={filtered} emptyMsg="No hay cotizaciones para el filtro seleccionado"/>
      </Card>
      {(showNew||recotizarQ) && <NewQuoteWizard contacts={contacts} setContacts={setContacts} products={products} specialPrices={specialPrices} onSave={addQuote} onClose={()=>{setShowNew(false);setRecotizarQ(null);}} initialQuote={recotizarQ||null} currentUser={currentUser}/>}
      {viewPDF && <QuotePDF quote={viewPDF} contacts={contacts} onClose={()=>setViewPDF(null)}/>}
      {viewNota && <NotaEntrega quote={viewNota} contacts={contacts} onClose={()=>setViewNota(null)}/>}
      {acceptOC && <AcceptOCModal quote={acceptOC} onSave={(updated)=>{
        replaceQuote(updated);
        if(logActivity) logActivity('Aceptó OC','Cotizaciones',`Cotización ${updated.id}`);
      }} onClose={()=>setAcceptOC(null)}/>}
      {requestAcceptOC && <AcceptOCModal quote={requestAcceptOC} requestMode onSave={()=>{}} onClose={()=>setRequestAcceptOC(null)}/>}
      {deleteModal && (
        <DeleteQuoteModal
          quote={deleteModal}
          onClose={()=>setDeleteModal(null)}
          onDeleted={(id, reverted, rsn) => {
            setQuotes(qs=>qs.filter(q=>q.id!==id));
            if(logActivity) logActivity('Eliminó cotización','Cotizaciones',`${id} — Motivo: ${rsn}${reverted?' — Stock revertido':''}`);
            setDeleteModal(null);
          }}
        />
      )}
      {rejectQ && (
        <Modal title={`Rechazar — ${rejectQ.id}`} onClose={()=>setRejectQ(null)} width={460}>
          <div style={{fontSize:12,color:G.textSec,marginBottom:14}}>
            Cotización a <b style={{color:G.text}}>{rejectQ.client}</b> por <b style={{color:G.accent}}>{fmtS(rejectQ.total)}</b>
          </div>
          <FTextarea label="Motivo del rechazo *" value={rejectReason} onChange={e=>setRejectReason(e.target.value)} rows={3} placeholder="Ej: El cliente optó por otro proveedor…"/>
          <div style={{display:'flex',justifyContent:'flex-end',gap:8,marginTop:8}}>
            <Btn variant="secondary" onClick={()=>setRejectQ(null)}>Cancelar</Btn>
            <Btn variant="danger" onClick={reject} disabled={rejecting||!rejectReason.trim()}>{rejecting?'Guardando…':'Confirmar Rechazo'}</Btn>
          </div>
        </Modal>
      )}
      {deliverModal && (
        <Modal title={`${requestDeliver?'Solicitar facturación':'Emitir Factura'} — ${deliverModal.id}`} onClose={()=>{setDeliverModal(null);setDeliverNum('');setRequestDeliver(false);}} width={480}>
          <div style={{background:G.bg,border:`1px solid ${G.border}`,borderRadius:6,padding:'12px 16px',marginBottom:16}}>
            <div style={{display:'flex',justifyContent:'space-between',marginBottom:4}}><span style={{color:G.textSec,fontSize:12}}>Cotización</span><span style={{color:G.accent,fontWeight:600}}>{deliverModal.id}</span></div>
            <div style={{display:'flex',justifyContent:'space-between',marginBottom:4}}><span style={{color:G.textSec,fontSize:12}}>Cliente</span><span style={{fontWeight:600}}>{deliverModal.client}</span></div>
            <div style={{display:'flex',justifyContent:'space-between'}}><span style={{color:G.textSec,fontSize:12}}>Total</span><span style={{color:G.accent,fontWeight:700,fontSize:15}}>{fmtS(deliverModal.total)}</span></div>
          </div>
          <Row>
            <div>
              <div style={{fontSize:11,color:G.textSec,marginBottom:4}}>Serie</div>
              <select value={deliverSerie} onChange={e=>setDeliverSerie(e.target.value)} style={{background:'#0A0A0A',border:`1px solid ${G.border}`,borderRadius:5,color:G.text,padding:'7px 11px',fontSize:13,width:'100%',outline:'none'}}>
                <option>F001</option><option>F002</option><option>B001</option>
              </select>
            </div>
            <div style={{flex:1}}>
              <div style={{fontSize:11,color:G.textSec,marginBottom:4}}>N° Correlativo *</div>
              <input value={deliverNum} onChange={e=>setDeliverNum(e.target.value)} placeholder="00001" style={{background:'#0A0A0A',border:`1px solid ${deliverNum?G.accent:G.border}`,borderRadius:5,color:G.text,padding:'7px 11px',fontSize:13,width:'100%',outline:'none',boxSizing:'border-box'}}/>
            </div>
          </Row>
          {deliverNum.trim() && (
            <div style={{background:G.accent+'11',border:`1px solid ${G.accent}33`,borderRadius:6,padding:'8px 12px',fontSize:12,color:G.textSec,marginBottom:4}}>
              N° Factura: <b style={{color:G.accent}}>{deliverSerie}-{deliverNum.trim()}</b>
            </div>
          )}
          <div style={{display:'flex',justifyContent:'flex-end',gap:8,marginTop:12}}>
            <Btn variant="secondary" onClick={()=>{setDeliverModal(null);setDeliverNum('');setRequestDeliver(false);}}>Cancelar</Btn>
            <Btn onClick={doDeliver} disabled={!deliverNum.trim()}>{requestDeliver?'Enviar solicitud':'✅ Confirmar Entrega'}</Btn>
          </div>
        </Modal>
      )}
    </div>
  );
}

// ── PRECIOS ESPECIALES ────────────────────────────────────────
function PreciosEspeciales({ specialPrices, setSpecialPrices, contacts, products, currentUser }) {
  const [selClient, setSelClient] = useState('');
  const [showModal, setShowModal] = useState(false);
  const [form, setForm] = useState({productId:'',special:'',expiry:'31/12/2026'});
  const [saving, setSaving] = useState(false);
  const sf = (k,v) => setForm(f=>({...f,[k]:v}));

  const isAdmin = currentUser?.role === 'Administrador';
  const hasPrecEspAll = isAdmin || !!currentUser?.perms?.precEspAll;

  // Si no tiene precEspAll, solo ve sus clientes de cartera
  const clients = hasPrecEspAll
    ? (contacts||[]).filter(c=>c.type==='cliente')
    : (contacts||[]).filter(c=>c.type==='cliente' && c.ownerId===currentUser?.id);
  const effectiveClient = selClient || (clients[0]?.id||'');
  const myPrices = (specialPrices||[]).filter(sp=>sp.clientId===+effectiveClient);
  const client = clients.find(c=>c.id===+effectiveClient);

  const save = async () => {
    const prod = (products||[]).find(p=>p.id===+form.productId);
    if(!prod||!form.special||!effectiveClient) return;
    setSaving(true);
    try {
      const res = await window.api('/special-prices', {
        method: 'POST',
        body: JSON.stringify({clientId:+effectiveClient, productId:+form.productId, special:+form.special, expiry:form.expiry||'31/12/2026'})
      });
      if (res && res.ok) {
        const created = await res.json();
        setSpecialPrices(sp=>[...sp.filter(x=>!(x.clientId===+effectiveClient&&x.productId===+form.productId)), created]);
        setShowModal(false); setForm({productId:'',special:'',expiry:'31/12/2026'});
      }
    } finally { setSaving(false); }
  };

  const del = async (id) => {
    const res = await window.api(`/special-prices/${id}`, {method:'DELETE'});
    if (res && res.ok) setSpecialPrices(sp=>sp.filter(x=>x.id!==id));
  };

  const cols = [
    {key:'product',label:'Producto',render:r=><span style={{fontSize:12}}>{r.product}</span>},
    {key:'std',label:'P. Estándar',w:110,render:r=><span style={{color:G.textSec}}>{fmtS(r.std)}</span>},
    {key:'special',label:'P. Especial',w:110,render:r=><span style={{color:G.accent,fontWeight:700}}>{fmtS(r.special)}</span>},
    {key:'diff',label:'Descuento',w:100,render:r=>{
      const pct=(((r.std-r.special)/r.std)*100).toFixed(1);
      return <span style={{color:G.error,fontSize:12}}>-{pct}%</span>;
    }},
    {key:'expiry',label:'Vigencia',w:100,render:r=><span style={{fontSize:11,color:G.textSec}}>{r.expiry}</span>},
    {key:'del',label:'',w:50,render:r=><Btn sm variant="danger" onClick={()=>del(r.id)}>✕</Btn>},
  ];

  return (
    <div>
      <PageHeader title="PRECIOS ESPECIALES" subtitle="Precios personalizados por cliente"/>
      <div style={{display:'flex',gap:12,alignItems:'center',marginBottom:20}}>
        <FSelect label="" value={effectiveClient} onChange={e=>setSelClient(e.target.value)} options={clients.map(c=>({value:c.id,label:`${c.name} — RUC ${c.ruc}`}))}/>
        <Btn onClick={()=>setShowModal(true)} style={{flexShrink:0}}>+ Agregar Precio Especial</Btn>
      </div>
      {client && (
        <div style={{background:G.card,border:`1px solid ${G.border}`,borderRadius:8,padding:'12px 18px',marginBottom:16,display:'flex',gap:24,flexWrap:'wrap'}}>
          <div><div style={{...T.sm}}>Cliente</div><div style={{fontSize:13,fontWeight:600,color:G.text}}>{client.name}</div></div>
          <div><div style={{...T.sm}}>RUC</div><div style={{fontSize:13,color:G.text}}>{client.ruc}</div></div>
          <div><div style={{...T.sm}}>Crédito habitual</div><CreditBadge days={client.credit}/></div>
          <div><div style={{...T.sm}}>Precios especiales activos</div><div style={{fontSize:13,fontWeight:700,color:G.accent}}>{myPrices.length}</div></div>
        </div>
      )}
      <Card noPad><Table cols={cols} rows={myPrices} emptyMsg="No hay precios especiales para este cliente"/></Card>
      {showModal && (
        <Modal title="Agregar Precio Especial" onClose={()=>setShowModal(false)} width={460}>
          <FSelect label="Producto *" value={form.productId} onChange={e=>sf('productId',e.target.value)} options={[{value:'',label:'Seleccionar producto…'},...(products||[]).map(p=>({value:p.id,label:`${p.name} — S/ ${p.sell}`}))]}/>
          {form.productId && <div style={{...T.sm,marginBottom:8}}>Precio estándar: <b style={{color:G.text}}>{fmtS((products||[]).find(p=>p.id===+form.productId)?.sell||0)}</b></div>}
          <FInput label="Precio especial (S/) *" type="number" value={form.special} onChange={e=>sf('special',e.target.value)} placeholder="0.00"/>
          {form.special&&form.productId && (() => {
            const std=(products||[]).find(p=>p.id===+form.productId)?.sell||0;
            const pct=(((std-+form.special)/std)*100).toFixed(1);
            return <div style={{color:G.error,fontSize:12,marginBottom:12}}>Descuento: -{pct}% sobre precio base</div>;
          })()}
          <FInput label="Vigencia (DD/MM/YYYY)" value={form.expiry} onChange={e=>sf('expiry',e.target.value)} placeholder="31/12/2026"/>
          <div style={{display:'flex',justifyContent:'flex-end',gap:8}}>
            <Btn variant="secondary" onClick={()=>setShowModal(false)}>Cancelar</Btn>
            <Btn onClick={save} disabled={saving}>{saving?'Guardando…':'Guardar'}</Btn>
          </div>
        </Modal>
      )}
    </div>
  );
}

// ── FACTURACIÓN ───────────────────────────────────────────────
function Facturacion({ quotes, setQuotes, contacts, currentUser, logActivity }) {
  const [viewNota, setViewNota] = useState(null);
  const [viewPDF, setViewPDF] = useState(null);
  const [invoiceModal, setInvoiceModal] = useState(null);
  const [deleteModal, setDeleteModal] = useState(null);
  const [serie, setSerie] = useState('F001');
  const [num, setNum] = useState('');
  const isAdminFact = currentUser?.role === 'Administrador';
  const canDelete     = isAdminFact || !!currentUser?.perms?.eliminarOC || !!currentUser?.perms?.eliminarFacturas;
  const canManagePay  = isAdminFact || !!currentUser?.perms?.gestionarPagos || !!currentUser?.perms?.contabilidad;

  const payCobrar = async (q) => {
    console.log('[Cobrar] Marcando pagada:', q.id);
    const res = await window.api(`/quotes/${q.id}/pay`, {method:'PUT'});
    console.log('[Cobrar] Respuesta:', res?.status, res?.ok);
    if(res && res.ok) {
      const updated = await res.json();
      setQuotes(qs=>qs.map(x=>x.id===q.id?updated:x));
      if(logActivity) logActivity('Marcó como pagada','Facturación',`Factura ${q.invoice||q.id} — ${fmtS(q.total)}`);
      if(window.refreshDashboard) window.refreshDashboard();
    } else if (res) {
      const err = await res.json().catch(()=>({}));
      console.error('[Cobrar] Error:', err);
      alert(err.error || `Error al marcar como pagada (${res.status})`);
    }
  };
  const unpayFn = async (q) => {
    console.log('[Unpay] Revirtiendo pago:', q.id);
    const res = await window.api(`/quotes/${q.id}/unpay`, {method:'PUT'});
    console.log('[Unpay] Respuesta:', res?.status, res?.ok);
    if(res && res.ok) {
      const updated = await res.json();
      setQuotes(qs=>qs.map(x=>x.id===q.id?updated:x));
      if(logActivity) logActivity('Revirtió a pendiente','Facturación',`Factura ${q.invoice||q.id} — ${fmtS(q.total)}`);
      if(window.refreshDashboard) window.refreshDashboard();
    } else if (res) {
      const err = await res.json().catch(()=>({}));
      console.error('[Unpay] Error:', err);
      alert(err.error || `Error al revertir pago (${res.status})`);
    }
  };
  const [filterYear,  setFilterYear]  = useState('todos');
  const [filterMonth, setFilterMonth] = useState('todos');
  const [filterClient,setFilterClient]= useState('todos');
  const [searchInv, setSearchInv] = useState('');

  const allAccepted = (quotes||[]).filter(q=>q.status==='aceptada'||q.status==='entregada');
  const clientes = (contacts||[]).filter(c=>c.type==='cliente');
  const MMAP = {'01':'Ene','02':'Feb','03':'Mar','04':'Abr','05':'May','06':'Jun','07':'Jul','08':'Ago','09':'Sep','10':'Oct','11':'Nov','12':'Dic'};
  const MONTHS = ['todos','Ene','Feb','Mar','Abr','May','Jun','Jul','Ago','Sep','Oct','Nov','Dic'];

  // Años disponibles en las cotizaciones
  const availYears = ['todos',...[...new Set(allAccepted.map(q=>{
    const d=(q.deliveryDate||q.date||'').split('/')[2];
    return d||'';
  }).filter(Boolean))].sort((a,b)=>+b-+a)];

  const accepted = allAccepted.filter(q=>{
    const dateStr = q.deliveryDate||q.date||'';
    const parts = dateStr.split('/');
    const qm = parts[1]||null;
    const qy = parts[2]||null;
    const matchMonth  = filterMonth==='todos' || MMAP[qm]===filterMonth;
    const matchYear   = filterYear==='todos'  || qy===filterYear;
    const matchClient = filterClient==='todos' || String(q.clientId)===filterClient;
    const matchInv    = !searchInv || (q.invoice||'').toLowerCase().includes(searchInv.toLowerCase()) || q.id.toLowerCase().includes(searchInv.toLowerCase());
    return matchMonth && matchYear && matchClient && matchInv;
  });

  const hasFilter = filterYear!=='todos'||filterMonth!=='todos'||filterClient!=='todos'||!!searchInv;
  const selectSt = {background:'#1A1A1A',border:`1px solid ${G.border}`,color:G.text,padding:'4px 8px',borderRadius:5,fontSize:12,cursor:'pointer'};

  const filterBar = (
    <div style={{display:'flex',gap:8,alignItems:'center',flexWrap:'wrap',marginBottom:14}}>
      <select value={filterYear} onChange={e=>setFilterYear(e.target.value)} style={selectSt}>
        {availYears.map(y=><option key={y} value={y}>{y==='todos'?'Todos los años':y}</option>)}
      </select>
      <select value={filterMonth} onChange={e=>setFilterMonth(e.target.value)} style={selectSt}>
        {MONTHS.map(m=><option key={m} value={m}>{m==='todos'?'Todos los meses':m}</option>)}
      </select>
      <select value={filterClient} onChange={e=>setFilterClient(e.target.value)} style={selectSt}>
        <option value="todos">Todos los clientes</option>
        {clientes.map(c=><option key={c.id} value={String(c.id)}>{c.name}</option>)}
      </select>
      <div style={{display:'flex',alignItems:'center',gap:4}}>
        <span style={{fontSize:11,color:G.textSec}}>🔍</span>
        <input value={searchInv} onChange={e=>setSearchInv(e.target.value)} placeholder="N° Factura o COT…" style={{background:'#1A1A1A',border:`1px solid ${searchInv?G.accent:G.border}`,borderRadius:5,color:G.text,padding:'4px 8px',fontSize:12,outline:'none',width:160}}/>
        {searchInv && <button onClick={()=>setSearchInv('')} style={{background:'none',border:'none',color:G.textSec,cursor:'pointer',fontSize:12}}>✕</button>}
      </div>
      {hasFilter && (
        <button onClick={()=>{setFilterYear('todos');setFilterMonth('todos');setFilterClient('todos');setSearchInv('');}} style={{background:G.error+'22',border:`1px solid ${G.error}44`,color:G.error,padding:'4px 8px',borderRadius:5,fontSize:11,cursor:'pointer'}}>
          ✕ Limpiar
        </button>
      )}
    </div>
  );

  const emitir = async (q) => {
    if (!num.trim()) return;
    const invoiceNum = `${serie}-${num.trim()}`;
    const res = await window.api(`/quotes/${q.id}/deliver`, {method:'PUT', body:JSON.stringify({invoice:invoiceNum})});
    if (res && res.ok) {
      const updated = await res.json();
      setQuotes(qs=>qs.map(x=>x.id===q.id?updated:x));
    }
    setInvoiceModal(null); setNum('');
  };

  const cols = [
    {key:'id',label:'Cotización',w:140,render:q=><span style={{color:G.accent,fontWeight:600,cursor:'pointer'}} onClick={()=>setViewPDF(q)}>{q.id}</span>},
    {key:'date',label:'Fecha OC',w:100,render:q=><span>{q.ocDate||q.date}</span>},
    {key:'client',label:'Cliente',render:q=><span style={{fontWeight:500}}>{q.client}</span>},
    {key:'createdBy',label:'Vendedor',w:90,render:q=><span style={{fontSize:11,color:G.textSec}}>{q.createdBy||'—'}</span>},
    {key:'credit',label:'Plazo',w:90,render:q=><CreditBadge days={q.credit}/>},
    {key:'deliveryDate',label:'Entrega',w:100,render:q=><span style={{fontSize:11}}>{q.deliveryDate||'—'}</span>},
    {key:'total',label:'Total',w:120,render:q=><span style={{fontWeight:700,color:G.accent}}>{fmtS(q.total)}</span>},
    {key:'dueDate',label:'Vence cobro',w:110,render:q=>(
      q.dueDate ? <span style={{fontSize:11,color:q.daysLeft<7?G.error:G.textSec}}>{q.dueDate}</span> : <span style={{color:G.textSec}}>—</span>
    )},
    {key:'invoice',label:'Factura',w:130,render:q=>(
      q.invoice
        ? <span style={{color:'#29B6F6',fontWeight:600,fontSize:12}}>{q.invoice} ✓</span>
        : <Btn sm variant="primary" onClick={e=>{e.stopPropagation();setInvoiceModal(q);}}>Emitir Factura</Btn>
    )},
    {key:'pago',label:'Cobro',w:120,render:q=>{
      if(q.credit===0||q.paidAt)
        return <div style={{display:'flex',alignItems:'center',gap:4}}>
          <span style={{background:G.accent+'22',color:G.accent,padding:'2px 7px',borderRadius:3,fontSize:11,fontWeight:600}}>✅ Pagado</span>
          {q.paidAt && canManagePay && (!q.paymentLocked || isAdminFact) && <Btn sm variant="ghost" style={{color:G.error,borderColor:G.error+'55',padding:'2px 6px'}} onClick={e=>{e.stopPropagation();unpayFn(q);}}>↩️</Btn>}
          {q.paidAt && q.paymentLocked && !isAdminFact && <span style={{color:G.textSec,fontSize:10}}>Bloqueado</span>}
        </div>;
      return canManagePay
        ? <Btn sm variant="accent" onClick={e=>{e.stopPropagation();payCobrar(q);}}>✅ Cobrar</Btn>
        : <span style={{color:G.textSec,fontSize:11}}>Pendiente</span>;
    }},
    {key:'nota',label:'',w:100,render:q=>(<Btn sm variant="ghost" onClick={e=>{e.stopPropagation();setViewNota(q);}}>📋 Entrega</Btn>)},
    {key:'pdf',label:'',w:50,render:q=><Btn sm variant="ghost" onClick={e=>{e.stopPropagation();setViewPDF(q);}}>📄</Btn>},
    {key:'del',label:'',w:44,render:q=>canDelete?<Btn sm variant="danger" style={{padding:'3px 7px',opacity:0.75}} onClick={e=>{e.stopPropagation();setDeleteModal(q);}}>🗑️</Btn>:null},
  ];

  const sinFactura = accepted.filter(q=>!q.invoice).length;
  const conFactura = accepted.filter(q=>q.invoice).length;

  return (
    <div>
      <PageHeader title="FACTURACIÓN" subtitle="Cotizaciones con Orden de Compra confirmada"/>
      {filterBar}
      <div style={{display:'flex',gap:12,marginBottom:18}}>
        <div style={{background:G.card,border:`1px solid ${G.warning}44`,borderRadius:8,padding:'12px 20px',display:'flex',gap:20,alignItems:'center'}}>
          <div style={{textAlign:'center'}}><div style={{fontSize:26,fontWeight:700,color:G.warning,fontFamily:"'Barlow Condensed',sans-serif"}}>{sinFactura}</div><div style={{fontSize:10,color:G.textSec}}>Pendientes de facturar</div></div>
          <div style={{width:1,background:G.border}}/>
          <div style={{textAlign:'center'}}><div style={{fontSize:26,fontWeight:700,color:G.accent,fontFamily:"'Barlow Condensed',sans-serif"}}>{conFactura}</div><div style={{fontSize:10,color:G.textSec}}>Facturadas</div></div>
          <div style={{width:1,background:G.border}}/>
          <div style={{textAlign:'center'}}><div style={{fontSize:26,fontWeight:700,color:'#29B6F6',fontFamily:"'Barlow Condensed',sans-serif"}}>{fmtS(accepted.reduce((s,q)=>s+q.total,0))}</div><div style={{fontSize:10,color:G.textSec}}>Total en OC</div></div>
        </div>
      </div>
      <Card noPad>
        <Table cols={cols} rows={accepted} emptyMsg="No hay cotizaciones para el filtro seleccionado"/>
      </Card>
      {invoiceModal && (
        <Modal title="Emitir Factura Electrónica" onClose={()=>setInvoiceModal(null)} width={500}>
          <div style={{background:G.bg,border:`1px solid ${G.border}`,borderRadius:6,padding:'12px 16px',marginBottom:16}}>
            <div style={{display:'flex',justifyContent:'space-between',marginBottom:4}}><span style={{color:G.textSec,fontSize:12}}>Cotización</span><span style={{color:G.accent,fontWeight:600}}>{invoiceModal.id}</span></div>
            <div style={{display:'flex',justifyContent:'space-between',marginBottom:4}}><span style={{color:G.textSec,fontSize:12}}>Cliente</span><span style={{fontWeight:600}}>{invoiceModal.client}</span></div>
            <div style={{display:'flex',justifyContent:'space-between'}}><span style={{color:G.textSec,fontSize:12}}>Total</span><span style={{color:G.accent,fontWeight:700,fontSize:15}}>{fmtS(invoiceModal.total)}</span></div>
          </div>
          <Row>
            <div>
              <div style={{fontSize:11,color:G.textSec,marginBottom:4}}>Serie</div>
              <select value={serie} onChange={e=>setSerie(e.target.value)} style={{background:'#0A0A0A',border:`1px solid ${G.border}`,borderRadius:5,color:G.text,padding:'7px 11px',fontSize:13,width:'100%',outline:'none'}}>
                <option>F001</option><option>F002</option><option>B001</option>
              </select>
            </div>
            <div style={{flex:1}}>
              <div style={{fontSize:11,color:G.textSec,marginBottom:4}}>N° Correlativo *</div>
              <input value={num} onChange={e=>setNum(e.target.value)} placeholder="00001" style={{background:'#0A0A0A',border:`1px solid ${num?G.accent:G.border}`,borderRadius:5,color:G.text,padding:'7px 11px',fontSize:13,width:'100%',outline:'none',boxSizing:'border-box'}}/>
            </div>
          </Row>
          {num.trim() && (
            <div style={{background:G.accent+'11',border:`1px solid ${G.accent}33`,borderRadius:6,padding:'8px 12px',fontSize:12,color:G.textSec,marginBottom:4}}>
              N° Factura: <b style={{color:G.accent}}>{serie}-{num.trim()}</b>
            </div>
          )}
          <div style={{display:'flex',justifyContent:'flex-end',gap:8,marginTop:12}}>
            <Btn variant="secondary" onClick={()=>{setInvoiceModal(null);setNum('');}}>Cancelar</Btn>
            <Btn onClick={()=>emitir(invoiceModal)} disabled={!num.trim()}>✅ Emitir Factura</Btn>
          </div>
        </Modal>
      )}
      {viewPDF && <QuotePDF quote={viewPDF} contacts={contacts} onClose={()=>setViewPDF(null)}/>}
      {viewNota && <NotaEntrega quote={viewNota} contacts={contacts} onClose={()=>setViewNota(null)}/>}
      {deleteModal && (
        <DeleteQuoteModal
          quote={deleteModal}
          onClose={()=>setDeleteModal(null)}
          onDeleted={(id, reverted, rsn) => {
            setQuotes(qs=>qs.filter(q=>q.id!==id));
            if(logActivity) logActivity('Eliminó cotización','Facturación',`${id} — Motivo: ${rsn}${reverted?' — Stock revertido':''}`);
            setDeleteModal(null);
          }}
        />
      )}
    </div>
  );
}

// ── NOTA DE ENTREGA ───────────────────────────────────────────
function NotaEntrega({ quote, onClose, contacts }) {
  const client = (contacts||[]).find(c=>c.id===quote.clientId)||{name:quote.client,ruc:'',attn:'',direccion:''};
  const tipos = ['Venta','Consignación','Traslado','Recojo','Primera Compra','Devolución','Otros'];

  const [downloadingNota, setDownloadingNota] = useState(false);

  const downloadNota = async () => {
    setDownloadingNota(true);
    try {
      const token = localStorage.getItem('eutToken');
      const res = await fetch(`/api/quotes/${quote.id}/delivery-note`, {
        headers: { Authorization: `Bearer ${token}` }
      });
      if (!res.ok) throw new Error('Error generando PDF');
      const blob = await res.blob();
      const blobUrl = URL.createObjectURL(new Blob([blob], { type: 'application/pdf' }));
      const link = document.createElement('a');
      link.href = blobUrl;
      link.download = `NOTA-${quote.id}.pdf`;
      link.target = '_blank';
      document.body.appendChild(link);
      link.click();
      setTimeout(() => {
        document.body.removeChild(link);
        URL.revokeObjectURL(blobUrl);
      }, 1000);
    } catch {
      alert('Error al generar el PDF. Intenta de nuevo.');
    } finally {
      setDownloadingNota(false);
    }
  };

  return (
    <div style={{position:'fixed',inset:0,background:'#000000e0',zIndex:1000,display:'flex',flexDirection:'column'}} onClick={onClose}>
      <div style={{height:50,background:G.card,borderBottom:`1px solid ${G.border}`,display:'flex',alignItems:'center',padding:'0 20px',gap:12,flexShrink:0}} onClick={e=>e.stopPropagation()}>
        <span style={{fontFamily:"'Barlow Condensed',sans-serif",fontSize:16,fontWeight:700,color:G.text,flex:1}}>Nota de Entrega — {quote.id}</span>
        <Btn onClick={downloadNota} disabled={downloadingNota} title="iPhone: toca Compartir → Guardar en Archivos">{downloadingNota?'Generando...':'⬇ Descargar PDF'}</Btn>
        <button onClick={onClose} style={{background:'none',border:'none',color:G.textSec,fontSize:18,cursor:'pointer',padding:'4px 8px'}}>✕</button>
      </div>
      <div style={{flex:1,overflow:'auto',padding:32,display:'flex',justifyContent:'center'}} onClick={e=>e.stopPropagation()}>
        <div id="nota-print-area" style={{background:'#fff',color:'#111',width:794,minHeight:1123,padding:'40px 48px',fontFamily:'Arial,sans-serif',fontSize:12,lineHeight:1.5,boxShadow:'0 8px 40px #00000060'}}>
          <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',marginBottom:20,paddingBottom:14,borderBottom:'3px solid #6DBF2E'}}>
            <div>
              <div style={{fontWeight:800,fontSize:20,letterSpacing:1}}>EUTPERU</div>
              <div style={{fontSize:9,color:'#4A8A1F',fontWeight:700,letterSpacing:0.5}}>EQUIPOS E IMPLEMENTOS DE SEGURIDAD</div>
            </div>
            <div style={{textAlign:'right',fontSize:11}}>
              <div style={{fontWeight:700,fontSize:13,marginBottom:2}}>E.U.T. PERÚ EIRL</div>
              <div>RUC: 20611733985</div>
              <div>Tel/WhatsApp: +51 986 401 657</div>
            </div>
          </div>
          <div style={{textAlign:'center',marginBottom:18}}>
            <div style={{fontSize:16,fontWeight:700,textTransform:'uppercase',letterSpacing:2}}>NOTA DE ENTREGA DE PRODUCTOS</div>
            <div style={{fontSize:11,color:'#666',marginTop:4}}>Ref. Cotización: {quote.id} · Fecha: {quote.deliveryDate||quote.date}</div>
          </div>
          <div style={{border:'1px solid #ddd',borderRadius:4,padding:'12px 16px',marginBottom:16}}>
            <div style={{fontWeight:700,color:'#6DBF2E',fontSize:11,marginBottom:8,textTransform:'uppercase'}}>Datos del Comprador</div>
            <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:4}}>
              <div><b>Razón Social:</b> {client.name}</div>
              <div><b>RUC:</b> {client.ruc||'—'}</div>
              <div><b>Atención:</b> {client.attn||'—'}</div>
              <div><b>Dirección:</b> {client.direccion||'—'}</div>
            </div>
          </div>
          <div style={{marginBottom:14,fontSize:12,lineHeight:1.6}}>Por medio de la siguiente, se hace constancia de la entrega de la siguiente mercadería:</div>
          <table style={{width:'100%',borderCollapse:'collapse',marginBottom:20,tableLayout:'fixed'}}>
            <colgroup>
              <col style={{width:'50px'}} />
              <col style={{width:'auto'}} />
              <col style={{width:'60px'}} />
              <col style={{width:'90px'}} />
            </colgroup>
            <thead>
              <tr style={{background:'#6DBF2E',color:'#fff'}}>
                {['ITEM','DESCRIPCIÓN','U.M.','CANTIDAD'].map(h=>(
                  <th key={h} style={{padding:'10px 10px',textAlign:h==='ITEM'||h==='U.M.'||h==='CANTIDAD'?'center':'left',fontSize:10,fontWeight:700,letterSpacing:0.5}}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {(quote.items||[]).map((item,i)=>(
                <tr key={i} style={{background:i%2===0?'#f9f9f9':'#fff',borderBottom:'1px solid #e0e0e0'}}>
                  <td style={{padding:'12px 10px',textAlign:'center',border:'1px solid #ddd',fontSize:11}}>{i+1}</td>
                  <td style={{padding:'12px 10px',border:'1px solid #ddd',fontSize:9,lineHeight:1.5,wordWrap:'break-word',whiteSpace:'normal'}}>{item.name}</td>
                  <td style={{padding:'12px 10px',textAlign:'center',border:'1px solid #ddd',fontSize:11}}>{item.um}</td>
                  <td style={{padding:'12px 10px',textAlign:'center',fontWeight:700,border:'1px solid #ddd',fontSize:11}}>{item.qty}</td>
                </tr>
              ))}
              {Array.from({length:Math.max(0,8-(quote.items||[]).length)}).map((_,i)=>(
                <tr key={`e${i}`} style={{height:40}}><td style={{padding:'12px 10px',border:'1px solid #ddd'}}>&nbsp;</td><td style={{padding:'12px 10px',border:'1px solid #ddd'}}>&nbsp;</td><td style={{padding:'12px 10px',border:'1px solid #ddd'}}>&nbsp;</td><td style={{padding:'12px 10px',border:'1px solid #ddd'}}>&nbsp;</td></tr>
              ))}
            </tbody>
          </table>
          <div style={{border:'1px solid #ccc',borderRadius:4,padding:'10px 14px',marginBottom:20}}>
            <div style={{fontWeight:700,fontSize:11,marginBottom:10,textTransform:'uppercase'}}>Tipo de Movimiento</div>
            <div style={{display:'flex',gap:0,flexWrap:'wrap',border:'1px solid #ccc',borderRadius:3,overflow:'hidden'}}>
              {tipos.map((t,i)=>(
                <div key={t} style={{display:'flex',alignItems:'center',gap:6,padding:'7px 14px',borderRight:i<tipos.length-1?'1px solid #ccc':'none',flex:1,minWidth:100}}>
                  <div style={{width:14,height:14,borderRadius:'50%',border:'1.5px solid #999',flexShrink:0}}></div>
                  <span style={{fontSize:11,color:'#333'}}>{t}</span>
                </div>
              ))}
            </div>
          </div>
          <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:20,marginTop:16}}>
            <div style={{border:'1px solid #ccc',borderRadius:4,padding:'12px 16px',minHeight:100}}>
              <div style={{fontWeight:700,fontSize:11,marginBottom:40}}>ENTREGADO POR:</div>
              <div style={{borderTop:'1px solid #999',paddingTop:6,fontSize:10,color:'#555'}}>E.U.T. PERÚ EIRL — Firma</div>
            </div>
            <div style={{border:'1px solid #ccc',borderRadius:4,padding:'12px 16px',minHeight:100}}>
              <div style={{fontWeight:700,fontSize:11}}>RECIBIDO POR:</div>
              <div style={{fontSize:10,color:'#666',marginBottom:4}}>Fecha: ________________</div>
              <div style={{marginTop:24,borderTop:'1px solid #999',paddingTop:6,fontSize:10,color:'#555'}}>Nombre y Firma</div>
            </div>
          </div>
          <div style={{border:'1px solid #ccc',borderRadius:4,padding:'12px 16px',marginTop:16,minHeight:80}}>
            <div style={{fontWeight:700,fontSize:11,marginBottom:6,textTransform:'uppercase'}}>Observaciones</div>
            <div style={{borderBottom:'1px solid #ccc',marginBottom:10,paddingBottom:2}}>&nbsp;</div>
            <div style={{borderBottom:'1px solid #ccc',marginBottom:10,paddingBottom:2}}>&nbsp;</div>
            <div style={{borderBottom:'1px solid #ccc',paddingBottom:2}}>&nbsp;</div>
          </div>
        </div>
      </div>
    </div>
  );
}

const MESES_AP = ['','Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'];

// ── ANÁLISIS DE PRODUCTOS ─────────────────────────────────────
function AnalisisProductos({ quotes, products, contacts }) {
  const [tab, setTab] = React.useState('Más Vendidos');
  const [selClient, setSelClient] = React.useState('todos');
  const [histClient, setHistClient] = React.useState('todos');
  const [histMonth,  setHistMonth]  = React.useState('');
  const [expandedClient, setExpandedClient] = React.useState(null);

  const clientes = (contacts||[]).filter(c=>c.type==='cliente');

  const confirmedQuotes = (quotes||[]).filter(q=>q.status==='entregada'||q.status==='aceptada');
  const salesDateOf = q => q.deliveryDate || q.date || '';
  const monthKeyOf = q => {
    const parts = salesDateOf(q).split('/');
    return parts.length === 3 ? `${parts[1]}/${parts[2]}` : '';
  };
  const itemRevenue = (q, item) => {
    const subtotal = (q.items||[]).reduce((s,i)=>s+(+i.total||0),0);
    if (subtotal <= 0) return +item.total || 0;
    return ((+q.total || 0) * (+item.total || 0)) / subtotal;
  };

  // ── Tab: Más Vendidos ──────────────────────────────────────
  const allItems = confirmedQuotes
    .filter(q=>selClient==='todos'||q.clientId===+selClient)
    .flatMap(q=>(q.items||[]).map(item=>({...item,client:q.client,clientId:q.clientId,revenue:itemRevenue(q,item)})));

  const byProduct = {};
  allItems.forEach(item=>{
    const k = item.name;
    if(!byProduct[k]) byProduct[k]={name:k,um:item.um,totalQty:0,totalRevenue:0,clients:new Set()};
    byProduct[k].totalQty     += item.qty;
    byProduct[k].totalRevenue += item.revenue||0;
    byProduct[k].clients.add(item.client);
  });
  const productRanking = Object.values(byProduct).sort((a,b)=>b.totalQty-a.totalQty).map(p=>({...p,clients:[...p.clients]}));

  // ── Tab: Por Cliente ───────────────────────────────────────
  const byClient = {};
  confirmedQuotes.forEach(q=>{
    const k = q.clientId || q.client;
    if(!byClient[k]) byClient[k]={clientId:q.clientId,client:q.client,orders:0,revenue:0,products:new Set(),productMap:{}};
    byClient[k].orders++;
    byClient[k].revenue+=q.total||0;
    (q.items||[]).forEach(i=>{
      byClient[k].products.add(i.name);
      const pk = i.name;
      if(!byClient[k].productMap[pk]) byClient[k].productMap[pk]={name:pk,um:i.um,qty:0,revenue:0,orders:new Set()};
      byClient[k].productMap[pk].qty += i.qty || 0;
      byClient[k].productMap[pk].revenue += itemRevenue(q,i);
      byClient[k].productMap[pk].orders.add(q.id);
    });
  });
  const clientRanking = Object.values(byClient).sort((a,b)=>b.revenue-a.revenue).map(c=>({
    ...c,
    products:[...c.products],
    productRows:Object.values(c.productMap).sort((a,b)=>b.revenue-a.revenue).map(p=>({...p,orders:p.orders.size})),
  }));

  // ── Tab: Historial por Mes ─────────────────────────────────
  // Construir lista de meses disponibles (MM/YYYY) a partir de la fecha de venta/facturación
  const monthSet = new Set();
  confirmedQuotes.forEach(q=>{
    const monthKey = monthKeyOf(q);
    if (monthKey) monthSet.add(monthKey);
  });
  const availableMonths = [...monthSet].sort((a,b)=>{
    const [ma,ya] = a.split('/'); const [mb,yb] = b.split('/');
    return (+yb*12+(+mb)) - (+ya*12+(+ma));
  });

  // Si histMonth aún no fue inicializado, usar el mes más reciente
  const effectiveMonth = histMonth || availableMonths[0] || '';

  // Cotizaciones del mes/cliente seleccionado
  const histQuotes = confirmedQuotes.filter(q=>{
    const qMonth = monthKeyOf(q);
    const matchMonth  = qMonth === effectiveMonth;
    const matchClient = histClient==='todos' || q.clientId===+histClient;
    return matchMonth && matchClient;
  });

  // Agrupar items por producto
  const histMap = {};
  histQuotes.forEach(q=>{
    (q.items||[]).forEach(item=>{
      const k = item.name;
      if (!histMap[k]) histMap[k]={name:k,um:item.um,qty:0,unitPrice:item.unit,total:0};
      histMap[k].qty   += item.qty;
      histMap[k].total += itemRevenue(q,item);
    });
  });
  const histItems  = Object.values(histMap).sort((a,b)=>b.total-a.total);
  const histTotal  = histQuotes.reduce((s,q)=>s+(q.total||0),0);
  const histLabel  = effectiveMonth ? `${MESES_AP[+effectiveMonth.split('/')[0]]} ${effectiveMonth.split('/')[1]}` : '';
  const clientName = histClient==='todos' ? 'Todos los clientes' : (clientes.find(c=>c.id===+histClient)?.name||'');

  const prodCols=[
    {key:'rank',label:'#',w:40,render:(_,i)=><span style={{color:G.textSec,fontWeight:700}}>{i+1}</span>},
    {key:'name',label:'Producto',render:r=><span style={{fontSize:12,fontWeight:500}}>{r.name}</span>},
    {key:'um',label:'U.M.',w:60,render:r=><span style={{color:G.textSec,fontSize:11}}>{r.um}</span>},
    {key:'totalQty',label:'Und. Vendidas',w:110,render:r=><span style={{fontFamily:"'Barlow Condensed',sans-serif",fontSize:18,fontWeight:700,color:G.accent}}>{r.totalQty}</span>},
    {key:'totalRevenue',label:'Ingresos',w:120,render:r=><span style={{color:G.accent,fontWeight:600}}>{fmtS(r.totalRevenue)}</span>},
    {key:'clients',label:'Clientes',render:r=><div style={{display:'flex',gap:4,flexWrap:'wrap'}}>{r.clients.map(c=><Tag key={c} label={c} color={G.info}/>)}</div>},
  ];

  const clientCols=[
    {key:'rank',label:'#',w:40,render:(_,i)=><span style={{color:G.textSec,fontWeight:700}}>{i+1}</span>},
    {key:'client',label:'Cliente',render:r=><span style={{fontSize:13,fontWeight:600}}>{r.client}</span>},
    {key:'orders',label:'Pedidos',w:80,render:r=><span style={{fontFamily:"'Barlow Condensed',sans-serif",fontSize:18,fontWeight:700,color:G.accent}}>{r.orders}</span>},
    {key:'revenue',label:'Total Comprado',w:130,render:r=><span style={{color:G.accent,fontWeight:700}}>{fmtS(r.revenue)}</span>},
    {key:'products',label:'Productos comprados',render:r=><div style={{fontSize:10,color:G.textSec}}>{r.products.slice(0,3).join(', ')}{r.products.length>3?` +${r.products.length-3} más`:''}</div>},
  ];

  const histCols=[
    {key:'name',label:'Producto',render:r=><span style={{fontSize:12}}>{r.name}</span>},
    {key:'um',label:'U.M.',w:55,render:r=><span style={{color:G.textSec,fontSize:11}}>{r.um}</span>},
    {key:'qty',label:'Cantidad',w:90,render:r=><span style={{fontFamily:"'Barlow Condensed',sans-serif",fontSize:18,fontWeight:700,color:G.text}}>{r.qty}</span>},
    {key:'unitPrice',label:'P. Unitario',w:110,render:r=><span style={{color:G.textSec,fontSize:12}}>{fmtS(r.total/r.qty)}</span>},
    {key:'total',label:'Total',w:120,render:r=><span style={{color:G.accent,fontWeight:700}}>{fmtS(r.total)}</span>},
  ];

  const selectSt = {background:G.card2,border:`1px solid ${G.border}`,color:G.text,padding:'5px 10px',borderRadius:5,fontSize:12,cursor:'pointer',outline:'none'};

  return (
    <div>
      <PageHeader title="ANÁLISIS DE VENTAS" subtitle="Ventas por producto, cliente y mes"/>
      <div style={{display:'flex',gap:10,alignItems:'center',marginBottom:16,flexWrap:'wrap'}}>
        <Tabs tabs={['Más Vendidos','Por Cliente','Historial por Mes']} active={tab} onChange={setTab}/>
        {tab==='Más Vendidos' && (
          <select value={selClient} onChange={e=>setSelClient(e.target.value)} style={{...selectSt,marginLeft:'auto',marginBottom:20}}>
            <option value="todos">Todos los clientes</option>
            {clientes.map(c=><option key={c.id} value={c.id}>{c.name}</option>)}
          </select>
        )}
      </div>

      {tab==='Más Vendidos' && (
        <Card noPad>
          <Table cols={prodCols.map(c=>({...c,render:c.key==='rank'?(row,idx)=><span style={{color:G.textSec,fontWeight:700}}>{idx+1}</span>:c.render}))} rows={productRanking} emptyMsg="Sin datos de ventas confirmadas"/>
        </Card>
      )}

      {tab==='Por Cliente' && (
        <div style={{display:'grid',gap:10}}>
          {clientRanking.length===0 && <Card><div style={{color:G.textSec,fontSize:12}}>Sin datos</div></Card>}
          {clientRanking.map((c,idx)=>{
            const key = c.clientId || c.client;
            const open = expandedClient === key;
            return (
              <Card key={key} noPad>
                <div onClick={()=>setExpandedClient(open?null:key)} style={{display:'grid',gridTemplateColumns:'42px 1fr 90px 140px 28px',gap:10,alignItems:'center',padding:'12px 16px',cursor:'pointer'}}>
                  <span style={{color:G.textSec,fontWeight:700,fontSize:12}}>#{idx+1}</span>
                  <div style={{minWidth:0}}>
                    <div style={{fontSize:13,fontWeight:700,color:G.text,whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{c.client}</div>
                    <div style={{fontSize:10,color:G.textSec,marginTop:2}}>{c.products.length} producto{c.products.length!==1?'s':''} distinto{c.products.length!==1?'s':''}</div>
                  </div>
                  <div style={{textAlign:'right'}}>
                    <div style={{fontFamily:"'Barlow Condensed',sans-serif",fontSize:18,fontWeight:700,color:G.accent,lineHeight:1}}>{c.orders}</div>
                    <div style={{fontSize:9,color:G.textSec}}>pedidos</div>
                  </div>
                  <div style={{textAlign:'right',fontWeight:700,color:G.accent,fontSize:13}}>{fmtS(c.revenue)}</div>
                  <div style={{color:open?G.accent:G.textSec,fontSize:16,textAlign:'center'}}>{open?'−':'+'}</div>
                </div>
                {open && (
                  <div style={{padding:'0 16px 14px'}}>
                    <div style={{borderTop:`1px solid ${G.border}`,paddingTop:10}}>
                      <Table
                        cols={[
                          {key:'name',label:'Producto',render:r=><span style={{fontSize:12,fontWeight:500}}>{r.name}</span>},
                          {key:'um',label:'U.M.',w:55,render:r=><span style={{fontSize:11,color:G.textSec}}>{r.um}</span>},
                          {key:'qty',label:'Und.',w:70,render:r=><span style={{fontFamily:"'Barlow Condensed',sans-serif",fontSize:17,fontWeight:700,color:G.text}}>{r.qty}</span>},
                          {key:'orders',label:'Ventas',w:70,render:r=><span style={{fontSize:12,color:G.textSec}}>{r.orders}</span>},
                          {key:'revenue',label:'Ingresos',w:120,render:r=><span style={{fontWeight:700,color:G.accent}}>{fmtS(r.revenue)}</span>},
                        ]}
                        rows={c.productRows}
                        emptyMsg="Sin productos vendidos"
                      />
                    </div>
                  </div>
                )}
              </Card>
            );
          })}
        </div>
      )}

      {tab==='Historial por Mes' && (
        <div>
          {/* Filtros */}
          <div style={{display:'flex',gap:12,marginBottom:16,flexWrap:'wrap',alignItems:'flex-end'}}>
            <div>
              <div style={{fontSize:11,color:G.textSec,marginBottom:4}}>Cliente</div>
              <select value={histClient} onChange={e=>setHistClient(e.target.value)} style={selectSt}>
                <option value="todos">Todos los clientes</option>
                {clientes.map(c=><option key={c.id} value={c.id}>{c.name}</option>)}
              </select>
            </div>
            <div>
              <div style={{fontSize:11,color:G.textSec,marginBottom:4}}>Mes</div>
              <select value={effectiveMonth} onChange={e=>setHistMonth(e.target.value)} style={selectSt}>
                {availableMonths.length===0
                  ? <option value="">Sin datos</option>
                  : availableMonths.map(m=>{
                      const [mm,yyyy]=m.split('/');
                      return <option key={m} value={m}>{MESES_AP[+mm]} {yyyy}</option>;
                    })
                }
              </select>
            </div>
          </div>

          {/* Encabezado del periodo */}
          {effectiveMonth && (
            <div style={{background:G.card,border:`1px solid ${G.border}`,borderRadius:8,padding:'12px 18px',marginBottom:14,display:'flex',justifyContent:'space-between',alignItems:'center',flexWrap:'wrap',gap:8}}>
              <div>
                <div style={{fontFamily:"'Barlow Condensed',sans-serif",fontSize:20,fontWeight:700,color:G.text}}>{histLabel}</div>
                <div style={{fontSize:11,color:G.textSec,marginTop:2}}>{clientName} · {histQuotes.length} cotización{histQuotes.length!==1?'es':''} confirmada{histQuotes.length!==1?'s':''}</div>
              </div>
              <div style={{textAlign:'right'}}>
                <div style={{fontSize:11,color:G.textSec}}>Total del mes</div>
                <div style={{fontFamily:"'Barlow Condensed',sans-serif",fontSize:26,fontWeight:700,color:G.accent,lineHeight:1}}>{fmtS(histTotal)}</div>
              </div>
            </div>
          )}

          <Card noPad>
            <Table cols={histCols} rows={histItems} emptyMsg={availableMonths.length===0?"Sin ventas confirmadas":"Sin ventas para el filtro seleccionado"}/>
          </Card>

          {histItems.length>0 && (
            <div style={{display:'flex',justifyContent:'flex-end',marginTop:10}}>
              <div style={{background:G.card,border:`1px solid ${G.border}`,borderRadius:6,padding:'8px 18px',display:'flex',gap:20,alignItems:'center'}}>
                <span style={{fontSize:12,color:G.textSec}}>
                  {histItems.reduce((s,r)=>s+r.qty,0)} unidades vendidas
                </span>
                <div style={{width:1,background:G.border}}/>
                <span style={{fontSize:12,color:G.textSec}}>Subtotal {histLabel}:</span>
                <span style={{fontFamily:"'Barlow Condensed',sans-serif",fontSize:20,fontWeight:700,color:G.accent}}>{fmtS(histTotal)}</span>
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ── MIS VENTAS ────────────────────────────────────────────────
function MisVentas({ quotes, setQuotes, currentUser, users }) {
  const [filterEstado, setFilterEstado] = useState('todos');
  const canSeeAll = currentUser?.role === 'Administrador' || !!currentUser?.perms?.verVentasEquipo;
  const [targetUser, setTargetUser] = useState(currentUser?.username || '');
  const effectiveUser = canSeeAll ? (targetUser || null) : currentUser?.username;

  const misFacturas = (quotes||[])
    .filter(q => q.invoice && (!effectiveUser || q.createdBy === effectiveUser))
    .map(q => {
      const dateStr = q.deliveryDate||q.date||'';
      const days    = q.daysLeft||0;
      const credit  = q.credit||0;
      const paidAt  = q.paidAt||null;
      const estado  = paidAt ? 'cobrado' : (credit===0 ? 'cobrado' : (days<0 ? 'vencido' : days<=7 ? 'por_vencer' : 'pendiente'));
      return { id:q.id, invoice:q.invoice, client:q.client, date:dateStr, due:q.dueDate||'—', amount:q.total, days, credit, estado, paidAt, paymentLocked: !!q.paymentLocked };
    });

  const filtered = misFacturas.filter(f => filterEstado==='todos' || f.estado===filterEstado);

  const payCobrar = async (f) => {
    const res = await window.api(`/quotes/${f.id}/pay`, {method:'PUT'});
    if(res && res.ok) {
      const updated = await res.json();
      if(setQuotes) setQuotes(qs=>qs.map(q=>q.id===updated.id?updated:q));
    }
  };

  const unpayFn = async (f) => {
    const res = await window.api(`/quotes/${f.id}/unpay`, {method:'PUT'});
    if(res && res.ok) {
      const updated = await res.json();
      if(setQuotes) setQuotes(qs=>qs.map(q=>q.id===updated.id?updated:q));
    } else if (res) {
      const err = await res.json().catch(()=>({}));
      alert(err.error || `Error al revertir pago (${res.status})`);
    }
  };

  const totalFact    = misFacturas.reduce((s,f)=>s+f.amount, 0);
  const totalCobrado = misFacturas.filter(f=>f.estado==='cobrado').reduce((s,f)=>s+f.amount, 0);
  const pendiente    = misFacturas.filter(f=>f.estado==='pendiente'||f.estado==='por_vencer').reduce((s,f)=>s+f.amount, 0);
  const vencido      = misFacturas.filter(f=>f.estado==='vencido').reduce((s,f)=>s+f.amount, 0);

  const estadoMap = {pendiente:{c:G.warning,l:'Pendiente'},por_vencer:{c:G.warning,l:'Por Vencer'},cobrado:{c:G.accent,l:'Cobrado'},vencido:{c:G.error,l:'Vencido'}};

  const cols = [
    {key:'invoice',label:'N° Factura',w:130,render:r=><span style={{color:'#29B6F6',fontWeight:600,fontSize:12}}>{r.invoice}</span>},
    {key:'client', label:'Cliente',render:r=><span style={{fontWeight:500}}>{r.client}</span>},
    {key:'date',   label:'Fecha',w:100},
    {key:'due',    label:'Vence cobro',w:110,render:r=><span style={{fontSize:11,color:G.textSec}}>{r.due}</span>},
    {key:'amount', label:'Monto',w:120,render:r=><span style={{fontWeight:700,color:G.accent}}>{fmtS(r.amount)}</span>},
    {key:'credit', label:'Plazo',w:80,render:r=><CreditBadge days={r.credit}/>},
    {key:'estado', label:'Estado',w:110,render:r=>{
      const s=estadoMap[r.estado]||estadoMap.pendiente;
      return <span style={{background:s.c+'22',color:s.c,padding:'2px 8px',borderRadius:3,fontSize:11,fontWeight:600}}>{s.l}</span>;
    }},
    {key:'dias',   label:'Días',w:70,render:r=>r.credit>0?<DaysBadge days={r.days}/>:<span style={{fontSize:11,color:G.textSec}}>contado</span>},
    {key:'cobrar',label:'Cobro',w:100,render:r=> r.credit===0
      ? <span style={{background:G.accent+'22',color:G.accent,padding:'2px 8px',borderRadius:3,fontSize:11,fontWeight:600}}>Pagado</span>
      : (
        <span onClick={()=>r.paidAt ? (!r.paymentLocked || currentUser?.role==='Administrador') && unpayFn(r) : payCobrar(r)} style={{
          background:r.paidAt?G.accent+'22':G.error+'22',
          color:r.paidAt?G.accent:G.error,
          padding:'2px 8px',borderRadius:3,fontSize:11,fontWeight:600,cursor:(r.paidAt && r.paymentLocked && currentUser?.role!=='Administrador')?'default':'pointer',
        }}>
          {r.paidAt && r.paymentLocked && currentUser?.role!=='Administrador' ? 'Bloqueado' : (r.paidAt?'Pagado':'Pendiente')}
        </span>
      )
    },
  ];

  const estados = ['todos','pendiente','por_vencer','cobrado','vencido'];
  const etiqEstado = {todos:'Todos',pendiente:'Pendiente',por_vencer:'Por Vencer',cobrado:'Cobrado',vencido:'Vencido'};

  return (
    <div>
      <PageHeader title="MIS VENTAS" subtitle={canSeeAll && !targetUser ? `Todas las ventas del equipo · ${misFacturas.length} facturas` : `${misFacturas.length} facturas · ${effectiveUser||''}`}/>
      <div style={{display:'flex',gap:12,marginBottom:20,flexWrap:'wrap'}}>
        <KPICard label="Total Facturado" value={fmtS(totalFact)} color={G.accent} icon="📄"/>
        <KPICard label="Cobrado" value={fmtS(totalCobrado)} color={G.accent} icon="✅"/>
        <KPICard label="Pendiente" value={fmtS(pendiente)} color={G.warning} icon="⏳"/>
        <KPICard label="Vencido" value={fmtS(vencido)} color={G.error} icon="🔴"/>
      </div>
      {canSeeAll && (
        <div style={{display:'flex',gap:8,alignItems:'center',marginBottom:12,flexWrap:'wrap'}}>
          <span style={{fontSize:11,color:G.textSec,flexShrink:0}}>Empleado:</span>
          <select value={targetUser} onChange={e=>setTargetUser(e.target.value)} style={{background:G.card2,border:`1px solid ${G.border}`,color:G.text,padding:'4px 8px',borderRadius:5,fontSize:12,cursor:'pointer'}}>
            <option value="">Todos los empleados</option>
            {(users||[]).filter(u=>u.username).map(u=><option key={u.id} value={u.username}>{u.name}{u.apellidos?' '+u.apellidos:''} (@{u.username})</option>)}
          </select>
        </div>
      )}
      <div style={{display:'flex',gap:6,marginBottom:16,flexWrap:'wrap'}}>
        {estados.map(e=>(
          <button key={e} onClick={()=>setFilterEstado(e)} style={{background:filterEstado===e?G.accent+'22':G.card2,border:`1px solid ${filterEstado===e?G.accent:G.border}`,color:filterEstado===e?G.accent:G.textSec,padding:'5px 12px',borderRadius:4,fontSize:12,fontWeight:600,cursor:'pointer'}}>
            {etiqEstado[e]}
          </button>
        ))}
      </div>
      <Card noPad>
        <Table cols={cols} rows={filtered} emptyMsg="No tienes facturas registradas"/>
      </Card>
    </div>
  );
}

Object.assign(window, { Cotizaciones, PreciosEspeciales, Facturacion, NotaEntrega, AnalisisProductos, MisVentas });
