// WorldMap — MapLibre GL choropleth (Carto Positron basemap)

// Kept on window for DrillContinent.jsx compatibility
function colorForShare(value, max) {
  if (value === 0 || max === 0) return null;
  const r = value / max;
  if (r > 0.6)  return "var(--xn-blue-900)";
  if (r > 0.3)  return "var(--xn-blue-700)";
  if (r > 0.15) return "var(--xn-blue-500)";
  if (r > 0.05) return "var(--xn-blue-400)";
  if (r > 0.01) return "var(--xn-blue-300)";
  return "var(--xn-blue-200)";
}
window.colorForShare = colorForShare;

// Hex scale for MapLibre (CSS vars not supported inside paint expressions)
const CHORO_SCALE = [
  [0.60, "#0B1F5C"],
  [0.30, "#173FB0"],
  [0.15, "#2A6BF7"],
  [0.05, "#4F8BFF"],
  [0.01, "#82AEFF"],
  [0.00, "#B6D0FF"],
];
function valueToHex(value, max) {
  if (!value || !max) return "#D4DCE8";
  const r = value / max;
  for (const [thresh, color] of CHORO_SCALE) {
    if (r > thresh) return color;
  }
  return "#B6D0FF";
}

function buildFillExpr(byIso, max) {
  // MapLibre match syntax: ["match", input, v1, out1, v2, out2, ..., fallback]
  const pairs = [["ESP", "#294B28"]];
  for (const [iso, row] of Object.entries(byIso)) {
    if (iso !== "ESP") pairs.push([iso, valueToHex(row.value, max)]);
  }
  const expr = ["match", ["get", "iso3"]];
  for (const [iso, color] of pairs) { expr.push(iso, color); }
  expr.push("#D4DCE8"); // fallback — no data
  return expr;
}

const NUM_TO_ISO = {
  "004":"AFG","008":"ALB","012":"DZA","024":"AGO","032":"ARG","036":"AUS","040":"AUT","044":"BHS","050":"BGD","051":"ARM",
  "056":"BEL","068":"BOL","070":"BIH","072":"BWA","076":"BRA","084":"BLZ","100":"BGR","104":"MMR","112":"BLR","116":"KHM",
  "120":"CMR","124":"CAN","140":"CAF","148":"TCD","152":"CHL","156":"CHN","158":"TWN","170":"COL","178":"COG","180":"COD",
  "188":"CRI","191":"HRV","192":"CUB","196":"CYP","203":"CZE","208":"DNK","214":"DOM","218":"ECU","222":"SLV","226":"GNQ",
  "231":"ETH","232":"ERI","233":"EST","242":"FJI","246":"FIN","250":"FRA","260":"ATF","262":"DJI","266":"GAB","268":"GEO",
  "270":"GMB","275":"PSE","276":"DEU","288":"GHA","292":"GIB","300":"GRC","304":"GRL","320":"GTM","324":"GIN","328":"GUY",
  "332":"HTI","340":"HND","348":"HUN","352":"ISL","356":"IND","360":"IDN","364":"IRN","368":"IRQ","372":"IRL","376":"ISR",
  "380":"ITA","384":"CIV","388":"JAM","392":"JPN","398":"KAZ","400":"JOR","404":"KEN","408":"PRK","410":"KOR","414":"KWT",
  "417":"KGZ","418":"LAO","422":"LBN","426":"LSO","428":"LVA","430":"LBR","434":"LBY","440":"LTU","442":"LUX","450":"MDG",
  "454":"MWI","458":"MYS","466":"MLI","478":"MRT","480":"MUS","484":"MEX","496":"MNG","498":"MDA","499":"MNE","504":"MAR",
  "508":"MOZ","516":"NAM","524":"NPL","528":"NLD","540":"NCL","554":"NZL","558":"NIC","562":"NER","566":"NGA","578":"NOR",
  "586":"PAK","591":"PAN","598":"PNG","600":"PRY","604":"PER","608":"PHL","616":"POL","620":"PRT","630":"PRI","634":"QAT",
  "642":"ROU","643":"RUS","646":"RWA","682":"SAU","686":"SEN","688":"SRB","694":"SLE","702":"SGP","703":"SVK","704":"VNM",
  "705":"SVN","706":"SOM","710":"ZAF","716":"ZWE","724":"ESP","728":"SSD","729":"SDN","748":"SWZ","752":"SWE","756":"CHE",
  "760":"SYR","762":"TJK","764":"THA","768":"TGO","780":"TTO","784":"ARE","788":"TUN","792":"TUR","795":"TKM","800":"UGA",
  "804":"UKR","807":"MKD","818":"EGY","826":"GBR","834":"TZA","840":"USA","854":"BFA","858":"URY","860":"UZB","862":"VEN",
  "882":"WSM","887":"YEM","894":"ZMB",
};
function numToIso(id) {
  return NUM_TO_ISO[String(id).padStart(3, "0")] || null;
}

