/* ============================================================
   CART — botón flotante + cajón con checkout en pasos + PSE + WhatsApp
   ============================================================ */
const { PAYMENTS: _PAYMENTS, WA: _WA, GOOGLE_MAPS_API_KEY: _GKEY,
  DELIVERY_FEE: _DFEE, DELIVERY_SURCHARGE_KM: _DSUR, DELIVERY_SURCHARGE_MIN_KM: _DMIN,
  DELIVERY_SURCHARGE_MAX_KM: _DMAX, FREE_DELIVERY_MIN: _DFREE, RESTAURANT_LOCATION: _RLOC } = window;

/* ---- Carga (una sola vez) del SDK de Google Maps Places ---- */
function loadGoogleMaps(key) {
  if (window.google && window.google.maps && window.google.maps.places) return Promise.resolve();
  if (window.__gmapsPromise) return window.__gmapsPromise;
  window.__gmapsPromise = new Promise((resolve, reject) => {
    const s = document.createElement("script");
    s.src = `https://maps.googleapis.com/maps/api/js?key=${encodeURIComponent(key)}&libraries=places&language=es&region=CO`;
    s.async = true;
    s.onload = resolve;
    s.onerror = () => reject(new Error("No se pudo cargar Google Maps"));
    document.head.appendChild(s);
  });
  return window.__gmapsPromise;
}

/* ---- Autocompletado gratuito (OpenStreetMap · Nominatim), sin clave ---- */
function osmLabel(x) {
  const a = x.address || {};
  const road = [a.road, a.house_number].filter(Boolean).join(" ");
  const area = a.neighbourhood || a.suburb || a.quarter || a.residential || a.city_district || a.borough;
  const city = a.city || a.town || a.municipality || a.county;
  const parts = [road || a.name || x.name, area, city].filter(Boolean);
  const uniq = parts.filter((v, i) => parts.indexOf(v) === i);
  return uniq.join(", ");
}
async function osmSearch(q) {
  // viewbox de Bogotá para sesgar resultados cercanos (sin excluir otras ciudades)
  const url = "https://nominatim.openstreetmap.org/search?format=jsonv2&addressdetails=1" +
    "&limit=6&countrycodes=co&accept-language=es" +
    "&viewbox=-74.25,4.85,-73.99,4.48" +
    "&q=" + encodeURIComponent(q);
  const r = await fetch(url);
  if (!r.ok) throw new Error("net");
  const data = await r.json();
  const list = (Array.isArray(data) ? data : [])
    .map(x => ({ label: osmLabel(x), lat: parseFloat(x.lat), lon: parseFloat(x.lon) }))
    .filter(x => x.label);
  const seen = new Set(); const out = [];
  for (const item of list) { if (!seen.has(item.label)) { seen.add(item.label); out.push(item); } }
  return out.slice(0, 6);
}

