// js/components/pages/NotasFrete.jsx
// FRT-C2 (2026-05-09) — Notas de frete (visão Amir/admin) — criar, editar,
// transição de status (confirm pickup / mark in transit), ver detalhes.
// Roles: admin, freight_manager.
// Visão Abbes (mobile receive) virá em FRT-C3.
// Deps runtime: sb, toast, Modal, Icon, fmt, fmtDate, SmartSelect (globals)
(function() {
  'use strict';
  const {useState, useEffect, useMemo, useCallback} = React;

  // ══════════════════════════════════════════════════════════════
  // HELPERS — [Wave NotasFrete 2026-05-19 v223.23] MOVIDOS PRA:
  //   - js/lib/notas_frete/helpers.js (fmtUSD/fmtBRL/fmtShortDate/emptyForm/emptyItemForm)
  //   - js/components/widgets/notas_frete/Primitives.jsx (statusBadge retorna JSX)
  // Resolve via window.ZNX.lib.notas_frete.helpers + window.ZNX.widgets.notas_frete.Primitives.
  // ══════════════════════════════════════════════════════════════

  // ══════════════════════════════════════════════════════════════
  // COMPONENTE PRINCIPAL
  // ══════════════════════════════════════════════════════════════

  function NotasFrete({ user }) {
    // [Wave NotasFrete 2026-05-19 v223.23] Bloco agregado refs+fail-loud — 4 widgets + lib helpers
    // regra_estender_bloco_refs_fail_loud + regra_validacao_helpers_runtime_quando_ordem_scripts_uncertain.
    const _h = window.ZNX?.lib?.notas_frete?.helpers;
    const _Primitives = window.ZNX?.widgets?.notas_frete?.Primitives;
    const _NotasFreteList = window.ZNX?.widgets?.notas_frete?.NotasFreteList;
    const _NotaFreteFormModal = window.ZNX?.widgets?.notas_frete?.NotaFreteFormModal;
    const _NotaFreteViewModal = window.ZNX?.widgets?.notas_frete?.NotaFreteViewModal;
    const _missing = [];
    if (!_h) _missing.push('lib.helpers');
    if (!_Primitives) _missing.push('Primitives');
    if (!_NotasFreteList) _missing.push('NotasFreteList');
    if (!_NotaFreteFormModal) _missing.push('NotaFreteFormModal');
    if (!_NotaFreteViewModal) _missing.push('NotaFreteViewModal');
    if (_missing.length > 0) {
      if (typeof window.znxCaptureRpcError === 'function') {
        window.znxCaptureRpcError('NotasFrete_widgets_missing', { missing: _missing });
      }
      console.error('[NotasFrete] widgets/lib faltando:', _missing);
    }
    // Aliases pra usar no body (com fallback defensive — não quebra render se lib falhar)
    const fmtUSD = _h?.fmtUSD || (v => String(v));
    const fmtBRL = _h?.fmtBRL || (v => String(v));
    const fmtShortDate = _h?.fmtShortDate || (s => String(s));
    const emptyForm = _h?.emptyForm || (() => ({ carrier_id:'', freight_model:'', total_cost_usd:0, exchange_rate_usd_brl:5.0, exchange_rate_source:'manual', notes:'', items:[] }));
    const emptyItemForm = _h?.emptyItemForm || (() => ({ product_id:'', expected_qty:1, unit_cost_usd:0, notes:'' }));

    // === Hooks (TODOS antes de early return) ===
    const [carriers, setCarriers] = useState([]);
    const [products, setProducts] = useState([]);
    const [notes, setNotes] = useState([]);
    const [items, setItems] = useState([]); // todos items das notas (pra mostrar no view)
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    const [filterCarrierId, setFilterCarrierId] = useState('');
    const [filterStatus, setFilterStatus] = useState('all'); // all|abertas|fechadas
    const [searchQ, setSearchQ] = useState('');

    const [modalMode, setModalMode] = useState(null); // 'new'|'edit'|'view'|null
    const [modalNoteId, setModalNoteId] = useState(null); // regra_state_id_vs_objeto
    const [form, setForm] = useState(emptyForm());
    const [itemForm, setItemForm] = useState(emptyItemForm());
    const [saving, setSaving] = useState(false);
    const [actionInFlight, setActionInFlight] = useState(false);

    const isAdmin = user?.role === 'admin';
    const canManage = user?.role === 'admin' || user?.role === 'freight_manager';

    // === Loaders ===
    const loadAll = useCallback(async () => {
      if (typeof sb === 'undefined' || !sb.from) return;
      setLoading(true);
      setError(null);
      try {
        const [c, p, n, i] = await Promise.all([
          sb.from('freight_carriers').select('id,name,active').is('deleted_at', null).order('name'),
          sb.from('products').select('id,name,brand,volume,categoria').is('deleted_at', null).eq('active', true).order('name').limit(2000),
          sb.from('freight_notes').select('*').is('deleted_at', null).order('emitted_at', { ascending: false }).limit(1000),
          sb.from('freight_note_items').select('id,note_id,product_id,expected_qty,received_qty,unit_cost_usd,notes').limit(5000),
        ]);
        if (c.error) throw c.error;
        if (p.error) throw p.error;
        if (n.error) throw n.error;
        if (i.error) throw i.error;
        setCarriers(c.data || []);
        setProducts(p.data || []);
        setNotes(n.data || []);
        setItems(i.data || []);
      } catch (e) {
        console.error('[NotasFrete] load error:', e);
        setError(e?.message || String(e));
        if (typeof Sentry !== 'undefined') Sentry.captureException(e, { extra: { context: 'NotasFrete.loadAll' } });
      } finally {
        setLoading(false);
      }
    }, []);

    useEffect(() => {
      // [v224.72] cancelled flag preventivo · full fix = passar cancelled pra loadAll (deferred)
      let cancelled = false;
      loadAll();
      return () => { cancelled = true; };
    }, [loadAll]);

    // === Derivados ===
    const carrierMap = useMemo(() => Object.fromEntries(carriers.map(c => [c.id, c])), [carriers]);
    const productMap = useMemo(() => Object.fromEntries(products.map(p => [p.id, p])), [products]);

    const filteredNotes = useMemo(() => {
      let list = notes;
      if (filterCarrierId) list = list.filter(n => n.carrier_id === filterCarrierId);
      if (filterStatus === 'abertas') {
        list = list.filter(n => ['EMITIDA','CONFIRMADA_FRETEIRO','EM_TRANSITO','EM_RECEBIMENTO','EM_DISPUTA'].includes(n.status));
      } else if (filterStatus === 'fechadas') {
        list = list.filter(n => ['COMPLETA','FECHADA_COM_PERDA','EXTRAVIADA','CANCELADA'].includes(n.status));
      }
      const q = searchQ.trim().toLowerCase();
      if (q) {
        list = list.filter(n =>
          (n.number || '').toLowerCase().includes(q) ||
          (carrierMap[n.carrier_id]?.name || '').toLowerCase().includes(q) ||
          (n.freight_model || '').toLowerCase().includes(q)
        );
      }
      return list;
    }, [notes, filterCarrierId, filterStatus, searchQ, carrierMap]);

    const stats = useMemo(() => {
      const open = notes.filter(n => ['EMITIDA','CONFIRMADA_FRETEIRO','EM_TRANSITO','EM_RECEBIMENTO','EM_DISPUTA'].includes(n.status)).length;
      const em_transito = notes.filter(n => n.status === 'EM_TRANSITO').length;
      const completa = notes.filter(n => n.status === 'COMPLETA').length;
      const com_perda = notes.filter(n => n.status === 'FECHADA_COM_PERDA').length;
      return { open, em_transito, completa, com_perda };
    }, [notes]);

    // Lookup nota selecionada (regra_state_id_vs_objeto)
    const modalNote = useMemo(
      () => modalNoteId ? notes.find(n => n.id === modalNoteId) : null,
      [modalNoteId, notes]
    );
    const modalNoteItems = useMemo(
      () => modalNote ? items.filter(i => i.note_id === modalNote.id) : [],
      [modalNote, items]
    );

    // === Handlers ===
    function openNewModal() {
      setModalNoteId(null);
      setForm(emptyForm());
      setItemForm(emptyItemForm());
      setModalMode('new');
    }
    function openEditModal(note) {
      setModalNoteId(note.id);
      const noteItems = items.filter(i => i.note_id === note.id);
      setForm({
        carrier_id: note.carrier_id,
        freight_model: note.freight_model || '',
        total_cost_usd: Number(note.total_cost_usd) || 0,
        exchange_rate_usd_brl: Number(note.exchange_rate_usd_brl) || 5.0,
        exchange_rate_source: note.exchange_rate_source || 'manual',
        notes: note.notes || '',
        items: noteItems.map(i => ({
          product_id: i.product_id,
          expected_qty: Number(i.expected_qty),
          unit_cost_usd: Number(i.unit_cost_usd),
          notes: i.notes || '',
        })),
      });
      setItemForm(emptyItemForm());
      setModalMode('edit');
    }
    function openViewModal(note) {
      setModalNoteId(note.id);
      setModalMode('view');
    }
    function closeModal() {
      setModalMode(null);
      setModalNoteId(null);
      setForm(emptyForm());
      setItemForm(emptyItemForm());
    }

    function addItemToForm() {
      if (!itemForm.product_id) { toast('Selecione um produto', 'error'); return; }
      const qty = Number(itemForm.expected_qty);
      if (!qty || qty <= 0) { toast('Quantidade > 0', 'error'); return; }
      if (Number(itemForm.unit_cost_usd) < 0) { toast('Custo USD não pode ser negativo', 'error'); return; }
      // Dedup: já tem esse product_id?
      if (form.items.some(i => i.product_id === itemForm.product_id)) {
        toast('Esse produto já está na lista. Edite a quantidade na linha.', 'error');
        return;
      }
      setForm(f => ({ ...f, items: [...f.items, { ...itemForm }] }));
      setItemForm(emptyItemForm());
    }
    function removeItemFromForm(idx) {
      setForm(f => ({ ...f, items: f.items.filter((_, i) => i !== idx) }));
    }

    async function handleSubmit() {
      if (!canManage) { toast('⛔ Sem permissão.', 'error'); return; }
      if (saving) return;
      // Validação
      if (!form.carrier_id) { toast('Selecione um freteiro', 'error'); return; }
      if (form.items.length === 0) { toast('Adicione ao menos 1 item', 'error'); return; }
      if (Number(form.exchange_rate_usd_brl) <= 0) { toast('Câmbio USD/BRL deve ser > 0', 'error'); return; }
      if (Number(form.total_cost_usd) < 0) { toast('Custo total não pode ser negativo', 'error'); return; }

      setSaving(true);
      try {
        const idem = (window.crypto?.randomUUID?.() || (Date.now() + '-' + Math.random()));
        if (modalMode === 'new') {
          const { data, error } = await sb.rpc('create_freight_note_v1', {
            payload: {
              idempotency_key: idem,
              carrier_id: form.carrier_id,
              freight_model: form.freight_model || null,
              total_cost_usd: Number(form.total_cost_usd),
              exchange_rate_usd_brl: Number(form.exchange_rate_usd_brl),
              exchange_rate_source: form.exchange_rate_source || 'manual',
              notes: form.notes || null,
              items: form.items.map(it => ({
                product_id: it.product_id,
                expected_qty: Number(it.expected_qty),
                unit_cost_usd: Number(it.unit_cost_usd),
                notes: it.notes || null,
              })),
            },
          });
          if (error) throw error;
          if (!data?.success) throw new Error(data?.error_message || 'Falha ao criar nota');
          toast('✅ Nota criada: ' + (data.number || ''));
        } else if (modalMode === 'edit') {
          if (!modalNoteId) { toast('ID da nota inválido', 'error'); return; }
          const { data, error } = await sb.rpc('update_freight_note_v1', {
            payload: {
              note_id: modalNoteId,
              freight_model: form.freight_model || null,
              total_cost_usd: Number(form.total_cost_usd),
              exchange_rate_usd_brl: Number(form.exchange_rate_usd_brl),
              exchange_rate_source: form.exchange_rate_source,
              notes: form.notes || null,
              items: form.items.map(it => ({
                product_id: it.product_id,
                expected_qty: Number(it.expected_qty),
                unit_cost_usd: Number(it.unit_cost_usd),
                notes: it.notes || null,
              })),
            },
          });
          if (error) throw error;
          if (!data?.success) throw new Error(data?.error_message || 'Falha ao editar nota');
          toast('✅ Nota atualizada');
        }
        closeModal();
        await loadAll();
      } catch (e) {
        console.error('[NotasFrete] submit error:', e);
        toast('❌ ' + (e?.message || 'Erro inesperado'), 'error');
        if (typeof Sentry !== 'undefined') Sentry.captureException(e, { extra: { context: 'NotasFrete.handleSubmit', modalMode } });
      } finally {
        setSaving(false);
      }
    }

    async function handleConfirmPickup(noteId) {
      if (actionInFlight) return;
      setActionInFlight(true);
      try {
        const idem = (window.crypto?.randomUUID?.() || (Date.now() + '-' + Math.random()));
        const { data, error } = await sb.rpc('confirm_carrier_pickup_v1', { p_note_id: noteId, p_idempotency_key: idem });
        if (error) throw error;
        if (!data?.success) throw new Error(data?.error_message || 'Falha');
        toast('✅ Pickup confirmado');
        await loadAll();
      } catch (e) {
        toast('❌ ' + (e?.message || 'Erro'), 'error');
        if (typeof Sentry !== 'undefined') Sentry.captureException(e, { extra: { context: 'NotasFrete.handleConfirmPickup', noteId } });
      } finally {
        setActionInFlight(false);
      }
    }

    async function handleMarkInTransit(noteId) {
      if (actionInFlight) return;
      setActionInFlight(true);
      try {
        const idem = (window.crypto?.randomUUID?.() || (Date.now() + '-' + Math.random()));
        const { data, error } = await sb.rpc('mark_carrier_in_transit_v1', { p_note_id: noteId, p_idempotency_key: idem });
        if (error) throw error;
        if (!data?.success) throw new Error(data?.error_message || 'Falha');
        toast('✅ Em trânsito');
        await loadAll();
      } catch (e) {
        toast('❌ ' + (e?.message || 'Erro'), 'error');
        if (typeof Sentry !== 'undefined') Sentry.captureException(e, { extra: { context: 'NotasFrete.handleMarkInTransit', noteId } });
      } finally {
        setActionInFlight(false);
      }
    }

    // === Privacy guard ===
    if (!canManage && user?.role !== 'financeiro') {
      return (
        <div style={{ padding: 40, textAlign: 'center' }}>
          <div style={{ fontSize: 48, marginBottom: 10 }}>🔒</div>
          <div style={{ fontSize: 18, fontWeight: 700, color: '#B91C1C' }}>Acesso restrito</div>
          <div style={{ fontSize: 13, color: '#6B7280', marginTop: 6 }}>
            Apenas admin, freight_manager e financeiro podem ver notas de frete.
          </div>
        </div>
      );
    }

    // === Total da nota em edição (preview) ===
    const formTotalUSD = useMemo(
      () => form.items.reduce((s, i) => s + Number(i.expected_qty || 0) * Number(i.unit_cost_usd || 0), 0),
      [form.items]
    );
    const formTotalBRL = useMemo(
      () => formTotalUSD * Number(form.exchange_rate_usd_brl || 0),
      [formTotalUSD, form.exchange_rate_usd_brl]
    );

    return (
      <div className="page-content" style={{ padding: 24 }}>
        {/* Header */}
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 18, flexWrap: 'wrap', gap: 12 }}>
          <div>
            <div style={{ fontSize: 22, fontWeight: 800, color: '#1B2A4A', display: 'flex', alignItems: 'center', gap: 8 }}>
              📋 Notas de Frete
            </div>
            <div style={{ fontSize: 12, color: '#6B7280', marginTop: 2 }}>
              Criação e gestão de notas PY→BR · estado da rota
            </div>
          </div>
          {canManage && (
            <button className="btn-gold" onClick={openNewModal} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <Icon n="plus" size={14} /> Nova Nota
            </button>
          )}
        </div>

        {/* [Wave NotasFrete v223.23] Stats → Primitives.StatCard */}
        {_Primitives?.StatCard && (
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(160px, 1fr))', gap: 12, marginBottom: 20 }}>
            <_Primitives.StatCard label="Em aberto" value={stats.open} color="#2563EB" icon="file" />
            <_Primitives.StatCard label="Em trânsito" value={stats.em_transito} color="#EA580C" icon="truck" />
            <_Primitives.StatCard label="Completas" value={stats.completa} color="#16A34A" icon="check" />
            <_Primitives.StatCard label="Com perda" value={stats.com_perda} color="#DC2626" icon="alert" />
          </div>
        )}

        {/* [Wave NotasFrete v223.23] Filtros + Tabela → NotasFreteList widget */}
        {_NotasFreteList ? (
          <_NotasFreteList
            data={{filteredNotes, items, carriers, carrierMap, loading, error, canManage}}
            filters={{filterCarrierId, setFilterCarrierId, filterStatus, setFilterStatus, searchQ, setSearchQ}}
            actions={{openViewModal, handleConfirmPickup, handleMarkInTransit, actionInFlight}}
            helpers={{fmtUSD, fmtShortDate, Th: _Primitives?.Th, statusBadge: _Primitives?.statusBadge}}/>
        ) : <div style={{padding:12,color:'#DC2626'}}>⚠️ NotasFreteList widget não carregou.</div>}

        {/* [Wave NotasFrete v223.23] Modal NEW/EDIT → NotaFreteFormModal widget */}
        {(modalMode === 'new' || modalMode === 'edit') && _NotaFreteFormModal && (
          <_NotaFreteFormModal
            form={{state: form, setState: setForm, items: form.items, saving}}
            itemForm={{state: itemForm, setState: setItemForm}}
            config={{carriers, products, productMap, modalMode, formTotalUSD, formTotalBRL}}
            actions={{onClose: closeModal, onSave: handleSubmit, onAddItem: addItemToForm, onRemoveItem: removeItemFromForm}}
            helpers={{fmtUSD, fmtBRL, Th: _Primitives?.Th, Field: _Primitives?.Field}}/>
        )}
        {(modalMode === 'new' || modalMode === 'edit') && !_NotaFreteFormModal && (
          <div style={{padding:12,color:'#DC2626'}}>⚠️ NotaFreteFormModal widget não carregou.</div>
        )}

        {/* [Wave NotasFrete v223.23] Modal VIEW → NotaFreteViewModal widget */}
        {modalMode === 'view' && modalNote && _NotaFreteViewModal && (
          <_NotaFreteViewModal
            note={modalNote}
            items={modalNoteItems}
            carrier={carrierMap[modalNote.carrier_id]}
            productMap={productMap}
            canManage={canManage}
            actions={{
              onClose: closeModal,
              onEdit: () => { closeModal(); openEditModal(modalNote); },
              handleConfirmPickup, handleMarkInTransit, actionInFlight
            }}
            helpers={{fmtUSD, fmtShortDate, ViewStat: _Primitives?.ViewStat, Th: _Primitives?.Th, statusBadge: _Primitives?.statusBadge}}/>
        )}
        {modalMode === 'view' && modalNote && !_NotaFreteViewModal && (
          <div style={{padding:12,color:'#DC2626'}}>⚠️ NotaFreteViewModal widget não carregou.</div>
        )}
      </div>
    );
  }

  // ══════════════════════════════════════════════════════════════
  // SUB-COMPONENTES — [Wave NotasFrete 2026-05-19 v223.23] MOVIDOS PRA:
  //   - js/components/widgets/notas_frete/Primitives.jsx
  //   (StatCard, ViewStat, Th, Field, statusBadge)
  // ══════════════════════════════════════════════════════════════

  // ══════════════════════════════════════════════════════════════
  // EXPORT
  // ══════════════════════════════════════════════════════════════
  window.ZNX = window.ZNX || {};
  window.ZNX.components = window.ZNX.components || {};
  window.ZNX.components.NotasFrete = NotasFrete;
  window.NotasFrete = NotasFrete;

  window.ZNX.refactor_phase_6_loaded = window.ZNX.refactor_phase_6_loaded || {};
  window.ZNX.refactor_phase_6_loaded.NotasFrete = true;
})();
