// PonteREI — utilities (formatters, hooks, contexts, reveal observer)

const { useState, useEffect, useContext, createContext, useRef, useMemo, useCallback } = React;

// ---------- I18N CONTEXT ----------
const LocaleContext = createContext({ locale: "pt", setLocale: () => {} });
const useLocale = () => useContext(LocaleContext);

const t = (path, locale) => {
  const parts = path.split(".");
  let cur = window.I18N;
  for (const p of parts) cur = cur?.[p];
  if (!cur) return path;
  return typeof cur === "object" && cur[locale] ? cur[locale] : cur;
};

// ---------- ROUTER (hash-based) ----------
const RouterContext = createContext({ path: "/", navigate: () => {} });
const useRouter = () => useContext(RouterContext);

function useHashRouter() {
  const [path, setPath] = useState(() => parseHash());

  useEffect(() => {
    const handler = () => {
      setPath(parseHash());
      window.scrollTo({ top: 0, behavior: "instant" });
    };
    window.addEventListener("hashchange", handler);
    return () => window.removeEventListener("hashchange", handler);
  }, []);

  const navigate = useCallback((to) => {
    if (to.startsWith("#")) to = to.slice(1);
    if (!to.startsWith("/")) to = "/" + to;
    window.location.hash = to;
  }, []);

  return { path, navigate };
}

function parseHash() {
  const h = window.location.hash || "#/";
  return h.slice(1) || "/";
}

// ---------- FORMATTERS ----------
const formatBRL = (v, opts = {}) => {
  if (v == null) return "—";
  const n = Number(v);
  const minimumFractionDigits = opts.minDecimals ?? 0;
  const maximumFractionDigits = opts.maxDecimals ?? 0;
  if (opts.compact && n >= 1000000) {
    return "R$ " + (n / 1000000).toLocaleString("pt-BR", { maximumFractionDigits: 1 }) + "M";
  }
  if (opts.compact && n >= 1000) {
    return "R$ " + (n / 1000).toLocaleString("pt-BR", { maximumFractionDigits: 0 }) + "k";
  }
  return n.toLocaleString("pt-BR", {
    style: "currency",
    currency: "BRL",
    minimumFractionDigits,
    maximumFractionDigits,
  });
};

const formatUSD = (v, opts = {}) => {
  if (v == null) return "—";
  const n = Number(v);
  const minimumFractionDigits = opts.minDecimals ?? 0;
  const maximumFractionDigits = opts.maxDecimals ?? 0;
  return n.toLocaleString("en-US", {
    style: "currency",
    currency: "USD",
    minimumFractionDigits,
    maximumFractionDigits,
  });
};

const formatPct = (v, decimals = 1) => {
  if (v == null) return "—";
  return Number(v).toFixed(decimals).replace(".", ",") + "%";
};

const formatPctEN = (v, decimals = 1) => {
  if (v == null) return "—";
  return Number(v).toFixed(decimals) + "%";
};

const formatPctLocalized = (v, locale, decimals = 1) =>
  locale === "pt" ? formatPct(v, decimals) : formatPctEN(v, decimals);

const formatNum = (v, locale = "pt") => {
  if (v == null) return "—";
  return Number(v).toLocaleString(locale === "pt" ? "pt-BR" : "en-US");
};

const formatDate = (iso, locale = "pt") => {
  if (!iso) return "—";
  const d = new Date(iso);
  return d.toLocaleDateString(locale === "pt" ? "pt-BR" : "en-US", { day: "2-digit", month: "short", year: "numeric" });
};

const localized = (val, locale) => {
  if (val == null) return "";
  if (typeof val === "string") return val;
  if (typeof val === "object" && (val.pt || val.en)) return val[locale] || val.pt || val.en;
  return String(val);
};

// ---------- REVEAL OBSERVER ----------
function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll(".reveal:not(.in)");
    if (!els.length) return;
    const obs = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            e.target.classList.add("in");
            obs.unobserve(e.target);
          }
        });
      },
      { rootMargin: "-50px 0px" }
    );
    els.forEach((el) => obs.observe(el));
    return () => obs.disconnect();
  });
}

// ---------- TOAST CONTEXT ----------
const ToastContext = createContext({ push: () => {} });
const useToast = () => useContext(ToastContext);

function ToastProvider({ children }) {
  const [toasts, setToasts] = useState([]);
  const push = useCallback((text) => {
    const id = Date.now() + Math.random();
    setToasts((cur) => [...cur, { id, text }]);
    setTimeout(() => setToasts((cur) => cur.filter((t) => t.id !== id)), 5000);
  }, []);
  return (
    <ToastContext.Provider value={{ push }}>
      {children}
      <div className="toast-container">
        {toasts.map((tt) => (
          <div key={tt.id} className="toast" role="status">
            <span className="toast-icon" aria-hidden>
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2"><path d="M5 12l5 5 9-9" /></svg>
            </span>
            <div className="toast-text">{tt.text}</div>
          </div>
        ))}
      </div>
    </ToastContext.Provider>
  );
}

