// Root App — auth gate, screen routing, global state, API layer.

// API_BASE:
//   - vazio = same origin (production via Caddy)
//   - override via window.PERICIEI_API_BASE em config.js (dev sem Caddy)
const API_BASE = (window.PERICIEI_API_BASE ?? '').replace(/\/$/, '');
const LS = {
  TOKEN:  'periciei.token',       // JWT do usuário logado
  TENANT: 'periciei.tenant',
  USER:   'periciei.user',
};

// Fetch wrapper — injeta Authorization: Bearer e trata expiração.
function apiFetch(path, opts = {}) {
  const token = localStorage.getItem(LS.TOKEN);
  const headers = { ...(opts.headers || {}) };
  if (token) headers['Authorization'] = `Bearer ${token}`;
  return fetch(`${API_BASE}${path}`, { ...opts, headers });
}

function App() {
  // ─── Auth ────────────────────────────────────────────────────────────────
  const [token, setToken] = useState(() => localStorage.getItem(LS.TOKEN));
  const [user, setUser]   = useState(() => {
    try { return JSON.parse(localStorage.getItem(LS.USER) || 'null'); } catch { return null; }
  });

  // ─── Domain state ────────────────────────────────────────────────────────
  // Inicializa vazio. Tudo vem da API — sem mocks vazando pra UI real.
  const [tenant, setTenant]     = useState(() => {
    try { return JSON.parse(localStorage.getItem(LS.TENANT) || 'null') || null; }
    catch { return null; }
  });
  const [usage, setUsage]       = useState({ credit_balance: 0, can_create_analysis: false });
  const [periciaTypes, setPericiaTypes] = useState([]);
  const [analyses, setAnalyses] = useState([]);
  const [billing, setBilling]   = useState([]);

  // ─── Navigation ─────────────────────────────────────────────────────────
  const [screen, setScreen]           = useState('dashboard'); // dashboard | analises | settings | analise-detalhe
  const [activeAnalysisId, setActive] = useState(null);

  // ─── Modals + drawer ───────────────────────────────────────────────────
  const [showNew, setShowNew] = useState(false);
  const [showBuy, setShowBuy] = useState(false);
  const [sidebarOpen, setSidebarOpen] = useState(false);
  // PDF protegido: backend devolveu 422 PDF_PASSWORD_REQUIRED/INVALID e
  // estamos aguardando senha do usuário pra retentar o mesmo upload.
  const [pdfPasswordPrompt, setPdfPasswordPrompt] = useState(null); // {bundle, error}

  // ─── Effects: fetch real data; fall back silently if backend offline. ───
  useEffect(() => {
    if (!token) return;
    const ctrl = new AbortController();
    (async () => {
      try {
        const me = await apiFetch('/v1/auth/me', { signal: ctrl.signal });
        if (me.status === 401) { handleLogout(); return; }
        if (me.ok) {
          const data = await me.json();
          if (data.tenant) {
            setTenant(data.tenant);
            localStorage.setItem(LS.TENANT, JSON.stringify(data.tenant));
          }
          if (data.user) {
            setUser(data.user);
            localStorage.setItem(LS.USER, JSON.stringify(data.user));
          }
        }
        const u = await apiFetch('/v1/usage', { signal: ctrl.signal });
        if (u.ok) {
          const usageData = await u.json();
          setUsage((prev) => ({ ...prev, ...usageData }));
        }
        const pt = await apiFetch('/v1/pericia-types', { signal: ctrl.signal });
        if (pt.ok) {
          const d = await pt.json();
          setPericiaTypes(Array.isArray(d) ? d : []);
        }
        const a = await apiFetch('/v1/analyses?limit=50', { signal: ctrl.signal });
        if (a.ok) {
          const data = await a.json();
          setAnalyses(Array.isArray(data.items) ? data.items : []);
        }
      } catch (_e) {
        // Backend offline: mantém estado vazio. Mostra empty states.
      }
    })();
    return () => ctrl.abort();
  }, [token]);

  // ─── Auth actions ────────────────────────────────────────────────────────
  const handleAuth = ({ token: newToken, user: newUser, tenant: newTenant }) => {
    localStorage.setItem(LS.TOKEN, newToken);
    if (newUser)   localStorage.setItem(LS.USER, JSON.stringify(newUser));
    if (newTenant) localStorage.setItem(LS.TENANT, JSON.stringify(newTenant));
    setToken(newToken);
    if (newUser)   setUser(newUser);
    if (newTenant) setTenant(newTenant);
  };
  const handleLogout = () => {
    localStorage.removeItem(LS.TOKEN);
    localStorage.removeItem(LS.TENANT);
    localStorage.removeItem(LS.USER);
    setToken(null);
    setUser(null);
    setScreen('dashboard');
  };

  // ─── Navigation helpers ──────────────────────────────────────────────────
  const navigate = (id) => {
    if (id === 'creditos') { setShowBuy(true); return; }
    setActive(null);
    setScreen(id);
  };
  const openAnalise = (id) => { setActive(id); setScreen('analise-detalhe'); };

  useEffect(() => {
    const fn = () => setShowBuy(true);
    window.addEventListener('open-buy', fn);
    return () => window.removeEventListener('open-buy', fn);
  }, []);

  // ─── New analysis submission ────────────────────────────────────────────
  // Aceita `pdf_password` opcional pra retry após backend pedir senha de PDF.
  // Mantém o bundle completo em `pdfPasswordPrompt.bundle` pra retry sem o
  // usuário re-selecionar o arquivo.
  const submitNewAnalysis = async (bundle, { pdf_password } = {}) => {
    const { file, pericia_type_code, requerente_nome, idempotency_key } = bundle;
    const fd = new FormData();
    fd.append('file', file);
    fd.append('pericia_type_code', pericia_type_code);
    if (requerente_nome) fd.append('requerente_nome', requerente_nome);
    if (pdf_password) fd.append('pdf_password', pdf_password);

    try {
      const res = await apiFetch('/v1/analyses', {
        method: 'POST',
        headers: { 'Idempotency-Key': idempotency_key },
        body: fd,
      });
      if (res.status === 402) {
        setShowNew(false);
        setPdfPasswordPrompt(null);
        setShowBuy(true);
        alert('Saldo insuficiente. Recarregue créditos antes de enviar uma nova análise.');
        return;
      }
      // PDF protegido — abrir modal de senha mantendo o file no bundle.
      if (res.status === 422) {
        const body = await res.json().catch(() => ({}));
        const code = body?.detail?.code;
        if (code === 'PDF_PASSWORD_REQUIRED' || code === 'PDF_PASSWORD_INVALID') {
          setShowNew(false);
          setPdfPasswordPrompt({
            bundle,
            error: code === 'PDF_PASSWORD_INVALID' ? 'Senha incorreta. Tente novamente.' : null,
          });
          return;
        }
      }
      if (!res.ok) {
        const body = await res.json().catch(() => ({}));
        const msg = typeof body.detail === 'string' ? body.detail : (body?.detail?.message || res.status);
        alert(`Falha ao enviar: ${msg}`);
        return;
      }
      const created = await res.json();
      setAnalyses((prev) => [{
        ...created,
        artifacts: { spreadsheet: null, report_pdf: null, memory_md: null },
        viability_result: null,
        criteria_met: null,
        events: [{ type: 'analysis.queued', at: created.created_at }],
      }, ...prev]);
      setUsage((prev) => ({ ...prev, credit_balance: Math.max(0, (prev.credit_balance ?? 0) - 1) }));
      setShowNew(false);
      setPdfPasswordPrompt(null);
      openAnalise(created.id);
    } catch (e) {
      alert(`Falha de conexão ao enviar análise: ${e.message || e}`);
    }
  };

  // ─── Purchase ────────────────────────────────────────────────────────────
  const handlePurchase = (pkg, method) => {
    setShowBuy(false);
    setTimeout(() => {
      alert(`Redirecionando para o Asaas…\n\nPacote: ${pkg.credits} créditos · ${fmtBRL.format(pkg.price)}\nMétodo: ${method.toUpperCase()}\n\nApós confirmação, o webhook creditará automaticamente sua conta.`);
      // Optimistic credit (simulado) — backend real credita via webhook Asaas
      setUsage((prev) => ({
        ...prev,
        credit_balance: (prev.credit_balance ?? 0) + pkg.credits,
        last_purchase: { credits: pkg.credits, at: new Date().toISOString() },
      }));
    }, 200);
  };

  // ─── Render: login or app shell ─────────────────────────────────────────
  if (!token) {
    return <LoginScreen onAuth={handleAuth} />;
  }

  const currentNav =
    screen === 'analise-detalhe' ? 'analises' :
    screen === 'comprar' ? 'creditos' :
    screen;

  // navega + fecha o drawer no mobile
  const navigateAndClose = (id) => {
    navigate(id);
    setSidebarOpen(false);
  };

  return (
    <div className="h-full flex flex-col">
      <div className="flex flex-1 min-h-0">
        <Sidebar
          current={currentNav}
          onNavigate={navigateAndClose}
          tenant={tenant}
          user={user}
          usage={usage}
          onLogout={handleLogout}
          isOpen={sidebarOpen}
          onClose={() => setSidebarOpen(false)}
        />
        <main className="flex-1 min-w-0 flex flex-col overflow-hidden">
          <Topbar
            title={
              screen === 'dashboard' ? 'Visão geral'
              : screen === 'analises' ? 'Análises'
              : screen === 'settings' ? 'Configurações'
              : screen === 'analise-detalhe' ? 'Detalhe da análise'
              : screen === 'admin' ? 'Painel administrativo'
              : ''
            }
            breadcrumb={null}
            onMenuClick={() => setSidebarOpen(true)}
            right={
              <>
                <button
                  onClick={() => setShowBuy(true)}
                  className="inline-flex items-center gap-1.5 sm:gap-2 text-[12.5px] text-ink-700 hover:text-ink-900 border border-ink-200 hover:border-ink-300 rounded-md px-2 sm:px-3 h-8 transition-colors whitespace-nowrap"
                  title={`${usage.credit_balance} créditos`}
                >
                  <Icon.Coins />
                  <span className="tabular whitespace-nowrap"><span className="font-semibold text-ink-900">{usage.credit_balance}</span><span className="hidden sm:inline"> créditos</span></span>
                </button>
                <Button size="sm" onClick={() => setShowNew(true)}>
                  <Icon.Plus /><span className="hidden sm:inline ml-1">Nova análise</span><span className="sm:hidden ml-0.5">Nova</span>
                </Button>
              </>
            }
          />

          <div className="flex-1 min-h-0 overflow-y-auto bg-ink-50">
            <div key={screen}>
              {screen === 'dashboard' && (
                <Dashboard
                  usage={usage}
                  analyses={analyses}
                  onOpenNew={() => setShowNew(true)}
                  onOpenBuy={() => setShowBuy(true)}
                  onOpenAnalise={openAnalise}
                />
              )}
              {screen === 'analises' && (
                <AnalisesAll
                  analyses={analyses}
                  onOpenAnalise={openAnalise}
                  onOpenNew={() => setShowNew(true)}
                />
              )}
              {screen === 'analise-detalhe' && (
                <AnalysisDetail
                  analysisId={activeAnalysisId}
                  analyses={analyses}
                  onBack={() => setScreen('dashboard')}
                  onAnalysesUpdate={setAnalyses}
                />
              )}
              {screen === 'settings' && (
                <SettingsScreen
                  tenant={tenant}
                  onTenantUpdate={setTenant}
                  billing={billing}
                />
              )}
              {screen === 'admin' && user?.role === 'SUPERADMIN' && (
                <AdminPanel />
              )}
            </div>
          </div>

          <LegalFooter />
        </main>
      </div>

      <NewAnalysisModal
        open={showNew}
        onClose={() => setShowNew(false)}
        usage={usage}
        periciaTypes={periciaTypes}
        onSubmit={submitNewAnalysis}
      />
      <BuyCreditsModal
        open={showBuy}
        onClose={() => setShowBuy(false)}
        onPurchase={handlePurchase}
      />
      <PdfPasswordModal
        open={pdfPasswordPrompt != null}
        prompt={pdfPasswordPrompt}
        onClose={() => setPdfPasswordPrompt(null)}
        onSubmit={submitNewAnalysis}
      />
    </div>
  );
}

