/* =====================================================================
   GREAT LAKES REALTY — UI kit (shared primitives, exported to window)
   ===================================================================== */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ---------- store hook ---------- */
function useStore() {
  const [s, setS] = useState(window.GLR.get());
  useEffect(() => window.GLR.subscribe(setS), []);
  return s;
}

/* ---------- app router: supports legacy hash URLs and clean SEO paths ---------- */
function currentRoute() {
  if (location.hash && location.hash.slice(1)) return location.hash.slice(1);
  if (window.__GLR_ROUTE__) return window.__GLR_ROUTE__;
  return location.pathname || "/";
}
function navigate(to) {
  if (currentRoute() === to) return;
  history.pushState({}, "", to);
  window.dispatchEvent(new Event("glr:navigate"));
  window.scrollTo({ top: 0, behavior: "instant" in window ? "instant" : "auto" });
}
function useRoute() {
  const [path, setPath] = useState(currentRoute());
  useEffect(() => {
    const on = () => { setPath(currentRoute()); };
    window.addEventListener("hashchange", on);
    window.addEventListener("popstate", on);
    window.addEventListener("glr:navigate", on);
    return () => {
      window.removeEventListener("hashchange", on);
      window.removeEventListener("popstate", on);
      window.removeEventListener("glr:navigate", on);
    };
  }, []);
  return path;
}