/* ---- Campo de dirección con autocompletado ---- */
function AddressField({ value, onChange, error }) {
  const ref = useRef(null);

  // --- Ruta 1: Google Maps (solo si hay clave) ---
  useEffect(() => {
    if (!_GKEY || !ref.current) return;
    let ac;
    loadGoogleMaps(_GKEY).then(() => {
      if (!ref.current || !window.google) return;
      ac = new window.google.maps.places.Autocomplete(ref.current, {
        componentRestrictions: { country: "co" },
        fields: ["formatted_address", "name", "geometry"],
        types: ["address"],
      });
      ac.addListener("place_changed", () => {
        const p = ac.getPlace();
        const addr = p.formatted_address || p.name || ref.current.value;
        const geo = (p.geometry && p.geometry.location) ? { lat: p.geometry.location.lat(), lng: p.geometry.location.lng() } : null;
        onChange(addr, geo);
      });
    }).catch(() => {});
  }, []);

  // --- Ruta 2 (por defecto): OpenStreetMap, gratis y sin clave ---
  const [sugs, setSugs] = useState([]);
  const [open, setOpen] = useState(false);
  const [loading, setLoading] = useState(false);
  const [failed, setFailed] = useState(false);
  const tRef = useRef(null);
  const seqRef = useRef(0);

  function handleType(v) {
    onChange(v, null); // limpia la geolocalización al escribir manualmente
    if (_GKEY) return; // Google maneja sus propias sugerencias
    if (tRef.current) clearTimeout(tRef.current);
    const q = v.trim();
    if (q.length < 4) { setSugs([]); setOpen(false); return; }
    setLoading(true); setOpen(true); setFailed(false);
    const seq = ++seqRef.current;
    tRef.current = setTimeout(() => {
      osmSearch(q)
        .then(list => { if (seq !== seqRef.current) return; setSugs(list); setLoading(false); })
        .catch(() => { if (seq !== seqRef.current) return; setSugs([]); setLoading(false); setFailed(true); });
    }, 450);
  }
  function pick(s) { onChange(s.label, { lat: s.lat, lng: s.lon }); setSugs([]); setOpen(false); }

  const showList = !_GKEY && open && (loading || sugs.length > 0);

  return (
    <label className="fld addr-fld"><span>Dirección de entrega</span>
      <input ref={ref} value={value}
        onChange={(e) => handleType(e.target.value)}
        onFocus={() => { if (!_GKEY && sugs.length) setOpen(true); }}
        onBlur={() => setTimeout(() => setOpen(false), 160)}
        placeholder="Ej: Calle 142C # 61-20, Cedritos…" autoComplete="off" maxLength={120} />

      {showList && (
        <div className="addr-sugs" role="listbox">
          {loading && <div className="addr-sug addr-sug-load">Buscando direcciones…</div>}
          {!loading && sugs.map((s, i) => (
            <button type="button" key={i} className="addr-sug"
              onMouseDown={(e) => { e.preventDefault(); pick(s); }}>
              <Icon d={I.pin} size={15} /> <span>{s.label}</span>
            </button>
          ))}
        </div>
      )}

      {error
        ? <small className="fld-err">{error}</small>
        : <small className="fld-hint">
            {failed
              ? "No pudimos cargar sugerencias; escribe tu dirección completa (calle/carrera, número y barrio)."
              : (_GKEY
                  ? "Selecciona tu dirección de la lista de sugerencias."
                  : "Empieza a escribir y elige tu dirección de la lista, o escríbela completa.")}
          </small>}
    </label>
  );
}

function cartCount(cart) { return cart.reduce((s, l) => s + l.qty, 0); }
function cartSubtotal(cart) { return cart.reduce((s, l) => s + l.unitPrice * l.qty, 0); }
function cartRanged(cart) { return cart.some(l => l.ranged && !l.size); }

// Opciones de tamaño para platos con rango de precio (por peso, en gramos)
const SIZES = [
  { id: "pequeno", idx: 0 },
  { id: "mediano", idx: 1 },
  { id: "grande", idx: 2 },
];
function sizeWeight(line, sizeId) {
  if (line.weights && line.weights.length === 3) {
    const s = SIZES.find(x => x.id === sizeId);
    return line.weights[s.idx];
  }
  return null;
}
function sizePrice(line, sizeId) {
  const lo = (line.from != null ? line.from : line.to) || 0;
  const hi = (line.to != null ? line.to : line.from) || 0;
  if (sizeId === "pequeno") return lo;
  if (sizeId === "grande") return hi;
  return Math.round(((lo + hi) / 2) / 1000) * 1000; // mediano
}
function sizeLabel(line, sizeId) {
  const w = sizeWeight(line, sizeId);
  return w ? (w + " g") : ({ pequeno: "Pequeño", mediano: "Mediano", grande: "Grande" }[sizeId]);
}

/* ---- Botón flotante ---- */
function FloatingCart({ cart, onOpen }) {
  const n = cartCount(cart);
  if (!n) return null;
  return (
    <button className="fab" onClick={onOpen}>
      <span className="fab-ic"><Icon d={I.cart} size={22} /><span className="fab-badge">{n}</span></span>
      <span className="fab-txt">Mi pedido</span>
      <span className="fab-total">{fmt(cartSubtotal(cart))}{cartRanged(cart) ? "+" : ""}</span>
    </button>
  );
}

