"use client";

import { useEffect, useState } from "react";
import "leaflet/dist/leaflet.css";
import { PropertyCardLive } from "./_property-card-live";
import { useCurrency } from "./_currency";

export type Listing = {
  id: string;
  title: string;
  price: number;
  type: string;
  bedrooms: number | null;
  bathrooms: number | null;
  area_sqm: number | null;
  city: string | null;
  province: string | null;
  images: string[] | null;
  featured: boolean | null;
  special_deal: boolean | null;
  special_deal_label: string | null;
  lat: number | null;
  lng: number | null;
};

export function ListingsView({ listings }: { listings: Listing[] }) {
  const [view, setView] = useState<"grid" | "map">("grid");
  const withCoords = listings.filter(
    (l): l is Listing & { lat: number; lng: number } =>
      l.lat != null && l.lng != null,
  );

  return (
    <section className="mx-auto max-w-site px-7 pb-20">
      <div className="mb-8 flex justify-end">
        <div className="inline-flex rounded-full border border-border bg-surface p-1">
          <Tab active={view === "grid"} onClick={() => setView("grid")}>
            Grid
          </Tab>
          <Tab
            active={view === "map"}
            onClick={() => setView("map")}
            disabled={withCoords.length === 0}
          >
            Map
          </Tab>
        </div>
      </div>

      {view === "grid" ? (
        <div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
          {listings.map((p) => (
            <PropertyCardLive
              key={p.id}
              title={p.title}
              price={p.price}
              type={p.type}
              bedrooms={p.bedrooms}
              bathrooms={p.bathrooms}
              areaSqm={p.area_sqm}
              city={p.city}
              province={p.province}
              imageUrl={p.images?.[0] ?? null}
              featured={p.featured ?? false}
              specialDealLabel={p.special_deal ? p.special_deal_label : null}
              href={`/p/${p.id}`}
            />
          ))}
        </div>
      ) : (
        <ListingsMap listings={withCoords} />
      )}
    </section>
  );
}

function Tab({
  active,
  onClick,
  disabled,
  children,
}: {
  active: boolean;
  onClick: () => void;
  disabled?: boolean;
  children: React.ReactNode;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      disabled={disabled}
      className={`rounded-full px-5 py-2 text-[14px] transition disabled:opacity-50 ${
        active
          ? "bg-text text-bg"
          : "bg-transparent text-text-muted hover:text-text"
      }`}
    >
      {children}
    </button>
  );
}

function ListingsMap({
  listings,
}: {
  listings: (Listing & { lat: number; lng: number })[];
}) {
  const { format } = useCurrency();
  const [Leaflet, setLeaflet] =
    useState<null | typeof import("react-leaflet")>(null);
  const [L, setL] = useState<null | typeof import("leaflet")>(null);

  useEffect(() => {
    let cancelled = false;
    Promise.all([import("react-leaflet"), import("leaflet")]).then(
      ([rl, leaflet]) => {
        if (cancelled) return;
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        delete (leaflet.Icon.Default.prototype as any)._getIconUrl;
        leaflet.Icon.Default.mergeOptions({
          iconRetinaUrl:
            "https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png",
          iconUrl:
            "https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png",
          shadowUrl:
            "https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png",
        });
        setLeaflet(rl);
        setL(leaflet);
      },
    );
    return () => {
      cancelled = true;
    };
  }, []);

  if (!Leaflet || !L) {
    return (
      <div className="flex h-[500px] items-center justify-center rounded-2xl border border-border bg-surface text-[13px] text-text-soft">
        Loading map…
      </div>
    );
  }

  if (listings.length === 0) {
    return (
      <p className="mt-8 text-center text-text-muted">
        No listings have coordinates yet.
      </p>
    );
  }

  const { MapContainer, TileLayer, Marker, Popup } = Leaflet;

  // Center on first; bounds fit all.
  const center: [number, number] = [listings[0]!.lat, listings[0]!.lng];

  function pricePinIcon(label: string) {
    return L!.divIcon({
      className: "price-pin-wrap",
      html: `<div class="price-pin">${label}</div>`,
      iconSize: [0, 0],
      iconAnchor: [0, 14],
    });
  }

  return (
    <div className="overflow-hidden rounded-2xl border border-border">
      <MapContainer
        center={center}
        zoom={11}
        scrollWheelZoom
        style={{ height: "70vh", width: "100%" }}
      >
        <TileLayer
          attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        {listings.map((l) => (
          <Marker
            key={l.id}
            position={[l.lat, l.lng]}
            title={l.title}
            icon={pricePinIcon(format(l.price))}
          >
            <Popup>
              <div className="w-48">
                {l.images?.[0] && (
                  // eslint-disable-next-line @next/next/no-img-element
                  <img
                    src={l.images[0]}
                    alt={l.title}
                    className="mb-2 h-24 w-full rounded object-cover"
                  />
                )}
                <a
                  href={`/p/${l.id}`}
                  className="text-sm font-semibold hover:underline"
                >
                  {l.title}
                </a>
                <p className="mt-1 text-xs text-zinc-500">
                  {[l.city, l.province].filter(Boolean).join(", ")}
                </p>
                <p className="mt-1 text-sm font-semibold">{format(l.price)}</p>
              </div>
            </Popup>
          </Marker>
        ))}
      </MapContainer>
    </div>
  );
}