// Still needed by DrillContinent.jsx (SVG map)
function useWorldData() {
  const [data, setData] = React.useState(null);
  React.useEffect(() => {
    let cancelled = false;
    fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-110m.json")
      .then(r => r.json())
      .then(topo => {
        if (cancelled) return;
        setData(window.topojson.feature(topo, topo.objects.countries));
      })
      .catch(e => console.error("world-atlas load failed", e));
    return () => { cancelled = true; };
  }, []);
  return data;
}

function WorldMapView({ hs, metric, years, selected, setSelected, rows: rowsProp }) {
  const CF = window.CF;
  const rows = rowsProp || CF.countriesRange(hs, metric, years);
  const total = rows.reduce((a, r) => a + r.value, 0);
  const max = Math.max(...rows.map(r => r.value));
  const byIso = Object.fromEntries(rows.map(r => [r.iso, r]));

  const containerRef = React.useRef(null);
  const mapRef = React.useRef(null);
  const dataRef = React.useRef({ byIso, max });
  dataRef.current = { byIso, max };
  const setSelectedRef = React.useRef(setSelected);
  setSelectedRef.current = setSelected;

  const [hover, setHover] = React.useState(null);
  const [tipPos, setTipPos] = React.useState({ x: 0, y: 0 });

  // Init MapLibre once
  React.useEffect(() => {
    if (!window.maplibregl || mapRef.current) return;

    const map = new window.maplibregl.Map({
      container: containerRef.current,
      style: {
        version: 8,
        sources: {},
        layers: [
          { id: "background", type: "background", paint: { "background-color": "#ffffff" } },
        ],
      },
      center: [15, 25],
      zoom: 1.3,
      minZoom: 0.8,
      maxZoom: 7,
      attributionControl: false,
    });
    mapRef.current = map;

    map.addControl(new window.maplibregl.AttributionControl({ compact: true }), "bottom-right");
    map.addControl(new window.maplibregl.NavigationControl({ showCompass: false }), "top-right");

    map.on("load", () => {
      fetch("https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_110m_admin_0_countries.geojson")
        .then(r => r.json())
        .then(geo => {
          // Natural Earth already has iso_a3 — copy to iso3 for consistency
          geo.features.forEach(f => { f.properties.iso3 = f.properties.iso_a3; });

          map.addSource("countries", { type: "geojson", data: geo });

          const { byIso: d, max: m } = dataRef.current;
          map.addLayer({
            id: "countries-fill",
            type: "fill",
            source: "countries",
            paint: {
              "fill-color": buildFillExpr(d, m),
              "fill-opacity": 0.88,
            },
          });

          map.addLayer({
            id: "countries-outline",
            type: "line",
            source: "countries",
            paint: { "line-color": "#FFFFFF", "line-width": 0.6, "line-opacity": 1 },
          });

          map.addLayer({
            id: "countries-selected",
            type: "line",
            source: "countries",
            filter: ["==", ["get", "iso3"], selected || ""],
            paint: { "line-color": "#0B1F5C", "line-width": 2.5 },
          });
        });

      map.on("mousemove", "countries-fill", (e) => {
        const feat = e.features?.[0];
        if (!feat) { setHover(null); return; }
        const iso = feat.properties?.iso3;
        if (iso === "ESP") { map.getCanvas().style.cursor = "default"; setHover({ iso, name: "España", noData: true, isOrigin: true }); setTipPos({ x: e.originalEvent.clientX, y: e.originalEvent.clientY }); return; }
        const name = feat.properties?.name || iso;
        const row = iso
          ? (dataRef.current.byIso[iso] || dataRef.current.byIso[window.iso3toIso2?.(iso)])
          : null;
        map.getCanvas().style.cursor = row ? "pointer" : "default";
        setHover(row ? row : { iso, name, noData: true });
        setTipPos({ x: e.originalEvent.clientX, y: e.originalEvent.clientY });
      });

      map.on("mouseleave", "countries-fill", () => {
        setHover(null);
        map.getCanvas().style.cursor = "";
      });

      map.on("click", "countries-fill", (e) => {
        const iso = e.features?.[0]?.properties?.iso3;
        console.log("[map click] iso=", iso, "byIso keys sample=", Object.keys(dataRef.current.byIso).slice(0,5));
        if (!iso) return;
        const row = dataRef.current.byIso[iso]
          || dataRef.current.byIso[window.iso3toIso2 ? window.iso3toIso2(iso) : iso];
        console.log("[map click] row=", row, "calling setSelected");
        setSelectedRef.current(iso);
      });
    });

    return () => { map.remove(); mapRef.current = null; };
  }, []);

  // Update choropleth when data changes
  React.useEffect(() => {
    const map = mapRef.current;
    if (!map || !map.isStyleLoaded()) return;
    const tryUpdate = () => {
      if (!map.getSource("countries")) return;
      map.setPaintProperty("countries-fill", "fill-color", buildFillExpr(byIso, max));
    };
    if (map.loaded()) tryUpdate();
    else map.once("idle", tryUpdate);
  }, [rows, metric]);

  // Update selected highlight
  React.useEffect(() => {
    const map = mapRef.current;
    if (!map) return;
    const tryUpdate = () => {
      if (!map.getLayer("countries-selected")) return;
      map.setFilter("countries-selected", ["==", ["get", "iso3"], selected || ""]);
    };
    if (map.isStyleLoaded()) tryUpdate();
    else map.once("load", tryUpdate);
  }, [selected]);

  const top3 = rows.slice(0, 3);
  const emerging = rows.find(r => !r.eu && r.value < max * 0.1 && r.value > max * 0.03);
  const asianEmerging = rows.find(r => r.continent === "Asia" && r.value < max * 0.1);

  return (
    <div className="cf-fade-in">
      <div className="cf-insight">
        <div className="icon"><I.Sparkles size={18} /></div>
        <div className="body">
          <span className="tag">INSIGHT</span>
          <strong>{top3[0]?.name}</strong>, <strong>{top3[1]?.name}</strong> y <strong>{top3[2]?.name}</strong> concentran{" "}
          <strong className="cf-mono">
            {CF.fmtPct((top3[0]?.value + top3[1]?.value + top3[2]?.value) / total)}
          </strong> de las exportaciones españolas de <strong>{CF.HS[hs].label.toLowerCase()}</strong>.
          {emerging && <>{" "}Emergente destacado: <strong>{emerging.name}</strong>.</>}
          {asianEmerging && <>{" "}Asia: <strong>{asianEmerging.name}</strong>.</>}
        </div>
      </div>

      <div className="cf-worldmap-wrap">
        <div className="cf-panel-head" style={{margin:0, marginBottom:14}}>
          <div>
            <h2>Distribución geográfica · {CF.HS[hs].label}</h2>
            <p>Choroplético por país destino · pulsa un mercado para abrir el desglose</p>
          </div>
          <div className="cf-legend">
            <span>Intensidad</span>
            <div className="cf-legend-scale">
              {["#B6D0FF","#82AEFF","#4F8BFF","#2A6BF7","#173FB0","#0B1F5C"].map(c => (
                <span key={c} style={{background: c}} />
              ))}
            </div>
            <span className="cf-legend-labels"><span>0</span><span>·</span><span>{CF.fmtVal(max, metric)}</span></span>
          </div>
        </div>

        <div className="cf-maplibre-container" ref={containerRef} />

        {hover && (
          <div className="cf-map-tooltip" style={{
            left: Math.min(tipPos.x + 14, window.innerWidth - 220),
            top: tipPos.y - 80,
          }}>
            <div className="name">{hover.name} {!hover.noData && <span style={{opacity:.55, fontWeight:500, fontSize:11}}>· {hover.continent}</span>}</div>
            {hover.isOrigin
              ? null
              : hover.noData
              ? <div className="row" style={{opacity:.6, fontSize:11, marginTop:2}}>Sin datos de exportación</div>
              : <>
                  <div className="row"><span className="k">{CF.metricLabel(metric)}</span> <span className="v">{CF.fmtVal(hover.value, metric)}</span></div>
                  <div className="row"><span className="k">Cuota</span> <span className="v">{CF.fmtPct(hover.value / total)}</span></div>
                  <div className="row"><span className="k">Ranking</span> <span className="v">#{rows.findIndex(r => r.iso === hover.iso) + 1} / {rows.length}</span></div>
                </>
            }
          </div>
        )}
      </div>

      <div className="cf-panel" style={{marginTop:18}}>
        <div className="cf-panel-head">
          <div>
            <h2>Ranking de destinos · Top 15</h2>
            <p>Cuota sobre el total exportado en el período</p>
          </div>
        </div>
        <div className="cf-clist">
          {rows.slice(0, 15).map((c, i) => (
            <div
              key={c.iso}
              className={"cf-crow" + (selected === c.iso ? " selected" : "")}
              onClick={() => setSelected(c.iso)}
            >
              <span className="rank">{String(i + 1).padStart(2, "0")}</span>
              <span className="name">
                {c.name}
                {c.eu && <span className="eu">UE</span>}
                <span style={{color:"var(--xn-fg-4)", fontSize:11, marginLeft:6}}>{c.continent}</span>
              </span>
              <span className="val">{CF.fmtVal(c.value, metric)}</span>
              <div className="bar"><span style={{width: `${(c.value / max) * 100}%`}} /></div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

window.WorldMapView = WorldMapView;
window.useWorldData = useWorldData;
window.numToIso = numToIso;
window.buildFillExpr = buildFillExpr;