/* ---- Línea del carrito ---- */
function CartLine({ line, onQty, onRemove, onSize }) {
  return (
    <div className="cline">
      <Placeholder label={line.name} kind="" className="cline-ph" img={window.PHOTOS[line.name]} />
      <div className="cline-mid">
        <div className="cline-top">
          <span className="cline-name">{line.name}</span>
          <button className="cline-x" onClick={onRemove} aria-label="Quitar"><Icon d={I.close} size={16} /></button>
        </div>
        <div className="cline-opts">
          {line.rice && <span>{line.rice}</span>}
          {line.drink && <span>{line.drink}</span>}
          {line.notes && <span className="cline-note">“{line.notes}”</span>}
        </div>
        {line.ranged && (
          <label className="cline-size"><span>Tamaño</span>
            <select value={line.size || ""} onChange={(e) => onSize(e.target.value)}>
              <option value="" disabled>Elige un tamaño…</option>
              {SIZES.map(s => <option key={s.id} value={s.id}>{sizeLabel(line, s.id)}</option>)}
            </select>
          </label>
        )}
        <div className="cline-bot">
          <Stepper value={line.qty} onChange={onQty} size="sm" />
          <span className="cline-price">{fmt(line.unitPrice * line.qty)}{line.ranged && !line.size ? "+" : ""}</span>
        </div>
      </div>
    </div>
  );
}

/* ---- PSE simulado ---- */
function PseModal({ total, onClose, onApproved }) {
  const banks = ["Bancolombia", "Davivienda", "BBVA", "Banco de Bogotá", "Nequi", "Banco Caja Social"];
  const [bank, setBank] = useState("");
  const [stage, setStage] = useState("select"); // select | processing | done
  useEffect(() => {
    if (stage === "processing") { const t = setTimeout(() => setStage("done"), 1800); return () => clearTimeout(t); }
    if (stage === "done") { const t = setTimeout(onApproved, 1300); return () => clearTimeout(t); }
  }, [stage]);
  return (
    <div className="overlay pse-overlay" onClick={stage === "select" ? onClose : undefined}>
      <div className="pse" onClick={(e) => e.stopPropagation()}>
        <div className="pse-head"><span className="pse-logo">PSE</span><span>Pagos Seguros en Línea</span></div>
        {stage === "select" && <>
          <p className="pse-amount">Vas a pagar <b>{fmt(total)}</b></p>
          <span className="block-label">Selecciona tu banco</span>
          <div className="pse-banks">
            {banks.map(b => (
              <button key={b} className={"opt " + (bank === b ? "on" : "")} onClick={() => setBank(b)}>{b}</button>
            ))}
          </div>
          <button className="btn-add" disabled={!bank} onClick={() => setStage("processing")}>Continuar al banco</button>
          <button className="pse-cancel" onClick={onClose}>Cancelar</button>
        </>}
        {stage === "processing" && <div className="pse-state">
          <div className="spinner" />
          <p>Conectando con {bank}…</p>
          <small>Simulación de pasarela PSE</small>
        </div>}
        {stage === "done" && <div className="pse-state">
          <div className="pse-check"><Icon d={I.check} size={30} stroke="#fff" sw={2.2} /></div>
          <p>¡Pago aprobado!</p>
          <small>Enviando tu pedido…</small>
        </div>}
      </div>
    </div>
  );
}

