// src/components/CountriesMap/index.tsx
import React, { useEffect, useMemo, useRef, useState } from "react";
import {
  ComposableMap,
  Geographies,
  Geography,
  Marker,
  Annotation,
  ZoomableGroup,
} from "react-simple-maps";
import styled from "styled-components";
import {
  s_Text16_700 as Text16_700,
} from "../Typography";
import { useSingleton } from "cms/factory";

/* =================== constants =================== */
const MAP_HEIGHT = 520;
const GEO_URL = "/data/countries-110m.json";
const CARD_W = 290;
const CARD_H = 160;

const MIN_ZOOM = 0.8;
const MAX_ZOOM = 8;
const INITIAL_ZOOM = 4;
const ZOOM_STEP = 1.25;

const clamp = (n: number, min: number, max: number) =>
  Math.min(max, Math.max(min, n));


/* =================== CMS types/selection =================== */
type CmsItem = { id: string; text: string; order: number };
type CmsCountry = {
  id: string;
  code: "usa" | "kaz" | "uzb" | "kgz" | "tjk" | "tur" | "cyp" | "arm" | "uae";
  name: string;
  isEnabled: boolean;
  order: number;
  flag?: { url?: string | null } | null;
  items: CmsItem[];
};
type CmsSection = {
  id: string;
  title?: string | null;
  countries: CmsCountry[];
};

const SELECTION = `
  id
  title
  countries(orderBy: { order: asc }) {
    id code name isEnabled order
    flag { url }
    items(orderBy: { order: asc }) { id text order }
  }
`;

/* =================== layout map (coords/offsets) =================== */
/** координаты и смещения — «жёсткие», не редактируются в CMS */
const LAYOUT: Record<
  CmsCountry["code"],
  { coord: [number, number]; dx: number; dy: number; label?: string }
> = {
  usa: { coord: [-97, 39], dx: 850, dy: -210, label: "United States of America" },
  kaz: { coord: [67, 48], dx: -80, dy: -130 },
  uzb: { coord: [64.6, 41.3], dx: 250, dy: -140 },
  kgz: { coord: [74.7, 41.2], dx: 150, dy: 0 },
  tjk: { coord: [71, 38.9], dx: 50, dy: 80 },
  tur: { coord: [35, 39], dx: -100, dy: -100 },
  cyp: { coord: [33, 35], dx: -200, dy: -30 },
  arm: { coord: [45, 40], dx: -120, dy: 100 },
  uae: { coord: [54.4, 24.3], dx: -10, dy: 45 },
};

/* =================== fallback (твои текущие данные) =================== */
type CountryCard = {
  id: string;                // code
  name: string;
  coord: [number, number];
  dx: number;
  dy: number;
  items: string[];
  flagUrl?: string | null;   // + флаг из CMS (если есть)
  label?: string;
};

const FALLBACK: CountryCard[] = [
  { id: "usa", name: "United States of America", coord: [-97, 39], dx: 60, dy: -10, items: ["NYSE institutional broker"] },
  { id: "kaz", name: "Kazakhstan", coord: [67, 48], dx: 40, dy: -20, items: ["Freedom Bank","Freedom Broker","Freedom Life","Freedom Insurance","Freedom Pay","Freedom Telecom","Freedom Travel"] },
  { id: "uzb", name: "Uzbekistan", coord: [64.6, 41.3], dx: 50, dy: 0, items: ["Freedom Broker Uzbekistan","Freedom Pay Uzbekistan","Freedom Telecom Uzbekistan"] },
  { id: "kgz", name: "Kyrgyzstan", coord: [74.7, 41.2], dx: 40, dy: 0, items: ["Freedom Broker Kyrgyzstan","Freedom Telecom Kyrgyzstan"] },
  { id: "tjk", name: "Tajikistan", coord: [71, 38.9], dx: 40, dy: 20, items: ["Freedom Broker Tajikistan","Freedom Telecom Tajikistan"] },
  { id: "tur", name: "Turkey", coord: [35, 39], dx: -10, dy: 30, items: ["Freedom Broker"] },
  { id: "cyp", name: "Cyprus", coord: [33, 35], dx: -10, dy: 30, items: ["Freedom Finance Europe"] },
  { id: "arm", name: "Armenia", coord: [45, 40], dx: -10, dy: 30, items: ["Brokerage"] },
  { id: "uae", name: "United Arab Emirates", coord: [54.4, 24.3], dx: -10, dy: 30, items: ["Freedom Telecom International","Freedom Broker"] },
];

