const { useMemo: useMemoListings, useState: useStateListings } = React;

const HFB_CATEGORIES = [
  { id: "all", label: "All" },
  { id: "condo", label: "Condos" },
  { id: "house", label: "Houses" },
  { id: "townhouse", label: "Townhouses" },
  { id: "serviced-apartment", label: "Serviced apartments" },
  { id: "business", label: "Business" },
  { id: "retail", label: "Retail" },
  { id: "office", label: "Office" },
  { id: "shophouse", label: "Shophouse" },
  { id: "hotel", label: "Hotel" },
  { id: "special-sale", label: "Special sale deals" },
  { id: "special-rent", label: "Special rent deals" }
];
const RESULTS_PAGE_SIZE = 60;

function numericOptions(values, max = 12) {
  return [...new Set(values
    .map((value) => Number(value))
    .filter((value) => Number.isInteger(value) && value > 0 && value <= max)
    .sort((a, b) => a - b))];
}

function ListingSearchCard({ item, currency }) {
  const href = window.HONListingStore.detailHref(item);
  const gallery = item.gallery && item.gallery.length ? item.gallery : [item.heroImage || item.img].filter(Boolean);
  const remember = () => window.HON_SAVE_LISTING_SEARCH && window.HON_SAVE_LISTING_SEARCH();
  return (
    <article className="hfb-card" onClick={(event) => {
      if (event.target.closest("button, a")) return;
      remember();
      window.location.href = href;
    }}>
      <ListingImageCarousel images={gallery} title={item.title} className="hfb-card__image">
        <span className="hfb-card__status">{item.status}</span>
        <span className="hfb-card__price">{fmtMoney(item.price, currency)}{item.transaction === "rent" ? " / month" : ""}</span>
      </ListingImageCarousel>
      <div className="hfb-card__body">
        <h3><a href={href} onClick={remember}>{item.title}</a></h3>
        <dl>
          <div><dt>Bedroom</dt><dd>{item.beds || "Ask"}</dd></div>
          <div><dt>Bathroom</dt><dd>{item.baths || "Ask"}</dd></div>
          <div><dt>Area</dt><dd>{item.sqm ? `${item.sqm} sqm` : "Ask"}</dd></div>
          <div><dt>Type</dt><dd>{item.propertyType || item.category || "Home"}</dd></div>
        </dl>
        <p>{item.neighborhood || item.district || "Bangkok"}</p>
      </div>
    </article>
  );
}

