document.addEventListener("DOMContentLoaded", () => {
 const svg = d3.select("#map");
 let projection, path;
 let geoDataGlobal = null;
 let stateToSafe = {};
 let currentActiveName = null;
 let syncingFromMap = false; // Flag to stop recursive calls when map initiates the slide change
 let hoverActiveName = null;

 function safeNameFromLabel(name) {
  return String(name || "").toLowerCase().replace(/\s+/g, "-");
 }

 // ---------- SWIPER HANDLING ----------
 function getOrInitSwiper() {  
  const el = document.querySelector("#map_slider");
  if (!el) return null;

  if (window.mapSwiper && !window.mapSwiper.destroyed) return window.mapSwiper;

  window.mapSwiper = new Swiper("#map_slider", {
   slidesPerView: 3,
   spaceBetween: 20,
   loop: false,
  //  autoplay:true,
   observer: true,
   observeParents: true,
   navigation: {
    nextEl: ".custom_slider_controls .map_slide_next",
    prevEl: ".custom_slider_controls .map_slide_prev",
   },
   breakpoints: {
    0: { slidesPerView: 1, spaceBetween: 5 },
    767: { slidesPerView: 2, spaceBetween: 10 },
    991: { slidesPerView: 3 },
   },
   on: {
    init(swiper) {
     updateArrows(swiper);
     if (swiper.slides.length > 0) {
      activateStateFromSlide(swiper);
     }
    },
    // FIX: Use slideChange for instant state synchronization from the slider.
    slideChange(swiper) { 
     // Only sync map state if the slide change was NOT initiated by a map click.
     if (!syncingFromMap) {
      activateStateFromSlide(swiper);
     }
     updateArrows(swiper);
    },
    // Ensure arrows update at the end of transition
    slideChangeTransitionEnd(swiper) {
     updateArrows(swiper);
    },
   },
  });

  return window.mapSwiper;
 }

 function updateArrows(swiper) {
  const prev = document.querySelector(".custom_slider_controls .map_slide_prev");
  const next = document.querySelector(".custom_slider_controls .map_slide_next");

  if (!prev || !next) return;

  if (swiper.isBeginning) {
   prev.classList.add("swiper-button-disabled");
   prev.style.pointerEvents = "none";
   prev.style.opacity = "0.3";
  } else {
   prev.classList.remove("swiper-button-disabled");
   prev.style.pointerEvents = "auto";
   prev.style.opacity = "1";
  }

  if (swiper.isEnd) {
   next.classList.add("swiper-button-disabled");
   next.style.pointerEvents = "none";
   next.style.opacity = "0.3";
  } else {
   next.classList.remove("swiper-button-disabled");
   next.style.pointerEvents = "auto";
   next.style.opacity = "1";
  }
 }

 // ---------- MAP ⇄ SLIDER SYNC ----------
 function activateStateFromSlide(swiper) {
  if (!swiper) swiper = window.mapSwiper;
  if (!swiper) return;

  const realIndex = swiper.realIndex || swiper.activeIndex;
  const slides = document.querySelectorAll("#map_slider .swiper-slide");
  const activeSlide = slides[realIndex];
  const safeName = activeSlide?.getAttribute("data-state")?.trim()?.toLowerCase();
  if (!safeName) return;

  // Ensure we don't re-activate the same state
  if (currentActiveName === safeName) return;

  // Activate map state (second argument false prevents activating the slide again)
  setActiveBySafeName(safeName, false); 
 }

 function activateSlideByState(safeName) {
  if (!safeName) return;
  const swiper = getOrInitSwiper();
  if (!swiper) return;

  const slides = Array.from(document.querySelectorAll("#map_slider .swiper-slide"));
  const targetIndex = slides.findIndex(slide =>
   (slide.getAttribute("data-state") || "").trim().toLowerCase() === safeName
  );
  if (targetIndex === -1) return;

  if (swiper.activeIndex === targetIndex) return;

  // FIX: Set flag before sliding to prevent map re-activation by the slideChange event
  syncingFromMap = true;
  swiper.slideTo(targetIndex, 400);
  // Clear the flag after the transition time plus a buffer
  setTimeout(() => (syncingFromMap = false), 420); 
 }

 // ---------- MAP HIGHLIGHT / INTERACTION ----------
 function setActiveBySafeName(safeName, moveSlide = true) {
  d3.selectAll(".label_group").classed("active", false);
  d3.selectAll("path.m_state").classed("active", false);

  if (!safeName) {
   currentActiveName = null;
   return;
  }
    
  // Prevent redundant map updates if the state is already active
  if (currentActiveName === safeName && !moveSlide) return;

  d3.selectAll(".label_group." + safeName).classed("active", true);
  d3.selectAll("path.m_state").each(function(d) {
   let m_stateProp = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
   m_stateProp = m_stateProp.toLowerCase().trim();
   if (stateToSafe[m_stateProp] === safeName)
    d3.select(this).classed("active", true);
  });

  currentActiveName = safeName;
  if (moveSlide) activateSlideByState(safeName); // Triggers slider sync
 }

 function setTemporaryHover(safeName) {
  if (!safeName || safeName === currentActiveName) return;

  if (hoverActiveName && hoverActiveName !== currentActiveName) {
   d3.selectAll(".label_group." + hoverActiveName).classed("active", false);
   d3.selectAll("path.m_state").each(function(d) {
    let m = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
    if (stateToSafe[m.toLowerCase().trim()] === hoverActiveName)
     d3.select(this).classed("active", false);
   });
  }

  d3.selectAll(".label_group." + safeName).classed("active", true);
  d3.selectAll("path.m_state").each(function(d) {
   let m = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
   if (stateToSafe[m.toLowerCase().trim()] === safeName)
    d3.select(this).classed("active", true);
  });

  hoverActiveName = safeName;
 }

 function clearTemporaryHover() {
  if (hoverActiveName && hoverActiveName !== currentActiveName) {
   d3.selectAll(".label_group." + hoverActiveName).classed("active", false);
   d3.selectAll("path.m_state").each(function(d) {
    let m = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
    if (stateToSafe[m.toLowerCase().trim()] === hoverActiveName)
     d3.select(this).classed("active", false);
   });
  }
  hoverActiveName = null;
 }

 function attachInteractions() {
  d3.selectAll("path.m_state").on(".map", null);
  d3.selectAll(".label_group").on(".map", null);

  d3.selectAll("path.m_state")
   .on("mouseover.map", function(event, d) {
    const n = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
    const safe = stateToSafe[n.toLowerCase().trim()] || safeNameFromLabel(n);
    setTemporaryHover(safe);
   })
   .on("mouseout.map", clearTemporaryHover)
   .on("click.map", function(event, d) {
    const n = (d.properties && (d.properties.NAME_1 || d.properties.name)) || "";
    const safe = stateToSafe[n.toLowerCase().trim()] || safeNameFromLabel(n);
    setActiveBySafeName(safe, true); // moveSlide = true to sync slider
   });

  d3.selectAll(".label_group")
   .on("mouseover.map", function() {
    const classes = (this.getAttribute("class") || "").split(/\s+/);
    const safe = classes.find(c => c !== "label_group" && c !== "active");
    setTemporaryHover(safe);
   })
   .on("mouseout.map", clearTemporaryHover)
   .on("click.map", function() {
    const classes = (this.getAttribute("class") || "").split(/\s+/);
    const safe = classes.find(c => c !== "label_group" && c !== "active");
    setActiveBySafeName(safe, true); // moveSlide = true to sync slider
   });
 }

 // ---------- LABEL DRAWING ----------
 function drawLabel({ svg, projection, center, name, lat, lng, hDir, hLen, vDir, vLen }) {
  const [cx, cy] = lat && lng ? projection([lng, lat]) : center;
  const parent = document.getElementById("map-wrapper");
  const svgWidth = parent.clientWidth;
  const scale = svgWidth / 1200;
  const dotRadius = 3 * scale;
  const h = hLen * scale;
  const v = vLen * scale;
  const fontSize = 14 * scale;
  const padding = 10 * scale;
  const boxHeight = 26 * scale;
  const safeName = safeNameFromLabel(name);

  const group = svg.append("g").attr("class", "label_group " + safeName);
  group.append("circle").attr("class", "location_dot").attr("cx", cx).attr("cy", cy).attr("r", dotRadius);

  const hx = hDir === "right" ? cx + h : cx - h;
  group.append("line").attr("class", "connector_line").attr("x1", cx).attr("y1", cy).attr("x2", hx).attr("y2", cy);

  const vy = vDir === "down" ? cy + v : cy - v;
  group.append("line").attr("class", "connector_line").attr("x1", hx).attr("y1", cy).attr("x2", hx).attr("y2", vy);

  const labelX = hx;
  const labelY = vy;
  const boxWidth = name.length * (7 * scale) + padding * 3;

  group.append("rect").attr("class", "label_box").attr("x", labelX - boxWidth / 2).attr("y", labelY - boxHeight / 2)
   .attr("width", boxWidth).attr("height", boxHeight).attr("rx", 14 * scale);

  group.append("text").attr("class", "label_text").attr("x", labelX).attr("y", labelY)
   .attr("dominant-baseline", "middle").attr("text-anchor", "middle").style("font-size", fontSize + "px")
   .text(name);
 }

 // ---------- LABEL CONFIGS ----------
 const labelConfigs = [
  { m_state: "Perlis", name: "Perlis", lat: 6.610376, lng: 100.240903, hDir: "left", hLen: 10, vDir: "up", vLen: 30 },
  { m_state: "Kedah", name: "Kedah", lat: 6.111422, lng: 100.9312, hDir: "right", hLen: 50, vDir: "up", vLen: 30 },
  { m_state: "Penang", name: "Penang", lat: 5.285864, lng: 100.493668, hDir: "left", hLen: 30, vDir: "down", vLen: 50 },
  { m_state: "Perak", name: "Perak", lat: 4.099753, lng: 100.907049, hDir: "left", hLen: 60, vDir: "down", vLen: 1 },
  { m_state: "Kelantan", name: "Kelantan", lat: 6.012705, lng: 102.250905, hDir: "right", hLen: 120, vDir: "up", vLen: 0 },
  { m_state: "Terengganu", name: "Terengganu", lat: 5.044188, lng: 102.997404, hDir: "right", hLen: 120, vDir: "up", vLen: 0 },
  { m_state: "Selangor", name: "Selangor", lat: 3.613306, lng: 101.184196, hDir: "left", hLen: 74, vDir: "down", vLen: 1 },
  { m_state: "KualaLumpur", name: "Kuala Lumpur", lat: 3.152954, lng: 101.691444, hDir: "left", hLen: 80, vDir: "down", vLen: 30 },
  { m_state: "Putrajaya", name: "Putrajaya", lat: 2.935609, lng: 101.692961, hDir: "left", hLen: 13, vDir: "down", vLen: 70 },
  { m_state: "Melaka", name: "Melaka", lat: 2.297552, lng: 102.28276, hDir: "right", hLen: 13, vDir: "down", vLen: 70 },
  { m_state: "NegeriSembilan", name: "Negeri Sembilan", lat: 2.962658, lng: 102.248178, hDir: "right", hLen: 190, vDir: "up", vLen: 30 },
  { m_state: "Pahang", name: "Pahang", lat: 3.880965, lng: 102.591956, hDir: "right", hLen: 160, vDir: "up", vLen: 0 },
  { m_state: "Johor", name: "Johor", lat: 1.895016, lng: 103.859798, hDir: "right", hLen: 65, vDir: "up", vLen: 0 },
  { m_state: "Labuan", name: "Labuan", lat: 5.280694, lng: 111.183774, hDir: "left", hLen: 60, vDir: "up", vLen: 20 },
  { m_state: "Sarawak", name: "Sarawak", lat: 2.88229, lng: 108.846506, hDir: "left", hLen: 60, vDir: "up", vLen: 70 },
  { m_state: "Sabah", name: "Sabah", lat: 5.873501, lng: 112.669104, hDir: "left", hLen: 60, vDir: "up", vLen: 70 },
 ];

 const baseURL = window.location.origin;
 
 const geoJsonUrl = `${baseURL}/assets/map/malaysia_states.json`;
 d3.json(geoJsonUrl).then((geoData) => {
  geoDataGlobal = geoData;

  // Coordinate offset for East Malaysia (Sabah, Sarawak, Labuan) for better visual grouping
  geoData.features.forEach(f => {
   const n = f.properties.NAME_1 || f.properties.name;
   if (["Sabah", "Sarawak", "Labuan"].includes(n)) {
    if (f.geometry && Array.isArray(f.geometry.coordinates)) {
     // Assuming a simple 4 degree offset for visualization purposes
     f.geometry.coordinates = f.geometry.coordinates.map(poly =>
      poly.map(ring => ring.map(([x, y]) => [x - 4, y]))
     );
    }
   }
  });

  function render() {
   d3.selectAll("#map > *").remove();

   const parent = document.getElementById("map-wrapper");
   const w = parent.clientWidth;
   const h = parent.clientHeight;

   projection = d3.geoMercator().fitSize([w, h], geoData);
   path = d3.geoPath().projection(projection);

   svg.selectAll("path.m_state")
    .data(geoData.features)
    .enter()
    .append("path")
    .attr("class", "m_state")
    .attr("d", path);

   stateToSafe = {};
   labelConfigs.forEach(L => stateToSafe[L.m_state.toLowerCase().trim()] = safeNameFromLabel(L.name));

   labelConfigs.forEach(L => {
    const feature = geoData.features.find(f => {
     const n = (f.properties && (f.properties.NAME_1 || f.properties.name)) || "";
     return n.toLowerCase().trim() === String(L.m_state).toLowerCase().trim();
    });
    if (!feature) return;
    const center = path.centroid(feature);

    drawLabel({
     svg,
     projection,
     center,
     name: L.name,
     lat: L.lat,
     lng: L.lng,
     hDir: L.hDir,
     hLen: L.hLen,
     vDir: L.vDir,
     vLen: L.vLen,
    });
   });

   attachInteractions();
   const swiper = getOrInitSwiper();
   if (currentActiveName) setActiveBySafeName(currentActiveName);
  }

  render();

  // Debounced resize handler for responsiveness
  window.addEventListener("resize", () => {
   if (window._malaysia_map_resize_timer) clearTimeout(window._malaysia_map_resize_timer);
   window._malaysia_map_resize_timer = setTimeout(() => {
    render();
    window._malaysia_map_resize_timer = null;
   }, 120);
  });
 });

 // Global function exposure for external calls if needed
 window.__setActiveBySafeName = function(name) {
  setActiveBySafeName(name);
 };
});