/* ---------- icons ---------- */
const PATHS = {
  search: "M11 19a8 8 0 100-16 8 8 0 000 16zM21 21l-4.3-4.3",
  pin: "M12 21s7-6.4 7-11.5A7 7 0 005 9.5C5 14.6 12 21 12 21z|M12 12.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5z",
  lock: "M6 10V8a6 6 0 1112 0v2|M5 10h14v10H5z|M12 14v3",
  arrow: "M5 12h14M13 6l6 6-6 6",
  arrowUR: "M7 17L17 7M7 7h10v10",
  check: "M4 12.5l5 5 11-11",
  chevD: "M6 9l6 6 6-6",
  chevR: "M9 6l6 6-6 6",
  chevL: "M15 6l-6 6 6 6",
  building: "M4 21V5a1 1 0 011-1h9a1 1 0 011 1v16|M15 21V9h4a1 1 0 011 1v11|M7 8h2M7 12h2M7 16h2|M3 21h18",
  phone: "M5 4h4l2 5-2.5 1.5a11 11 0 005 5L15 13l5 2v4a2 2 0 01-2 2A16 16 0 013 6a2 2 0 012-2z",
  mail: "M3 6h18v12H3z|M3 7l9 6 9-6",
  menu: "M4 7h16M4 12h16M4 17h16",
  x: "M6 6l12 12M18 6L6 18",
  filter: "M3 5h18M6 12h12M10 19h4",
  plus: "M12 5v14M5 12h14",
  edit: "M4 20h4L18.5 9.5a2.1 2.1 0 00-3-3L5 17v3z|M13.5 6.5l3 3",
  trash: "M4 7h16|M9 7V5a1 1 0 011-1h4a1 1 0 011 1v2|M6 7l1 13h10l1-13",
  upload: "M12 16V4|M8 8l4-4 4 4|M5 16v3a1 1 0 001 1h12a1 1 0 001-1v-3",
  image: "M3 5h18v14H3z|M3 16l5-5 4 4 3-3 6 6|M8.5 9a1.5 1.5 0 100-3 1.5 1.5 0 000 3z",
  folder: "M3 6h6l2 2h10v11H3z",
  file: "M6 3h8l4 4v14H6z|M14 3v4h4",
  download: "M12 4v10|M8 11l4 4 4-4|M5 19h14",
  eye: "M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7z|M12 14.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5z",
  grid: "M4 4h7v7H4z|M13 4h7v7h-7z|M4 13h7v7H4z|M13 13h7v7h-7z",
  list: "M8 6h13M8 12h13M8 18h13|M3 6h.01M3 12h.01M3 18h.01",
  shield: "M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6z|M9 12l2 2 4-4",
  cal: "M4 6h16v15H4z|M4 10h16|M8 3v4M16 3v4",
  sliders: "M4 7h10M18 7h2M4 17h2M10 17h10|M14 4v6M8 14v6",
  dash: "M4 4h7v5H4z|M4 12h7v8H4z|M13 4h7v8h-7z|M13 15h7v5h-7z",
  doc: "M6 3h8l4 4v14H6z|M9 12h6M9 16h6M9 8h3",
  users: "M16 19v-2a3 3 0 00-3-3H7a3 3 0 00-3 3v2|M10 11a3 3 0 100-6 3 3 0 000 6|M20 19v-2a3 3 0 00-2-2.9|M16 5.1A3 3 0 0117 11",
  star: "M12 4l2.3 4.7 5.2.8-3.8 3.6.9 5.1L12 16l-4.6 2.4.9-5.1-3.8-3.6 5.2-.8z",
  ext: "M14 5h5v5|M19 5l-7 7|M19 13v6H5V5h6",
  msg: "M4 5h16v11H9l-5 4z",
  clock: "M12 21a9 9 0 100-18 9 9 0 000 18z|M12 8v4l3 2",
  ruler: "M3 8h18v8H3z|M7 8v3M11 8v3M15 8v3M19 8v3",
  car: "M5 13l1.5-5h11L19 13|M3 13h18v5H3z|M7 18v2M17 18v2|M6.5 15.5h.01M17.5 15.5h.01",
  signature: "M3 17c3 0 3-9 6-9s2 7 4 7 2-4 4-4 1 2 4 2|M4 21h16",
  logout: "M14 8V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2h6a2 2 0 002-2v-2|M10 12h11|M18 9l3 3-3 3",
  settings: "M12 15a3 3 0 100-6 3 3 0 000 6z|M19 12a7 7 0 00-.1-1.2l2-1.6-2-3.4-2.4 1a7 7 0 00-2-1.2l-.4-2.6H10.9l-.4 2.6a7 7 0 00-2 1.2l-2.4-1-2 3.4 2 1.6A7 7 0 005 12a7 7 0 00.1 1.2l-2 1.6 2 3.4 2.4-1a7 7 0 002 1.2l.4 2.6h4.2l.4-2.6a7 7 0 002-1.2l2.4 1 2-3.4-2-1.6A7 7 0 0019 12z",
};
function Icon({ name, size = 18, stroke = 1.6, fill, style, className }) {
  const d = PATHS[name] || "";
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke={fill ? "none" : "currentColor"} strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round"
      style={style} className={className} aria-hidden="true">
      {d.split("|").map((p, i) => <path key={i} d={p} fill={fill || "none"} />)}
    </svg>
  );
}

/* ---------- toast ---------- */
let _toastFn = null;
function showToast(msg) { if (_toastFn) _toastFn(msg); }
function ToastHost() {
  const [msg, setMsg] = useState(null);
  useEffect(() => { _toastFn = (m) => { setMsg(m); clearTimeout(window._tt); window._tt = setTimeout(() => setMsg(null), 2600); }; }, []);
  if (!msg) return null;
  return <div className="toast"><Icon name="check" size={16} /> {msg}</div>;
}

/* ---------- logo ---------- */
function Logo({ size = "", onNavy = false, onClick }) {
  const b = useStore().branding;
  const initials = b.name.split(" ").map((w) => w[0]).slice(0, 2).join("");
  return (
    <div className={"logo " + (size === "lg" ? "lg " : "") + (onNavy ? "on-navy" : "")} onClick={onClick} style={{ cursor: onClick ? "pointer" : "default" }}>
      <div className="seal">{b.logoDataUrl ? <img src={b.logoDataUrl} alt="" /> : initials}</div>
      <div className="wm"><b>{b.name}</b><span>{b.tagline}</span></div>
    </div>
  );
}