// ─── Full analyses list (sidebar "Análises") ──────────────────────────────
function AnalisesAll({ analyses, onOpenAnalise, onOpenNew }) {
  const [statusFilter, setStatusFilter] = useState('ALL');
  const [q, setQ] = useState('');

  const filtered = analyses.filter((a) => {
    if (statusFilter !== 'ALL' && a.status !== statusFilter) return false;
    if (q.trim()) {
      const needle = q.trim().toLowerCase();
      const hay = (a.requerente_nome || '') + ' ' + a.id;
      if (!hay.toLowerCase().includes(needle)) return false;
    }
    return true;
  });

  const counts = useMemo(() => {
    const c = { ALL: analyses.length, COMPLETE: 0, INPROGRESS: 0, FAILED: 0, QUEUED: 0 };
    for (const a of analyses) {
      if (a.status === 'COMPLETE') c.COMPLETE++;
      else if (a.status === 'FAILED') c.FAILED++;
      else if (a.status === 'QUEUED') c.QUEUED++;
      else c.INPROGRESS++;
    }
    return c;
  }, [analyses]);

  const FILTERS = [
    { id: 'ALL',        label: 'Todas',        n: counts.ALL },
    { id: 'COMPLETE',   label: 'Concluídas',   n: counts.COMPLETE },
    { id: 'INPROGRESS', label: 'Em andamento', n: counts.INPROGRESS },
    { id: 'QUEUED',     label: 'Em fila',      n: counts.QUEUED },
    { id: 'FAILED',     label: 'Falhas',       n: counts.FAILED },
  ];

  return (
    <div className="px-4 sm:px-8 py-5 sm:py-7 max-w-[1280px] mx-auto">
      <div className="flex flex-wrap items-end justify-between gap-3 mb-5">
        <div>
          <h1 className="text-[19px] sm:text-[22px] font-bold text-ink-900 tracking-tightish">Análises</h1>
          <p className="mt-1 text-[12.5px] sm:text-[13px] text-ink-500">Histórico das análises do escritório.</p>
        </div>
        <Button onClick={onOpenNew}><Icon.Plus /> Nova análise</Button>
      </div>

      <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-4">
        <div className="flex flex-wrap gap-1.5 -mx-1 px-1 overflow-x-auto sm:overflow-visible">
          {FILTERS.map((f) => {
            const active = statusFilter === (f.id === 'INPROGRESS' ? 'INPROGRESS' : f.id);
            const onClick = () => setStatusFilter(f.id === 'INPROGRESS' ? 'INPROGRESS' : f.id);
            return (
              <button
                key={f.id}
                onClick={onClick}
                className={`inline-flex items-center gap-1.5 text-[12.5px] font-medium px-3 h-8 rounded-md border transition-colors shrink-0 ${
                  active
                    ? 'bg-navy-50 text-navy-800 border-navy-800/40'
                    : 'bg-white text-ink-700 border-ink-200 hover:border-ink-300'
                }`}
              >
                {f.label}
                <span className={`tabular text-[11px] ${active ? 'text-navy-800' : 'text-ink-500'}`}>{f.n}</span>
              </button>
            );
          })}
        </div>
        <div className="relative w-full sm:w-72">
          <span className="absolute left-2.5 top-1/2 -translate-y-1/2 text-ink-400"><Icon.Search /></span>
          <input
            value={q}
            onChange={(e) => setQ(e.target.value)}
            placeholder="Buscar por requerente…"
            className="w-full h-9 pl-8 pr-3 rounded-md border border-ink-200 bg-white text-[13px] placeholder:text-ink-400 focus:border-navy-800 focus:ring-2 focus:ring-navy-800/15 transition-colors"
          />
        </div>
      </div>

      {/* Mobile: lista de cards. Desktop: tabela. */}
      <div className="sm:hidden bg-white rounded-lg border border-ink-200 shadow-card divide-y divide-ink-100">
        {filtered.map((a) => {
          const inProg = (a.status !== 'COMPLETE' && a.status !== 'FAILED');
          return (
            <button
              key={a.id}
              onClick={() => onOpenAnalise(a.id)}
              className="w-full text-left px-4 py-3 flex items-center gap-3 active:bg-ink-50"
            >
              <div className="flex-1 min-w-0">
                <div className="flex items-center justify-between gap-2 mb-1">
                  <div className="text-[14px] text-ink-900 font-medium truncate">
                    {a.requerente_nome || <span className="text-ink-400">(sem nome)</span>}
                  </div>
                  {inProg ? null : <ViabilityChip value={a.viability_result} />}
                </div>
                <div className="flex items-center gap-2 text-[11.5px] text-ink-500">
                  <span className="tabular">{fmtDateTime.format(new Date(a.created_at))}</span>
                  <span>·</span>
                  <StatusBadge status={a.status} />
                </div>
              </div>
              <span className="text-ink-400 shrink-0"><Icon.ArrowR /></span>
            </button>
          );
        })}
        {filtered.length === 0 && (
          <div className="px-5 py-12 text-center text-ink-500 text-[13px]">Nenhuma análise corresponde aos filtros.</div>
        )}
      </div>

      <div className="hidden sm:block bg-white rounded-lg border border-ink-200 overflow-hidden shadow-card">
        <table className="w-full text-[13px]">
          <thead className="bg-ink-50 border-b border-ink-200">
            <tr className="text-left text-[11.5px] uppercase tracking-tracker text-ink-500 font-medium">
              <th className="px-5 py-2.5">Data</th>
              <th className="px-5 py-2.5">Requerente</th>
              <th className="px-5 py-2.5">Tipo</th>
              <th className="px-5 py-2.5">Status</th>
              <th className="px-5 py-2.5">Viabilidade</th>
              <th className="px-5 py-2.5 w-0"></th>
            </tr>
          </thead>
          <tbody>
            {filtered.map((a) => {
              const inProg = (a.status !== 'COMPLETE' && a.status !== 'FAILED');
              return (
                <tr
                  key={a.id}
                  onClick={() => onOpenAnalise(a.id)}
                  className="border-b border-ink-100 last:border-0 hover:bg-ink-50 cursor-pointer transition-colors"
                >
                  <td className="px-5 py-3 text-ink-700 tabular whitespace-nowrap">{fmtDateTime.format(new Date(a.created_at))}</td>
                  <td className="px-5 py-3 text-ink-900 font-medium">{a.requerente_nome || <span className="text-ink-400">—</span>}</td>
                  <td className="px-5 py-3 text-ink-700">
                    Revisional Veículo <span className="text-ink-400 font-mono text-[11px]">{a.pericia_version_label}</span>
                  </td>
                  <td className="px-5 py-3"><StatusBadge status={a.status} /></td>
                  <td className="px-5 py-3">
                    {inProg ? <span className="text-ink-400 text-[12px]">apurando…</span> : <ViabilityChip value={a.viability_result} />}
                  </td>
                  <td className="px-5 py-3 text-ink-400"><Icon.ArrowR /></td>
                </tr>
              );
            })}
            {filtered.length === 0 && (
              <tr><td colSpan="6" className="px-5 py-14 text-center text-ink-500 text-[13px]">Nenhuma análise corresponde aos filtros.</td></tr>
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// Exposes apiFetch globally so other screens (detail, settings) can use it.
window.apiFetch = apiFetch;
window.API_BASE = API_BASE;

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
