"use client";

import type { Feature, FeatureCollection } from "geojson";
import type * as Leaflet from "leaflet";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";

const districtNames = [
  "Achham", "Arghakhanchi", "Baglung", "Baitadi", "Bajhang", "Bajura", "Banke", "Bara", "Bardiya", "Bhaktapur",
  "Bhojpur", "Chitwan", "Dadeldhura", "Dailekh", "Dang", "Darchula", "Dhading", "Dhankuta", "Dhanusha", "Dolakha",
  "Dolpa", "Doti", "Gorkha", "Gulmi", "Humla", "Ilam", "Jajarkot", "Jhapa", "Jumla", "Kailali",
  "Kalikot", "Kanchanpur", "Kapilvastu", "Kaski", "Kathmandu", "Kavrepalanchok", "Khotang", "Lalitpur", "Lamjung", "Mahottari",
  "Makwanpur", "Manang", "Morang", "Mugu", "Mustang", "Myagdi", "Nawalpur", "Nuwakot", "Okhaldhunga", "Palpa",
  "Panchthar", "Parbat", "Parsa", "Pyuthan", "Ramechhap", "Rasuwa", "Rautahat", "Rolpa", "Rukum East", "Rukum West",
  "Rupandehi", "Salyan", "Sankhuwasabha", "Saptari", "Sarlahi", "Sindhuli", "Sindhupalchok", "Siraha", "Solukhumbu", "Sunsari",
  "Surkhet", "Syangja", "Tanahu", "Taplejung", "Terhathum", "Udayapur", "Nawalparasi West"
].sort((a, b) => a.localeCompare(b));

type DistrictLayer = Leaflet.Path & { districtName?: string };

const geojsonUrls = [
  "https://raw.githubusercontent.com/mesaugat/geoJSON-Nepal/master/nepal-districts-new.geojson",
  "https://raw.githubusercontent.com/mesaugat/geoJSON-Nepal/master/nepal-districts.geojson"
];

function districtStyle(): Leaflet.PathOptions {
  return {
    color: "#00f3ff",
    dashArray: "2",
    fillColor: "#102030",
    fillOpacity: 0.3,
    opacity: 0.9,
    weight: 1.5
  };
}

function highlightStyle(): Leaflet.PathOptions {
  return {
    color: "#ffff99",
    dashArray: undefined,
    fillColor: "#ffcc00",
    fillOpacity: 0.8,
    opacity: 1,
    weight: 3
  };
}

function generateNepalMockPolygons(): FeatureCollection {
  const bounds = { minLat: 26.3, maxLat: 30.5, minLng: 80.0, maxLng: 88.2 };
  return {
    type: "FeatureCollection" as const,
    features: districtNames.map((name, index) => {
      const column = index % 11;
      const row = Math.floor(index / 11);
      const centerLat = bounds.minLat + (row / 7) * (bounds.maxLat - bounds.minLat);
      const centerLng = bounds.minLng + (column / 10) * (bounds.maxLng - bounds.minLng);
      const latSpan = 0.28 + (index % 4) * 0.04;
      const lngSpan = 0.34 + (index % 5) * 0.04;
      const coords = [
        [centerLng - lngSpan / 2, centerLat - latSpan / 2],
        [centerLng + lngSpan / 2, centerLat - latSpan / 3],
        [centerLng + lngSpan / 2.5, centerLat + latSpan / 2],
        [centerLng - lngSpan / 3, centerLat + latSpan / 2.2],
        [centerLng - lngSpan / 2, centerLat - latSpan / 2]
      ];
      return {
        type: "Feature" as const,
        properties: { DISTRICT: name },
        geometry: { type: "Polygon" as const, coordinates: [[...coords, coords[0]]] }
      };
    })
  };
}

function getDistrictName(feature: Feature, index: number) {
  const properties = feature.properties as Record<string, unknown> | null;
  const name = properties?.DIST_EN ?? properties?.DISTRICT ?? properties?.NAME_2 ?? properties?.NAME;
  return typeof name === "string" && name.trim().length > 0
    ? name.trim()
    : districtNames[index] ?? `District ${index + 1}`;
}

