"use client";

import { useEffect, useState } from "react";
import Link from "next/link";
import { AdvancedMarker, useMap } from "@vis.gl/react-google-maps";
import { MapPin, Zap, Search } from "lucide-react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { GoogleMapFrame, type GoogleMapConfig } from "./google-map";
import { groupMapPoints, type MapPoint } from "@/lib/map-points";

function MapCamera({ points, selected }: { points: MapPoint[]; selected?: MapPoint }) {
  const map = useMap();
  useEffect(() => {
    if (!map) return;
    if (selected) {
      map.panTo({ lat: selected.latitude, lng: selected.longitude });
      map.setZoom(16);
    } else if (points.length) {
      const bounds = new google.maps.LatLngBounds();
      points.forEach(point => bounds.extend({ lat: point.latitude, lng: point.longitude }));
      map.fitBounds(bounds, 48);
      if (points.every(point => point.latitude === points[0].latitude && point.longitude === points[0].longitude)) map.setZoom(15);
    }
  }, [map, points, selected]);
  return null;
}
export function AssetMap({ points, kind, config, loadError, loadNotice }: {
  points: MapPoint[];
  kind: "locations" | "chargepoints";
  config: GoogleMapConfig;
  loadError?: string;
  loadNotice?: string;
}) {
  const [search, setSearch] = useState("");
  const [selectedId, setSelectedId] = useState("");
  const groups = groupMapPoints(points);
  const validPoints = groups.flatMap(group => group.points);
  const filtered = validPoints.filter(point => `${point.name} ${point.description ?? ""}`.toLowerCase().includes(search.trim().toLowerCase()));
  const selected = filtered.find(point => point.id === selectedId);
  const Icon = kind === "locations" ? MapPin : Zap;
  return (
    <section className="panel overflow-hidden">
      <div className="flex flex-wrap items-center justify-between gap-3 border-b p-5">
        <div><h2 className="text-xl font-semibold">{kind === "locations" ? "Locations" : "Chargepoints"} on the map</h2>
          <p className="mt-1 text-sm text-muted-foreground">{validPoints.length} mapped · Select a marker or search the loaded {kind}.</p>
        </div>
        <div className="relative w-full sm:w-72">
          <Search aria-hidden="true" className="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
          <Input aria-label={`Search mapped ${kind}`} placeholder={`Search ${kind}…`} value={search} onChange={event => { setSearch(event.target.value); setSelectedId(""); }} className="pl-10" />
        </div>
      </div>
      {loadError && <p role="alert" className="px-5 py-3 text-destructive">{loadError}</p>}
      {loadNotice && <p role="status" className="px-5 py-3 text-sm text-muted-foreground">{loadNotice}</p>}
      {points.length > validPoints.length && <p role="status" className="px-5 py-3 text-sm text-muted-foreground">{points.length - validPoints.length} records have invalid coordinates and cannot be mapped.</p>}
      <div className="grid gap-0 lg:grid-cols-[300px_minmax(0,1fr)]">
        <aside aria-label={`Mapped ${kind}`} className="max-h-72 overflow-y-auto border-b p-3 lg:max-h-[560px] lg:border-r lg:border-b-0">
          {filtered.length ? filtered.map(point => (
            <div key={point.id} className={`mb-2 rounded-lg border p-3 ${selectedId === point.id ? "border-primary bg-accent/30" : "border-transparent hover:bg-muted"}`}>
              <button type="button" aria-pressed={selectedId === point.id} className="flex w-full items-start gap-3 text-left" onClick={() => setSelectedId(point.id)}>
                <Icon aria-hidden="true" className="mt-0.5 size-4 shrink-0 text-primary" />
                <span className="min-w-0"><span className="block font-medium">{point.name}</span>
                  {point.description && <span className="mt-1 block text-xs text-muted-foreground">{point.description}</span>}
                  {point.status && <span className="mt-1 block text-xs text-muted-foreground">{point.status}</span>}
                </span>
              </button>
              {selectedId === point.id && <Button asChild variant="outline" size="sm" className="mt-3 w-full"><Link href={point.href}>View details</Link></Button>}
            </div>
          )) : <p role="status" className="p-4 text-sm text-muted-foreground">No matching {kind} with valid coordinates.</p>}
        </aside>
        <GoogleMapFrame config={config} className="h-[440px] lg:h-[560px]">
          <MapCamera points={filtered} selected={selected} />
          {groupMapPoints(filtered).map(group => (
            <AdvancedMarker key={group.id} position={{ lat: group.points[0].latitude, lng: group.points[0].longitude }} title={group.points.map(point => point.name).join(", ")} onClick={() => setSelectedId(group.points[0].id)}>
              <div className="flex size-10 items-center justify-center rounded-full border-2 border-background bg-primary text-primary-foreground shadow-lg">
                {group.points.length > 1 ? <span className="font-semibold">{group.points.length}</span> : <Icon aria-hidden="true" className="size-5" />}
              </div>
            </AdvancedMarker>
          ))}
        </GoogleMapFrame>
      </div>
    </section>
  );
}
