const { useState, useEffect, useCallback } = React;
const API_BASE = "";

function useApi(token){
  const form = useCallback(async (path, fields, method="POST")=>{
    const r = await fetch(API_BASE+path,{method,
      headers:{"Content-Type":"application/x-www-form-urlencoded",...(token?{Authorization:`Bearer ${token}`}:{})},
      body: method==="GET"?undefined:new URLSearchParams(fields||{})});
    const d = await r.json().catch(()=>({}));
    if(!r.ok) throw new Error(d.detail||`Erro ${r.status}`);
    return d;
  },[token]);
  const get = useCallback(async (path, params)=>{
    const qs = params?"?"+new URLSearchParams(params).toString():"";
    const r = await fetch(API_BASE+path+qs,{headers: token?{Authorization:`Bearer ${token}`}:{}});
    const d = await r.json().catch(()=>({}));
    if(!r.ok) throw new Error(d.detail||`Erro ${r.status}`);
    return d;
  },[token]);
  const upload = useCallback(async (path, fd)=>{
    const r = await fetch(API_BASE+path,{method:"POST",headers: token?{Authorization:`Bearer ${token}`}:{},body:fd});
    const d = await r.json().catch(()=>({}));
    if(!r.ok) throw new Error(d.detail||`Erro ${r.status}`);
    return d;
  },[token]);
  const download = useCallback(async (path, params, fallbackName)=>{
    const qs = params?"?"+new URLSearchParams(params).toString():"";
    const r = await fetch(API_BASE+path+qs,{headers: token?{Authorization:`Bearer ${token}`}:{}});
    if(!r.ok){ const d = await r.json().catch(()=>({})); throw new Error(d.detail||`Erro ${r.status}`); }
    const blob = await r.blob();
    const cd = r.headers.get("Content-Disposition")||"";
    const m = cd.match(/filename="([^"]+)"/);
    const nome = m?m[1]:fallbackName;
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a"); a.href=url; a.download=nome; a.click();
    URL.revokeObjectURL(url);
  },[token]);
  return {form,get,upload,download};
}

function Alert({kind,children}){ if(!children) return null; return <div className={`alert-app ${kind}`} style={{whiteSpace:"pre-line"}}>{children}</div>; }
function Spin(){ return <span className="spinner-border spinner-border-sm me-2" role="status"></span>; }

function Login({onLogin}){
  const [user,setUser]=useState("admin"); const [pass,setPass]=useState("");
  const [err,setErr]=useState(""); const [loading,setLoading]=useState(false);
  const {form}=useApi(null);
  const entrar=async()=>{ setErr(""); setLoading(true);
    try{ const d=await form("/auth/login",{username:user,password:pass}); onLogin(d.access_token,d.role,user); }
    catch(e){ setErr(e.message); } finally{ setLoading(false); }
  };
  return (
    <div className="login-wrap">
      <div className="login-box">
        <div className="login-logo-img-wrap">
          <img src="logo.png" alt="CIOT HUB" className="login-logo-img"
               onError={e=>{e.target.style.display='none'; e.target.parentElement.querySelector('.login-logo-fallback').style.display='inline-flex';}}/>
          <span className="login-logo-fallback" style={{display:'none'}}><span className="dot"></span> SEFAZ Consulta</span>
        </div>
        <div className="app-card">
          <div className="app-card__body">
            <h3 className="h3 mb-1">Entrar</h3>
            <p className="text-sm" style={{color:"var(--color-text-tertiary)"}}>Acesse com seu usuário e senha.</p>
            <div className="mt-3">
              <label className="frm">Usuário</label>
              <input className="form-control" value={user} onChange={e=>setUser(e.target.value)} onKeyDown={e=>e.key==="Enter"&&entrar()} autoFocus />
            </div>
            <div className="mt-2">
              <label className="frm">Senha</label>
              <input type="password" className="form-control" value={pass} onChange={e=>setPass(e.target.value)} onKeyDown={e=>e.key==="Enter"&&entrar()} />
            </div>
            <button className="btn btn-primary w-100 mt-3" onClick={entrar} disabled={loading||!pass}>
              {loading?<><Spin/>Entrando...</>:<><i className="bi bi-box-arrow-in-right me-2"></i>Entrar</>}
            </button>
            <Alert kind="err">{err}</Alert>
          </div>
        </div>
      </div>
    </div>
  );
}


