/* ===========================================================
   PIPOQUE — App: estado global, roteamento, montagem
   Dados de produtos/configurações/usuários/pedidos vêm da API.
   Carrinho e paleta seguem no localStorage (transientes/UI).
   =========================================================== */
const { useState, useEffect, useRef, createContext, useContext } = React;

const AppCtx = createContext(null);
const useApp = () => useContext(AppCtx);
window.useApp = useApp;

/* ---------- parse de rota (hash) ---------- */
function parseRoute() {
  const raw = (window.location.hash || '#/').replace(/^#/, '');
  const [path, qs] = raw.split('?');
  const query = {};
  if (qs) qs.split('&').forEach((kv) => { const [k, v] = kv.split('='); query[decodeURIComponent(k)] = decodeURIComponent(v || ''); });
  const seg = path.replace(/^\//, '').split('/');
  let name = 'home';
  if (seg[0] === 'cardapio') name = 'menu';
  else if (seg[0] === 'checkout') name = 'checkout';
  else if (seg[0] === 'pagamento') name = 'payment';
  else if (seg[0] === 'pedido') name = 'confirm';
  else if (seg[0] === 'admin') name = 'admin';
  return { name, seg, query, path };
}

function AppProvider({ children }) {
  const toast = useToast();

  const [products, setProductsState] = useState([]);
  const [settings, setSettingsState] = useState(null);
  const [users, setUsersState] = useState([]);
  const [orders, setOrdersState] = useState([]);
  const [loaded, setLoaded] = useState(false);    // produtos + settings públicos carregados
  const [loadError, setLoadError] = useState(false);

  const [cart, setCartState] = useState(() => LS.get(KEYS.cart, []));
  const [palette, setPaletteState] = useState(() => LS.get(KEYS.palette, 'pop') || 'pop');
  const [session, setSession] = useState(() => LS.get(KEYS.session, null));
  const [route, setRoute] = useState(parseRoute);
  const [cartOpen, setCartOpen] = useState(false);
  const [customer, setCustomer] = useState(() => {
    const raw = getCookie('pipoque_customer');
    try { return raw ? JSON.parse(raw) : {}; } catch (e) { return {}; }
  });

  /* ---- carga inicial pública (produtos + configurações) ---- */
  useEffect(() => {
    (async () => {
      try {
        const [p, s] = await Promise.all([api('/products'), api('/settings')]);
        setProductsState(p);
        setSettingsState(s);
      } catch (e) {
        setLoadError(true);
      } finally {
        setLoaded(true);
      }
    })();
  }, []);

  /* ---- dados do admin: só quando há sessão (token) ---- */
  useEffect(() => {
    if (!session) { setUsersState([]); setOrdersState([]); return; }
    (async () => {
      try {
        const [u, o] = await Promise.all([api('/users', { auth: true }), api('/orders', { auth: true })]);
        setUsersState(u);
        setOrdersState(o);
      } catch (e) {
        if (e.status === 401) { setSession(null); LS.set(KEYS.session, null); }
      }
    })();
  }, [session]);

  /* rota */
  useEffect(() => {
    const onHash = () => { setRoute(parseRoute()); window.scrollTo(0, 0); };
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);
  const navigate = (to) => {
    if (('#' + window.location.hash.replace(/^#/, '')) === to || window.location.hash === to) { setRoute(parseRoute()); }
    window.location.hash = to;
  };

  /* paleta no body */
  useEffect(() => {
    document.body.setAttribute('data-palette', palette);
    LS.set(KEYS.palette, palette);
  }, [palette]);

  /* botnav padding */
  useEffect(() => {
    document.body.classList.toggle('has-botnav', route.name !== 'admin');
  }, [route.name]);

  /* helper de erro padrão para mutações */
  const fail = (e, fallbackMsg) => {
    if (e && e.status === 401) { toast('Sessão expirada, entre novamente 🔒'); setSession(null); LS.set(KEYS.session, null); }
    else toast((e && e.message) || fallbackMsg || 'Algo deu errado 😕');
    return null;
  };

  /* ---- produtos (API) ---- */
  const addProduct = async (data) => {
    try { const p = await api('/products', { method: 'POST', body: data, auth: true }); setProductsState((v) => [...v, p]); return p; }
    catch (e) { return fail(e, 'Não foi possível cadastrar o produto'); }
  };
  const updateProduct = async (id, patch) => {
    try { const p = await api('/products/' + id, { method: 'PUT', body: patch, auth: true }); setProductsState((v) => v.map((x) => x.id === id ? p : x)); return p; }
    catch (e) { return fail(e, 'Não foi possível atualizar o produto'); }
  };
  const removeProduct = async (id) => {
    try { await api('/products/' + id, { method: 'DELETE', auth: true }); setProductsState((v) => v.filter((x) => x.id !== id)); return true; }
    catch (e) { return fail(e, 'Não foi possível excluir o produto'); }
  };

  /* ---- settings (API) ---- */
  const updateSettings = async (v) => {
    try { const s = await api('/settings', { method: 'PUT', body: v, auth: true }); setSettingsState(s); return s; }
    catch (e) { return fail(e, 'Não foi possível salvar as configurações'); }
  };

  /* ---- users (API) ---- */
  const addUser = async (u) => {
    try { const nu = await api('/users', { method: 'POST', body: u, auth: true }); setUsersState((v) => [...v, nu]); return nu; }
    catch (e) { return fail(e, 'Não foi possível criar o usuário'); }
  };
  const updateUser = async (id, patch) => {
    try {
      const nu = await api('/users/' + id, { method: 'PUT', body: patch, auth: true });
      setUsersState((v) => v.map((u) => u.id === id ? nu : u));
      if (session && session.id === id) { const ns = { ...session, ...nu }; setSession(ns); LS.set(KEYS.session, ns); }
      return nu;
    } catch (e) { return fail(e, 'Não foi possível atualizar o usuário'); }
  };
  const removeUser = async (id) => {
    try { await api('/users/' + id, { method: 'DELETE', auth: true }); setUsersState((v) => v.filter((u) => u.id !== id)); return true; }
    catch (e) { return fail(e, 'Não foi possível remover o usuário'); }
  };
  const changePassword = async (current, next) => {
    try { await api('/account/password', { method: 'POST', body: { current, next }, auth: true }); return true; }
    catch (e) { return fail(e, 'Não foi possível alterar a senha'); }
  };

  /* ---- upload genérico de imagem (dataURL -> caminho em /uploads) ---- */
  const uploadImage = async (dataUrl) => {
    try { const r = await api('/uploads', { method: 'POST', body: { imageData: dataUrl }, auth: true }); return r.url; }
    catch (e) { return fail(e, 'Não foi possível enviar a imagem'); }
  };

  /* ---- Pix / Mercado Pago (públicos) ---- */
  const createPix = async (orderPayload) => {
    try { return await api('/pix', { method: 'POST', body: orderPayload }); }
    catch (e) { toast(e.message || 'Falha ao gerar o Pix'); return null; }
  };
  const renewPix = async (orderId) => {
    try { return await api('/pix/' + orderId + '/renew', { method: 'POST' }); }
    catch (e) { toast(e.message || 'Falha ao gerar novo Pix'); return null; }
  };
  const getPixStatus = async (paymentId) => {
    try { return await api('/pix/' + paymentId); }
    catch (e) { return null; }
  };

  /* ---- orders (API) ---- */
  const addOrder = async (o) => {
    try { const no = await api('/orders', { method: 'POST', body: o }); setOrdersState((v) => [...v, no]); return no; }
    catch (e) { return null; } // checkout trata a ausência; o WhatsApp já foi aberto
  };
  const updateOrder = async (id, patch) => {
    try { const no = await api('/orders/' + id, { method: 'PUT', body: patch, auth: true }); setOrdersState((v) => v.map((o) => o.id === id ? no : o)); return no; }
    catch (e) { return fail(e, 'Não foi possível atualizar o pedido'); }
  };

  /* ---- cart (localStorage) ---- */
  const persistCart = (v) => { setCartState(v); LS.set(KEYS.cart, v); };
  const addToCart = (item) => {
    let next;
    if (item.productId) {
      const existing = cart.find((l) => l.productId === item.productId && !l.custom);
      if (existing) {
        next = cart.map((l) => l === existing ? { ...l, qty: l.qty + (item.qty || 1) } : l);
      } else {
        next = [...cart, { ...item, lineId: 'l' + Date.now() + Math.random().toString(36).slice(2, 5), qty: item.qty || 1 }];
      }
    } else {
      next = [...cart, { ...item, lineId: 'l' + Date.now() + Math.random().toString(36).slice(2, 5), qty: item.qty || 1 }];
    }
    persistCart(next);
  };
  const quickAdd = (product) => {
    addToCart({ productId: product.id, name: product.name, glyph: product.glyph, color: product.color, image: product.image || '', unitPrice: product.price, optsText: '' });
    setCartOpen(true);
  };
  const setQty = (lineId, qty) => {
    if (qty <= 0) { persistCart(cart.filter((l) => l.lineId !== lineId)); return; }
    persistCart(cart.map((l) => l.lineId === lineId ? { ...l, qty } : l));
  };
  const removeLine = (lineId) => persistCart(cart.filter((l) => l.lineId !== lineId));
  const clearCart = () => persistCart([]);
  const cartCount = cart.reduce((s, l) => s + l.qty, 0);
  const cartSubtotal = cart.reduce((s, l) => s + l.unitPrice * l.qty, 0);

  /* ---- palette ---- */
  const setPalette = (p) => setPaletteState(p);

  /* ---- auth ---- */
  const login = async (username, password) => {
    try {
      const { token, user } = await api('/login', { method: 'POST', body: { username, password } });
      apiToken.set(token);
      setSession(user); LS.set(KEYS.session, user);
      return true;
    } catch (e) { return false; }
  };
  const logout = () => { setSession(null); LS.set(KEYS.session, null); apiToken.set(''); };

  /* ---- customer (cookies) ---- */
  const saveCustomer = (data) => {
    const merged = { ...customer, ...data };
    setCustomer(merged);
    setCookie('pipoque_customer', JSON.stringify(merged));
  };

  /* ---- auto-logout do admin após 20 min de inatividade ---- */
  useEffect(() => {
    if (!session) return;
    const IDLE_MS = 20 * 60 * 1000;
    let timer;
    const expire = () => {
      logout();
      toast('Sessão encerrada por inatividade 🔒');
      if (parseRoute().name === 'admin') navigate('#/admin');
    };
    const reset = () => { clearTimeout(timer); timer = setTimeout(expire, IDLE_MS); };
    const events = ['mousemove', 'mousedown', 'keydown', 'scroll', 'touchstart'];
    events.forEach((e) => window.addEventListener(e, reset, { passive: true }));
    reset();
    return () => { clearTimeout(timer); events.forEach((e) => window.removeEventListener(e, reset)); };
  }, [session]);

  const value = {
    products, addProduct, updateProduct, removeProduct,
    settings, updateSettings,
    users, addUser, updateUser, removeUser, changePassword, uploadImage,
    createPix, renewPix, getPixStatus,
    orders, addOrder, updateOrder,
    cart, addToCart, quickAdd, setQty, removeLine, clearCart, cartCount, cartSubtotal,
    palette, setPalette,
    route, navigate,
    cartOpen, setCartOpen,
    session, login, logout,
    customer, saveCustomer,
    loaded, loadError,
  };
  return <AppCtx.Provider value={value}>{children}</AppCtx.Provider>;
}

/* ---------- telas de carregamento / erro ---------- */
function Splash() {
  return (
    <div className="login-wrap" style={{ background: 'var(--hero-bg)', color: 'var(--hero-ink)' }}>
      <div style={{ textAlign: 'center' }}>
        <Pipo size={96} className="big-mascot" />
        <p style={{ fontFamily: 'Fredoka', fontWeight: 700, fontSize: 18, marginTop: 14 }}>Carregando o Pipoque…</p>
      </div>
    </div>
  );
}
function LoadError() {
  return (
    <div className="login-wrap" style={{ background: 'var(--hero-bg)', color: 'var(--hero-ink)' }}>
      <div className="card" style={{ background: 'var(--surface)', color: 'var(--ink)', padding: 32, maxWidth: 420, textAlign: 'center' }}>
        <Pipo size={84} />
        <h2 style={{ fontFamily: 'Fredoka', marginTop: 10 }}>Não foi possível carregar</h2>
        <p className="muted" style={{ fontSize: 14.5, marginTop: 6 }}>Verifique sua conexão com o servidor e tente novamente.</p>
        <button className="btn btn-primary" style={{ marginTop: 16 }} onClick={() => window.location.reload()}>Recarregar</button>
      </div>
    </div>
  );
}

/* ---------- App shell ---------- */
function App() {
  const app = useApp();
  const { route, session, loaded, loadError, settings } = app;

  if (!loaded) return <Splash />;
  if (loadError || !settings) return <LoadError />;

  if (route.name === 'admin') {
    return session ? <AdminShell /> : <AdminLogin />;
  }

  let pageEl;
  if (route.name === 'menu') pageEl = <MenuPage />;
  else if (route.name === 'checkout') pageEl = <CheckoutPage />;
  else if (route.name === 'payment') pageEl = <PaymentPage />;
  else if (route.name === 'confirm') pageEl = <ConfirmPage />;
  else pageEl = <HomePage />;

  return (
    <React.Fragment>
      <AppHeader />
      {pageEl}
      <Footer />
      <CartDrawer />
      <BottomNav />
    </React.Fragment>
  );
}

/* ---------- mount ---------- */
function Root() {
  return (
    <ToastProvider>
      <AppProvider>
        <App />
      </AppProvider>
    </ToastProvider>
  );
}

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