const { useState, useEffect, useRef, useMemo } = React;

/* ============================================================
   CONFIG
============================================================ */
const WEBHOOK_URL = "https://wautom.agenflex.com/webhook/45929a1d-f07b-4aba-9885-c540e4778aad";
const STORAGE_KEY = "agenflex_cadastro_v1";

const UFS = [
  ["AC","Acre"],["AL","Alagoas"],["AP","Amapá"],["AM","Amazonas"],["BA","Bahia"],
  ["CE","Ceará"],["DF","Distrito Federal"],["ES","Espírito Santo"],["GO","Goiás"],
  ["MA","Maranhão"],["MT","Mato Grosso"],["MS","Mato Grosso do Sul"],["MG","Minas Gerais"],
  ["PA","Pará"],["PB","Paraíba"],["PR","Paraná"],["PE","Pernambuco"],["PI","Piauí"],
  ["RJ","Rio de Janeiro"],["RN","Rio Grande do Norte"],["RS","Rio Grande do Sul"],
  ["RO","Rondônia"],["RR","Roraima"],["SC","Santa Catarina"],["SP","São Paulo"],
  ["SE","Sergipe"],["TO","Tocantins"]
];

/* ============================================================
   MASKS & VALIDATORS
============================================================ */
const onlyDigits = (s) => (s || "").replace(/\D/g, "");

function maskCNPJ(v){
  const d = onlyDigits(v).slice(0,14);
  let o = d;
  if(d.length>2) o = d.slice(0,2)+"."+d.slice(2);
  if(d.length>5) o = d.slice(0,2)+"."+d.slice(2,5)+"."+d.slice(5);
  if(d.length>8) o = d.slice(0,2)+"."+d.slice(2,5)+"."+d.slice(5,8)+"/"+d.slice(8);
  if(d.length>12) o = d.slice(0,2)+"."+d.slice(2,5)+"."+d.slice(5,8)+"/"+d.slice(8,12)+"-"+d.slice(12);
  return o;
}
function maskCEP(v){
  const d = onlyDigits(v).slice(0,8);
  return d.length>5 ? d.slice(0,5)+"-"+d.slice(5) : d;
}
function maskPhone(v){
  const d = onlyDigits(v).slice(0,11);
  if(d.length<=2) return d.length?("("+d):"";
  if(d.length<=6) return "("+d.slice(0,2)+") "+d.slice(2);
  if(d.length<=10) return "("+d.slice(0,2)+") "+d.slice(2,6)+"-"+d.slice(6);
  return "("+d.slice(0,2)+") "+d.slice(2,7)+"-"+d.slice(7);
}
const MASKS = { cnpj:maskCNPJ, cep:maskCEP, phone:maskPhone };

const isEmail = (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test((v||"").trim());

// CNPJ — validação dos dígitos verificadores (módulo 11)
function isValidCNPJ(value){
  const c = onlyDigits(value);
  if(c.length!==14) return false;
  if(/^(\d)\1{13}$/.test(c)) return false; // rejeita 00000000000000 etc.
  const dv = (base)=>{
    const len = base.length;
    let pos = len-7, sum = 0;
    for(let i=len; i>=1; i--){
      sum += parseInt(base.charAt(len-i),10) * pos--;
      if(pos<2) pos=9;
    }
    const r = sum % 11;
    return r < 2 ? 0 : 11 - r;
  };
  if(dv(c.slice(0,12)) !== parseInt(c.charAt(12),10)) return false;
  if(dv(c.slice(0,13)) !== parseInt(c.charAt(13),10)) return false;
  return true;
}

// Consulta dados públicos do CNPJ (Receita) via BrasilAPI
async function fetchCNPJ(digits){
  const res = await fetch("https://brasilapi.com.br/api/cnpj/v1/"+digits, { headers:{ "Accept":"application/json" } });
  if(!res.ok) return null;
  return res.json();
}

// Consulta endereço pelo CEP via ViaCEP
async function fetchCEP(digits){
  const res = await fetch("https://viacep.com.br/ws/"+digits+"/json/");
  if(!res.ok) return null;
  const j = await res.json();
  return j && j.erro ? null : j;
}

// UUID v4 para identificar a submissão (idempotência no N8N)
function uuid(){
  if(typeof crypto!=="undefined" && crypto.randomUUID) return crypto.randomUUID();
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(ch)=>{
    const r = Math.random()*16|0; const v = ch==="x" ? r : (r&0x3|0x8);
    return v.toString(16);
  });
}