/* ---------- status tag ---------- */
function StatusTag({ status }) {
  const map = { available: ["avail", "Available"], loi: ["loi", "Under LOI"], closed: ["closed", "Closed"] };
  const [c, t] = map[status] || ["", status];
  return <span className={"tag " + c}><span className="dot" /> {t}</span>;
}

/* ---------- responsive hook ---------- */
function useIsMobile(bp = 760) {
  const [m, setM] = useState(() => typeof window !== "undefined" && window.matchMedia("(max-width:" + bp + "px)").matches);
  useEffect(() => {
    const mq = window.matchMedia("(max-width:" + bp + "px)");
    const on = () => setM(mq.matches);
    on();
    mq.addEventListener ? mq.addEventListener("change", on) : mq.addListener(on);
    return () => mq.removeEventListener ? mq.removeEventListener("change", on) : mq.removeListener(on);
  }, [bp]);
  return window.__FORCE_MOBILE || m;
}

/* ---------- top nav ---------- */
function Nav({ cur }) {
  const items = [["Properties", "/properties"], ["Services", "/services"], ["About", "/about"], ["Contact", "/contact"]];
  const mobile = useIsMobile(760);
  const [open, setOpen] = useState(false);
  const goM = (p) => { setOpen(false); navigate(p); };
  return (
    <header className="nav">
      <div className="wrap-wide nav-in">
        <Logo onClick={() => navigate("/")} />
        {!mobile && (
          <nav className="nav-links">
            {items.map(([l, p]) => (
              <a key={l} className={cur === l ? "cur" : ""} onClick={() => navigate(p)}>{l}</a>
            ))}
            <button className="btn ghost sm" style={{ marginLeft: 10 }} onClick={() => openPortalSidecar()}>
              <Icon name="lock" size={15} /> Client Portal
            </button>
          </nav>
        )}
        {mobile && (
          <button className="btn ghost sm nav-burger" aria-label="menu" onClick={() => setOpen(!open)}>
            <Icon name={open ? "x" : "menu"} size={20} />
          </button>
        )}
      </div>
      {mobile && open && (
        <div className="nav-drawer">
          {items.map(([l, p]) => (
            <a key={l} className={cur === l ? "cur" : ""} onClick={() => goM(p)}>{l}<Icon name="chevR" size={16} /></a>
          ))}
          <button className="btn block" style={{ marginTop: 8 }} onClick={() => { setOpen(false); openPortalSidecar(); }}><Icon name="lock" size={15} /> Client Portal</button>
        </div>
      )}
    </header>
  );
}

/* ---------- footer ---------- */
function Footer() {
  const b = useStore().branding;
  return (
    <footer className="footer">
      <div className="wrap-wide">
        <div className="cols">
          <div className="fcol">
            <Logo onNavy />
            <p style={{ marginTop: 16, maxWidth: 280 }}>Commercial real estate brokerage serving Indianapolis and the Great Lakes region. Disciplined representation since {b.est}.</p>
            <div className="seal-est" style={{ marginTop: 14 }}>Est. {b.est}</div>
          </div>
          <div className="fcol"><h5>Firm</h5>
            <a onClick={() => navigate("/services")}>Services</a>
            <a onClick={() => navigate("/about")}>About</a>
            <a onClick={() => navigate("/track-record")}>Track Record</a>
            <a onClick={() => navigate("/contact")}>Contact</a></div>
          <div className="fcol"><h5>Properties</h5>
            <a onClick={() => navigate("/properties")}>Available</a>
            <a onClick={() => navigate("/track-record")}>Closed Deals</a>
            <a onClick={() => openPortalSidecar()}>Client Portal</a>
            <a onClick={() => navigate("/admin")}>Admin</a></div>
          <div className="fcol"><h5>Contact</h5>
            <a href={"tel:" + b.phone}>{b.phone}</a>
            <a href={"mailto:" + b.email}>{b.email}</a>
            <p style={{ whiteSpace: "pre-line" }}>{b.address}</p></div>
        </div>
        <div className="legal">
          <span>© {new Date().getFullYear()} {b.name}. All rights reserved.</span>
          <span>Information deemed reliable but not guaranteed.</span>
        </div>
      </div>
    </footer>
  );
}

