"use client";

import dynamic from "next/dynamic";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useRef, useState } from "react";

import { CadInput } from "@/components/site-finder/CadInput";
import { MapFilterBar } from "@/components/site-finder/entry/MapFilterBar";
import { ParcelDrawer } from "@/components/site-finder/entry/ParcelDrawer";
import { ParcelLegend } from "@/components/site-finder/entry/ParcelLegend";
import { RecentParcels } from "@/components/site-finder/entry/RecentParcels";
import {
  addLocalRecentParcel,
  useParcelsBboxQuery,
} from "@/lib/site-finder-api";
import type {
  ParcelBboxFilters,
  ParcelBboxItem,
  BboxCoords,
} from "@/lib/site-finder-api";

// EntryMap uses Leaflet — must load without SSR
const EntryMap = dynamic(
  () =>
    import("@/components/site-finder/entry/EntryMap").then((m) => m.EntryMap),
  {
    ssr: false,
    loading: () => (
      <div
        style={{
          flex: 1,
          minHeight: 480,
          background: "var(--bg-card-alt)",
          border: "1px dashed var(--border-strong)",
          borderRadius: 12,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          color: "var(--fg-tertiary)",
          fontSize: 14,
        }}
      >
        Загрузка карты...
      </div>
    ),
  },
);

// ── FilterCountBridge ──────────────────────────────────────────────────────────
// Reads parcel counts for current bbox without re-mounting EntryMap.

interface FilterBarBridgeProps {
  filters: ParcelBboxFilters;
  onChange: (f: ParcelBboxFilters) => void;
  bbox: BboxCoords | null;
}

function FilterBarBridge({ filters, onChange, bbox }: FilterBarBridgeProps) {
  // useParcelsBboxQuery has no keepPreviousData (unlike useParcelAnalyzeQuery),
  // and its queryKey carries the bbox — so on every pan/zoom both `data` go
  // undefined mid-fetch. We hold the last fully-resolved pair so the counter
  // doesn't flash "0 / 0" while fetching (#1419), and so totalCount/matchCount
  // are always taken from the *same* committed frame — never a new bbox's
  // matchCount over an old bbox's totalCount, which could read matchCount >
  // totalCount and break the X ⊆ Y invariant (#1420).
  const allQuery = useParcelsBboxQuery(bbox, {});
  const filteredQuery = useParcelsBboxQuery(bbox, filters);

  const lastCounts = useRef<{ totalCount: number; matchCount: number } | null>(
    null,
  );

  // Only commit a new pair once BOTH queries have data for the current render;
  // until then keep the previous pair (placeholderData: keepPreviousData
  // equivalent, scoped to this bridge).
  if (allQuery.data != null && filteredQuery.data != null) {
    lastCounts.current = {
      totalCount: allQuery.data.length,
      matchCount: filteredQuery.data.length,
    };
  }

  const counts = lastCounts.current ?? { totalCount: 0, matchCount: 0 };

  return (
    <MapFilterBar
      filters={filters}
      onChange={onChange}
      totalCount={counts.totalCount}
      matchCount={counts.matchCount}
    />
  );
}

// ── Page ──────────────────────────────────────────────────────────────────────

export default function SiteFinderPage() {
  const router = useRouter();
  const [filters, setFilters] = useState<ParcelBboxFilters>({});
  const [selectedParcel, setSelectedParcel] = useState<ParcelBboxItem | null>(
    null,
  );
  const [bbox, setBbox] = useState<BboxCoords | null>(null);

  function handleParcelSelect(parcel: ParcelBboxItem) {
    setSelectedParcel(parcel);
  }

  function handleParcelDeselect() {
    setSelectedParcel(null);
  }

  function handleParcelOpen(parcel: ParcelBboxItem) {
    // Record the visit so RecentParcels stays populated, then navigate.
    addLocalRecentParcel({
      cad_num: parcel.cad_num,
      address: parcel.address,
      area_ha: parcel.area_ha,
      district: parcel.district,
      visited_at: new Date().toISOString(),
    });
    router.push(`/site-finder/analysis/${encodeURIComponent(parcel.cad_num)}`);
  }

  function handleCadSubmit(cad: string) {
    router.push(`/site-finder/analysis/${encodeURIComponent(cad)}`);
  }

  return (
    <main
      style={{
        minHeight: "100vh",
        background: "var(--bg-app)",
        display: "flex",
        flexDirection: "column",
      }}
    >
      {/* Header */}
      <header
        style={{
          background: "var(--bg-card)",
          borderBottom: "1px solid var(--border-card)",
          padding: "12px 24px",
          display: "flex",
          alignItems: "center",
          gap: 16,
          flexShrink: 0,
        }}
      >
        <Link
          href="/"
          style={{
            fontSize: 13,
            color: "var(--fg-secondary)",
            textDecoration: "none",
          }}
        >
          ← Главная
        </Link>
        <span style={{ color: "var(--border-soft)" }}>·</span>
        <h1
          style={{
            margin: 0,
            fontSize: 16,
            fontWeight: 600,
            color: "var(--fg-primary)",
          }}
        >
          SiteFinder · карта участков
        </h1>
        <Link
          href="/site-finder/compare"
          style={{
            marginLeft: "auto",
            fontSize: 13,
            color: "var(--accent)",
            textDecoration: "none",
            fontWeight: 500,
          }}
        >
          Сравнить участки
        </Link>
      </header>

      {/* Filter bar */}
      <div style={{ flexShrink: 0 }}>
        <FilterBarBridge filters={filters} onChange={setFilters} bbox={bbox} />
      </div>

      {/* Main layout. На планшете/телефоне .gd-split встаёт в колонку
          (карта над сайдбаром), .gd-map-shell держит высоту карты (issue #66). */}
      <div
        className="gd-split"
        style={{
          flex: 1,
          display: "flex",
          gap: 0,
          overflow: "hidden",
          minHeight: 0,
        }}
      >
        {/* Map area — position: relative so ParcelDrawer can anchor absolutely here */}
        <div
          className="gd-map-shell"
          style={{
            flex: 1,
            padding: 16,
            display: "flex",
            flexDirection: "column",
            minHeight: 0,
            position: "relative",
          }}
        >
          <EntryMap
            filters={filters}
            selectedCad={selectedParcel?.cad_num ?? null}
            onParcelOpen={handleParcelOpen}
            onParcelSelect={handleParcelSelect}
            onParcelDeselect={handleParcelDeselect}
            onBboxChange={setBbox}
          />

          {/* ParcelDrawer — anchored to map area right edge, not page */}
          <ParcelDrawer
            parcel={selectedParcel}
            onClose={handleParcelDeselect}
          />
        </div>

        {/* Right sidebar — always visible; CadInput accessible parallel with drawer */}
        <div
          className="gd-split-aside"
          style={{
            width: 300,
            flexShrink: 0,
            padding: "16px 16px 16px 0",
            display: "flex",
            flexDirection: "column",
            gap: 12,
            overflowY: "auto",
          }}
        >
          <CadInput onSubmit={handleCadSubmit} loading={false} />
          <RecentParcels />
          <ParcelLegend />
        </div>
      </div>
    </main>
  );
}