// ---------- COMMON ICONS ----------
const Icon = {
  ChevronDown: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><polyline points="6 9 12 15 18 9" /></svg>,
  ChevronRight: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><polyline points="9 18 15 12 9 6" /></svg>,
  ChevronLeft: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><polyline points="15 18 9 12 15 6" /></svg>,
  ArrowRight: (p) => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" /></svg>,
  Plus: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg>,
  Close: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg>,
  Heart: (p) => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" /></svg>,
  MapPin: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" /><circle cx="12" cy="10" r="3" /></svg>,
  Bed: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M2 9V20M22 20V13a2 2 0 0 0-2-2H2M2 14h20" /><circle cx="6" cy="9" r="2" /></svg>,
  Bath: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M9 6 6 9M3 11h18M5 11v8a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-8M5 11V5a2 2 0 0 1 2-2h2v3" /></svg>,
  Square: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 3h18v18H3z" /></svg>,
  Car: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 17h14M3 17l2-7h14l2 7M5 17v3h2v-3M17 17v3h2v-3" /><circle cx="7" cy="14" r="1.5" /><circle cx="17" cy="14" r="1.5" /></svg>,
  Globe: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="10" /><path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" /></svg>,
  Shield: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" /><path d="m9 12 2 2 4-4" /></svg>,
  Trending: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><polyline points="22 7 13.5 15.5 8.5 10.5 2 17" /><polyline points="16 7 22 7 22 13" /></svg>,
  Coins: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="8" cy="8" r="6" /><path d="M18.09 10.37A6 6 0 1 1 10.34 18M7 6h1v4M16.71 13.88l.7.71-2.82 2.82" /></svg>,
  Building: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="4" y="2" width="16" height="20" rx="2" /><path d="M9 22v-4h6v4M8 6h.01M16 6h.01M12 6h.01M12 10h.01M12 14h.01M16 10h.01M16 14h.01M8 10h.01M8 14h.01" /></svg>,
  Users: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" /><circle cx="9" cy="7" r="4" /><path d="M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75" /></svg>,
  Doc: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /><polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /></svg>,
  Filter: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" /></svg>,
  Menu: (p) => <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><line x1="3" y1="6" x2="21" y2="6" /><line x1="3" y1="12" x2="21" y2="12" /><line x1="3" y1="18" x2="21" y2="18" /></svg>,
  Camera: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" /><circle cx="12" cy="13" r="4" /></svg>,
  School: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m4 6 8-4 8 4M2 11h20M2 11v9h20v-9M6 11v9M10 11v9M14 11v9M18 11v9" /></svg>,
  Walk: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="13" cy="4" r="2" /><path d="m15 22-3-7 2-4 4 2v3M9 12l-2 6 1 4M14 9h3l3 3" /></svg>,
  Bike: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="6" cy="17" r="3" /><circle cx="18" cy="17" r="3" /><path d="m6 17 4-7 4 5 4-5M14 5h3l1 5" /></svg>,
  Droplet: (p) => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 2.69 5.5 9.5a7 7 0 1 0 13 0z" /></svg>,
  Tree: (p) => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 22V12M12 12 8 8M12 12l4-4M8 8a4 4 0 1 1 8 0c0 1.5-1 3-2 3.5l1.5 2.5h-7L10 11.5C9 11 8 9.5 8 8z" /></svg>,
  Star: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" {...p}><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" /></svg>,
  Eye: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" /><circle cx="12" cy="12" r="3" /></svg>,
  Bookmark: (p) => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z" /></svg>,
};

// PonteREI mark — bridge silhouette in a circle
function LogoMark({ size = 22 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 32 32" fill="none">
      <circle cx="16" cy="16" r="15" stroke="currentColor" strokeWidth="1.5" />
      <path d="M3 19 C 8 12, 12 12, 16 16 C 20 20, 24 20, 29 13" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" fill="none" />
      <line x1="9" y1="22" x2="9" y2="14" stroke="currentColor" strokeWidth="1" strokeLinecap="round" />
      <line x1="13" y1="22" x2="13" y2="15" stroke="currentColor" strokeWidth="1" strokeLinecap="round" />
      <line x1="19" y1="22" x2="19" y2="17" stroke="currentColor" strokeWidth="1" strokeLinecap="round" />
      <line x1="23" y1="22" x2="23" y2="16" stroke="currentColor" strokeWidth="1" strokeLinecap="round" />
    </svg>
  );
}

Object.assign(window, {
  LocaleContext, useLocale, t, localized,
  RouterContext, useRouter, useHashRouter,
  formatBRL, formatUSD, formatPct, formatPctEN, formatPctLocalized, formatNum, formatDate,
  useReveal, ToastContext, useToast, ToastProvider,
  Icon, LogoMark,
});