/* ============================================================
   FIELD SCHEMA
============================================================ */
const SECTIONS = [
  {
    id:"empresa", label:"Dados da Empresa", short:"Empresa",
    intro:"Informações cadastrais e fiscais da sua empresa.",
    fields:[
      {name:"razao_social", label:"Razão Social", required:true, col:2},
      {name:"nome_fantasia", label:"Nome Fantasia", required:false, col:2},
      {name:"cnpj", label:"CNPJ", required:true, mask:"cnpj", placeholder:"00.000.000/0000-00", inputMode:"numeric"},
      {name:"inscricao_estadual", label:"Inscrição Estadual", required:true,
        toggle:{name:"ie_isento", label:"Isento / não possuo"}},
      {name:"inscricao_municipal", label:"Inscrição Municipal", required:false},
      {name:"regime_tributario", label:"Regime Tributário", required:true, type:"radio",
        options:["Simples Nacional","Lucro Presumido","Lucro Real"], col:2},
    ]
  },
  {
    id:"contatos", label:"Contatos", short:"Contatos",
    intro:"Pessoas e e-mails para comunicação comercial e financeira.",
    groups:[
      { title:"Comprador", fields:[
        {name:"nome_comprador", label:"Nome do Comprador", required:true, col:2},
        {name:"telefone_comprador", label:"Telefone / WhatsApp", required:true, mask:"phone", placeholder:"(00) 00000-0000", inputMode:"tel"},
        {name:"email_comprador", label:"E-mail do Comprador", required:true, type:"email", placeholder:"nome@empresa.com.br"},
      ]},
      { title:"E-mails de cobrança", fields:[
        {name:"email_nota_fiscal", label:"E-mail para Nota Fiscal", required:true, type:"email", placeholder:"fiscal@empresa.com.br"},
        {name:"email_boletos", label:"E-mail para Boletos", required:true, type:"email", placeholder:"boletos@empresa.com.br"},
      ]},
      { title:"Financeiro", fields:[
        {name:"responsavel_financeiro", label:"Responsável Financeiro", required:true, col:2},
        {name:"telefone_financeiro", label:"Telefone do Financeiro", required:true, mask:"phone", placeholder:"(00) 00000-0000", inputMode:"tel"},
        {name:"email_financeiro", label:"E-mail do Financeiro", required:true, type:"email", placeholder:"financeiro@empresa.com.br"},
      ]},
    ]
  },
  {
    id:"faturamento", label:"Endereço de Faturamento", short:"Faturamento",
    intro:"Endereço vinculado ao CNPJ para emissão de documentos.",
    fields:[
      {name:"fat_cep", label:"CEP", required:true, mask:"cep", placeholder:"00000-000", inputMode:"numeric", col:1},
      {name:"fat_endereco", label:"Endereço", required:true, col:2},
      {name:"fat_numero", label:"Número", required:true, col:1},
      {name:"fat_complemento", label:"Complemento", required:false, col:1},
      {name:"fat_bairro", label:"Bairro", required:true, col:1},
      {name:"fat_cidade", label:"Cidade", required:true, col:1},
      {name:"fat_estado", label:"Estado", required:true, type:"uf", col:1},
    ]
  },
  {
    id:"entrega", label:"Endereço de Entrega", short:"Entrega",
    intro:"Para onde os produtos serão enviados.",
    sameAs:true,
    fields:[
      {name:"ent_cep", label:"CEP", required:true, mask:"cep", placeholder:"00000-000", inputMode:"numeric", col:1},
      {name:"ent_endereco", label:"Endereço", required:true, col:2},
      {name:"ent_numero", label:"Número", required:true, col:1},
      {name:"ent_complemento", label:"Complemento", required:false, col:1},
      {name:"ent_bairro", label:"Bairro", required:true, col:1},
      {name:"ent_cidade", label:"Cidade", required:true, col:1},
      {name:"ent_estado", label:"Estado", required:true, type:"uf", col:1},
    ]
  },
  {
    id:"logistica", label:"Agendamento e Transporte", short:"Logística",
    intro:"Opcional — preencha se houver agendamento de recebimento.",
    groups:[
      { title:"Em caso de agendamento", note:"Campos opcionais", fields:[
        {name:"contato_recebimento", label:"Contato no Recebimento", required:false, col:2},
        {name:"telefone_recebimento", label:"Telefone do Recebimento", required:false, mask:"phone", placeholder:"(00) 00000-0000", inputMode:"tel"},
        {name:"horario_recebimento", label:"Horário de Recebimento", required:false, placeholder:"Ex.: 08h às 17h"},
      ]},
      { title:"Transporte", fields:[
        {name:"transportadora_cliente", label:"Transportadora do Cliente", required:false, col:2, placeholder:"Deixe em branco se for por nossa conta"},
      ]},
    ]
  },
];