/* =================== map CMS → view =================== */
function mapCountries(section?: CmsSection | null): CountryCard[] {
  const list = section?.countries ?? [];
  if (!list.length) return [];

  return list
    .filter((c) => c.isEnabled && LAYOUT[c.code])
    .map((c) => {
      const lay = LAYOUT[c.code];
      return {
        id: c.code,
        name: c.name,
        coord: lay.coord,
        dx: lay.dx,
        dy: lay.dy,
        label: lay.label,
        items: (c.items ?? []).map((i) => i.text),
        flagUrl: c.flag?.url ?? null,
      };
    });
}

function updateScaleKeepCenter(newScale: number) {
  const g = document.querySelector<SVGGElement>("g.rsm-zoomable-group");
  const svg = g?.closest("svg") as SVGSVGElement | null;
  if (!g || !svg) return;

  const transform = g.getAttribute("transform") || "";
  const matchT = transform.match(/translate\((-?\d+\.?\d*)[, ]+(-?\d+\.?\d*)\)/);
  const matchS = transform.match(/scale\((-?\d+\.?\d*)\)/);

  let tx = matchT ? parseFloat(matchT[1]) : 0;
  let ty = matchT ? parseFloat(matchT[2]) : 0;
  const currentScale = matchS ? parseFloat(matchS[1]) : 1;

  // центр SVG
  const cx = svg.clientWidth / 2;
  const cy = svg.clientHeight / 2;

  // пересчёт translate
  const ratio = newScale / currentScale;
  tx = cx - (cx - tx) * ratio;
  ty = cy - (cy - ty) * ratio;

  g.setAttribute("transform", `translate(${tx} ${ty}) scale(${newScale})`);
}