/* ---------- Leaflet map ---------- */
function LeafletMap({ listings, activeId, onPick, height = 520, center = [39.79, -86.16], zoom = 11, interactive = true }) {
  const ref = useRef(null);
  const map = useRef(null);
  const markers = useRef({});

  useEffect(() => {
    if (!window.L || !ref.current || map.current) return;
    const m = window.L.map(ref.current, { zoomControl: interactive, scrollWheelZoom: false, dragging: interactive, attributionControl: false });
    m.setView(center, zoom);
    window.L.tileLayer("https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png", { maxZoom: 19, subdomains: "abcd" }).addTo(m);
    window.L.control.attribution({ prefix: false }).addAttribution("© OpenStreetMap, © CARTO").addTo(m);
    map.current = m;
    return () => { m.remove(); map.current = null; markers.current = {}; };
  }, []);

  useEffect(() => {
    const m = map.current; if (!m || !window.L) return;
    Object.values(markers.current).forEach((mk) => m.removeLayer(mk));
    markers.current = {};
    const pts = [];
    listings.forEach((l, i) => {
      if (l.lat == null) return;
      const html = `<div class="glr-pin ${l.id === activeId ? "active" : ""}"><span>${i + 1}</span></div>`;
      const icon = window.L.divIcon({ html, className: "", iconSize: [30, 30], iconAnchor: [15, 28] });
      const mk = window.L.marker([l.lat, l.lng], { icon }).addTo(m);
      mk.on("click", () => onPick && onPick(l.id));
      markers.current[l.id] = mk;
      pts.push([l.lat, l.lng]);
    });
    if (pts.length > 1) { try { m.fitBounds(pts, { padding: [50, 50], maxZoom: 13 }); } catch (e) {} }
    else if (pts.length === 1) m.setView(pts[0], 14);
  }, [listings, activeId]);

  return (
    <div style={{ height, position: "relative", background: "var(--paper-3)" }}>
      <div ref={ref} style={{ position: "absolute", inset: 0 }} />
      {!window.L && <div className="map-fallback" />}
    </div>
  );
}

