"use client";

import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import useSWR from "swr";
import { ArrowLeft, Crosshair, ExternalLink, Save, Trash2 } from "lucide-react";
import type { Map as LeafletMap } from "leaflet";
import { Marker, Tooltip } from "react-leaflet";
import { toast } from "sonner";
import { ApiError, apiSend, fetcher } from "@/lib/api";
import type { Desa } from "@/lib/types";
import { downloadGpx, roundPoint, type LatLng } from "@/lib/gpx";
import { useSession } from "@/lib/use-session";
import { BaseLayerChoice, GpxUpload, MapShell, Recenter, pointIcon } from "@/components/map/map-shell";
import { PageHeader } from "@/components/page-header";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";

const DEFAULT_CENTER: LatLng = [-7.3841, 109.0363];

function angka(nilai: string): number | null {
  if (nilai.trim() === "") return null;
  const parsed = Number(nilai);
  return Number.isFinite(parsed) ? parsed : null;
}

export default function PetaKantorPage() {
  const { user } = useSession();
  const isAdmin = user?.role === "ADMIN";
  const { data: desa, mutate } = useSWR<Desa>("/desa", fetcher);
  const mapRef = useRef<LeafletMap | null>(null);
  const [lat, setLat] = useState("");
  const [lng, setLng] = useState("");
  const [zoom, setZoom] = useState(16);
  const [layer, setLayer] = useState("osm");
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    if (!desa) return;
    setLat(desa.petaLat == null ? "" : String(desa.petaLat));
    setLng(desa.petaLng == null ? "" : String(desa.petaLng));
    setZoom(desa.petaZoom ?? 16);
  }, [desa]);

  const titik: LatLng | null =
    angka(lat) !== null && angka(lng) !== null ? [Number(lat), Number(lng)] : null;
  const pusat: LatLng = titik ?? DEFAULT_CENTER;
  const icon = pointIcon("#0f766e");

  function letakkan([lintang, bule]: LatLng) {
    setLat(String(lintang));
    setLng(String(bule));
  }

  function fokus() {
    if (!titik) return;
    mapRef.current?.setView(titik, zoom);
  }

  async function simpan() {
    if (!titik) {
      toast.error("Klik peta dulu untuk menentukan titik kantor");
      return;
    }
    setSaving(true);
    try {
      await apiSend("/desa", "PUT", { petaLat: titik[0], petaLng: titik[1], petaZoom: zoom });
      toast.success("Lokasi kantor desa tersimpan");
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menyimpan lokasi kantor");
    } finally {
      setSaving(false);
    }
  }

  async function kosongkan() {
    setSaving(true);
    try {
      await apiSend("/desa", "PUT", { petaLat: null, petaLng: null, petaZoom: null });
      setLat("");
      setLng("");
      toast.success("Koordinat kantor dikosongkan");
      await mutate();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal mengosongkan koordinat");
    } finally {
      setSaving(false);
    }
  }

  return (
    <div className="animate-fade-in space-y-6">
      <PageHeader
        title="Peta Lokasi Kantor"
        description="Tentukan titik koordinat kantor desa. Titik ini yang tampil pada peta di halaman depan website."
        action={
          <Button asChild variant="outline">
            <Link href="/admin/pengaturan">
              <ArrowLeft className="h-4 w-4" />
              Kembali ke Identitas Desa
            </Link>
          </Button>
        }
      />

      <div className="grid gap-5 lg:grid-cols-[1.6fr_1fr]">
        <Card>
          <CardHeader className="flex-row items-center justify-between space-y-0">
            <CardTitle className="text-base">Klik peta untuk memindahkan titik</CardTitle>
            {titik && (
              <a
                href={`https://www.openstreetmap.org/?mlat=${titik[0]}&mlon=${titik[1]}#map=${zoom}/${titik[0]}/${titik[1]}`}
                target="_blank"
                rel="noreferrer"
                className="inline-flex items-center gap-1 text-xs font-medium text-primary hover:underline"
              >
                Buka di OpenStreetMap
                <ExternalLink className="h-3 w-3" />
              </a>
            )}
          </CardHeader>
          <CardContent className="space-y-4">
            <MapShell
              center={pusat}
              zoom={zoom}
              layerId={layer}
              mapRef={(map) => {
                mapRef.current = map;
              }}
              onPoint={(p) => letakkan(p)}
              onZoom={setZoom}
            >
              {titik && (
                <Marker position={titik} icon={icon}>
                  <Tooltip permanent direction="right" offset={[12, 0]}>
                    Kantor {desa?.nama ?? "Desa"}
                  </Tooltip>
                </Marker>
              )}
              {desa?.petaLat != null && desa?.petaLng != null && (
                <Recenter
                  point={[Number(desa.petaLat), Number(desa.petaLng)]}
                  zoom={desa.petaZoom ?? 16}
                />
              )}
            </MapShell>

            {!titik && (
              <p className="text-sm text-muted-foreground">
                Belum ada titik. Klik lokasi kantor pada peta di atas, lalu simpan.
              </p>
            )}

            <BaseLayerChoice value={layer} onChange={setLayer} />
          </CardContent>
        </Card>

        <Card>
          <CardHeader>
            <CardTitle className="text-base">Koordinat &amp; tampilan</CardTitle>
          </CardHeader>
          <CardContent className="space-y-4">
            <label className="block text-sm font-medium">
              Latitude
              <Input
                value={lat}
                onChange={(event) => setLat(event.target.value)}
                placeholder="-7.3841000"
                inputMode="decimal"
                className="mt-1.5"
              />
            </label>
            <label className="block text-sm font-medium">
              Longitude
              <Input
                value={lng}
                onChange={(event) => setLng(event.target.value)}
                placeholder="109.0363000"
                inputMode="decimal"
                className="mt-1.5"
              />
            </label>
            <label className="block text-sm font-medium">
              Zoom
              <Input
                type="number"
                min={1}
                max={19}
                value={zoom}
                onChange={(event) => setZoom(Number(event.target.value) || 1)}
                className="mt-1.5"
              />
            </label>

            <div className="flex flex-wrap gap-2">
              <Button type="button" variant="outline" onClick={fokus} disabled={!titik}>
                <Crosshair className="h-4 w-4" />
                Pusatkan peta
              </Button>
              <GpxUpload
                onPoints={(points) => letakkan(roundPoint(points[0][0], points[0][1]))}
              />
              <Button
                type="button"
                variant="outline"
                disabled={!titik}
                onClick={() => downloadGpx("lokasi-kantor-desa.gpx", [titik!], "Lokasi Kantor")}
              >
                Ekspor ke GPX
              </Button>
            </div>

            {isAdmin && (
              <div className="flex flex-wrap gap-2 border-t pt-4">
                <Button onClick={simpan} disabled={saving}>
                  <Save className="h-4 w-4" />
                  {saving ? "Menyimpan…" : "Simpan"}
                </Button>
                <Button
                  variant="ghost"
                  onClick={kosongkan}
                  disabled={saving || !titik}
                  className="text-muted-foreground hover:text-destructive"
                >
                  <Trash2 className="h-4 w-4" />
                  Reset
                </Button>
              </div>
            )}
          </CardContent>
        </Card>
      </div>
    </div>
  );
}
