// js/components/pages/AuditoriaAdmin.jsx
// Tela admin "Auditoria" — leitura de admin_audit_log com filtros + diff modal
// [v123 RG5 — 2026-05-09] Permite admin ver TODAS ações sensíveis logadas pelos triggers:
// - cancel_sale, period_close/reopen, role_change, discount_request_*, cancel_request_*, etc.
// Privacy: APENAS admin (RLS no banco já garante; frontend duplica check defensivo).
//
// Regras aplicadas:
//   - regra_sistema_antes_da_feature (META) — listadas
//   - regra_state_id_vs_objeto — selectedRowId, não objeto
//   - regra_fmtdate_aceita_string_iso — fmtDate global agora defensivo
//   - regra_loading_state_obrigatorio — botão refresh com loading
//   - regra_auditoria_estado_real — refresh manual + 7d default
//   - regra_componente_vs_inline_duplicata — KCard reusado de Insights
(function() {
  'use strict';
  const {useState, useEffect, useMemo, useCallback, useRef} = React;

  // [BUGFIX 2026-05-09] fmtDateSafe era usado mas só existia em Marcas.jsx (escopo local).
  // Tab "Períodos Contábeis" crashava com "fmtDateSafe is not defined". Copia local aqui.
  // Wrapper aceita Date|string|null e normaliza pra YYYY-MM-DD antes de chamar fmtDate global.
  function fmtDateSafe(v){
    if(!v)return'—';
    let s;
    if(v instanceof Date){s=v.toISOString().split('T')[0];}
    else{s=String(v);if(s.includes('T'))s=s.split('T')[0];}
    return typeof fmtDate==='function'?fmtDate(s):s;
  }

function AuditoriaAdmin({user, allUsers}){
  const isAdmin = user?.role === 'admin';

  // States
  const [logs, setLogs] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [selectedRowId, setSelectedRowId] = useState(null);

  // Filtros
  const [filterAction, setFilterAction] = useState('');
  const [filterActor, setFilterActor] = useState('');
  const [filterTargetType, setFilterTargetType] = useState('');
  const [filterPeriod, setFilterPeriod] = useState('7d'); // hoje/7d/30d/90d/all
  const [searchText, setSearchText] = useState('');

  // Carregar logs
  const loadLogs = useCallback(async () => {
    if(!isAdmin) return;
    setLoading(true);
    setError(null);
    try {
      let query = sb.from('admin_audit_log')
        .select('*')
        .order('created_at', {ascending: false})
        .limit(500);

      // Filtro período
      if(filterPeriod !== 'all'){
        const days = filterPeriod === 'hoje' ? 1 : filterPeriod === '7d' ? 7 : filterPeriod === '30d' ? 30 : 90;
        const cut = new Date(Date.now() - days*86400000).toISOString();
        query = query.gte('created_at', cut);
      }

      const {data, error: qErr} = await query;
      if(qErr) throw qErr;
      setLogs(data || []);
    } catch(e){
      console.error('[AuditoriaAdmin] erro:', e);
      setError(e?.message || String(e));
      if(typeof Sentry !== 'undefined') Sentry.captureException(e, {extra:{context:'AuditoriaAdmin.loadLogs'}});
    } finally {
      setLoading(false);
    }
  }, [filterPeriod, isAdmin]);

  useEffect(() => {
    // [v224.72] cancelled flag preventivo · setState dentro loadLogs ainda pode rodar em unmount (full fix = passar cancelled pra loadLogs · deferred)
    let cancelled = false;
    loadLogs();
    return () => { cancelled = true; };
  }, [loadLogs]);

  // [ONDA1-A 2026-05-11] regra_early_return_e_hooks — early return move pra DEPOIS de TODOS os hooks.
  // ANTES: if(!isAdmin) return <Page/> aqui, mas useMemo/useState/useCallback/useRef vinham DEPOIS
  // → admin viraria não-admin (state external change) e React error #300 (hooks count mismatch).
  // Helpers
  const userName = useCallback((uid) => {
    if(!uid) return '—';
    if(uid === '00000000-0000-0000-0000-000000000000') return 'Sistema';
    const u = (allUsers||[]).find(x => x.auth_user_id === uid || x.id === uid);
    return u?.name || uid.slice(0,8) + '...';
  }, [allUsers]);

  const actionLabel = (action) => {
    if(!action) return '—';
    const map = {
      'sale_status_change_to_cancelada': '🚫 Cancelar venda',
      'sale_status_change_to_devolvida_(total)': '↩️ Devolução total',
      'sale_status_change_to_devolvida_(parcial)': '↩️ Devolução parcial',
      'sale_status_change_to_cancelada_(devolução)': '🚫 Cancelar (devolução)',
      'discount_request_approved': '✅ Aprovar desconto',
      'discount_request_denied': '❌ Recusar desconto',
      'discount_request_aprovado': '✅ Aprovar desconto',
      'discount_request_recusado': '❌ Recusar desconto',
      'cancel_request_approved': '✅ Aprovar cancelamento',
      'cancel_request_denied': '❌ Recusar cancelamento',
      'cancel_request_aprovado': '✅ Aprovar cancelamento',
      'cancel_request_recusado': '❌ Recusar cancelamento',
      'user_role_change': '👤 Mudar role usuário',
      'period_close': '📅 Fechar período contábil',
      'period_reopen': '🔓 Reabrir período',
      'hard_delete_bypass': '⚠️ DELETE forçado (emergency)'
    };
    return map[action] || action;
  };

  const actionColor = (action) => {
    if(!action) return '#9CA3AF';
    if(action.includes('approved') || action.includes('aprovado')) return '#15803D';
    if(action.includes('denied') || action.includes('recusado')) return '#B91C1C';
    if(action.includes('cancel') || action.includes('hard_delete')) return '#DC2626';
    if(action.includes('devolvida') || action.includes('devolu')) return '#EA580C';
    if(action.includes('period_close')) return '#2563EB';
    if(action.includes('period_reopen')) return '#7C3AED';
    if(action.includes('role_change')) return '#0891B2';
    return '#374151';
  };

  // Aplicar filtros locais
  const filtered = useMemo(() => {
    let arr = logs;
    if(filterAction) arr = arr.filter(l => l.action === filterAction);
    if(filterActor) arr = arr.filter(l => l.actor_id === filterActor);
    if(filterTargetType) arr = arr.filter(l => l.target_type === filterTargetType);
    if(searchText){
      const q = searchText.trim().toLowerCase();
      arr = arr.filter(l =>
        (l.action||'').toLowerCase().includes(q) ||
        (l.target_id||'').toLowerCase().includes(q) ||
        (l.reason||'').toLowerCase().includes(q) ||
        userName(l.actor_id).toLowerCase().includes(q) ||
        JSON.stringify(l.metadata||{}).toLowerCase().includes(q)
      );
    }
    return arr;
  }, [logs, filterAction, filterActor, filterTargetType, searchText, userName]);

  // Stats topo
  const stats = useMemo(() => {
    const total = filtered.length;
    const last24h = filtered.filter(l => new Date(l.created_at) > new Date(Date.now()-86400000)).length;
    const actionCounts = {};
    const actorCounts = {};
    filtered.forEach(l => {
      actionCounts[l.action] = (actionCounts[l.action]||0) + 1;
      actorCounts[l.actor_id] = (actorCounts[l.actor_id]||0) + 1;
    });
    const topAction = Object.entries(actionCounts).sort((a,b)=>b[1]-a[1])[0];
    const topActor = Object.entries(actorCounts).sort((a,b)=>b[1]-a[1])[0];
    return {total, last24h, topAction, topActor};
  }, [filtered]);

  // Opções dropdown únicos
  const uniqueActions = useMemo(() => [...new Set(logs.map(l=>l.action))].sort(), [logs]);
  const uniqueTargetTypes = useMemo(() => [...new Set(logs.map(l=>l.target_type))].filter(Boolean).sort(), [logs]);
  const uniqueActors = useMemo(() => {
    const ids = [...new Set(logs.map(l=>l.actor_id))].filter(Boolean);
    return ids.map(id => ({id, name: userName(id)})).sort((a,b)=>a.name.localeCompare(b.name));
  }, [logs, userName]);

  // Linha selecionada (lookup fresco)
  const selectedRow = selectedRowId ? logs.find(l => l.id === selectedRowId) : null;

  // [v128 P1-FAKE1 RG3 — 2026-05-09] Tab "Períodos Contábeis" — admin fecha mês de verdade
  const [activeTab, setActiveTab] = useState('logs');
  const [periods, setPeriods] = useState([]);
  const [periodsLoading, setPeriodsLoading] = useState(false);
  const [periodSaving, setPeriodSaving] = useState(false);
  const _periodInFlightRef = useRef(false);
  // [ONDA1-A 2026-05-11] regra_loading_state_obrigatorio — reopenPeriod precisa inflight
  const _reopenInFlightRef = useRef(false);
  const [reopening, setReopening] = useState(null); // period.id sendo reaberto

  const loadPeriods = useCallback(async () => {
    if(!isAdmin) return;
    setPeriodsLoading(true);
    try {
      const {data, error} = await sb.from('closed_periods').select('*').order('start_date', {ascending: false}).limit(50);
      if(error) throw error;
      setPeriods(data || []);
    } catch(e){
      console.error('[Auditoria] erro periods:', e);
      if(typeof Sentry !== 'undefined') Sentry.captureException(e, {extra:{context:'AuditoriaAdmin.loadPeriods'}});
    } finally { setPeriodsLoading(false); }
  }, [isAdmin]);

  useEffect(() => { if(activeTab === 'periods') loadPeriods(); }, [activeTab, loadPeriods]);

  async function closePeriod(){
    if(_periodInFlightRef.current) return;
    const today = new Date();
    const monthStart = new Date(today.getFullYear(), today.getMonth(), 1).toISOString().slice(0,10);
    const monthEnd = new Date(today.getFullYear(), today.getMonth()+1, 0).toISOString().slice(0,10);
    const monthLabel = today.toLocaleString('pt-BR', {month:'long', year:'numeric'});
    if(!await showConfirm({
      title: 'Fechar mês de ' + monthLabel + '?',
      message: 'Vai bloquear EDIÇÃO/EXCLUSÃO de qualquer venda, pagamento, recebível ou gasto cuja data caia no período ' + monthStart + ' até ' + monthEnd + '.\n\nReabrir só com justificativa de 10+ caracteres.\n\nConfirma?',
      confirmText: 'Sim, fechar',
      confirmColor: '#DC2626'
    })) return;
    _periodInFlightRef.current = true;
    setPeriodSaving(true);
    try {
      const {data, error} = await sb.rpc('close_period', {p_start_date: monthStart, p_end_date: monthEnd, p_notes: 'Fechamento mensal via tela admin Auditoria'});
      if(error){ toast('❌ ' + error.message); return; }
      toast('✅ Período ' + monthLabel + ' fechado. ID: ' + data);
      await loadPeriods();
    } catch(e){
      toast('❌ ' + (e.message || String(e)));
      if(typeof Sentry !== 'undefined') Sentry.captureException(e, {extra:{context:'closePeriod'}});
    } finally {
      _periodInFlightRef.current = false;
      setPeriodSaving(false);
    }
  }

  async function reopenPeriod(period){
    // [ONDA1-A 2026-05-11] regra_loading_state_obrigatorio — ref + state pra disabled no botão.
    if(_reopenInFlightRef.current){ toast('⏳ Reabrindo, aguarde…'); return; }
    const reason = window.prompt('Motivo pra reabrir o período de ' + period.start_date + ' a ' + period.end_date + ' (mín 10 caracteres):');
    if(!reason || reason.trim().length < 10){ toast('⚠ Motivo obrigatório (mín 10 chars)'); return; }
    _reopenInFlightRef.current = true;
    setReopening(period.id);
    try {
      const {error} = await sb.rpc('reopen_period', {p_period_id: period.id, p_reason: reason.trim()});
      if(error){ toast('❌ ' + error.message); return; }
      toast('✅ Período reaberto');
      await loadPeriods();
    } catch(e){
      toast('❌ ' + (e.message || String(e)));
    } finally {
      _reopenInFlightRef.current = false;
      setReopening(null);
    }
  }

  // [ONDA1-A 2026-05-11] regra_early_return_e_hooks — Privacy guard frontend DEPOIS de todos os hooks.
  if(!isAdmin){
    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 administradores podem ver auditoria de ações.</div>
      </div>
    );
  }

  // [Wave W1 PLAN 2026-05-18 v223.21] Bloco agregado refs+fail-loud — 5 widgets auditoria/
  // regra_estender_bloco_refs_fail_loud + regra_validacao_helpers_runtime_quando_ordem_scripts_uncertain.
  const _StatsCards = window.ZNX?.widgets?.auditoria?.StatsCards;
  const _FiltersBar = window.ZNX?.widgets?.auditoria?.FiltersBar;
  const _LogsTable = window.ZNX?.widgets?.auditoria?.LogsTable;
  const _PeriodsTab = window.ZNX?.widgets?.auditoria?.PeriodsTab;
  const _DetailsModal = window.ZNX?.widgets?.auditoria?.DetailsModal;
  const _missingWidgets = [];
  if (!_StatsCards) _missingWidgets.push('StatsCards');
  if (!_FiltersBar) _missingWidgets.push('FiltersBar');
  if (!_LogsTable) _missingWidgets.push('LogsTable');
  if (!_PeriodsTab) _missingWidgets.push('PeriodsTab');
  if (!_DetailsModal) _missingWidgets.push('DetailsModal');
  if (_missingWidgets.length > 0) {
    if (typeof window.znxCaptureRpcError === 'function') {
      window.znxCaptureRpcError('AuditoriaAdmin_widgets_missing', {
        missing: _missingWidgets,
        hint: 'Verificar js/components/widgets/auditoria/*.jsx carregaram em index.html'
      });
    }
    console.error('[AuditoriaAdmin] widgets faltando:', _missingWidgets);
  }

  return (
    <div>
      <div className="page-header">
        <div className="page-title">🛡️ Auditoria & Compliance</div>
        <div style={{display:'flex',gap:8}}>
          {activeTab === 'logs' && (
            <button className="btn-gold" onClick={loadLogs} disabled={loading} style={{display:'flex',alignItems:'center',gap:6}}>
              {loading ? '⏳ Carregando...' : '🔄 Atualizar'}
            </button>
          )}
          {activeTab === 'periods' && (
            <button className="btn-danger" onClick={closePeriod} disabled={periodSaving}>
              {periodSaving ? '⏳ Fechando...' : '📅 Fechar Mês Atual'}
            </button>
          )}
        </div>
      </div>

      {/* [L4 2026-05-09] Banner explicativo — Jamal não entendia pra que serve a página */}
      <div style={{background:'linear-gradient(135deg,#FEF3C7,#FDE68A)',border:'1px solid #D97706',borderRadius:10,padding:'14px 18px',marginBottom:14,fontSize:12.5}}>
        <div style={{display:'flex',gap:14,alignItems:'flex-start'}}>
          <div style={{fontSize:28}}>🛡️</div>
          <div style={{flex:1}}>
            <div style={{fontWeight:800,color:'#92400E',fontSize:14,marginBottom:6}}>O que é esta página?</div>
            <div style={{color:'#78350F',lineHeight:1.6,marginBottom:8}}>
              Aqui você vê <strong>tudo que foi alterado no sistema por funcionários</strong> — cancelamentos de venda, devoluções,
              aprovações/recusas de desconto, mudanças de role, fechamentos de mês contábil, etc. Tudo com <strong>quem fez · quando · por quê</strong>.
            </div>
            <div style={{color:'#78350F',lineHeight:1.6}}>
              <strong>Pra que serve:</strong> investigar incidentes ("quem cancelou a venda X?") · provar compliance ·
              detectar abuso (vendedora fazendo muito desconto) · histórico fiscal (períodos contábeis fechados).
            </div>
            <div style={{marginTop:10,display:'flex',flexWrap:'wrap',gap:6}}>
              <span style={{padding:'3px 10px',background:'#fff',borderRadius:12,fontSize:11,color:'#78350F',fontWeight:600}}>📋 Aba "Logs": tudo que mudou</span>
              <span style={{padding:'3px 10px',background:'#fff',borderRadius:12,fontSize:11,color:'#78350F',fontWeight:600}}>📅 Aba "Períodos": fechar mês contábil (impede edição retroativa)</span>
            </div>
          </div>
        </div>
      </div>

      {/* [L4] Filtros rápidos em 1 clique — pra o admin não precisar mexer em 4 dropdowns */}
      {activeTab === 'logs' && (
        <div style={{display:'flex',gap:8,flexWrap:'wrap',marginBottom:14}}>
          <button onClick={()=>{setFilterPeriod('hoje');setFilterAction('');setFilterActor('');setFilterTargetType('');setSearchText('');}}
            style={{padding:'8px 14px',background:filterPeriod==='hoje'&&!filterAction?'#1B2A4A':'#F3F4F6',color:filterPeriod==='hoje'&&!filterAction?'#fff':'#374151',border:'none',borderRadius:6,fontSize:12,fontWeight:600,cursor:'pointer'}}>
            🕐 Apenas hoje
          </button>
          <button onClick={()=>{setSearchText('cancel');setFilterPeriod('30d');setFilterAction('');setFilterActor('');setFilterTargetType('');}}
            style={{padding:'8px 14px',background:searchText==='cancel'?'#DC2626':'#F3F4F6',color:searchText==='cancel'?'#fff':'#374151',border:'none',borderRadius:6,fontSize:12,fontWeight:600,cursor:'pointer'}}>
            🚫 Só Cancelamentos
          </button>
          <button onClick={()=>{setSearchText('discount');setFilterPeriod('30d');setFilterAction('');setFilterActor('');setFilterTargetType('');}}
            style={{padding:'8px 14px',background:searchText==='discount'?'#15803D':'#F3F4F6',color:searchText==='discount'?'#fff':'#374151',border:'none',borderRadius:6,fontSize:12,fontWeight:600,cursor:'pointer'}}>
            💰 Só Descontos
          </button>
          <button onClick={()=>{setSearchText('role');setFilterPeriod('all');setFilterAction('');setFilterActor('');setFilterTargetType('');}}
            style={{padding:'8px 14px',background:searchText==='role'?'#0891B2':'#F3F4F6',color:searchText==='role'?'#fff':'#374151',border:'none',borderRadius:6,fontSize:12,fontWeight:600,cursor:'pointer'}}>
            👤 Mudança de Role
          </button>
          <button onClick={()=>{setSearchText('period');setFilterPeriod('all');setFilterAction('');setFilterActor('');setFilterTargetType('');}}
            style={{padding:'8px 14px',background:searchText==='period'?'#2563EB':'#F3F4F6',color:searchText==='period'?'#fff':'#374151',border:'none',borderRadius:6,fontSize:12,fontWeight:600,cursor:'pointer'}}>
            📅 Períodos Contábeis
          </button>
          <button onClick={()=>{setSearchText('');setFilterPeriod('7d');setFilterAction('');setFilterActor('');setFilterTargetType('');}}
            style={{padding:'8px 14px',background:'transparent',color:'#6B7280',border:'1px solid #E4E7EC',borderRadius:6,fontSize:12,fontWeight:600,cursor:'pointer'}}>
            ↻ Limpar filtros
          </button>
        </div>
      )}

      {/* Tab bar */}
      <div style={{display:'flex',gap:6,marginBottom:18,borderBottom:'2px solid #E4E7EC'}}>
        <button onClick={()=>setActiveTab('logs')} style={{padding:'10px 18px',border:'none',background:'transparent',color:activeTab==='logs'?'#1B2A4A':'#6B7280',fontWeight:activeTab==='logs'?700:500,fontSize:13,cursor:'pointer',borderBottom:activeTab==='logs'?'3px solid #B89840':'3px solid transparent',marginBottom:-2}}>
          📋 Logs de Ações
        </button>
        <button onClick={()=>setActiveTab('periods')} style={{padding:'10px 18px',border:'none',background:'transparent',color:activeTab==='periods'?'#1B2A4A':'#6B7280',fontWeight:activeTab==='periods'?700:500,fontSize:13,cursor:'pointer',borderBottom:activeTab==='periods'?'3px solid #B89840':'3px solid transparent',marginBottom:-2}}>
          📅 Períodos Contábeis
        </button>
      </div>

      {/* [Wave W1 v223.21] TAB Períodos Contábeis → PeriodsTab widget */}
      {activeTab === 'periods' && _PeriodsTab && (
        <_PeriodsTab periods={periods} periodsLoading={periodsLoading}
          reopenPeriod={reopenPeriod} reopening={reopening}
          userName={userName} fmtDateSafe={fmtDateSafe}/>
      )}
      {activeTab === 'periods' && !_PeriodsTab && (
        <div style={{padding:12,color:'#DC2626'}}>⚠️ PeriodsTab widget não carregou.</div>
      )}

      {/* TAB: Logs (existente) */}
      {activeTab === 'logs' && (
      <>{/* wrapper pra scope - código antigo continua abaixo */}

      {/* [Wave W1 v223.21] Stats topo 4 cards → StatsCards widget */}
      {_StatsCards ? <_StatsCards stats={stats} actionLabel={actionLabel} userName={userName}/>
        : <div style={{padding:12,color:'#DC2626'}}>⚠️ StatsCards widget não carregou.</div>}

      {/* [Wave W1 v223.21] Filtros logs → FiltersBar widget */}
      {_FiltersBar ? <_FiltersBar
        filterPeriod={filterPeriod} setFilterPeriod={setFilterPeriod}
        filterAction={filterAction} setFilterAction={setFilterAction}
        filterActor={filterActor} setFilterActor={setFilterActor}
        filterTargetType={filterTargetType} setFilterTargetType={setFilterTargetType}
        searchText={searchText} setSearchText={setSearchText}
        uniqueActions={uniqueActions} uniqueActors={uniqueActors}
        uniqueTargetTypes={uniqueTargetTypes} actionLabel={actionLabel}/>
        : <div style={{padding:12,color:'#DC2626'}}>⚠️ FiltersBar widget não carregou.</div>}

      {error && (
        <div className="card" style={{borderLeft:'4px solid #B91C1C',background:'#FEE2E2',marginBottom:14,padding:12}}>
          <strong style={{color:'#B91C1C'}}>Erro ao carregar:</strong> <span style={{color:'#7F1D1D'}}>{error}</span>
        </div>
      )}

      {/* [Wave W1 v223.21] Tabela principal logs + footer → LogsTable widget */}
      {_LogsTable ? <_LogsTable
        filtered={filtered} logs={logs} loading={loading}
        userName={userName} actionLabel={actionLabel} actionColor={actionColor}
        fmtDateSafe={fmtDateSafe} setSelectedRowId={setSelectedRowId}/>
        : <div style={{padding:12,color:'#DC2626'}}>⚠️ LogsTable widget não carregou.</div>}

      {/* [Wave W1 v223.21] Modal detalhes JSONB antes/depois → DetailsModal widget */}
      {selectedRow && _DetailsModal && (
        <_DetailsModal selectedRow={selectedRow}
          onClose={() => setSelectedRowId(null)}
          userName={userName} actionLabel={actionLabel} fmtDateSafe={fmtDateSafe}/>
      )}
      </>)}{/* fim do tab logs (P1-FAKE1 v128) */}
    </div>
  );
}

  window.ZNX = window.ZNX || {};
  window.ZNX.components = window.ZNX.components || {};
  window.ZNX.components.AuditoriaAdmin = AuditoriaAdmin;
  window.AuditoriaAdmin = AuditoriaAdmin;
})();