function PainelConsulta({token}){
  const {form,download}=useApi(token);
  const [chave,setChave]=useState("");
  const [res,setRes]=useState(null); const [err,setErr]=useState(""); const [loading,setLoading]=useState(false);
  const [baixando,setBaixando]=useState("");
  const soDigitos = chave.replace(/\D/g,"");

  const novaConsulta=()=>{ setChave(""); setRes(null); setErr(""); };
  const consultarNota=async()=>{ setErr(""); setRes(null); setLoading(true);
    try{ const d=await form("/documento/consultar",{chave}); setRes(d); }  // CNPJ vem do certificado no backend
    catch(e){ setErr(e.message); } finally{ setLoading(false); }
  };
  const baixar=async(tipo)=>{ if(!res) return; const ch=res.dados.chave; setBaixando(tipo);
    try{ if(tipo==="xml") await download("/documento/xml",{chave:ch},ch+".xml");
         else await download("/documento/pdf",{chave:ch},ch+".pdf"); }
    catch(e){ setErr(e.message); } finally{ setBaixando(""); }
  };
  const fmtDoc=(d)=>{ if(!d) return "—"; d=(""+d).replace(/\D/g,"");
    if(d.length===14) return `${d.slice(0,2)}.${d.slice(2,5)}.${d.slice(5,8)}/${d.slice(8,12)}-${d.slice(12)}`;
    if(d.length===11) return `${d.slice(0,3)}.${d.slice(3,6)}.${d.slice(6,9)}-${d.slice(9)}`; return d; };
  const fmtValor=(v)=>{ const n=parseFloat(v); return isNaN(n)?"—":n.toLocaleString("pt-BR",{style:"currency",currency:"BRL"}); };

  return (
    <>
      <div className="app-card">
        <div className="app-card__body">
          <div className="d-flex justify-content-between align-items-center mb-2">
            <label className="frm m-0" style={{fontSize:15,fontWeight:600,color:"var(--color-text-primary)"}}>Digite a Chave</label>
            <span className="text-sm" style={{color: soDigitos.length===44?"var(--color-success-600)":"var(--color-text-tertiary)"}}>
              Qtd. Caracteres: <strong>{soDigitos.length}</strong>{soDigitos.length===44 && <i className="bi bi-check-circle-fill ms-1"></i>}
            </span>
          </div>
          <input className="form-control font-mono mb-2" value={chave} maxLength={60} placeholder=""
                 onChange={e=>setChave(e.target.value)} onKeyDown={e=>e.key==="Enter"&&consultarNota()} autoFocus />
          <div className="row g-2 mt-1">
            <div className="col-6">
              <button className="btn btn-primary w-100 py-2" onClick={novaConsulta}>
                <i className="bi bi-file-earmark-plus me-2"></i>NOVA CONSULTA
              </button>
            </div>
            <div className="col-6">
              <button className="btn btn-primary w-100 py-2" onClick={consultarNota} disabled={loading||soDigitos.length!==44}>
                {loading?<><Spin/>BUSCANDO...</>:<><i className="bi bi-file-earmark-check me-2"></i>CONSULTA NOTA</>}
              </button>
            </div>
          </div>
          <Alert kind="err">{err}</Alert>
        </div>
      </div>

      {res && (
        <div className="app-card">
          <div className="app-card__head">
            <h3 className="h3 m-0">
              <i className="bi bi-receipt me-2" style={{color:"var(--color-brand-primary)"}}></i>{res.modelo} encontrada
              {res.origem==="sefaz"
                ? <span className="app-pill app-pill--info ms-2"><i className="bi bi-cloud-check"></i> da SEFAZ</span>
                : <span className="app-pill app-pill--neutral ms-2"><i className="bi bi-hdd"></i> local</span>}
            </h3>
            <div className="d-flex gap-1">
              <button className="icon-btn" onClick={()=>baixar("xml")} disabled={baixando==="xml"} title="Baixar XML">
                {baixando==="xml"?<span className="spinner-border spinner-border-sm"></span>:<><i className="bi bi-filetype-xml me-1"></i>XML</>}
              </button>
              <button className="icon-btn" onClick={()=>baixar("pdf")} disabled={baixando==="pdf"} title="Baixar PDF">
                {baixando==="pdf"?<span className="spinner-border spinner-border-sm"></span>:<><i className="bi bi-filetype-pdf me-1"></i>PDF</>}
              </button>
            </div>
          </div>
          <div className="app-card__body">
            <div style={{background:"var(--surface-subtle)",borderRadius:"var(--radius-md)",padding:"10px 14px",marginBottom:16}}>
              <div className="x-small" style={{color:"var(--color-text-tertiary)",textTransform:"uppercase",letterSpacing:".4px"}}>Chave de acesso</div>
              <div className="font-mono" style={{color:"var(--color-brand-primary)",fontSize:13}}>{res.dados.chave}</div>
            </div>
            <table className="app-table">
              <tbody>
                <tr><td style={{color:"var(--color-text-tertiary)",width:200}}>Natureza</td><td className="fw-medium">{res.dados.natureza||"—"}</td></tr>
                <tr><td style={{color:"var(--color-text-tertiary)"}}>Emissor</td><td className="fw-medium">{res.dados.emit_nome||res.dados.rem_nome||"—"} <span className="font-mono ms-2" style={{color:"var(--color-text-tertiary)"}}>{fmtDoc(res.dados.emit_doc||res.dados.rem_doc)}</span></td></tr>
                <tr><td style={{color:"var(--color-text-tertiary)"}}>Transportador</td><td className="fw-medium">{res.dados.transp_nome||"—"} <span className="font-mono ms-2" style={{color:"var(--color-text-tertiary)"}}>{fmtDoc(res.dados.transp_doc)}</span></td></tr>
                <tr><td style={{color:"var(--color-text-tertiary)"}}>Tomador</td><td className="fw-medium">{res.dados.toma_nome||res.dados.dest_nome||"—"} <span className="font-mono ms-2" style={{color:"var(--color-text-tertiary)"}}>{fmtDoc(res.dados.toma_doc||res.dados.dest_doc)}</span></td></tr>
                <tr><td style={{color:"var(--color-text-tertiary)"}}>Valor</td><td><span className="app-pill app-pill--success" style={{fontSize:13}}>{fmtValor(res.dados.valor)}</span></td></tr>
                <tr><td style={{color:"var(--color-text-tertiary)"}}>Emissão</td><td>{res.dados.data_emissao?new Date(res.dados.data_emissao).toLocaleString("pt-BR"):"—"}</td></tr>
                <tr><td style={{color:"var(--color-text-tertiary)"}}>Protocolo</td><td className="font-mono">{res.dados.protocolo||"—"}</td></tr>
                <tr><td style={{color:"var(--color-text-tertiary)"}}>Situação</td><td>{res.dados.cstat?<span className="app-pill app-pill--info">{res.dados.cstat} — {res.dados.motivo}</span>:"—"}</td></tr>
              </tbody>
            </table>
          </div>
        </div>
      )}
    </>
  );
}

