// App principal — orquestra todas as telas e estado
const { useState: useS, useEffect: useE, useRef: useR, useMemo: useM } = React;

function App() {
  // Perfil ativo:
  //   undefined = ainda checando sessão restaurável (admin via Supabase)
  //   null      = não logado (mostra LoginScreen)
  //   objeto    = logado (PIN local OU Admin via Supabase)
  const [perfil, setPerfil] = useS(undefined);
  const [tela, setTela] = useS('home');
  const [pedidos, setPedidos] = useS([]);
  const [clientes, setClientes] = useS([]);
  const [dadosCarregando, setDadosCarregando] = useS(true);
  const [erroCarregando, setErroCarregando] = useS('');
  const [aberto, setAberto] = useS(null);
  const [novo, setNovo] = useS(false);
  const [clienteEditando, setClienteEditando] = useS(null); // null | 'novo' | clienteObj

  // ─── CRUD de cliente — via Supabase (otimista no UI) ─────────
  const upsertCliente = async (c) => {
    try {
      const salvo = await window.ClientsAPI.upsertCliente(c);
      setClientes(cs => {
        const idx = cs.findIndex(x => x.id === salvo.id);
        return idx >= 0
          ? cs.map(x => x.id === salvo.id ? salvo : x)
          : [salvo, ...cs];
      });
      return salvo;
    } catch (err) {
      console.error('[upsertCliente]', err);
      alert('Erro ao salvar cliente: ' + err.message);
      throw err;
    }
  };
  const removerCliente = async (id) => {
    const antes = clientes;
    setClientes(cs => cs.filter(c => c.id !== id));
    try {
      await window.ClientsAPI.deleteCliente(id);
    } catch (err) {
      console.error('[removerCliente]', err);
      alert('Erro ao remover cliente: ' + err.message);
      setClientes(antes);
    }
  };

  // Tweaks
  const [tweaks, setTweak] = useTweaks(/*EDITMODE-BEGIN*/{
    "primaria": "#FF2E9A",
    "acento": "#2BE6F0",
    "fonteDisplay": "Space Grotesk",
    "fonteMono": "JetBrains Mono"
  }/*EDITMODE-END*/);

  // Aplicar tweaks na :root
  useE(() => {
    document.documentElement.style.setProperty('--primary', tweaks.primaria);
    document.documentElement.style.setProperty('--accent', tweaks.acento);
    document.documentElement.style.setProperty('--font-display', `"${tweaks.fonteDisplay}", system-ui, sans-serif`);
    document.documentElement.style.setProperty('--font-mono', `"${tweaks.fonteMono}", ui-monospace, monospace`);
  }, [tweaks]);

  // ─── Notificações ──────────────────────────────────────────
  // Alerta = pedido com falha de impressão OU pagamento aguardando
  const alertCount = useM(() => pedidos.filter(p =>
    p.statusImpressao === 'Falhou' || p.statusPagamento === 'Aguardando'
  ).length, [pedidos]);

  // ─── Badges da sidebar (contagens reais) ───────────────────
  const sidebarBadges = useM(() => ({
    fila: pedidos.filter(p =>
      ['Fila','Imprimindo','Pos-processamento'].includes(p.statusImpressao)
    ).length,
    envios: pedidos.filter(p =>
      p.statusImpressao === 'Pronto' && p.statusEntrega === 'Pendente'
    ).length,
    cancelados: pedidos.filter(p => p.statusImpressao === 'Cancelado').length,
  }), [pedidos]);

  // ─── Auto-tag + histórico — wrapper de updatePedido ────────
  // Aplica regras automáticas e registra cada mudança no histórico do pedido.
  const aplicarRegras = (antes, depois) => {
    let tagsFinal = depois.tags || [];
    const mudou = (campo) => antes[campo] !== depois[campo];

    // Auto-tag por transição de statusImpressao
    if (!mudou('statusImpressao')) {
      // sem mudança — tags ficam como o usuário enviou
    } else if (depois.statusImpressao === 'Falhou' && antes.statusImpressao !== 'Falhou') {
      if (!tagsFinal.includes('reimprimir')) tagsFinal = [...tagsFinal, 'reimprimir'];
    } else if (antes.statusImpressao === 'Falhou' && depois.statusImpressao !== 'Falhou') {
      tagsFinal = tagsFinal.filter(t => t !== 'reimprimir');
    }

    // Auto-tag por transição de statusPagamento
    if (mudou('statusPagamento')) {
      if (depois.statusPagamento === 'Aguardando' && antes.statusPagamento !== 'Aguardando') {
        if (!tagsFinal.includes('aguard-pgto')) tagsFinal = [...tagsFinal, 'aguard-pgto'];
      } else if (antes.statusPagamento === 'Aguardando' && depois.statusPagamento === 'Pago') {
        tagsFinal = tagsFinal.filter(t => t !== 'aguard-pgto' && t !== 'aguard-pix');
      }
    }

    return { ...depois, tags: tagsFinal };
  };

  const registrarHistorico = (antes, depois, quemNome) => {
    const entradas = [];
    const quando = new Date().toISOString();
    const quem = quemNome || '—';
    const camposStatus = [
      ['statusImpressao', 'impressão'],
      ['statusPagamento', 'pagamento'],
      ['statusEntrega', 'entrega'],
    ];
    for (const [campo, label] of camposStatus) {
      if (antes[campo] !== depois[campo]) {
        entradas.push({ campo, label, antes: antes[campo], depois: depois[campo], quando, quem });
      }
    }
    // Mudanças de tags (manuais ou via auto-tag)
    const tagsAntes = antes.tags || [];
    const tagsDepois = depois.tags || [];
    const adicionadas = tagsDepois.filter(t => !tagsAntes.includes(t));
    const removidas = tagsAntes.filter(t => !tagsDepois.includes(t));
    if (adicionadas.length || removidas.length) {
      entradas.push({
        campo: 'tags', label: 'tags',
        antes: removidas.length ? '−' + removidas.join(', −') : '',
        depois: adicionadas.length ? '+' + adicionadas.join(', +') : '',
        quando, quem,
      });
    }
    return entradas;
  };

  // Tocar som quando o número de alertas AUMENTAR (não na carga inicial)
  const prevAlertCount = useR(alertCount);
  const initialMount = useR(true);
  useE(() => {
    if (initialMount.current) {
      initialMount.current = false;
      prevAlertCount.current = alertCount;
      return;
    }
    if (alertCount > prevAlertCount.current) {
      playNotifSound();
    }
    prevAlertCount.current = alertCount;
  }, [alertCount]);

  // ─── Carregar pedidos + clientes do Supabase quando logar ─────
  useE(() => {
    if (!perfil) {
      setDadosCarregando(true);
      return;
    }
    if (!window.OrdersAPI || !window.ClientsAPI) {
      setErroCarregando('APIs não carregaram. Recarregue a página.');
      setDadosCarregando(false);
      return;
    }
    let cancelado = false;
    setDadosCarregando(true);
    setErroCarregando('');
    Promise.all([
      window.OrdersAPI.listPedidos(),
      window.ClientsAPI.listClientes(),
    ]).then(([peds, cls]) => {
      if (cancelado) return;
      setPedidos(peds);
      setClientes(cls);
      setDadosCarregando(false);
    }).catch(err => {
      if (cancelado) return;
      console.error('[carregar dados]', err);
      setErroCarregando('Erro ao carregar dados: ' + (err.message || err));
      setDadosCarregando(false);
    });
    return () => { cancelado = true; };
  }, [perfil]);

  // ─── Bootstrap — só restauramos sessão Admin (Supabase) ────────
  // PIN local NÃO persiste por segurança (cada reload pede PIN de novo).
  useE(() => {
    if (!window.Auth) {
      console.warn('[diskat-ops] window.Auth indisponível — só PIN local funcionará.');
      setPerfil(null);
      return;
    }
    let unsub = null;
    window.Auth.getSession().then(s => {
      const p = s ? window.Auth.buildPerfil(s) : null;
      setPerfil(p && p.role === 'admin' ? p : null);
    });
    // Listener: se admin fizer logout pelo Supabase OU sessão expirar, limpa.
    const sub = window.Auth.onAuthStateChange(s => {
      // Só reage a mudanças do Supabase pra perfis admin.
      // Perfis locais (PIN) ignoram esse listener — eles vivem só no state.
      if (!s) {
        // Logout do Supabase: se o perfil ativo era admin, limpa.
        setPerfil(prev => (prev && prev.role === 'admin') ? null : prev);
      }
    });
    if (sub && sub.data && sub.data.subscription) unsub = sub.data.subscription;
    return () => { if (unsub && typeof unsub.unsubscribe === 'function') unsub.unsubscribe(); };
  }, []);

  // Splash enquanto verifica sessão restaurável
  if (perfil === undefined) {
    return (
      <div style={{
        width:'100%', height:'100vh',
        background:'var(--bg-deep)',
        display:'flex', alignItems:'center', justifyContent:'center',
        color:'var(--text-3)', fontFamily:'var(--font-mono)', fontSize:11,
        letterSpacing:'0.18em', textTransform:'uppercase',
      }}>Carregando…</div>
    );
  }
  if (!perfil) return <LoginScreen onLogin={setPerfil}/>;

  // Tela de carregamento de dados (após login, antes do app renderizar com lista vazia)
  if (dadosCarregando) {
    return (
      <div style={{
        width:'100%', height:'100vh',
        background:'var(--bg-deep)',
        display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:16,
        color:'var(--text-3)', fontFamily:'var(--font-mono)', fontSize:11,
        letterSpacing:'0.18em', textTransform:'uppercase',
      }}>
        <div>Sincronizando dados…</div>
        {erroCarregando && (
          <div style={{ marginTop:10, fontSize:12, color:'var(--bad)', textTransform:'none', letterSpacing:'normal', fontFamily:'var(--font-body)', textAlign:'center', maxWidth:400, padding:'10px 16px', background:'rgba(255,77,106,0.08)', border:'1px solid rgba(255,77,106,0.3)', borderRadius:10 }}>
            {erroCarregando}
          </div>
        )}
      </div>
    );
  }

  // Logout: se for admin (sessão Supabase), encerra a sessão remota também.
  // PIN local: só limpa o state.
  const handleLogout = () => {
    if (perfil && perfil.role === 'admin' && window.Auth) {
      window.Auth.signOut().finally(() => setPerfil(null));
    } else {
      setPerfil(null);
    }
  };

  const updatePedido = async (novoP) => {
    const anterior = pedidos.find(p => p.id === novoP.id);
    if (!anterior) return;

    // Aplica regras (auto-tag) + registra histórico
    const aplicado = aplicarRegras(anterior, novoP);
    const novasEntradas = registrarHistorico(anterior, aplicado, perfil?.nome);
    const merged = {
      ...aplicado,
      historico: [...(anterior.historico || []), ...novasEntradas],
    };

    // Update otimista — UI responde imediato
    setPedidos(ps => ps.map(p => p.id === merged.id ? merged : p));
    if (aberto?.id === novoP.id) setAberto(merged);

    // Persiste no banco em background; reverte se falhar
    try {
      await window.OrdersAPI.updatePedido(merged.id, merged);
    } catch (err) {
      console.error('[updatePedido]', err);
      alert('Erro ao salvar alteração no pedido: ' + err.message);
      setPedidos(ps => ps.map(p => p.id === anterior.id ? anterior : p));
      if (aberto?.id === anterior.id) setAberto(anterior);
    }
  };
  const removerPedido = async (id) => {
    const antes = pedidos;
    setPedidos(ps => ps.filter(x => x.id !== id));
    if (aberto?.id === id) setAberto(null);
    try {
      await window.OrdersAPI.deletePedido(id);
    } catch (err) {
      console.error('[removerPedido]', err);
      alert('Erro ao excluir pedido: ' + err.message);
      setPedidos(antes);
    }
  };

  const titulos = {
    home:       { t: 'Início', s: null },
    pedidos:    { t: 'Pedidos', s: 'Selecione um filtro ou clique em um pedido' },
    fila:       { t: 'Fila de impressão 3D', s: 'Avance os cards conforme as peças progridem' },
    envios:     { t: 'Envios', s: 'Despache as peças prontas e acompanhe a entrega' },
    catalogo:   { t: 'Catálogo', s: 'Produtos do site Diskat Presentes — leitura ao vivo do banco' },
    clientes:   { t: 'Clientes', s: 'Cadastre, edite e organize seus clientes' },
    cancelados: { t: 'Pedidos cancelados', s: 'Restaure pra fila ou exclua definitivamente' },
  };
  const ti = titulos[tela];

  return (
    <div style={{ display:'flex', height:'100vh', background:'var(--bg-deep)', backgroundImage:'radial-gradient(circle at 15% 0%, rgba(255,46,154,0.18), transparent 45%), radial-gradient(circle at 90% 100%, rgba(43,230,240,0.10), transparent 45%)' }}>
      <Sidebar tela={tela} setTela={setTela} perfil={perfil} onLogout={handleLogout} badges={sidebarBadges}/>
      <main style={{ flex: 1, display:'flex', flexDirection:'column', overflow:'hidden' }}>
        <Topbar
          titulo={ti.t}
          subtitulo={ti.s}
          alertCount={alertCount}
          onBellClick={() => setTela('home')}
          action={
            tela === 'clientes' ? (
              window.pode && window.pode(perfil, 'criar:cliente') ? (
                <button onClick={() => setClienteEditando('novo')} style={{
                  padding:'9px 16px', background:'var(--primary)', color:'#fff', border:'none', borderRadius: 10,
                  fontSize: 13, fontWeight: 600, cursor:'pointer',
                  display:'flex', alignItems:'center', gap: 7,
                  boxShadow:'0 0 14px rgba(255,46,154,0.4)',
                }}><Icon.plus size={15}/> Novo cliente</button>
              ) : null
            ) : tela === 'catalogo' ? null : (
              window.pode && window.pode(perfil, 'criar:pedido') ? (
                <button onClick={() => setNovo(true)} style={{
                  padding:'9px 16px', background:'var(--primary)', color:'#fff', border:'none', borderRadius: 10,
                  fontSize: 13, fontWeight: 600, cursor:'pointer',
                  display:'flex', alignItems:'center', gap: 7,
                  boxShadow:'0 0 14px rgba(255,46,154,0.4)',
                }}><Icon.plus size={15}/> Novo pedido</button>
              ) : null
            )
          }
        />
        <div style={{ flex: 1, overflow:'auto' }}>
          {tela === 'home'       && <Home pedidos={pedidos} perfil={perfil} onAbrir={setAberto} onIrPara={(t) => t==='novo' ? setNovo(true) : setTela(t)}/>}
          {tela === 'pedidos'    && <PedidosLista pedidos={pedidos} onAbrir={setAberto}/>}
          {tela === 'fila'       && <FilaKanban pedidos={pedidos} onAbrir={setAberto} onUpdate={updatePedido}/>}
          {tela === 'envios'     && <Envios pedidos={pedidos} onAbrir={setAberto} onUpdate={updatePedido}/>}
          {tela === 'catalogo'   && <Catalogo/>}
          {tela === 'clientes'   && <ClientesLista clientes={clientes} pedidos={pedidos} onEditar={setClienteEditando} onRemover={removerCliente} onNovo={() => setClienteEditando('novo')}/>}
          {tela === 'cancelados' && <CanceladosLista pedidos={pedidos} onAbrir={setAberto} onUpdate={updatePedido} onRemover={removerPedido}/>}
        </div>
      </main>

      {aberto && <PedidoDetalhe pedido={aberto} onFechar={() => setAberto(null)} onUpdate={updatePedido} onRemover={removerPedido} perfil={perfil}/>}
      {novo && <NovoPedido clientes={clientes} onCancelar={() => setNovo(false)} onSalvar={async (p) => {
        try {
          // Remove o id se for fictício (Math.random) — deixa o banco gerar
          const { id, ...semId } = p;
          const criado = await window.OrdersAPI.createPedido(semId);
          setPedidos(ps => [criado, ...ps]);
          setNovo(false);
        } catch (err) {
          console.error('[criarPedido]', err);
          alert('Erro ao criar pedido: ' + err.message);
        }
      }} onAddCliente={upsertCliente}/>}
      {clienteEditando && <ClienteForm cliente={clienteEditando === 'novo' ? null : clienteEditando} onCancelar={() => setClienteEditando(null)} onSalvar={async (c) => {
        try {
          await upsertCliente(c);
          setClienteEditando(null);
        } catch (err) {
          // upsertCliente já mostra alert em erro
        }
      }}/>}

      {/* Tweaks panel */}
      <TweaksPanel title="Tweaks">
        <TweakSection title="Identidade visual">
          <TweakColor label="Magenta (primária)" value={tweaks.primaria} onChange={v => setTweak('primaria', v)}/>
          <TweakColor label="Ciano (acento)" value={tweaks.acento} onChange={v => setTweak('acento', v)}/>
        </TweakSection>
        <TweakSection title="Tipografia">
          <TweakSelect label="Display" value={tweaks.fonteDisplay} options={['Space Grotesk','Inter','DM Sans','Manrope','Sora']} onChange={v => setTweak('fonteDisplay', v)}/>
          <TweakSelect label="Monospace" value={tweaks.fonteMono} options={['JetBrains Mono','IBM Plex Mono','Fira Code','Space Mono']} onChange={v => setTweak('fonteMono', v)}/>
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

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