function ListingsPageApp() {
  const [stateTick, setStateTick] = useStateListings(0);
  const [siteTick, setSiteTick] = useStateListings(0);
  React.useEffect(() => {
    const refresh = () => setStateTick((tick) => tick + 1);
    window.addEventListener("hon:listings-updated", refresh);
    return () => window.removeEventListener("hon:listings-updated", refresh);
  }, []);
  React.useEffect(() => {
    const refresh = () => setSiteTick((tick) => tick + 1);
    window.addEventListener("hon:site-updated", refresh);
    return () => window.removeEventListener("hon:site-updated", refresh);
  }, []);
  const allItems = useMemoListings(() => window.HONListingStore.all().filter((item) => {
    const type = String(item.propertyType || item.category || "").toLowerCase();
    return !/(land|warehouse|factory)/.test(type) && String(item.city || "Bangkok").toLowerCase().includes("bangkok");
  }), [stateTick]);
  const [lang, setLangRaw] = useStateListings(() => {
    try {
      const saved = localStorage.getItem("hon_lang") || "en";
      return window.I18N && window.I18N[saved] ? saved : "en";
    } catch (e) { return "en"; }
  });
  const [currency, setCurrency] = useStateListings("THB");
  const stateKey = "hon_listing_search_state";
  const readInitialState = () => {
    try {
      const params = new URLSearchParams(window.location.search);
      const saved = JSON.parse(sessionStorage.getItem(stateKey) || "{}");
      return {
        mode: params.get("mode") || saved.mode || "all",
        visibleCount: Number(saved.visibleCount) || RESULTS_PAGE_SIZE,
        filters: {
          q: params.get("q") || saved.filters?.q || "",
          location: params.get("location") || saved.filters?.location || "Bangkok",
          category: params.get("category") || saved.filters?.category || "all",
          beds: params.get("beds") || saved.filters?.beds || "any",
          baths: params.get("baths") || saved.filters?.baths || "any",
          minPrice: params.get("minPrice") || saved.filters?.minPrice || "",
          maxPrice: params.get("maxPrice") || saved.filters?.maxPrice || "",
          minArea: params.get("minArea") || saved.filters?.minArea || "",
          maxArea: params.get("maxArea") || saved.filters?.maxArea || "",
          sort: params.get("sort") || saved.filters?.sort || "new"
        }
      };
    } catch (e) {
      return null;
    }
  };
  const initial = readInitialState();
  const [mode, setMode] = useStateListings(initial?.mode || "all");
  const [visibleCount, setVisibleCount] = useStateListings(initial?.visibleCount || RESULTS_PAGE_SIZE);
  const [filters, setFilters] = useStateListings(initial?.filters || {
    q: "",
    location: "Bangkok",
    category: "all",
    beds: "any",
    baths: "any",
    minPrice: "",
    maxPrice: "",
    minArea: "",
    maxArea: "",
    sort: "new"
  });
  const restoredScrollRef = React.useRef(false);

  const locations = [...new Set(["Bangkok", ...allItems.map((item) => item.district).filter(Boolean)])].sort();
  const bedOptions = numericOptions(allItems.map((item) => item.beds));
  const bathOptions = numericOptions(allItems.map((item) => item.baths));
  const t = window.I18N[lang] || window.I18N.en;
  void siteTick;
  const setLang = (code) => {
    const next = window.I18N && window.I18N[code] ? code : "en";
    setLangRaw(next);
    try { localStorage.setItem("hon_lang", next); } catch (e) {}
  };

  const filtered = useMemoListings(() => {
    const q = filters.q.trim().toLowerCase();
    const minPrice = Number(filters.minPrice) || 0;
    const maxPrice = Number(filters.maxPrice) || Infinity;
    const minArea = Number(filters.minArea) || 0;
    const maxArea = Number(filters.maxArea) || Infinity;
    const category = filters.category;
    const items = allItems.filter((item) => {
      const haystack = [item.title, item.district, item.neighborhood, item.station, item.propertyType, item.status].join(" ").toLowerCase();
      if (q && !haystack.includes(q)) return false;
      if (mode !== "all" && item.transaction !== mode) return false;
      if (category !== "all") {
        if (category === "special-sale" && item.dealType !== "special-sale" && item.frontSlot !== "special-sale") return false;
        else if (category === "special-rent" && item.dealType !== "special-rent" && item.frontSlot !== "special-rent") return false;
        else if (!category.startsWith("special") && item.category !== category) return false;
      }
      if (filters.location !== "Bangkok" && item.district !== filters.location) return false;
      if (filters.beds !== "any" && Number(item.beds) < Number(filters.beds)) return false;
      if (filters.baths !== "any" && Number(item.baths) < Number(filters.baths)) return false;
      if (Number(item.price) < minPrice || Number(item.price) > maxPrice) return false;
      if (Number(item.sqm) < minArea || Number(item.sqm) > maxArea) return false;
      return true;
    });
    return items.sort((a, b) => {
      if (filters.sort === "price-low") return Number(a.price) - Number(b.price);
      if (filters.sort === "price-high") return Number(b.price) - Number(a.price);
      if (filters.sort === "area-high") return Number(b.sqm) - Number(a.sqm);
      return String(a.n).localeCompare(String(b.n), undefined, { numeric: true });
    });
  }, [allItems, filters, mode]);
  React.useEffect(() => {
    setVisibleCount(RESULTS_PAGE_SIZE);
  }, [filters, mode]);
  React.useEffect(() => {
    const save = (force = false) => {
      if (!force && !restoredScrollRef.current) return;
      const state = { mode, filters, visibleCount, scrollY: window.scrollY };
      sessionStorage.setItem(stateKey, JSON.stringify(state));
    };
    window.HON_SAVE_LISTING_SEARCH = () => save(true);
    save();
    const params = new URLSearchParams();
    if (mode !== "all") params.set("mode", mode);
    Object.entries(filters).forEach(([key, value]) => {
      if (value && value !== "any" && value !== "all" && !(key === "location" && value === "Bangkok") && !(key === "sort" && value === "new")) params.set(key, value);
    });
    const next = `${window.location.pathname}${params.toString() ? `?${params}` : ""}`;
    window.history.replaceState(null, "", next);
    return () => {
      save(true);
      if (window.HON_SAVE_LISTING_SEARCH) delete window.HON_SAVE_LISTING_SEARCH;
    };
  }, [mode, filters, visibleCount]);
  React.useEffect(() => {
    try {
      const saved = JSON.parse(sessionStorage.getItem(stateKey) || "{}");
      setTimeout(() => {
        if (saved.scrollY) window.scrollTo(0, saved.scrollY);
        restoredScrollRef.current = true;
      }, 350);
    } catch (e) {}
  }, []);

  const set = (key, value) => setFilters((current) => ({ ...current, [key]: value }));

  return (
    <>
      <ScrollProgress />
      <Header lang={lang} setLang={setLang} t={t} onBook={() => { document.getElementById("listings-contact")?.scrollIntoView({ behavior: "smooth", block: "start" }); }} />
      <main className="listings-page">
        <section className="listings-page__hero">
          <div className="shell">
            <a className="detail-back" href="/#top">Back to home</a>
            <div className="section__num">Bangkok listings</div>
            <h1>Listings</h1>
            <p>Bangkok-only listings, excluding land, warehouses, and factories. Search by type, rent or sale, price, area, and bedrooms.</p>
          </div>
        </section>

        <section className="listings-contact shell" id="listings-contact" aria-label="Contact Noey">
          <div>
            <div className="section__num">Contact Noey</div>
            <h2>Ask for a shortlist, viewing time, or missing details.</h2>
            <p>Send the property name or your brief. Noey replies on LINE, WhatsApp, or email.</p>
          </div>
          <ContactLinks className="listings-contact__links" />
        </section>

        <section className="hfb-search shell" aria-label="Listing search">
          <div className="hfb-search__title">
            <span>Search</span>
            <strong>Find Your Perfect Home</strong>
          </div>
          <div className="hfb-search__grid">
            <label>Search<input value={filters.q} onChange={(e) => set("q", e.target.value)} placeholder="Any" /></label>
            <label>Main Location<select value={filters.location} onChange={(e) => set("location", e.target.value)}>{locations.map((loc) => <option key={loc}>{loc}</option>)}</select></label>
            <label>For Rent or For Sale<select value={mode} onChange={(e) => setMode(e.target.value)}><option value="all">Any</option><option value="rent">For Rent</option><option value="sale">For Sale</option></select></label>
            <label>Property Type<select value={filters.category} onChange={(e) => set("category", e.target.value)}>{HFB_CATEGORIES.map((cat) => <option key={cat.id} value={cat.id}>{cat.label}</option>)}</select></label>
            <label>Beds<select value={filters.beds} onChange={(e) => set("beds", e.target.value)}><option value="any">Any</option>{bedOptions.map((n) => <option key={n}>{n}</option>)}</select></label>
            <label>Baths<select value={filters.baths} onChange={(e) => set("baths", e.target.value)}><option value="any">Any</option>{bathOptions.map((n) => <option key={n}>{n}</option>)}</select></label>
            <label>Min Price<input value={filters.minPrice} onChange={(e) => set("minPrice", e.target.value)} inputMode="numeric" placeholder="Any" /></label>
            <label>Max Price<input value={filters.maxPrice} onChange={(e) => set("maxPrice", e.target.value)} inputMode="numeric" placeholder="Any" /></label>
            <label>Min Area (Sq M)<input value={filters.minArea} onChange={(e) => set("minArea", e.target.value)} inputMode="numeric" placeholder="Any" /></label>
            <label>Max Area (Sq M)<input value={filters.maxArea} onChange={(e) => set("maxArea", e.target.value)} inputMode="numeric" placeholder="Any" /></label>
          </div>
          <div className="hfb-search__actions">
            <div className="currency">
              {Object.keys(CURRENCIES).map((c) => <button key={c} data-active={currency === c} onClick={() => setCurrency(c)}>{c}</button>)}
            </div>
            <button className="real-btn" onClick={() => {
              setMode("all");
              setFilters({ q: "", location: "Bangkok", category: "all", beds: "any", baths: "any", minPrice: "", maxPrice: "", minArea: "", maxArea: "", sort: "new" });
            }}>Reset</button>
          </div>
        </section>

        <section className="hfb-results shell">
          <div className="hfb-results__bar">
            <strong>{filtered.length}</strong><span>Results</span>
            <label>Sort By:<select value={filters.sort} onChange={(e) => set("sort", e.target.value)}><option value="new">Date New to Old</option><option value="price-low">Price Low to High</option><option value="price-high">Price High to Low</option><option value="area-high">Area High to Low</option></select></label>
          </div>
          <div className="hfb-category-row" aria-label="Categories">
            {HFB_CATEGORIES.map((cat) => <button key={cat.id} data-active={filters.category === cat.id} onClick={() => set("category", cat.id)}>{cat.label}</button>)}
          </div>
          <div className="hfb-grid">
            {filtered.slice(0, visibleCount).map((item) => <ListingSearchCard key={item.id || item.slug} item={item} currency={currency} />)}
          </div>
          {filtered.length > visibleCount && (
            <div className="hfb-load-more">
              <button className="real-btn" onClick={() => setVisibleCount((count) => count + RESULTS_PAGE_SIZE)}>
                Show more listings
              </button>
              <span>{Math.min(visibleCount, filtered.length)} of {filtered.length}</span>
            </div>
          )}
          {!filtered.length && <p className="hfb-empty">No matching Bangkok listings. Try widening the price, area, or category filters.</p>}
        </section>
      </main>
      <Footer t={t} />
      <MobileNav t={t} onBook={() => { document.getElementById("listings-contact")?.scrollIntoView({ behavior: "smooth", block: "start" }); }} />
      <AdminQuickButton />
    </>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<ListingsPageApp />);