function PainelMonitor({token,isAdmin}){
  const {get,form}=useApi(token);
  const [empresas,setEmpresas]=useState([]); const [st,setSt]=useState(null);
  const [err,setErr]=useState(""); const [rodando,setRodando]=useState(false);
  const [novo,setNovo]=useState({cnpj:"",razao:""}); const [addErr,setAddErr]=useState("");
  const [notas,setNotas]=useState([]); const [filtroCnpj,setFiltroCnpj]=useState("");
  const [filtroTipo,setFiltroTipo]=useState("");
  const carregarNotas=async()=>{ try{ const params={}; if(filtroCnpj)params.cnpj=filtroCnpj; if(filtroTipo)params.tipo=filtroTipo; setNotas(await get("/monitor/notas-do-dia", Object.keys(params).length?params:undefined)); }catch(e){} };
  const carregar=async()=>{ try{ setEmpresas(await get("/empresas")); setSt(await get("/monitor/status")); await carregarNotas(); }catch(e){ setErr(e.message); } };
  useEffect(()=>{ carregar(); const t=setInterval(()=>{ get("/monitor/status").then(setSt).catch(()=>{}); carregarNotas(); }, 15000); return ()=>clearInterval(t); },[]);
  useEffect(()=>{ carregarNotas(); },[filtroCnpj,filtroTipo]);

  const addEmpresa=async()=>{ setAddErr("");
    try{ await form("/empresas",{cnpj:novo.cnpj,razao_social:novo.razao}); setNovo({cnpj:"",razao:""}); await carregar(); }
    catch(e){ setAddErr(e.message); }
  };
  const rodarAgora=async()=>{ setErr(""); setRodando(true);
    try{ setSt(await form("/monitor/rodar-agora",{})); await carregar(); }
    catch(e){ setErr(e.message); } finally{ setRodando(false); }
  };
  const toggle=async(ligar)=>{ try{ setSt(await form(ligar?"/monitor/iniciar":"/monitor/parar",{})); }catch(e){ setErr(e.message); } };
  const fmtCnpj=(d)=>{ d=(""+d).replace(/\D/g,""); return d.length===14?`${d.slice(0,2)}.${d.slice(2,5)}.${d.slice(5,8)}/${d.slice(8,12)}-${d.slice(12)}`:d; };
  const fmtHora=(s)=>{ if(!s) return "—"; try{ return new Date(s).toLocaleString("pt-BR"); }catch(e){ return s; } };

  return (
    <>
      <div className="app-card">
        <div className="app-card__head">
          <h3 className="h3 m-0"><i className="bi bi-activity me-2" style={{color:"var(--color-brand-primary)"}}></i>Monitor de notas</h3>
          {st && (st.ativo
            ? <span className="app-pill app-pill--success"><i className="bi bi-broadcast"></i> Ativo</span>
            : <span className="app-pill app-pill--neutral"><i className="bi bi-pause-circle"></i> Parado</span>)}
        </div>
        <div className="app-card__body">
          <p className="text-sm mb-3" style={{color:"var(--color-text-tertiary)"}}>
            Verifica automaticamente as notas disponíveis dos CNPJs cadastrados. Roda no servidor a cada {st?Math.round(st.ciclo_seg/60):60} min,
            respeitando um intervalo mínimo de {st?Math.round(st.intervalo_min_seg/60):55} min por CNPJ (proteção contra consumo indevido na SEFAZ).
          </p>
          <div className="d-flex gap-2 flex-wrap">
            <button className="btn btn-primary" onClick={rodarAgora} disabled={rodando}>
              {rodando?<><Spin/>Verificando...</>:<><i className="bi bi-arrow-clockwise me-1"></i>Verificar agora</>}
            </button>
            {isAdmin && st && (st.ativo
              ? <button className="btn btn-outline-danger" onClick={()=>toggle(false)}><i className="bi bi-pause-fill me-1"></i>Pausar monitor</button>
              : <button className="btn btn-secondary-app" onClick={()=>toggle(true)}><i className="bi bi-play-fill me-1"></i>Ativar monitor</button>)}
          </div>
          <Alert kind="err">{err}</Alert>
          {st && st.rodou_em && (
            <div className="text-sm mt-3" style={{color:"var(--color-text-tertiary)"}}>Última verificação: {new Date(st.rodou_em).toLocaleString("pt-BR")}</div>
          )}
        </div>
      </div>

      <div className="app-card">
        <div className="app-card__head">
          <h3 className="h3 m-0"><i className="bi bi-list-check me-2" style={{color:"var(--color-brand-primary)"}}></i>Notas do dia <span style={{color:"var(--color-text-muted)",fontWeight:400,fontSize:14}}>({notas.length})</span></h3>
          {empresas.length>1 && (
            <select className="form-select" style={{width:"auto",fontSize:13}} value={filtroCnpj} onChange={e=>setFiltroCnpj(e.target.value)}>
              <option value="">Todos os CNPJs</option>
              {empresas.map((e,i)=><option key={i} value={e.cnpj}>{e.razao_social||e.cnpj}</option>)}
            </select>
          )}
        </div>
        <div className="app-card__body">
          <div className="d-flex gap-2 flex-wrap mb-3">
            {[["","Todos"],["cte","CT-e"],["nfe","NF-e"],["evento","Eventos"]].map(([v,lbl])=>(
              <button key={v} className={"btn btn-sm "+(filtroTipo===v?"btn-primary":"btn-outline-secondary")}
                      onClick={()=>setFiltroTipo(v)} style={{fontSize:12.5}}>{lbl}</button>
            ))}
          </div>
          {notas.length===0?<div className="empty"><i className="bi bi-calendar-x" style={{fontSize:24,display:"block",marginBottom:8}}></i>Nenhuma nota recebida hoje.</div>:(
            <div style={{overflowX:"auto"}}>
              <table className="app-table">
                <thead><tr><th>Tipo</th><th>Chave</th><th>Razão emissor</th><th>Transportador</th><th>Tomador</th><th>Hora emissão</th></tr></thead>
                <tbody>
                  {notas.map((n,i)=>(
                    <tr key={i}>
                      <td><span className={"app-pill "+(n.tipo_cat==="cte"?"app-pill--brand":n.tipo_cat==="nfe"?"app-pill--success":n.tipo_cat==="evento"?"app-pill--neutral":"app-pill--neutral")} style={{fontSize:11}}>{n.tipo||"—"}</span></td>
                      <td className="font-mono" style={{fontSize:11.5}}>{n.chave||"—"}</td>
                      <td>{n.razao_emissor||"—"}</td>
                      <td>{n.transportador||"—"}</td>
                      <td>{n.tomador||"—"}</td>
                      <td style={{color:"var(--color-text-tertiary)"}}>{fmtHora(n.hora_emissao)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      </div>

      <div className="app-card">
        <div className="app-card__head">
          <h3 className="h3 m-0"><i className="bi bi-clock-history me-2" style={{color:"var(--color-brand-primary)"}}></i>Última verificação por CNPJ</h3>
        </div>
        <div className="app-card__body">
          {st && st.processados && st.processados.length>0 ? (
            <table className="app-table">
              <thead><tr><th>CNPJ</th><th>Resultado</th></tr></thead>
              <tbody>
                {st.processados.map((p,i)=>(
                  <tr key={i}>
                    <td className="font-mono">{fmtCnpj(p.cnpj)}</td>
                    <td>
                      {p.status==="ok" && <span className="app-pill app-pill--success"><i className="bi bi-check-circle"></i> {p.novos} novas</span>}
                      {p.status==="pulado_intervalo" && <span className="app-pill app-pill--neutral"><i className="bi bi-hourglass-split"></i> aguardando intervalo ({Math.round(p.faltam_seg/60)} min)</span>}
                      {p.status==="erro" && <span className="app-pill app-pill--danger"><i className="bi bi-x-circle"></i> {p.detalhe}</span>}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          ) : <div className="empty">Nenhum ciclo executado ainda.</div>}
        </div>
      </div>

      <div className="app-card">
        <div className="app-card__head"><h3 className="h3 m-0"><i className="bi bi-building me-2" style={{color:"var(--color-brand-primary)"}}></i>CNPJs monitorados <span style={{color:"var(--color-text-muted)",fontWeight:400,fontSize:14}}>({empresas.length})</span></h3></div>
        <div className="app-card__body">
          {isAdmin && (
            <div className="row g-2 mb-3">
              <div className="col-md-4"><input className="form-control font-mono" placeholder="CNPJ" value={novo.cnpj} onChange={e=>setNovo({...novo,cnpj:e.target.value})}/></div>
              <div className="col-md-6"><input className="form-control" placeholder="Razão social (opcional)" value={novo.razao} onChange={e=>setNovo({...novo,razao:e.target.value})}/></div>
              <div className="col-md-2"><button className="btn btn-primary w-100" onClick={addEmpresa} disabled={!novo.cnpj}><i className="bi bi-plus-lg"></i></button></div>
            </div>
          )}
          <Alert kind="err">{addErr}</Alert>
          {empresas.length===0?<div className="empty"><i className="bi bi-inbox" style={{fontSize:24,display:"block",marginBottom:8}}></i>Nenhum CNPJ cadastrado.</div>:(
            <table className="app-table">
              <thead><tr><th>CNPJ</th><th>Razão social</th><th>Monitorar</th></tr></thead>
              <tbody>
                {empresas.map((e,i)=>(
                  <tr key={i}>
                    <td className="font-mono">{fmtCnpj(e.cnpj)}</td>
                    <td>{e.razao_social||"—"}</td>
                    <td>{e.monitorar?<span className="app-pill app-pill--success"><i className="bi bi-check"></i> Sim</span>:<span className="app-pill app-pill--neutral">Não</span>}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>
      </div>
    </>
  );
}

function PainelAdmin({token}){
  const {form,get,upload}=useApi(token);
  const [nu,setNu]=useState({username:"",senha:"",role:"operador"});
  const [uMsg,setUMsg]=useState(null); const [uErr,setUErr]=useState("");
  const criarUsuario=async()=>{ setUErr(""); setUMsg(null);
    try{ const d=await form("/admin/usuarios",nu); setUMsg(`Usuário "${d.username}" criado (${d.role}).`); setNu({username:"",senha:"",role:"operador"}); }
    catch(e){ setUErr(e.message); }
  };
  const [pfx,setPfx]=useState(null); const [senhaCert,setSenhaCert]=useState("");
  const [cMsg,setCMsg]=useState(null); const [cErr,setCErr]=useState(""); const [cLoading,setCLoading]=useState(false);
  const enviarCert=async()=>{ setCErr(""); setCMsg(null); setCLoading(true);
    try{ const fd=new FormData(); fd.append("arquivo",pfx); fd.append("senha",senhaCert);
      const d=await upload("/admin/certificado",fd);
      setCMsg(`Certificado de "${d.titular}" ativo. Válido até ${d.valido_ate}.`+(d.aviso?`\n\n${d.aviso}`:"")); setSenhaCert(""); setPfx(null);
    }catch(e){ setCErr(e.message); } finally{ setCLoading(false); }
  };
  const [logs,setLogs]=useState([]); const [lErr,setLErr]=useState("");
  const carregarLogs=async()=>{ setLErr(""); try{ setLogs(await get("/admin/logs",{limit:80})); }catch(e){ setLErr(e.message); } };
  useEffect(()=>{ carregarLogs(); },[]);
  const statusPill=(s)=>{
    if(["concluida","iniciada"].includes(s)) return <span className="app-pill app-pill--success"><i className="bi bi-check-circle"></i> {s}</span>;
    if(["erro","validacao_falhou","timeout_kill","cancelada"].includes(s)) return <span className="app-pill app-pill--danger"><i className="bi bi-x-circle"></i> {s}</span>;
    return <span className="app-pill app-pill--neutral">{s}</span>;
  };
  return (
    <>
      <div className="app-card">
        <div className="app-card__head"><h3 className="h3 m-0"><i className="bi bi-person-plus me-2" style={{color:"var(--color-brand-primary)"}}></i>Criar usuário</h3></div>
        <div className="app-card__body">
          <p className="text-sm mb-3" style={{color:"var(--color-text-tertiary)"}}>Operadores só acessam a tela de consulta. Admins gerenciam tudo.</p>
          <div className="row g-2">
            <div className="col-md-4"><label className="frm">Usuário</label><input className="form-control" value={nu.username} onChange={e=>setNu({...nu,username:e.target.value})}/></div>
            <div className="col-md-4"><label className="frm">Senha</label><input type="password" className="form-control" value={nu.senha} onChange={e=>setNu({...nu,senha:e.target.value})}/></div>
            <div className="col-md-4"><label className="frm">Perfil</label>
              <select className="form-select" value={nu.role} onChange={e=>setNu({...nu,role:e.target.value})}>
                <option value="operador">Operador</option><option value="admin">Administrador</option>
              </select>
            </div>
          </div>
          <button className="btn btn-primary mt-3" onClick={criarUsuario} disabled={!nu.username||!nu.senha}><i className="bi bi-plus-lg me-1"></i>Criar usuário</button>
          <Alert kind="err">{uErr}</Alert><Alert kind="ok">{uMsg}</Alert>
        </div>
      </div>
      <div className="app-card">
        <div className="app-card__head"><h3 className="h3 m-0"><i className="bi bi-shield-lock me-2" style={{color:"var(--color-brand-primary)"}}></i>Certificado digital (A1)</h3></div>
        <div className="app-card__body">
          <p className="text-sm mb-3" style={{color:"var(--color-text-tertiary)"}}>O .pfx sobe por HTTPS, é validado e guardado cifrado no servidor. A senha nunca é exibida nem retornada.</p>
          <label className="frm">Arquivo .pfx</label>
          <input type="file" className="form-control" accept=".pfx,.p12" onChange={e=>setPfx(e.target.files[0])}/>
          <label className="frm mt-2">Senha do certificado</label>
          <input type="password" className="form-control" value={senhaCert} onChange={e=>setSenhaCert(e.target.value)}/>
          <button className="btn btn-secondary-app mt-3" onClick={enviarCert} disabled={cLoading||!pfx||!senhaCert}>
            {cLoading?<><Spin/>Enviando...</>:<><i className="bi bi-upload me-1"></i>Enviar certificado</>}
          </button>
          <Alert kind="err">{cErr}</Alert><Alert kind="ok">{cMsg}</Alert>
        </div>
      </div>
      <div className="app-card">
        <div className="app-card__head">
          <h3 className="h3 m-0"><i className="bi bi-journal-text me-2" style={{color:"var(--color-brand-primary)"}}></i>Logs de auditoria</h3>
          <button className="icon-btn" onClick={carregarLogs}><i className="bi bi-arrow-clockwise me-1"></i>Atualizar</button>
        </div>
        <div className="app-card__body">
          <Alert kind="err">{lErr}</Alert>
          {logs.length===0?<div className="empty"><i className="bi bi-inbox" style={{fontSize:24,display:"block",marginBottom:8}}></i>Sem registros ainda.</div>:(
            <div style={{overflowX:"auto"}}>
              <table className="app-table">
                <thead><tr><th>Quando</th><th>Usuário</th><th>Modelo</th><th>Status</th><th>Chave / detalhe</th><th>IP</th></tr></thead>
                <tbody>
                  {logs.map(l=>(
                    <tr key={l.id}>
                      <td style={{color:"var(--color-text-tertiary)"}}>{new Date(l.em).toLocaleString("pt-BR")}</td>
                      <td>{l.usuario_id??"—"}</td>
                      <td style={{color:"var(--color-text-tertiary)"}}>{l.modelo||"—"}</td>
                      <td>{statusPill(l.status)}</td>
                      <td className="font-mono" style={{maxWidth:280,whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",fontSize:12}}>{l.chave||l.detalhe||"—"}</td>
                      <td className="font-mono" style={{color:"var(--color-text-tertiary)"}}>{l.ip||"—"}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      </div>
    </>
  );
}

function PainelParametrizacao({token}){
  const {get}=useApi(token);
  const [cert,setCert]=useState(null); const [err,setErr]=useState(""); const [loading,setLoading]=useState(true);
  const carregar=async()=>{ setLoading(true); try{ setCert(await get("/admin/certificado")); }catch(e){ setErr(e.message); } finally{ setLoading(false); } };
  useEffect(()=>{ carregar(); },[]);
  const fmtCnpj=(d)=>{ d=(""+(d||"")).replace(/\D/g,""); return d.length===14?`${d.slice(0,2)}.${d.slice(2,5)}.${d.slice(5,8)}/${d.slice(8,12)}-${d.slice(12)}`:(d||"—"); };
  const fmtData=(s)=>{ if(!s) return "—"; try{ return new Date(s).toLocaleDateString("pt-BR"); }catch(e){ return s; } };

  return (
    <>
      <div className="app-card">
        <div className="app-card__head">
          <h3 className="h3 m-0"><i className="bi bi-shield-check me-2" style={{color:"var(--color-brand-primary)"}}></i>Certificado digital ativo</h3>
          <button className="icon-btn" onClick={carregar}><i className="bi bi-arrow-clockwise me-1"></i>Atualizar</button>
        </div>
        <div className="app-card__body">
          <Alert kind="err">{err}</Alert>
          {loading ? <div className="empty"><Spin/>Carregando...</div> :
           !cert || !cert.configurado ? (
            <div className="empty">
              <i className="bi bi-shield-x" style={{fontSize:28,display:"block",marginBottom:8}}></i>
              Nenhum certificado configurado.<br/>
              <span className="text-sm">O administrador precisa enviar o .pfx na aba Administração.</span>
            </div>
           ) : (
            <>
              {cert.vencido && (
                <div className="alert-app err mb-3"><i className="bi bi-exclamation-triangle-fill me-2"></i>
                  Este certificado está <strong>VENCIDO</strong>. As consultas à SEFAZ vão falhar até a renovação.</div>
              )}
              {!cert.vencido && cert.dias_restantes!=null && cert.dias_restantes<30 && (
                <div className="alert-app mb-3" style={{background:"var(--color-warning-50)",color:"var(--color-warning-800)",border:"1px solid var(--color-warning-200)"}}>
                  <i className="bi bi-exclamation-triangle me-2"></i>Faltam apenas <strong>{cert.dias_restantes} dias</strong> para o vencimento. Programe a renovação.</div>
              )}
              <div className="kpi mb-3">
                <div className="item">
                  <div className="n" style={{fontSize:16}}>{fmtCnpj(cert.cnpj)}</div>
                  <div className="l">CNPJ</div>
                </div>
                <div className="item">
                  <div className="n" style={{fontSize:16,color: cert.vencido?"var(--color-danger-600)":(cert.dias_restantes<30?"var(--color-warning-600)":"var(--color-success-600)")}}>
                    {cert.dias_restantes!=null ? (cert.vencido?`vencido há ${Math.abs(cert.dias_restantes)}d`:`${cert.dias_restantes} dias`) : "—"}
                  </div>
                  <div className="l">{cert.vencido?"situação":"para vencer"}</div>
                </div>
                <div className="item">
                  <div className="n" style={{fontSize:16}}>{fmtData(cert.valido_ate)}</div>
                  <div className="l">válido até</div>
                </div>
              </div>
              <table className="app-table">
                <tbody>
                  <tr><td style={{color:"var(--color-text-tertiary)",width:200}}>Razão social</td><td className="fw-medium">{cert.razao_social||"—"}</td></tr>
                  <tr><td style={{color:"var(--color-text-tertiary)"}}>CNPJ</td><td className="font-mono">{fmtCnpj(cert.cnpj)}</td></tr>
                  <tr><td style={{color:"var(--color-text-tertiary)"}}>Titular (CN)</td><td className="text-sm">{cert.titular||"—"}</td></tr>
                  <tr><td style={{color:"var(--color-text-tertiary)"}}>Emissor (AC)</td><td className="text-sm">{cert.emissor||"—"}</td></tr>
                  <tr><td style={{color:"var(--color-text-tertiary)"}}>Válido de</td><td>{fmtData(cert.valido_de)}</td></tr>
                  <tr><td style={{color:"var(--color-text-tertiary)"}}>Válido até</td><td>{fmtData(cert.valido_ate)}</td></tr>
                  <tr><td style={{color:"var(--color-text-tertiary)"}}>Situação</td><td>
                    {cert.vencido
                      ? <span className="app-pill app-pill--danger"><i className="bi bi-x-circle"></i> Vencido</span>
                      : <span className="app-pill app-pill--success"><i className="bi bi-check-circle"></i> Válido</span>}
                  </td></tr>
                </tbody>
              </table>
              <p className="text-sm mt-3" style={{color:"var(--color-text-tertiary)"}}>
                <i className="bi bi-info-circle me-1"></i>
                Este é o CNPJ usado automaticamente nas consultas à SEFAZ. A senha do certificado fica cifrada no servidor e nunca é exibida.
              </p>
            </>
           )}
        </div>
      </div>
    </>
  );
}

function App(){
  const [auth,setAuth]=useState(null);
  const [tab,setTab]=useState("consulta");
  const [empresaNome,setEmpresaNome]=useState("");
  const [monitorOn,setMonitorOn]=useState(false);
  const {get}=useApi(auth?.token);
  // Lê a config pública (flags de UI) uma vez ao montar.
  useEffect(()=>{
    fetch("/config").then(r=>r.json()).then(c=>setMonitorOn(!!c.monitor_habilitado)).catch(()=>{});
  },[]);
  // Carrega a razão social do certificado ativo para exibir no topo.
  useEffect(()=>{
    if(!auth) return;
    get("/admin/certificado").then(c=>setEmpresaNome(c?.razao_social||"")).catch(()=>{});
  },[auth]);
  if(!auth) return <Login onLogin={(token,role,username)=>{ setAuth({token,role,username}); setTab("consulta"); }}/>;
  const isAdmin = auth.role==="admin";
  const avatarCor = isAdmin ? "var(--color-success-600)" : "#64748b";
  const iniciais = auth.username.slice(0,2).toUpperCase();
  // Abas ocultas redirecionam para Consultar.
  let tabAtual = tab;
  if(tab==="parametros" && !isAdmin) tabAtual="consulta";
  if(tab==="monitor" && !monitorOn) tabAtual="consulta";
  const Tab=({id,icon,label})=>(
    <button className={`navbar-app__link ${tabAtual===id?"is-active":""}`} onClick={()=>setTab(id)}><i className={`bi ${icon}`}></i> <span>{label}</span></button>
  );
  return (
    <>
      <header className="navbar-app">
        <div className="navbar-app__logo-faixa">
          <img src="logo.png" alt="CIOT HUB" className="navbar-app__logo-img"
               onError={e=>{e.target.style.display='none';}}/>
        </div>
        <nav className="navbar-app__menu">
          <Tab id="consulta" icon="bi-search" label="Consultar"/>
          {monitorOn && <Tab id="monitor" icon="bi-activity" label="Monitor"/>}
          {isAdmin && <Tab id="parametros" icon="bi-shield-check" label="Certificado"/>}
          {isAdmin && <Tab id="admin" icon="bi-gear" label="Administração"/>}
        </nav>
        <div className="navbar-app__user">
          {empresaNome && <span className="navbar-app__empresa">{empresaNome}</span>}
          <span className="navbar-app__avatar" style={{background:avatarCor}}>{iniciais}</span>
          <span className="navbar-app__user-name">{auth.username}</span>
          <span className="app-pill" style={{background:isAdmin?"var(--color-success-50)":"var(--surface-emphasis)",color:isAdmin?"var(--color-success-800)":"var(--color-text-secondary)",marginLeft:4}}>{isAdmin?"ADMIN":"OPERADOR"}</span>
          <button className="navbar-app__logout ms-2" onClick={()=>setAuth(null)} title="Sair"><i className="bi bi-box-arrow-right"></i></button>
        </div>
      </header>
      <div className="container-fluid py-4 px-4" style={{maxWidth:1100,margin:"0 auto"}}>
        {tabAtual==="consulta" && <PainelConsulta token={auth.token}/>}
        {tabAtual==="monitor" && monitorOn && <PainelMonitor token={auth.token} isAdmin={isAdmin}/>}
        {tabAtual==="parametros" && isAdmin && <PainelParametrizacao token={auth.token}/>}
        {tabAtual==="admin" && isAdmin && <PainelAdmin token={auth.token}/>}
      </div>
    </>
  );
}
ReactDOM.createRoot(document.getElementById("root")).render(<App/>);
