// js/components/widgets/Devolucoes.jsx
// Registro de devoluções de vendas — estoque + financeiro.
// Movido de index.html em Fase 5 do refactor (2026-04-29): L6299-L6477
// Inclui DEV_MOTIVOS const
// Deps runtime: Modal, Icon, StatusBadge, showConfirm, fmt, fmtDate, itemNet, nid, today, genIdUUID, dualWrite, toast (globals)
(function() {
  'use strict';
  const {useState, useEffect, useRef, useCallback, useMemo} = React;

const DEV_MOTIVOS=['Produto com defeito','Pedido errado','Desistência','Outro'];
let _inFlightSaveNewDevolucao=false;
function Devolucoes({devolucoes,setDevolucoes,sales,setSales,products,setProducts,clients,receivables,setReceivables}){
  const EMPTY_DEV={saleId:'',items:[],motivo:'',date:today(),estoqueAcao:'Repor no estoque',finAcao:'Estorno para o cliente'};
  const[modal,setModal]=useState(null);
  const[form,setForm]=useState(EMPTY_DEV);
  const[saleSearch,setSaleSearch]=useState('');
  const selectedSale=useMemo(()=>sales.find(s=>nid(s.id,form.saleId)),[sales,form.saleId]);
  // [ONDA-A #9 2026-05-11] regra_loading_state_obrigatorio + regra_idem_estavel
  // 2 cliques sem disabled = repõe stock 2x + estorna receivable 2x (CRÍTICO financeiro).
  const savingRef=useRef(false);
  const[isSaving,setIsSaving]=useState(false);
  const saveIdemRef=useRef(null);
  useEffect(()=>{savingRef.current=false;setIsSaving(false);saveIdemRef.current=null;},[modal]);

  function toggleItem(it){
    setForm(f=>{
      const exists=f.items.find(x=>x.productId===it.productId&&x.price===it.price);
      if(exists)return{...f,items:f.items.filter(x=>!(x.productId===it.productId&&x.price===it.price))};
      return{...f,items:[...f.items,{...it,returnQty:it.qty}]};
    });
  }

  async function save(){
    // [ONDA-A #9 2026-05-11] savingRef early return + isSaving UI feedback.
    if(savingRef.current||_inFlightSaveNewDevolucao)return;
    if(!await znxGuard(['admin','estoquista']))return;
    if(!form.saleId){toast('Selecione a venda de origem.');return;}
    if(form.items.length===0){toast('Selecione pelo menos um produto.');return;}
    savingRef.current=true;
    setIsSaving(true);
    _inFlightSaveNewDevolucao=true;
    try {
      const devTotal=form.items.reduce((s,i)=>s+(i.returnQty*itemNet(i)),0);
      const devolucaoId=genIdUUID();
      // [ONDA-A #9] idem key estável — lazy init, mantém durante retry.
      // TODO: createDevolucaoAtomic ainda não aceita idempotencyKey — passar quando RPC for atualizada.
      if(!saveIdemRef.current){
        saveIdemRef.current=(window.crypto?.randomUUID?.()||(Date.now()+'-'+Math.random()));
      }

      // [BUG-FIX 20260504] process_devolucao_v2 RPC atomica faz TUDO:
      // - INSERT devolucao + items
      // - UPDATE products stock (se Repor)
      // - UPDATE/abate receivable (se Estorno) — antes só state local!
      // - INSERT client_credit_history + UPDATE clients.credit_balance (se Credito)
      //   — antes só state local!
      // - UPDATE sale.status Devolvida (total/parcial) — antes só state local!
      // 1 chamada, 1 transacao, ROLLBACK se algo falhar.
      const result=await createDevolucaoAtomic({form,items:form.items,devolucaoId,idempotencyKey:saveIdemRef.current});
      if(!result.success){
        toast('❌ '+(mapErrorToUX(result.errorCode,result.errorMessage)||result.errorMessage||'Erro ao registrar devolução.'));
        return;
      }
      const num=result.devolucaoNumber;

      // Sync state local com o que o banco persistiu (UI imediata)
      // Stock — atualizar local pra refletir UPDATE feito pela RPC
      if(form.estoqueAcao==='Repor no estoque'){
        setProducts(prev=>prev.map(p=>{
          const it=form.items.find(i=>nid(i.productId,p.id));
          if(!it)return p;
          // Decantes não recebem stock (RPC pula) — UI também pula
          if(p.is_decant===true||p.isDecant===true)return p;
          return{...p,stock:(p.stock||0)+Number(it.returnQty)};
        }));
      }
      // Receivables — refletir abate
      if(result.finAcao==='Estorno para o cliente'){
        setReceivables(prev=>{
          const idx=prev.findIndex(r=>r.saleId===form.saleId&&r.status==='Pendente');
          if(idx<0)return prev;
          const r=prev[idx];
          const newVal=Math.max(0,r.value-devTotal);
          const upd=newVal===0?{...r,status:'Pago',value:0}:{...r,value:newVal};
          return prev.map((x,i)=>i===idx?upd:x);
        });
      }
      // Credit — refletir novo balance no cliente local (se aplicavel)
      if(result.finAcao==='Crédito para próxima compra'&&result.newCreditBalance!=null){
        const sale=sales.find(s=>nid(s.id,form.saleId));
        if(sale&&sale.clientId&&typeof window!=='undefined'){
          // setClients gerenciado em outro lugar — confiar no JSONB sync via trigger
        }
      }
      // Sale status atualizado pela RPC
      setSales(prev=>prev.map(s=>nid(s.id,form.saleId)?{...s,status:result.saleNewStatus||s.status}:s));

      // Devolucao no JSONB local — trigger AFTER WRITE ja sincroniza, mas refletir local
      setDevolucoes(prev=>[...prev,{...form,id:result.devolucaoId||devolucaoId,number:num,total:devTotal,saleId:form.saleId}]);
      setModal(null);
      // [ONDA-A #9] sucesso confirmado → reset idem key pra próxima devolução
      saveIdemRef.current=null;
      toast('✅ Devolução '+num+' registrada — '+(result.saleNewStatus||'').replace(/.*\((.*)\)/,'$1')+' aplicada.');
    } catch(e) {
      const msg=e.message||'Erro inesperado. Tente novamente.';
      toast('❌ '+msg);
      if(typeof Sentry!=='undefined')Sentry.captureException(e,{extra:{context:'save_devolucoes',errorMessage:e.message}});
    } finally {
      _inFlightSaveNewDevolucao=false;
      savingRef.current=false;
      setIsSaving(false);
    }
  }

  const filteredSales=useMemo(()=>sales.filter(s=>!saleSearch||s.number.toLowerCase().includes(saleSearch.toLowerCase())||(clients.find(c=>c.id===s.clientId)?.name||'').toLowerCase().includes(saleSearch.toLowerCase())),[sales,saleSearch,clients]);

  return(
    <div>
      <div className="page-header">
        <div className="page-title">Devoluções</div>
        <button className="btn-gold" onClick={()=>{setForm(EMPTY_DEV);setSaleSearch('');setModal('new')}} style={{display:'flex',alignItems:'center',gap:6}}><Icon n="plus" size={14}/>Nova Devolução</button>
      </div>

      {devolucoes.length===0&&<div className="card" style={{textAlign:'center',color:'#6B7280',padding:40,fontSize:14}}>Nenhuma devolução registrada.</div>}

      {devolucoes.length>0&&(
        <div className="card" style={{padding:0}}>
          <table>
            <thead><tr><th>Nº</th><th>Data</th><th>Venda</th><th>Motivo</th><th>Total Devolvido</th><th>Estoque</th><th>Financeiro</th></tr></thead>
            <tbody>
              {devolucoes.map(d=>{
                const s=sales.find(x=>x.id===d.saleId);
                return(
                  <tr key={d.id}>
                    <td className="gold">{d.number}</td>
                    <td>{fmtDate(d.date)}</td>
                    <td>{s?.number||'—'}</td>
                    <td className="dim">{d.motivo}</td>
                    <td style={{color:'#DC2626'}}>{fmt(d.total)}</td>
                    <td><span style={{fontSize:11,color:'#16A34A'}}>{d.estoqueAcao}</span></td>
                    <td><span style={{fontSize:11,color:'#EA580C'}}>{d.finAcao}</span></td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}

      {modal==='new'&&(
        <Modal title="Nova Devolução" onClose={()=>setModal(null)} large>
          <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:14,marginBottom:16}}>
            <div className="form-group">
              <label>Venda de Origem (buscar por número ou cliente)</label>
              <input value={saleSearch} onChange={e=>{setSaleSearch(e.target.value);setForm(f=>({...f,saleId:'',items:[]}))}} placeholder="VND-001 ou nome do cliente..."/>
              {saleSearch&&!form.saleId&&(
                <div style={{background:'#FFFFFF',border:'1px solid #2563EB55',borderRadius:8,maxHeight:180,overflowY:'auto',marginTop:4}}>
                  {filteredSales.slice(0,10).map(s=>{
                    const c=clients.find(x=>x.id===s.clientId);
                    return(
                      <div key={s.id} style={{padding:'8px 12px',cursor:'pointer',borderBottom:'1px solid #F3F4F6',fontSize:13}}
                        onMouseDown={()=>{setForm(f=>({...f,saleId:s.id,items:[]}));setSaleSearch(`${s.number} — ${c?.name||''}`);}}
                        onMouseEnter={e=>e.currentTarget.style.background='#F3F4F6'}
                        onMouseLeave={e=>e.currentTarget.style.background='transparent'}>
                        <span className="gold">{s.number}</span> · {c?.name||'—'} · {fmtDate(s.date)} · {fmt(saleFinalTotal(s))}
                      </div>
                    );
                  })}
                  {filteredSales.length===0&&<div style={{padding:12,color:'#6B7280',fontSize:13}}>Nenhuma venda encontrada</div>}
                </div>
              )}
            </div>
            <div className="form-group"><label>Data da Devolução</label><input type="date" value={form.date} onChange={e=>setForm(f=>({...f,date:e.target.value}))}/></div>
            <div className="form-group"><label>Motivo</label>
              <SmartSelect value={form.motivo} onChange={val=>setForm(f=>({...f,motivo:val}))} options={[{value:'',label:'— Selecione —'},...DEV_MOTIVOS.map(m=>({value:m,label:m}))]}/>
            </div>
            <div className="form-group"><label>Ação sobre o Estoque</label>
              <SmartSelect value={form.estoqueAcao} onChange={val=>setForm(f=>({...f,estoqueAcao:val}))} options={['Repor no estoque','Descartar',
              ].map(x=>({value:x,label:x}))}/>
            </div>
            <div className="form-group" style={{gridColumn:'1/-1'}}><label>Ação Financeira</label>
              <SmartSelect value={form.finAcao} onChange={val=>setForm(f=>({...f,finAcao:val}))} options={['Estorno para o cliente','Crédito para próxima compra','Sem reembolso'].map(x=>({value:x,label:x}))}/>

            </div>
          </div>

          {selectedSale&&(
            <div style={{background:'#F9FAFB',borderRadius:8,padding:14,marginBottom:14}}>
              <div style={{fontSize:11,color:'#9CA3AF',marginBottom:10,textTransform:'uppercase',letterSpacing:1}}>Selecione os Produtos Devolvidos</div>
              <table>
                <thead><tr><th>✓</th><th>Produto</th><th>Qtd Original</th><th>Qtd Devolvida</th><th>Valor Unit.</th></tr></thead>
                <tbody>
                  {(selectedSale.items||[]).map((it,i)=>{
                    const p=products.find(x=>nid(x.id,it.productId));
                    const checked=form.items.find(x=>x.productId===it.productId&&x.price===it.price);
                    return(
                      <tr key={i} style={{background:checked?'#F0FDF4':'transparent'}}>
                        <td><input type="checkbox" checked={!!checked} onChange={()=>toggleItem(it)}/></td>
                        <td>{p?.name||it.name||'—'}</td>
                        <td>{it.qty}</td>
                        <td>{checked?<input type="number" min="1" max={it.qty} value={checked.returnQty} onChange={e=>setForm(f=>({...f,items:f.items.map(x=>x.productId===it.productId&&x.price===it.price?{...x,returnQty:Math.min(it.qty,Number(e.target.value))}:x)}))} style={{width:60,padding:'3px 6px',fontSize:12}}/>:'—'}</td>
                        <td>{fmt(itemNet(it))}</td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
              {form.items.length>0&&<div style={{marginTop:10,textAlign:'right',color:'#2563EB',fontWeight:700}}>Total a estornar: {fmt(form.items.reduce((s,i)=>s+(i.returnQty*itemNet(i)),0))}</div>}
            </div>
          )}

          <div style={{display:'flex',gap:10,justifyContent:'flex-end'}}>
            <button className="btn-outline" onClick={()=>setModal(null)} disabled={isSaving}>Cancelar</button>
            <button className="btn-gold" onClick={save} disabled={isSaving} style={{opacity:isSaving?0.6:1,cursor:isSaving?'not-allowed':'pointer'}}>{isSaving?'⏳ Registrando…':'Registrar Devolução'}</button>
          </div>
        </Modal>
      )}
    </div>
  );
}

// ══════════════════════════════════════════════════════════════
// GASTOS
// ══════════════════════════════════════════════════════════════

  window.ZNX = window.ZNX || {};
  window.ZNX.components = window.ZNX.components || {};
  window.ZNX.components.Devolucoes = Devolucoes;
  window.Devolucoes = Devolucoes;
  window.DEV_MOTIVOS = typeof DEV_MOTIVOS !== 'undefined' ? DEV_MOTIVOS : [];

  window.ZNX.refactor_phase_5_loaded = window.ZNX.refactor_phase_5_loaded || {};
  window.ZNX.refactor_phase_5_loaded.Devolucoes = true;

})();