/* ---------- misc ---------- */
function Stat({ n, l }) { return <div className="stat"><div className="n">{n}</div><div className="l">{l}</div></div>; }
function KV({ k, v }) { return <div className="kv"><div className="k">{k}</div><div className="v">{v}</div></div>; }
/* window grid for an elevation */
function winGrid(x, y, w, h, cols, rows, s = "rgba(255,255,255,0.22)") {
  const els = [];
  for (let c = 1; c < cols; c++) els.push(<line key={"v" + x + c} x1={x + (w / cols) * c} y1={y} x2={x + (w / cols) * c} y2={y + h} stroke={s} strokeWidth="1" />);
  for (let r = 1; r < rows; r++) els.push(<line key={"h" + y + r} x1={x} y1={y + (h / rows) * r} x2={x + w} y2={y + (h / rows) * r} stroke={s} strokeWidth="1" />);
  return els;
}
function Skyline({ type }) {
  const S = "rgba(255,255,255,0.34)", F = "rgba(255,255,255,0.05)";
  const wrap = (kids) => (
    <svg viewBox="0 0 240 92" preserveAspectRatio="xMidYMax meet" style={{ position: "absolute", left: 0, right: 0, bottom: 0, width: "100%", height: "78%" }}>
      <line x1="0" y1="91" x2="240" y2="91" stroke={S} strokeWidth="1.2" />{kids}
    </svg>
  );
  if (type === "Industrial" || type === "Flex") return wrap(<g fill={F} stroke={S} strokeWidth="1.3">
    <rect x="18" y="40" width="150" height="51" />
    <path d="M18 40 l12 -12 l12 12 M42 40 l12 -12 l12 12 M66 40 l12 -12 l12 12 M90 40 l12 -12 l12 12 M114 40 l12 -12 l12 12 M138 40 l12 -12 l12 12" fill="none" />
    {[0, 1, 2, 3, 4].map((i) => <rect key={i} x={28 + i * 28} y="68" width="18" height="23" fill="rgba(255,255,255,0.03)" />)}
    <rect x="176" y="58" width="46" height="33" />{winGrid(176, 58, 46, 33, 3, 2)}
  </g>);
  if (type === "Retail") return wrap(<g fill={F} stroke={S} strokeWidth="1.3">
    {[18, 78, 138].map((x, i) => <g key={i}><rect x={x} y="46" width="54" height="45" /><path d={`M${x - 3} 46 h60 l-6 9 h-48 z`} fill="rgba(255,255,255,0.06)" /><rect x={x + 16} y="64" width="22" height="27" fill="rgba(255,255,255,0.03)" /></g>)}
  </g>);
  if (type === "Land") return wrap(<g stroke={S} strokeWidth="1.2" fill="none">
    <path d="M0 74 q60 -10 120 -2 t120 -6" />
    <path d="M30 70 v-14 M30 56 l10 4 M110 66 v-18 M110 48 l10 4 M190 68 v-12 M190 56 l10 4" />
    <path d="M14 84 h212 M40 84 v-6 M90 84 v-6 M150 84 v-6 M200 84 v-6" strokeDasharray="2 4" opacity="0.6" />
  </g>);
  if (type === "Multifamily" || type === "Mixed-Use") return wrap(<g fill={F} stroke={S} strokeWidth="1.3">
    <rect x="40" y="20" width="70" height="71" />{winGrid(40, 20, 70, 71, 4, 7)}
    <rect x="118" y="48" width="84" height="43" />{winGrid(118, 48, 84, 43, 5, 3)}
  </g>);
  // Office (default): three towers
  return wrap(<g fill={F} stroke={S} strokeWidth="1.3">
    <rect x="24" y="34" width="46" height="57" />{winGrid(24, 34, 46, 57, 4, 7)}
    <rect x="86" y="12" width="58" height="79" />{winGrid(86, 12, 58, 79, 5, 10)}
    <rect x="160" y="44" width="40" height="47" />{winGrid(160, 44, 40, 47, 3, 6)}
    <rect x="206" y="60" width="22" height="31" />{winGrid(206, 60, 22, 31, 2, 4)}
  </g>);
}
function PhotoBox({ dataUrl, label = "Property", h = 200, type = "Office", style }) {
  if (dataUrl) return <img className="phbox" src={dataUrl} alt={label} style={{ width: "100%", height: h, objectFit: "cover", display: "block", ...style }} />;
  return (
    <div className="phbox" style={{ height: h, background: "linear-gradient(160deg,#22466b 0%,#163655 42%,#0d2339 100%)", position: "relative", overflow: "hidden", ...style }}>
      <div style={{ position: "absolute", inset: 0, opacity: 0.10, backgroundImage: "linear-gradient(#fff 1px,transparent 1px),linear-gradient(90deg,#fff 1px,transparent 1px)", backgroundSize: "20px 20px" }} />
      <div style={{ position: "absolute", inset: 0, background: "radial-gradient(120% 90% at 80% -10%, rgba(255,255,255,0.10), transparent 55%)" }} />
      <Skyline type={type} />
    </div>
  );
}

Object.assign(window, {
  useStore, navigate, useRoute, useIsMobile, Icon, showToast, ToastHost,
  Logo, StatusTag, Nav, Footer, LeafletMap, Stat, KV, PhotoBox,
});
