// -----------------------------------------------------------------------------
// Author: Simon-Pierre Boucher
// Contact: contact@spboucher.ai
// Project: Toit-Ka
// components/MapView.tsx : Toit-Ka Maps — carte du produit propulsée par le
// framework partagé Ka Maps (Mapbox Standard 3D, pastilles de prix par
// univers, « Rechercher dans cette zone », aperçu React).
// -----------------------------------------------------------------------------
import { useCallback, useEffect, useMemo } from "react";
import { useNavigate } from "react-router-dom";
import "mapbox-gl/dist/mapbox-gl.css";
import "@groupe-ka/ka-maps/styles.css";
import type { MapProperty } from "@groupe-ka/ka-maps";
import { cameraFromParams, cameraToParams } from "@groupe-ka/ka-maps";
import {
  KaBrandBadge,
  KaMapView,
  LoadingIndicator,
  PropertyPreview,
  ResultCount,
  SearchAreaControl,
  Tilt3DControl,
  useKaMap,
} from "@groupe-ka/ka-maps/react";
import { ListingFilters, sourceName } from "../api";
import { Ico } from "./Icons";
import { toitKaMapTheme } from "../kamaps/theme";
import { toitKaMapAdapter } from "../kamaps/adapter";
import { MAPBOX_TOKEN } from "../kamaps/config";

const QUEBEC_CENTER = { lat: 46.4, lng: -72.5 };

/** Aperçu compact d'une annonce — même langage visuel que ListingCard. */
function PreviewCard({ p }: { p: MapProperty }) {
  const navigate = useNavigate();
  const extra = (p.extra ?? {}) as {
    tx?: string; title?: string | null; priceLabel?: string | null; source?: string;
  };
  const louer = extra.tx === "louer";
  const prix = p.price != null
    ? `${p.price.toLocaleString("fr-CA", { maximumFractionDigits: 0 })} $${louer ? " /mois" : ""}`
    : extra.priceLabel || "Prix sur demande";
  const meta = [
    louer ? "À louer" : "À vendre",
    p.propertyType,
    p.bedrooms != null ? `${p.bedrooms} ch.` : "",
  ].filter(Boolean).join(" · ");
  return (
    <div className="mv-pop">
      {p.thumbnailUrl ? (
        <img src={p.thumbnailUrl} alt="" loading="lazy" />
      ) : (
        <div className="mv-noimg" aria-hidden="true"><Ico name="home" size={30} /></div>
      )}
      <div className="mv-pop-body">
        <div className="mv-pop-price">{prix}</div>
        <div className="mv-pop-title">{p.address ?? extra.title ?? ""}</div>
        <div className="mv-pop-meta">{meta}</div>
        <div className="mv-pop-src">{sourceName(extra.source ?? "")}</div>
        <a
          className="mv-pop-cta"
          href={p.originalUrl}
          onClick={(e) => {
            e.preventDefault();
            navigate(p.originalUrl ?? "/");
          }}
        >
          Voir la fiche →
        </a>
      </div>
    </div>
  );
}

/** Pont déclaratif : sélection/survol venus de la liste de résultats. */
function SelectionBridge({ selectedUid, hoveredUid }: {
  selectedUid: string | null;
  hoveredUid: string | null;
}) {
  const map = useKaMap();
  useEffect(() => { map?.select(selectedUid, "app"); }, [map, selectedUid]);
  useEffect(() => { map?.setHovered(hoveredUid, "app"); }, [map, hoveredUid]);
  return null;
}

export interface MapViewProps {
  filters: ListingFilters;
  selectedUid?: string | null;
  hoveredUid?: string | null;
  onSelect?: (uid: string | null) => void;
}

export default function MapView({
  filters, selectedUid = null, hoveredUid = null, onSelect,
}: MapViewProps) {
  const initialCamera = useMemo(() => {
    const cam = cameraFromParams(new URLSearchParams(window.location.search));
    return cam ?? { ...QUEBEC_CENTER, zoom: 6.2 };
  }, []);

  const onMoveEnd = useCallback((center: { lat: number; lng: number }, zoom: number) => {
    const url = new URL(window.location.href);
    url.search = cameraToParams({ ...center, zoom }, url.searchParams).toString();
    window.history.replaceState(null, "", url);
  }, []);

  const mapFilters = useMemo(
    () => Object.fromEntries(
      Object.entries(filters).filter(([k, v]) => v && k !== "sort"),
    ),
    [filters],
  );

  return (
    <div className="mapview" role="application" aria-label="Carte des annonces">
      <KaMapView
        theme={toitKaMapTheme}
        adapter={toitKaMapAdapter}
        mapboxToken={MAPBOX_TOKEN}
        filters={mapFilters}
        center={initialCamera}
        zoom={initialCamera.zoom}
        pitch={50}
        cluster={{ maxZoom: 15, valueClamp: [500, 3_000_000] }}
        searchMode="manual"
        onMoveEnd={onMoveEnd}
        onSelect={(p) => onSelect?.(p?.id ?? null)}
      >
        <SelectionBridge selectedUid={selectedUid} hoveredUid={hoveredUid} />
        <KaBrandBadge />
        <Tilt3DControl />
        <SearchAreaControl />
        <LoadingIndicator label="Mise à jour des annonces…" />
        <ResultCount
          emptyTitle="Aucune annonce trouvée dans cette zone."
          emptyHint="Élargissez la carte ou modifiez vos filtres."
        />
        <PropertyPreview render={(p) => <PreviewCard p={p} />} />
        <div className="mv-legend" aria-hidden="true">
          <span><i className="mv-dot mv-dot-louer" /> À louer</span>
          <span><i className="mv-dot mv-dot-acheter" /> À vendre</span>
        </div>
      </KaMapView>
    </div>
  );
}