export function JarvisDistrictConsole() {
  const [active, setActive] = useState<Set<string>>(() => new Set());
  const [districtList, setDistrictList] = useState(districtNames);
  const [loadedCount, setLoadedCount] = useState(0);
  const mapRef = useRef<Leaflet.Map | null>(null);
  const layersRef = useRef<Map<string, DistrictLayer>>(new Map());
  const activeCount = active.size;
  const sortedDistricts = useMemo(() => districtList, [districtList]);

  const toggleDistrict = useCallback((name: string) => {
    setActive((current) => {
      const next = new Set(current);
      if (next.has(name)) {
        next.delete(name);
      } else {
        next.add(name);
      }
      return next;
    });
  }, []);

  useEffect(() => {
    if (mapRef.current) {
      return;
    }

    let cancelled = false;
    const layers = layersRef.current;

    async function loadGeoJson() {
      for (const url of geojsonUrls) {
        try {
          const response = await fetch(url);
          if (!response.ok) {
            continue;
          }
          return response.json();
        } catch {
          continue;
        }
      }
      return generateNepalMockPolygons();
    }

    import("leaflet").then(async (L) => {
      if (cancelled || mapRef.current) {
        return;
      }

      const map = L.map("mapContainer").setView([28.2, 84.0], 7);
      mapRef.current = map;

      L.tileLayer("https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png", {
        attribution: "&copy; OpenStreetMap"
      }).addTo(map);

      try {
        const geoData = await loadGeoJson();
        const features = Array.isArray(geoData.features) && geoData.features.length > 0
          ? geoData.features.slice(0, 77)
          : generateNepalMockPolygons().features;
        const paddedFeatures = features.length < 77
          ? [...features, ...generateNepalMockPolygons().features.slice(0, 77 - features.length)]
          : features;

        const layerGroup = L.geoJSON(
          { type: "FeatureCollection", features: paddedFeatures } as FeatureCollection,
          {
            style: districtStyle,
            onEachFeature: (feature, layer) => {
              const pathLayer = layer as DistrictLayer;
              const name = getDistrictName(feature as Feature, layers.size);
              pathLayer.districtName = name;
              layers.set(name, pathLayer);
              pathLayer.bindTooltip(`${layers.size}: ${name}`, {
                className: "neon-tooltip",
                direction: "center",
                permanent: false
              });
              pathLayer.on("click", () => toggleDistrict(name));
            }
          }
        ).addTo(map);

        setDistrictList(Array.from(layers.keys()).sort((a, b) => a.localeCompare(b)));
        setLoadedCount(layers.size);
        map.fitBounds(layerGroup.getBounds());
      } catch {
        setLoadedCount(0);
      }
    });

    return () => {
      cancelled = true;
      mapRef.current?.remove();
      mapRef.current = null;
      layers.clear();
    };
  }, [toggleDistrict]);

  useEffect(() => {
    layersRef.current.forEach((layer, name) => {
      layer.setStyle(active.has(name) ? highlightStyle() : districtStyle());
    });
  }, [active]);

  return (
    <>
      <div className="main-layout">
        <aside className="info-panel">
          <div className="panel-header">JARVIS CORE // STATUS</div>
          <div className="jarvis-status">
            <div className="status-line">
              <span className="status-label">System</span>
              <span className="status-value">ONLINE · CRITICAL</span>
            </div>
            <div className="status-line">
              <span className="status-label">Districts Loaded</span>
              <span className="status-value">{loadedCount || 77}/77</span>
            </div>
            <div className="status-line">
              <span className="status-label">Channel</span>
              <span className="status-value">JUST CHILL NEPAL</span>
            </div>
          </div>

          <div className="stat-grid">
            <div className="stat-card">
              <strong>77</strong>
              <span className="muted">Total districts</span>
            </div>
            <div className="stat-card">
              <strong>{activeCount}</strong>
              <span className="muted">Highlighted</span>
            </div>
          </div>

          <div className="panel-header">DISTRICT CHECKLIST (1-77)</div>
          <div className="checklist-container">
            {sortedDistricts.map((name, index) => {
              const isActive = active.has(name);
              return (
                <button
                  className={`checklist-item${isActive ? " active" : ""}`}
                  key={name}
                  onClick={() => toggleDistrict(name)}
                  type="button"
                >
                  <span className="check-box" />
                  <span>{index + 1}. {name}</span>
                </button>
              );
            })}
          </div>
          <div className="footer-note">Tick a number or click a district on the map</div>
        </aside>

        <div className="map-panel">
          <div id="mapContainer" />
        </div>
      </div>
    </>
  );
}