/* =================== component =================== */
export default function CountriesMap() {
  const wrapRef = useRef<HTMLDivElement>(null);
  const [mapWidth, setMapWidth] = useState(1200);

  // CMS
  const { data, loading, error } = useSingleton<CmsSection>(
    "CountriesMapSection",
    SELECTION
  );

  const cmsCountries = useMemo(() => mapCountries(data), [data]);
  const COUNTRIES: CountryCard[] = cmsCountries.length ? cmsCountries : FALLBACK;

  // ширина контейнера
  useEffect(() => {
    if (!wrapRef.current) return;
    const observer = new ResizeObserver((entries) => {
      const entry = entries[0];
      if (entry) setMapWidth(entry.contentRect.width);
    });
    observer.observe(wrapRef.current);
    return () => observer.disconnect();
  }, []);

  const highlighted = useMemo(() => new Set(COUNTRIES.map((d) => d.name)), [COUNTRIES]);
  const [hovered, setHovered] = useState<string | null>(null);

  const mobile = typeof window !== "undefined" ? window.innerWidth < 700 : false;
  const initialCenter: [number, number] = mobile ? [65, 38] : [52, 38];

  const [center, setCenter] = useState<[number, number]>(initialCenter);
  const [zoom, setZoom] = useState(INITIAL_ZOOM);
  const [zoomScale, setZoomScale] = useState(INITIAL_ZOOM);

  useEffect(() => {
    updateScaleKeepCenter(zoomScale);
  },[zoomScale]);

  const zoomIn = () => setZoomScale(z => clamp(z * ZOOM_STEP, MIN_ZOOM, MAX_ZOOM));
  const zoomOut = () => setZoomScale(z => clamp(z / ZOOM_STEP, MIN_ZOOM, MAX_ZOOM));
  const resetView = () => {
    setCenter(initialCenter);
    setZoom(INITIAL_ZOOM);
  };


  return (
    <Wrap ref={wrapRef}>
      <ComposableMap
        key={mapWidth}
        projection="geoMercator"
        projectionConfig={{ scale: 110 }}
        width={mapWidth}
        height={MAP_HEIGHT}
        style={{ width: "100%", height: `${MAP_HEIGHT}px` }}
        preserveAspectRatio="none"
      >
        <ZoomableGroup
          center={center}
          zoom={zoom}
          minZoom={0.8}
          maxZoom={8}
          translateExtent={[[-1000, -500], [1000, 900]]}
          filterZoomEvent={(e) => e.type !== "wheel" && e.type !== "dblclick"}
          onMoveEnd={() => {
            setCenter(initialCenter);
            setZoom(zoom);
          }}
        >
          <Geographies geography={GEO_URL}>
            {({ geographies }: { geographies: any[] }) =>
              geographies.map((geo: any) => {
                const name = geo.properties.name as string;
                const isAlways = highlighted.has(name);
                const isActive = hovered === name;
                return (
                  <Geography
                    key={geo.rsmKey as string}
                    geography={geo}
                    onMouseEnter={() => setHovered(name)}
                    onMouseLeave={() => setHovered((prev) => (prev === name ? null : prev))}
                    style={{
                      default: {
                        fill: isActive ? "#0E7C44" : isAlways ? "#2EA86B" : "#CFE1E7",
                        stroke: "#FFFFFF",
                        strokeWidth: 0.6,
                        outline: "none",
                        transition: "fill .2s ease",
                      },
                      hover: { fill: "#0E7C44", outline: "none" },
                      pressed: { fill: "#0E7C44", outline: "none" },
                    }}
                  />
                );
              })
            }
          </Geographies>

          {/* markers (флаг или кружок) */}
          {COUNTRIES.map((c) => (
            <Marker
              key={`m-${c.id}`}
              coordinates={c.coord}
              onMouseEnter={() => setHovered(c.name)}
              onMouseLeave={() => setHovered((prev) => (prev === c.name ? null : prev))}
            >
              <g transform={`scale(${1 / zoom})`}>
                <circle r={5} fill="#E11D48" stroke="#fff" strokeWidth={2} />
              </g>
            </Marker>
          ))}

          {/* labels/cards */}
          {COUNTRIES.map((c) => {
            const pos = LAYOUT[c.id as CmsCountry["code"]];
            const items = c.items;
            const twoCols = items.length > 4;

            return (
              <Annotation
                key={`a-${c.id}`}
                subject={c.coord}
                dx={pos.dx / zoom}
                dy={pos.dy / zoom}
                connectorProps={{ stroke: "#94A3B8", strokeWidth: 0.5 }}
              >
                <g transform={`scale(${1 / (zoom + (mobile ? 0 : 0))})`} data-card={c.name}>
                  <foreignObject
                    x={-140}
                    y={-8}
                    width={CARD_W}
                    height={CARD_H}
                    style={{ pointerEvents: "auto" }}
                    onMouseEnter={() => setHovered(c.name)}
                    onMouseLeave={() => setHovered((prev) => (prev === c.name ? null : prev))}
                  >
                    <div
                      style={{
                        background: "#FFFFFF",
                        borderRadius: 16,
                        padding: "6px 12px",
                        boxShadow: "0px 8px 14.13px 0px #2764698F",
                        border: "1px solid #14935F",
                        margin: "0px 10px",
                        display: "flex",
                        flexDirection: "row",
                      }}
                    >
                      {c.flagUrl ? (
                        <img
                          src={c.flagUrl??undefined}
                          style={{width:16.67,height:16.67}}
                        />
                      ): (
                        <div
                          style={{
                            width: 16.67,
                            height: 16.67,
                            background: "#10B981",
                            borderRadius: 999,
                          }}
                        />
                      )}
                      <div style={{ paddingLeft: 8 }}>
                        <div
                          style={{
                            display: "flex",
                            alignItems: "center",
                            gap: 8,
                            marginBottom: 0,
                          }}
                        >
                          <Text16_700 style={{ fontFamily: "inherit" }}>
                            {c.label ?? c.name}
                          </Text16_700>
                        </div>

                        {items.length <= 1 ? (
                          items[0] ? (
                            <div style={{ fontSize: 12, lineHeight: "18px" }}>{items[0]}</div>
                          ) : null
                        ) : (
                          <ul
                            style={{
                              margin: 0,
                              fontSize: 12,
                              lineHeight: "16px",
                              display: twoCols ? "grid" : "block",
                              gridTemplateColumns: twoCols ? "1fr 1fr" : undefined,
                              columnGap: twoCols ? 16 : undefined,
                              listStyleType: 'disc'
                            }}
                          >
                            {items.map((t, i) => (
                              <li key={i}>
                                <div style={{ whiteSpace: "nowrap" }}>{t}</div>
                              </li>
                            ))}
                          </ul>
                        )}
                      </div>
                    </div>
                  </foreignObject>
                </g>
              </Annotation>
            );
          })}
        </ZoomableGroup>
      </ComposableMap>
      <ZoomControls>

        <ZoomBtn onClick={zoomIn} aria-label="Zoom in">+</ZoomBtn>
        <ZoomBtn onClick={zoomOut} aria-label="Zoom out">–</ZoomBtn>
      </ZoomControls>
    </Wrap>
  );
}

/* =================== styles =================== */
const Wrap = styled.div`
  position: relative;
  background: #e9f0f3;
  border-radius: 16px;
  overflow: hidden;
  width: 100%;
`;

const ZoomControls = styled.div`
  position: absolute;
  right: 12px;
  top: 12px;
  display: flex;
  gap: 8px;
  z-index: 2;
  pointer-events: auto;
  flex-direction: column;
`;

const ZoomBtn = styled.button`
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: #fff;
  border: 1px solid #14935f;
  box-shadow: 0px 8px 14.13px 0px #2764698f;
  font-weight: 700;
  line-height: 0;
  display: grid;
  place-items: center;
  cursor: pointer;
  user-select: none;
  &:active { transform: translateY(1px); }
`;