/* ---- Cajón del carrito ---- */
function CartDrawer({ open, cart, setCart, onClose, onScrollTo, isOpen, store }) {
  const [step, setStep] = useState(0);
  const [mode, setMode] = useState("domicilio"); // domicilio | recoger
  const [form, setForm] = useState({ name: "", phone: "", address: "", details: "", addressGeo: null });
  const [pay, setPay] = useState("pse");
  const [pse, setPse] = useState(false);
  const [tried, setTried] = useState(false); // marca intento de continuar para mostrar errores

  const sub = cartSubtotal(cart);
  const ranged = cartRanged(cart);
  const distanceKm = (_RLOC.lat != null && form.addressGeo)
    ? haversineKm(_RLOC.lat, _RLOC.lng, form.addressGeo.lat, form.addressGeo.lng)
    : null;
  function computeDelivery() {
    if (sub >= _DFREE) return 0; // envío gratis por monto mínimo
    if (distanceKm != null && distanceKm >= _DMIN && distanceKm < _DMAX) return _DFEE + _DSUR; // recargo silencioso por distancia
    return _DFEE;
  }
  const delivery = mode === "domicilio" ? computeDelivery() : 0;
  const total = sub + delivery;
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const errName = isValidName(form.name) ? "" : "Ingresa un nombre válido (solo letras).";
  const errPhone = isValidPhone(form.phone) ? "" : "Ingresa un teléfono válido (7 a 15 dígitos).";
  const errAddr = (mode === "recoger" || form.address.trim().length >= 6) ? "" : "Ingresa una dirección de entrega.";

  const validStep1 = !errName && !errPhone && !errAddr;

  function setQty(uid, q) { setCart(c => c.map(l => l.uid === uid ? { ...l, qty: q } : l)); }
  function remove(uid) { setCart(c => c.filter(l => l.uid !== uid)); }
  function setSize(uid, sizeId) {
    setCart(c => c.map(l => {
      if (l.uid !== uid) return l;
      const price = sizePrice(l, sizeId) + (l.drinkExtra || 0);
      return { ...l, size: sizeId, unitPrice: price };
    }));
  }

  function buildMsg() {
    const L = ["*PEDIDO — Dos Océanos*", "—————————————"];
    cart.forEach((l, i) => {
      L.push(`${i + 1}) ${l.name} ×${l.qty}`);
      if (l.rice) L.push(`   • ${l.rice}`);
      if (l.drink) L.push(`   • ${l.drink}`);
      if (l.ranged) L.push(`   • Tamaño: ${l.size ? sizeLabel(l, l.size) : "por confirmar"}`);
      if (l.notes) L.push(`   • Nota: ${l.notes}`);
      L.push(`   ${fmt(l.unitPrice * l.qty)}${l.ranged ? " (según tamaño)" : ""}`);
    });
    L.push("—————————————");
    L.push(`Subtotal: ${fmt(sub)}${ranged ? "+" : ""}`);
    if (mode === "domicilio") L.push(`Domicilio: ${delivery === 0 ? "Gratis" : fmt(delivery)}`);
    L.push(`*Total estimado: ${fmt(total)}${ranged ? "+" : ""}*`);
    L.push("—————————————");
    L.push(mode === "domicilio" ? "Entrega: Domicilio" : "Entrega: Recoger en el local");
    L.push(`Cliente: ${form.name}`);
    L.push(`Tel: ${form.phone}`);
    if (mode === "domicilio") {
      L.push(`Dirección: ${form.address}`);
      if (form.details.trim()) L.push(`Indicaciones: ${form.details}`);
    }
    const pm = _PAYMENTS.find(p => p.id === pay);
    L.push(`Pago: ${pm ? pm.label : pay}${pay === "pse" ? " (aprobado ✓)" : ""}`);
    return encodeURIComponent(L.join("\n"));
  }
  function sendWhatsApp() {
    window.open(`https://wa.me/${_WA}?text=${buildMsg()}`, "_blank");
    setCart([]); setStep(0); onClose();
  }
  function onPay() {
    if (pay === "pse") setPse(true);
    else sendWhatsApp();
  }

  const steps = ["Tu pedido", "Entrega", "Pago"];

  return (
    <>
      <div className={"drawer-scrim " + (open ? "on" : "")} onClick={onClose} />
      <aside className={"drawer " + (open ? "on" : "")} aria-hidden={!open}>
        <header className="drawer-head">
          <div className="drawer-steps">
            {steps.map((s, i) => (
              <span key={i} className={"dstep " + (i === step ? "on" : i < step ? "done" : "")}>{s}</span>
            ))}
          </div>
          <button className="drawer-x" onClick={onClose} aria-label="Cerrar"><Icon d={I.close} size={22} /></button>
        </header>

        <div className="drawer-body">
          {!isOpen && cart.length > 0 && (
            <div className="closed-note">
              <Icon d={I.clock} size={18} stroke="var(--sun)" />
              <div><b>Estamos cerrados ahora</b><span>{closedReason(store)}. Puedes dejar tu pedido listo y enviarlo cuando abramos.</span></div>
            </div>
          )}
          {cart.length === 0 && (
            <div className="empty">
              <Icon d={I.cart} size={40} stroke="var(--ink-soft)" />
              <p>Tu pedido está vacío</p>
              <button className="link" onClick={() => { onClose(); onScrollTo("menu"); }}>Ver la carta →</button>
            </div>
          )}

          {cart.length > 0 && step === 0 && (
            <div className="dstack">
              {cart.map(l => <CartLine key={l.uid} line={l} onQty={(q) => setQty(l.uid, q)} onRemove={() => remove(l.uid)} onSize={(s) => setSize(l.uid, s)} />)}
              <button className="link add-more" onClick={() => { onClose(); onScrollTo("menu"); }}>+ Agregar más platos</button>
            </div>
          )}

          {cart.length > 0 && step === 1 && (
            <div className="dstack form">
              <div className="seg">
                <button className={mode === "domicilio" ? "on" : ""} onClick={() => setMode("domicilio")}>Domicilio</button>
                <button className={mode === "recoger" ? "on" : ""} onClick={() => setMode("recoger")}>Recoger</button>
              </div>
              <label className="fld"><span>Nombre</span>
                <input value={form.name} onChange={(e) => set("name", filterName(e.target.value))}
                  placeholder="Tu nombre" autoComplete="name" maxLength={50} />
                {tried && errName && <small className="fld-err">{errName}</small>}</label>
              <label className="fld"><span>Teléfono</span>
                <input value={form.phone} onChange={(e) => set("phone", filterPhone(e.target.value))}
                  placeholder="3xx xxx xxxx" inputMode="tel" autoComplete="tel" maxLength={20} />
                {tried && errPhone && <small className="fld-err">{errPhone}</small>}</label>
              {mode === "domicilio" && <>
                <AddressField value={form.address}
                  onChange={(v, geo) => setForm(f => ({ ...f, address: filterAddress(v), addressGeo: geo }))}
                  error={tried ? errAddr : ""} />
                <label className="fld"><span>Apto / piso / indicaciones (opcional)</span>
                  <input value={form.details} onChange={(e) => set("details", filterNotes(e.target.value))} placeholder="Apto 302, torre B, dejar en portería…" maxLength={120} /></label>
              </>}
              {mode === "recoger" && <p className="pickup-note"><Icon d={I.pin} size={15} stroke="var(--coral)" /> Recoges en el local. Te avisamos por WhatsApp cuando esté listo.</p>}
            </div>
          )}

          {cart.length > 0 && step === 2 && (
            <div className="dstack form">
              <span className="block-label">¿Cómo quieres pagar?</span>
              <div className="pays">
                {_PAYMENTS.map(p => (
                  <button key={p.id} className={"pay " + (pay === p.id ? "on" : "")} onClick={() => setPay(p.id)}>
                    <span className="pay-l">{p.label}{p.pse && <span className="pay-pse">en línea</span>}</span>
                    <span className="pay-d">{p.desc}</span>
                  </button>
                ))}
              </div>
            </div>
          )}
        </div>

        {cart.length > 0 && (
          <footer className="drawer-foot">
            <div className="sumrows">
              <div><span>Subtotal</span><b>{fmt(sub)}{ranged ? "+" : ""}</b></div>
              {step >= 1 && mode === "domicilio" && <div><span>Domicilio</span><b>{delivery === 0 ? "Gratis" : fmt(delivery)}</b></div>}
              <div className="total"><span>Total{ranged ? " estimado" : ""}</span><b>{fmt(total)}{ranged ? "+" : ""}</b></div>
            </div>
            {mode === "domicilio" && delivery > 0 && sub < _DFREE && (
              <p className="freenote">Envío gratis en pedidos superiores a {fmt(_DFREE)}.</p>
            )}
            {ranged && <p className="rangednote">Algunos pescados se cobran según tamaño/peso; el valor final se confirma por WhatsApp.</p>}
            <div className="drawer-actions">
              {step > 0 && <button className="btn-ghost" onClick={() => setStep(step - 1)}><Icon d={I.back} size={18} /></button>}
              {step === 0 && <button className="btn-add" onClick={() => setStep(1)}>Continuar <Icon d={I.arrow} size={18} /></button>}
              {step === 1 && <button className="btn-add" onClick={() => { if (validStep1) { setTried(false); setStep(2); } else setTried(true); }}>Continuar al pago <Icon d={I.arrow} size={18} /></button>}
              {step === 2 && (isOpen
                ? (pay === "pse"
                  ? <button className="btn-add pse-btn" onClick={onPay}><span className="pse-chip">PSE</span> Pagar {fmt(total)}</button>
                  : <button className="btn-add wa" onClick={onPay}><Wa size={18} /> Enviar pedido</button>)
                : <button className="btn-add" disabled><Icon d={I.clock} size={18} /> Cerrado · pedidos en pausa</button>)}
            </div>
          </footer>
        )}
      </aside>

      {pse && <PseModal total={total} onClose={() => setPse(false)} onApproved={() => { setPse(false); sendWhatsApp(); }} />}
    </>
  );
}

Object.assign(window, { FloatingCart, CartDrawer, cartCount, cartSubtotal });