const FAT_TO_ENT = {
  fat_cep:"ent_cep", fat_endereco:"ent_endereco", fat_numero:"ent_numero",
  fat_complemento:"ent_complemento", fat_bairro:"ent_bairro", fat_cidade:"ent_cidade", fat_estado:"ent_estado"
};

const allFieldsOf = (sec) => sec.fields ? sec.fields : sec.groups.flatMap(g=>g.fields);

/* ============================================================
   STYLES
============================================================ */


/* ============================================================
   COMBOBOX (UF)
============================================================ */
function UFCombo({ value, onChange, invalid, id }){
  const [open,setOpen] = useState(false);
  const [q,setQ] = useState("");
  const [hl,setHl] = useState(0);
  const ref = useRef(null);
  const selected = UFS.find(u=>u[0]===value);
  const display = selected ? `${selected[1]} (${selected[0]})` : "";

  useEffect(()=>{
    const h=(e)=>{ if(ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown",h);
    return ()=>document.removeEventListener("mousedown",h);
  },[]);

  const list = useMemo(()=>{
    const t = q.trim().toLowerCase();
    if(!t) return UFS;
    return UFS.filter(([c,n])=> n.toLowerCase().includes(t) || c.toLowerCase().includes(t) ||
      n.normalize("NFD").replace(/[\u0300-\u036f]/g,"").toLowerCase().includes(t));
  },[q]);

  const pick = (uf)=>{ onChange(uf[0]); setQ(""); setOpen(false); };

  return (
    <div className="combo" ref={ref}>
      <input
        id={id}
        className={"input"+(invalid?" err":"")}
        autoComplete="off"
        placeholder="Selecione ou digite…"
        value={open ? q : display}
        onChange={(e)=>{ setQ(e.target.value); setOpen(true); setHl(0); }}
        onFocus={()=>{ setOpen(true); setQ(""); }}
        onKeyDown={(e)=>{
          if(e.key==="ArrowDown"){e.preventDefault();setOpen(true);setHl(h=>Math.min(h+1,list.length-1));}
          else if(e.key==="ArrowUp"){e.preventDefault();setHl(h=>Math.max(h-1,0));}
          else if(e.key==="Enter"){ if(open&&list[hl]){e.preventDefault();pick(list[hl]);} }
          else if(e.key==="Escape"){ setOpen(false); }
        }}
      />
      <span className="caret">
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M6 9l6 6 6-6" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/></svg>
      </span>
      {open && (
        <div className="combo-pop" role="listbox">
          {list.length===0 && <div className="combo-empty">Nenhum estado encontrado</div>}
          {list.map((uf,i)=>(
            <div key={uf[0]} className={"combo-opt"+(i===hl?" hl":"")}
                 onMouseEnter={()=>setHl(i)} onMouseDown={(e)=>{e.preventDefault();pick(uf);}}>
              <span>{uf[1]}</span><b>{uf[0]}</b>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

/* ============================================================
   FIELD
============================================================ */
function Field({ f, value, error, onChange, mirrored, toggleValue }){
  const fid = "f_"+f.name;
  const cls = "field"+(f.col===2?" col2":"")+(error?" invalid":"");

  if(f.type==="radio"){
    return (
      <div className={cls}>
        <label>{f.label}{f.required && <span className="req">*</span>}</label>
        <div className="radios">
          {f.options.map(opt=>(
            <label key={opt} className={"radio"+(value===opt?" sel":"")}>
              <input type="radio" name={f.name} value={opt} checked={value===opt} onChange={()=>onChange(f.name,opt)} />
              {opt}
            </label>
          ))}
        </div>
        {error && <div className="msg">{error}</div>}
      </div>
    );
  }

  return (
    <div className={cls}>
      {f.toggle ? (
        <div className="lbl-row">
          <label htmlFor={fid}>
            {f.label}
            {f.required ? <span className="req">*</span> : <span className="opt">(opcional)</span>}
          </label>
          <button type="button" className={"mini-toggle"+(toggleValue?" on":"")}
                  onClick={()=>onChange(f.toggle.name, !toggleValue)}>
            <span className="mini-box"><svg width="11" height="11" viewBox="0 0 24 24" fill="none"><path d="M5 12.5l4.5 4.5L19 7" stroke="#fff" strokeWidth="3.4" strokeLinecap="round" strokeLinejoin="round"/></svg></span>
            {f.toggle.label}
          </button>
        </div>
      ) : (
        <label htmlFor={fid}>
          {f.label}
          {f.required ? <span className="req">*</span> : <span className="opt">(opcional)</span>}
        </label>
      )}
      {f.type==="uf"
        ? <UFCombo id={fid} value={value} invalid={!!error} onChange={(v)=>onChange(f.name,v)} />
        : <input
            id={fid}
            className={"input"+(error?" err":"")+(mirrored?" mirrored":"")}
            type={f.type==="email"?"email":"text"}
            inputMode={f.inputMode}
            placeholder={f.placeholder||""}
            value={value||""}
            disabled={mirrored || (f.toggle && !!toggleValue)}
            autoComplete="off"
            onChange={(e)=>{
              const raw = e.target.value;
              onChange(f.name, f.mask ? MASKS[f.mask](raw) : raw);
            }}
          />}
      {error && <div className="msg">{error}</div>}
    </div>
  );
}

/* ============================================================
   APP
============================================================ */
function App(){
  const saved = (()=>{ try{ return JSON.parse(localStorage.getItem(STORAGE_KEY))||{}; }catch(e){ return {}; } })();
  const [data,setData] = useState(saved.data||{});
  const [step,setStep] = useState(saved.step||0);
  const [maxStep,setMaxStep] = useState(saved.maxStep||0);
  const [sameAddr,setSameAddr] = useState(saved.sameAddr||false);
  const [errors,setErrors] = useState({});
  const [status,setStatus] = useState("idle"); // idle | sending | success | error
  const [errMsg,setErrMsg] = useState("");
  const [subId,setSubId] = useState(saved.subId || uuid());
  const [cnpjInfo,setCnpjInfo] = useState(null); // {status:"loading|ok|warn|notfound|error", situacao}
  const [cepLoading,setCepLoading] = useState(""); // "" | "fat" | "ent"
  const topRef = useRef(null);
  const lastCnpj = useRef("");
  const lastCep = useRef({fat:"",ent:""});

  useEffect(()=>{
    localStorage.setItem(STORAGE_KEY, JSON.stringify({data,step,maxStep,sameAddr,subId}));
  },[data,step,maxStep,sameAddr,subId]);

  const sec = SECTIONS[step];
  const isEntrega = sec.id==="entrega";
  const mirrored = isEntrega && sameAddr;

  const setField = (name,val)=>{
    setData(d=>{
      const nd = {...d,[name]:val};
      // Inscrição Estadual isenta: trava o campo com "ISENTO"
      if(name==="ie_isento") nd.inscricao_estadual = val ? "ISENTO" : "";
      // keep entrega in sync while mirrored
      if(sameAddr && FAT_TO_ENT[name]) nd[FAT_TO_ENT[name]] = val;
      return nd;
    });
    setErrors(e=>{
      const n = {...e};
      if(n[name]) delete n[name];
      if(name==="ie_isento" && val) delete n.inscricao_estadual;
      return n;
    });
  };

  // wrapper: grava o campo e dispara as consultas de CNPJ/CEP quando completos
  const onFieldChange = (name,val)=>{
    setField(name,val);
    if(name==="cnpj"){
      if(isValidCNPJ(val)) doCnpjLookup(val);
      else setCnpjInfo(null);
    }
    if((name==="fat_cep"||name==="ent_cep") && onlyDigits(val).length===8){
      doCepLookup(name==="fat_cep"?"fat":"ent", val);
    }
  };

  // Preenche os campos de endereço de um prefixo (fat/ent), espelhando quando aplicável
  const fillAddress = (prefix, a)=>{
    setData(d=>{
      const nd = {...d};
      const apply = (px)=>{
        if(a.cep!=null && a.cep!=="") nd[px+"_cep"] = maskCEP(a.cep);
        if(a.endereco)    nd[px+"_endereco"] = a.endereco;
        if(a.bairro)      nd[px+"_bairro"]   = a.bairro;
        if(a.cidade)      nd[px+"_cidade"]   = a.cidade;
        if(a.estado)      nd[px+"_estado"]   = a.estado;
        if(a.complemento) nd[px+"_complemento"] = a.complemento;
      };
      apply(prefix);
      if(prefix==="fat" && sameAddr) apply("ent");
      return nd;
    });
    setErrors(e=>{
      const n = {...e};
      const clear = (px)=>[px+"_endereco",px+"_bairro",px+"_cidade",px+"_estado",px+"_cep"].forEach(k=>delete n[k]);
      clear(prefix);
      if(prefix==="fat" && sameAddr) clear("ent");
      return n;
    });
  };

  const doCepLookup = async (prefix, masked)=>{
    const digits = onlyDigits(masked);
    if(digits.length!==8 || lastCep.current[prefix]===digits) return;
    lastCep.current[prefix] = digits;
    setCepLoading(prefix);
    try{
      const a = await fetchCEP(digits);
      if(a) fillAddress(prefix,{ endereco:a.logradouro, bairro:a.bairro, cidade:a.localidade, estado:a.uf, complemento:a.complemento||"" });
    }catch(_){ /* silencioso: cliente preenche manualmente */ }
    finally{ setCepLoading(""); }
  };

  const doCnpjLookup = async (masked)=>{
    const digits = onlyDigits(masked);
    if(!isValidCNPJ(digits) || lastCnpj.current===digits) return;
    lastCnpj.current = digits;
    setCnpjInfo({status:"loading"});
    try{
      const c = await fetchCNPJ(digits);
      if(!c){ setCnpjInfo({status:"notfound"}); return; }
      const situacao = (c.descricao_situacao_cadastral||"").toUpperCase();
      const ativa = situacao==="ATIVA" || c.situacao_cadastral===2;
      setData(d=>{
        const nd = {...d};
        if(c.razao_social)  nd.razao_social  = c.razao_social;
        if(c.nome_fantasia) nd.nome_fantasia = c.nome_fantasia;
        if(c.opcao_pelo_simples===true) nd.regime_tributario = "Simples Nacional";
        if(c.cep)         nd.fat_cep         = maskCEP(c.cep);
        if(c.logradouro)  nd.fat_endereco    = c.logradouro;
        if(c.numero)      nd.fat_numero      = c.numero;
        if(c.complemento) nd.fat_complemento = c.complemento;
        if(c.bairro)      nd.fat_bairro      = c.bairro;
        if(c.municipio)   nd.fat_cidade      = c.municipio;
        if(c.uf)          nd.fat_estado      = c.uf;
        if(sameAddr) Object.entries(FAT_TO_ENT).forEach(([f,t])=>{ nd[t]=nd[f]||""; });
        return nd;
      });
      setErrors(e=>{
        const n = {...e};
        ["razao_social","fat_cep","fat_endereco","fat_numero","fat_bairro","fat_cidade","fat_estado"].forEach(k=>delete n[k]);
        return n;
      });
      setCnpjInfo({status: ativa?"ok":"warn", situacao});
    }catch(_){
      setCnpjInfo({status:"error"});
    }
  };

  const toggleSame = ()=>{
    const next = !sameAddr;
    setSameAddr(next);
    if(next){
      setData(d=>{ const nd={...d}; Object.entries(FAT_TO_ENT).forEach(([f,t])=>{ nd[t]=d[f]||""; }); return nd; });
      setErrors(e=>{ const n={...e}; Object.values(FAT_TO_ENT).forEach(t=>delete n[t]); return n; });
    }
  };

  const validateSection = ()=>{
    if(mirrored) return {};
    const errs={};
    allFieldsOf(sec).forEach(f=>{
      // Inscrição Estadual: dispensada quando marcada como isenta
      if(f.name==="inscricao_estadual" && data.ie_isento) return;
      const v = (data[f.name]||"").toString().trim();
      if(f.required && !v){ errs[f.name]="Campo obrigatório"; return; }
      if(v && f.type==="email" && !isEmail(v)) errs[f.name]="E-mail inválido";
      if(v && f.mask==="cnpj"){
        if(onlyDigits(v).length!==14) errs[f.name]="CNPJ incompleto";
        else if(!isValidCNPJ(v)) errs[f.name]="CNPJ inválido";
      }
      if(v && f.mask==="cep" && onlyDigits(v).length!==8) errs[f.name]="CEP incompleto";
      if(v && f.mask==="phone" && onlyDigits(v).length<10) errs[f.name]="Telefone incompleto";
    });
    return errs;
  };

  const goTop = ()=>{ if(topRef.current) topRef.current.scrollIntoView({block:"start"}); window.scrollTo({top:0,behavior:"smooth"}); };

  const next = ()=>{
    const errs = validateSection();
    if(Object.keys(errs).length){ setErrors(errs); return; }
    if(step < SECTIONS.length-1){
      const ns = step+1;
      setStep(ns); setMaxStep(m=>Math.max(m,ns)); setErrors({});
      requestAnimationFrame(goTop);
    } else {
      submit();
    }
  };
  const back = ()=>{ if(step>0){ setStep(step-1); setErrors({}); requestAnimationFrame(goTop); } };
  const jump = (i)=>{ if(i<=maxStep){ setStep(i); setErrors({}); requestAnimationFrame(goTop); } };

  const buildPayload = ()=>({
    formulario:"Cadastro Agenflex",
    submission_id:subId,
    enviado_em:new Date().toISOString(),
    empresa:{
      razao_social:data.razao_social||"", nome_fantasia:data.nome_fantasia||"",
      cnpj:data.cnpj||"", inscricao_estadual:data.inscricao_estadual||"",
      inscricao_estadual_isento:!!data.ie_isento,
      inscricao_municipal:data.inscricao_municipal||"", regime_tributario:data.regime_tributario||"",
      situacao_cadastral:(cnpjInfo && cnpjInfo.situacao) ? cnpjInfo.situacao : ""
    },
    contatos:{
      nome_comprador:data.nome_comprador||"", telefone_comprador:data.telefone_comprador||"",
      email_comprador:data.email_comprador||"", email_nota_fiscal:data.email_nota_fiscal||"",
      email_boletos:data.email_boletos||"", responsavel_financeiro:data.responsavel_financeiro||"",
      telefone_financeiro:data.telefone_financeiro||"", email_financeiro:data.email_financeiro||""
    },
    endereco_faturamento:{
      cep:data.fat_cep||"", endereco:data.fat_endereco||"", numero:data.fat_numero||"",
      complemento:data.fat_complemento||"", bairro:data.fat_bairro||"", cidade:data.fat_cidade||"", estado:data.fat_estado||""
    },
    endereco_entrega:{
      mesmo_endereco_faturamento:!!sameAddr,
      cep:data.ent_cep||"", endereco:data.ent_endereco||"", numero:data.ent_numero||"",
      complemento:data.ent_complemento||"", bairro:data.ent_bairro||"", cidade:data.ent_cidade||"", estado:data.ent_estado||""
    },
    logistica:{
      contato_recebimento:data.contato_recebimento||"", telefone_recebimento:data.telefone_recebimento||"",
      horario_recebimento:data.horario_recebimento||"", transportadora_cliente:data.transportadora_cliente||""
    }
  });

  const submit = async ()=>{
    const payload = buildPayload();
    console.log("Payload Agenflex →", payload);
    setStatus("sending"); setErrMsg("");
    try{
      const res = await fetch(WEBHOOK_URL,{
        method:"POST",
        headers:{ "Content-Type":"application/json" },
        body:JSON.stringify(payload)
      });
      if(!res.ok) throw new Error("HTTP "+res.status);
      setStatus("success");
      requestAnimationFrame(goTop);
    }catch(err){
      console.warn("Falha no envio:",err);
      setErrMsg(err.message||"Erro de conexão");
      setStatus("error");
      requestAnimationFrame(goTop);
    }
  };

  const reset = ()=>{
    localStorage.removeItem(STORAGE_KEY);
    setData({}); setStep(0); setMaxStep(0); setSameAddr(false); setErrors({}); setStatus("idle");
    setSubId(uuid()); setCnpjInfo(null); setCepLoading("");
    lastCnpj.current = ""; lastCep.current = {fat:"",ent:""};
    requestAnimationFrame(goTop);
  };

  const pct = Math.round(((step + 1) / SECTIONS.length) * 100);

  /* ---- render a section's fields ---- */
  const renderFields = (fields)=> (
    <div className="grid">
      {fields.map(f=>(
        <Field key={f.name} f={f} value={data[f.name]} error={errors[f.name]}
               onChange={onFieldChange}
               toggleValue={f.toggle ? data[f.toggle.name] : undefined}
               mirrored={mirrored && Object.values(FAT_TO_ENT).includes(f.name)} />
      ))}
    </div>
  );

  return (
    <div className="shell" ref={topRef}>
      {/* SIDEBAR */}
      <aside className="rail">
        <div className="brand"><img src="assets/agenflex-logo.png" alt="Agenflex — Embalagens personalizadas" /></div>
        <ul className="steps">
          {SECTIONS.map((s,i)=>{
            const state = status==="success" ? "done" : (i===step ? "active" : (i<maxStep || i<step ? "done" : (i<=maxStep?"done":"")));
            const isActive = i===step && status!=="success";
            const isDone = (i<step || (status==="success")) && !isActive;
            return (
              <li key={s.id}>
                <button className={"step"+(isActive?" active":"")+(isDone?" done":"")}
                        disabled={i>maxStep || status==="sending"} onClick={()=>jump(i)}>
                  <span className="dot">
                    {isDone
                      ? <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M5 12.5l4.5 4.5L19 7" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"/></svg>
                      : (i+1)}
                  </span>
                  <span className="step-label"><b>{s.short}</b><span>Etapa {i+1}</span></span>
                </button>
              </li>
            );
          })}
        </ul>
        <div className="rail-foot">
          <div className="progress-meta"><span>Progresso</span><b>{pct}%</b></div>
          <div className="bar"><i style={{width:pct+"%"}}></i></div>
        </div>
      </aside>

      {/* MAIN */}
      <main className="main">
        {status==="success" ? (
          <div className="result ok">
            <div className="ic"><svg width="38" height="38" viewBox="0 0 24 24" fill="none"><path d="M5 12.5l4.5 4.5L19 7" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"/></svg></div>
            <h2>Cadastro enviado!</h2>
            <p>Recebemos os dados da sua empresa. Nossa equipe dará sequência ao cadastro e entrará em contato em breve.</p>
            <div className="acts"><button className="btn btn-ghost" onClick={reset}>Novo cadastro</button></div>
          </div>
        ) : status==="error" ? (
          <div className="result bad">
            <div className="ic"><svg width="36" height="36" viewBox="0 0 24 24" fill="none"><path d="M12 8v5M12 16.5v.5" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"/><circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2"/></svg></div>
            <h2>Não foi possível enviar</h2>
            <p>Ocorreu um problema ao enviar o cadastro ({errMsg}). Verifique sua conexão e tente novamente — seus dados foram preservados.</p>
            <div className="acts">
              <button className="btn btn-ghost" onClick={()=>setStatus("idle")}>Revisar dados</button>
              <button className="btn btn-primary" onClick={submit}>Tentar novamente</button>
            </div>
          </div>
        ) : (
          <React.Fragment>
            <div className="pagehead">
              <p className="eyebrow">Formulário de Cadastro</p>
              <h1>Cadastro Agenflex</h1>
              <p>Preencha as etapas abaixo para abrirmos seu cadastro de cliente. Campos com <span className="req">*</span> são obrigatórios.</p>
            </div>

            <div className="card">
              <div className="card-head">
                <span className="sec-no">Etapa {step+1} de {SECTIONS.length}</span>
                <h2>{sec.label}</h2>
                <p className="sub">{sec.intro}</p>
              </div>
              <div className="card-body anim" key={sec.id}>
                {isEntrega && (
                  <div className={"sameas"+(sameAddr?" on":"")} onClick={toggleSame}>
                    <span className="chk"><svg width="13" height="13" viewBox="0 0 24 24" fill="none"><path d="M5 12.5l4.5 4.5L19 7" stroke="#fff" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"/></svg></span>
                    <span className="t">Mesmo endereço de faturamento<small>Usar os dados informados na etapa anterior</small></span>
                  </div>
                )}

                {sec.id==="empresa" && cnpjInfo && (
                  cnpjInfo.status==="loading" ? (
                    <div className="lookup"><span className="mini-spin"></span>Consultando CNPJ na Receita…</div>
                  ) : cnpjInfo.status==="ok" ? (
                    <div className="lookup ok">
                      <span className="li"><svg width="17" height="17" viewBox="0 0 24 24" fill="none"><path d="M5 12.5l4.5 4.5L19 7" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"/></svg></span>
                      <span>Empresa localizada e <b>ATIVA</b>. <small>Preenchemos os dados — confira e ajuste se precisar.</small></span>
                    </div>
                  ) : cnpjInfo.status==="warn" ? (
                    <div className="lookup warn">
                      <span className="li"><svg width="17" height="17" viewBox="0 0 24 24" fill="none"><path d="M12 8v5M12 16.5v.5" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"/><circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2"/></svg></span>
                      <span>Situação cadastral: <b>{cnpjInfo.situacao||"—"}</b>. <small>Dados preenchidos, mas confira a situação antes de prosseguir.</small></span>
                    </div>
                  ) : cnpjInfo.status==="notfound" ? (
                    <div className="lookup warn">
                      <span className="li"><svg width="17" height="17" viewBox="0 0 24 24" fill="none"><path d="M12 8v5M12 16.5v.5" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"/><circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2"/></svg></span>
                      <span>CNPJ não encontrado na base. <small>Confira o número ou preencha manualmente.</small></span>
                    </div>
                  ) : (
                    <div className="lookup err">
                      <span className="li"><svg width="17" height="17" viewBox="0 0 24 24" fill="none"><path d="M12 8v5M12 16.5v.5" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"/><circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2"/></svg></span>
                      <span>Não foi possível consultar o CNPJ agora. <small>Preencha os dados manualmente.</small></span>
                    </div>
                  )
                )}

                {((sec.id==="faturamento" && cepLoading==="fat") || (sec.id==="entrega" && cepLoading==="ent")) && (
                  <div className="cep-loading"><span className="mini-spin"></span>Buscando endereço pelo CEP…</div>
                )}

                {sec.fields && renderFields(sec.fields)}
                {sec.groups && sec.groups.map(g=>(
                  <div className="group" key={g.title}>
                    <p className="group-title">{g.title}{g.note && <em>{g.note}</em>}</p>
                    {renderFields(g.fields)}
                  </div>
                ))}
              </div>
              <div className="foot">
                <button className="btn btn-ghost" onClick={back} disabled={step===0||status==="sending"}>
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M15 18l-6-6 6-6" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/></svg>
                  Voltar
                </button>
                <button className="btn btn-primary" onClick={next} disabled={status==="sending"}>
                  {status==="sending"
                    ? <React.Fragment><span className="spin"></span>Enviando…</React.Fragment>
                    : step===SECTIONS.length-1
                      ? <React.Fragment>Enviar cadastro<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M5 12h14M13 6l6 6-6 6" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/></svg></React.Fragment>
                      : <React.Fragment>Continuar<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M9 6l6 6-6 6" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/></svg></React.Fragment>}
                </button>
              </div>
            </div>
            <p className="formnote">
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><rect x="5" y="11" width="14" height="9" rx="2" stroke="currentColor" strokeWidth="1.8"/><path d="M8 11V8a4 4 0 018 0v3" stroke="currentColor" strokeWidth="1.8"/></svg>
              Seus dados são enviados de forma segura à Agenflex.
            </p>
          </React.Fragment>
        )}
      </main>
    </div>
  );
}

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