// ===============================
// KONFIGURASI API
// ===============================
const API = {
  spbu: 'api/spbu.php',
  jalan: 'api/jalan.php',
  parsil: 'api/parsil.php'
};

// ===============================
// WARNA TEMA
// ===============================
const COLORS = {
  spbu24:    { fill: '#22c55e', stroke: '#15803d', glow: 'rgba(34,197,94,.35)' },
  spbuLtd:   { fill: '#f87171', stroke: '#dc2626', glow: 'rgba(248,113,113,.35)' },
  jalanNasional: '#f97316',
  jalanProvinsi:  '#3b82f6',
  jalanKabupaten: '#10b981',
  SHM: { stroke: '#d97706', fill: '#fef3c7' },
  HGB: { stroke: '#8b5cf6', fill: '#ede9fe' },
  HGU: { stroke: '#0891b2', fill: '#cffafe' },
  HP:  { stroke: '#ec4899', fill: '#fce7f3' },
};

// ===============================
// STATE GLOBAL
// ===============================
let map;
let layers = { spbu: null, jalan: null, parsil: null };

let currentGeom = null;
let drawPoints = [];
let tempLayer = null;
let savedDrawPoints = [];

let allSpbu = [], allJalan = [], allParsil = [];
let isDraggingMarker = false;

let vertexMarkers = [];
let undoStack = [];
let redoStack = [];

// Edit-in-place state
let editingFeature = null;   // { type:'jalan'|'parsil', id, layer, geomLayer, vertexMarkers }

// ===============================
// CUSTOM CONFIRM DIALOG
// ===============================
function showConfirm(message, title = 'Konfirmasi') {
  return new Promise(resolve => {
    const overlay = document.getElementById('confirm-overlay');
    document.getElementById('confirm-title').textContent = title;
    document.getElementById('confirm-message').textContent = message;
    overlay.classList.add('open');

    const btnOk = document.getElementById('confirm-ok');
    const btnCancel = document.getElementById('confirm-cancel');

    function cleanup() {
      overlay.classList.remove('open');
      btnOk.removeEventListener('click', onOk);
      btnCancel.removeEventListener('click', onCancel);
    }
    function onOk() { cleanup(); resolve(true); }
    function onCancel() { cleanup(); resolve(false); }

    btnOk.addEventListener('click', onOk);
    btnCancel.addEventListener('click', onCancel);
  });
}

// ===============================
// TOAST NOTIFICATION
// ===============================
function showToast(msg, type = 'ok') {
  const container = document.getElementById('toasts');
  const toast = document.createElement('div');
  toast.className = `toast ${type}`;
  toast.innerHTML = (type === 'ok' ? '✅ ' : '❌ ') + msg;
  container.appendChild(toast);
  setTimeout(() => toast.remove(), 3200);
}

// ===============================
// BUAT ICON SVG MARKER SPBU
// ===============================
function makeSpbuIcon(is24) {
  const c = is24 ? COLORS.spbu24 : COLORS.spbuLtd;
  const svg = `
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="40" viewBox="0 0 32 40">
      <defs>
        <filter id="glow-${is24 ? 'g' : 'r'}" x="-40%" y="-40%" width="180%" height="180%">
          <feGaussianBlur stdDeviation="2.5" result="blur"/>
          <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
        </filter>
      </defs>
      <ellipse cx="16" cy="38" rx="7" ry="2.5" fill="rgba(0,0,0,0.18)"/>
      <path d="M16 2 C9.4 2 4 7.4 4 14 C4 22 16 36 16 36 C16 36 28 22 28 14 C28 7.4 22.6 2 16 2Z"
            fill="${c.fill}" stroke="${c.stroke}" stroke-width="1.8"
            filter="url(#glow-${is24 ? 'g' : 'r'})"/>
      <circle cx="16" cy="14" r="7" fill="white" opacity="0.92"/>
      <text x="16" y="18.5" text-anchor="middle" font-size="10" font-family="sans-serif">⛽</text>
    </svg>`;

  return L.divIcon({
    html: svg,
    className: '',
    iconSize: [32, 40],
    iconAnchor: [16, 38],
    popupAnchor: [0, -38]
  });
}

// ===============================
// INIT MAP
// ===============================
function initMap() {
  map = L.map('map').setView([-0.0263, 109.3425], 14);

  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '© OpenStreetMap',
    maxZoom: 19
  }).addTo(map);

  map.on('click', onMapClick);

  map.on('mousemove', e => {
    document.getElementById('cur-lat').innerText = e.latlng.lat.toFixed(5);
    document.getElementById('cur-lng').innerText = e.latlng.lng.toFixed(5);
  });
}

// ===============================
// LOAD DATA
// ===============================
async function loadAllData() {
  try {
    const [spbuRes, jalanRes, parsilRes] = await Promise.all([
      fetch(API.spbu + '?action=list').then(r => r.json()),
      fetch(API.jalan + '?action=list').then(r => r.json()),
      fetch(API.parsil + '?action=list').then(r => r.json())
    ]);

    allSpbu   = spbuRes.data   || [];
    allJalan  = jalanRes.data  || [];
    allParsil = parsilRes.data || [];

    renderSpbuLayer();
    renderJalanLayer();
    renderParsilLayer();
    renderSpbuList();

  } catch (e) {
    console.error(e);
  } finally {
    document.getElementById('loading').style.display = 'none';
  }
}

// ===============================
// RENDER SPBU (POINT) — tanpa tooltip bubble
// ===============================
function renderSpbuLayer() {
  if (layers.spbu) map.removeLayer(layers.spbu);
  layers.spbu = L.layerGroup();

  allSpbu.forEach(s => {
    const is24 = s.statusbuka === 'full';
    const icon = makeSpbuIcon(is24);

    // ❌ Tidak ada .bindTooltip — bubble nama dihapus
    const marker = L.marker([s.lat, s.lng], { icon, draggable: true, title: s.namaspbu });

    marker.bindPopup(buildSpbuPopup(s));

    marker.on('click', () => {
      if (currentGeom) return;
      marker.openPopup();
    });

    marker.on('dragstart', () => {
      isDraggingMarker = true;
      marker.setOpacity(0.65);
    });

    marker.on('dragend', async () => {
      isDraggingMarker = false;
      marker.setOpacity(1);
      const newPos = marker.getLatLng();
      await updateSpbuCoordinates(s.id, newPos.lat, newPos.lng);
      s.lat = newPos.lat;
      s.lng = newPos.lng;
      marker.setPopupContent(buildSpbuPopup(s));
      showToast('Koordinat SPBU diperbarui');
    });

    layers.spbu.addLayer(marker);
  });

  layers.spbu.addTo(map);
}

function buildSpbuPopup(s) {
  const nama    = s.namaspbu || '—';
  const is24    = s.statusbuka === 'full';
  const status  = is24 ? 'Buka 24 Jam' : 'Tidak 24 Jam';
  const wa      = s.nomorwa || '—';
  const coord   = (s.lat && s.lng) ? `${Number(s.lat).toFixed(6)}, ${Number(s.lng).toFixed(6)}` : '—';
  const badgeCls = is24 ? 'bg' : 'br';

  return `
    <div class="pcard-detail">
      <div class="pcd-title" data-type="spbu">${nama}</div>
      <div class="pcd-rows">
        <div class="pcd-row">
          <span class="pcd-label">📍 Koordinat</span>
          <span class="pcd-val">${coord}</span>
        </div>
        <div class="pcd-row">
          <span class="pcd-label">⏰ Status</span>
          <span class="badge ${badgeCls}">${status}</span>
        </div>
        ${wa !== '—' ? `<div class="pcd-row"><span class="pcd-label">📱 WhatsApp</span><span class="pcd-val">${wa}</span></div>` : ''}
      </div>
      <div class="pcd-actions">
        <button class="pbtn pbtn-edit" onclick="editSpbu(${s.id})">✏️ Edit</button>
        <button class="pbtn pbtn-del"  onclick="hapusSpbu(${s.id})">🗑️ Hapus</button>
      </div>
    </div>`;
}

// ===============================
// EDIT / DELETE SPBU
// ===============================
function editSpbu(id) {
  const s = allSpbu.find(x => x.id == id);
  if (!s) return showToast('Data SPBU tidak ditemukan', 'er');
  document.getElementById('e-spbu-id').value     = s.id;
  document.getElementById('e-spbu-nama').value   = s.namaspbu  || '';
  document.getElementById('e-spbu-wa').value     = s.nomorwa   || '';
  document.getElementById('e-spbu-status').value = s.statusbuka || 'limited';
  openModal('m-edit-spbu');
}

async function hapusSpbu(id) {
  const ok = await showConfirm('Hapus SPBU ini? Tindakan tidak dapat dibatalkan.', 'Hapus SPBU');
  if (!ok) return;
  try {
    const res = await fetch(API.spbu, { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({action:'delete',id}) });
    const j = await res.json();
    if (j.status==='success') { loadAllData(); showToast('SPBU berhasil dihapus'); }
    else showToast(j.message||'Gagal hapus', 'er');
  } catch(e) { showToast('Gagal: '+e.message, 'er'); }
}

async function updateSpbu() {
  const id        = parseInt(document.getElementById('e-spbu-id').value||0);
  const namaspbu  = document.getElementById('e-spbu-nama').value;
  const nomorwa   = document.getElementById('e-spbu-wa').value;
  const statusbuka= document.getElementById('e-spbu-status').value;
  try {
    const res = await fetch(API.spbu, { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({action:'update',id,namaspbu,nomorwa,statusbuka}) });
    const j = await res.json();
    if (j.status==='success') { closeModal('m-edit-spbu'); loadAllData(); showToast('SPBU diperbarui'); }
    else showToast(j.message||'Gagal update', 'er');
  } catch(e) { showToast('Gagal: '+e.message, 'er'); }
}

async function updateSpbuCoordinates(id, lat, lng) {
  const spbu = allSpbu.find(x => x.id == id);
  if (!spbu) return;
  await fetch(API.spbu, {
    method: 'POST', headers: {'Content-Type':'application/json'},
    body: JSON.stringify({ action:'update', id, namaspbu:spbu.namaspbu, nomorwa:spbu.nomorwa, statusbuka:spbu.statusbuka, koordinat:{type:'Point', coordinates:[lng,lat]} })
  });
}

// ===============================
// RENDER LIST & STATS
// ===============================
function renderSpbuList() {
  const el = document.getElementById('spbu-list');
  if (!el) return;

  document.getElementById('cnt-total').innerText  = allSpbu.length;
  document.getElementById('cnt-24').innerText     = allSpbu.filter(s=>s.statusbuka==='full').length;
  document.getElementById('cnt-jalan').innerText  = allJalan.length;
  document.getElementById('cnt-parsil').innerText = allParsil.length;

  if (!allSpbu.length) { el.innerHTML = '<div class="empty">Belum ada SPBU tercatat.</div>'; return; }

  el.innerHTML = allSpbu.map(s => {
    const lat = parseFloat(s.lat)||0, lng = parseFloat(s.lng)||0;
    const dot = s.statusbuka==='full' ? 'dot-green' : 'dot-red';
    return `
      <div class="spbu-item" onclick="flyTo(${lat},${lng})">
        <div class="si-top">
          <div class="si-name"><span class="si-dot ${dot}"></span>${s.namaspbu||'—'}</div>
          <div class="si-actions" onclick="event.stopPropagation()">
            <button class="ib edt" title="Edit"  onclick="editSpbu(${s.id})">✏️</button>
            <button class="ib del" title="Hapus" onclick="hapusSpbu(${s.id})">🗑️</button>
          </div>
        </div>
      </div>`;
  }).join('');
}

function flyTo(lat, lng) {
  if (map) map.setView([lat, lng], 16);
}

// ===============================
// SEARCH
// ===============================
function setupSearch() {
  const input = document.getElementById('search-input');
  const results = document.getElementById('search-results');
  if (!input || !results) return;

  input.addEventListener('input', () => {
    const q = input.value.trim().toLowerCase();
    results.innerHTML = '';
    if (!q) { results.classList.remove('open'); return; }

    const hits = [];

    allSpbu.forEach(s => {
      if ((s.namaspbu||'').toLowerCase().includes(q)) {
        hits.push({ label: s.namaspbu, sub: 'SPBU · Point', icon: '⛽', action: () => { flyTo(s.lat, s.lng); input.value=''; results.classList.remove('open'); } });
      }
    });
    allJalan.forEach(j => {
      if ((j.nama||'').toLowerCase().includes(q)) {
        hits.push({ label: j.nama, sub: `Jalan ${j.status||''}`, icon: '🛣️', action: () => {
          try { const geom = JSON.parse(j.geom); const coords = geom.coordinates; const mid = coords[Math.floor(coords.length/2)]; map.setView([mid[1],mid[0]],16); } catch(e){}
          input.value=''; results.classList.remove('open');
        }});
      }
    });
    allParsil.forEach(p => {
      if ((p.nama||'').toLowerCase().includes(q)) {
        hits.push({ label: p.nama, sub: `Parsil · ${p.status_kepemilikan||'SHM'}`, icon: '🗺️', action: () => {
          try { const geom = JSON.parse(p.geom); const coords = geom.coordinates[0]; const cx = coords.reduce((a,c)=>a+c[0],0)/coords.length; const cy = coords.reduce((a,c)=>a+c[1],0)/coords.length; map.setView([cy,cx],17); } catch(e){}
          input.value=''; results.classList.remove('open');
        }});
      }
    });

    if (!hits.length) {
      results.innerHTML = '<div class="sr-empty">Tidak ada hasil</div>';
    } else {
      results.innerHTML = hits.slice(0,8).map((h,i) => `
        <div class="sr-item" data-idx="${i}">
          <span class="sr-icon">${h.icon}</span>
          <div class="sr-text">
            <div class="sr-label">${h.label}</div>
            <div class="sr-sub">${h.sub}</div>
          </div>
        </div>`).join('');
      results.querySelectorAll('.sr-item').forEach((el,i) => {
        el.addEventListener('click', () => hits[i].action());
      });
    }
    results.classList.add('open');
  });

  document.addEventListener('click', e => {
    if (!e.target.closest('#search-wrap')) results.classList.remove('open');
  });
}

// ===============================
// RENDER JALAN (LINE)
// ===============================
function renderJalanLayer() {
  if (layers.jalan) map.removeLayer(layers.jalan);

  const geojson = allJalan.map(j => ({
    type: 'Feature',
    geometry: JSON.parse(j.geom),
    properties: j
  }));

  layers.jalan = L.geoJSON(geojson, {
    style: f => {
      const s = f.properties.status;
      let color = COLORS.jalanKabupaten;
      if (s === 'nasional') color = COLORS.jalanNasional;
      else if (s === 'provinsi') color = COLORS.jalanProvinsi;
      return { color, weight: 4, opacity: 0.9 };
    },
    onEachFeature: (f, layer) => {
      layer.bindPopup(buildJalanPopup(f.properties));
      layer.on('click', e => {
        if (currentGeom) return;
        L.DomEvent.stopPropagation(e);
        layer.openPopup();
      });
    }
  }).addTo(map);
}

function buildJalanPopup(p) {
  const nama   = p.nama || '—';
  const status = p.status || 'kabupaten';
  let statusLabel='Kabupaten', badgeClass='bb-green';
  if (status==='nasional')  { statusLabel='Nasional';  badgeClass='bb-orange'; }
  else if (status==='provinsi') { statusLabel='Provinsi'; badgeClass='bb-blue'; }
  const panjang = p.panjang_meter ? Number(p.panjang_meter).toFixed(2)+' m' : '—';

  return `
    <div class="pcard-detail">
      <div class="pcd-title" data-type="jalan">${nama}</div>
      <div class="pcd-rows">
        <div class="pcd-row">
          <span class="pcd-label">🛣️ Status</span>
          <span class="badge ${badgeClass}">${statusLabel}</span>
        </div>
        <div class="pcd-row">
          <span class="pcd-label">📏 Panjang</span>
          <span class="pcd-val">${panjang}</span>
        </div>
      </div>
      <div class="pcd-actions">
        <button class="pbtn pbtn-edit" onclick="editJalan(${p.id})">✏️ Edit Atribut</button>
        <button class="pbtn pbtn-move" onclick="startEditGeomJalan(${p.id})">📐 Edit Geometri</button>
        <button class="pbtn pbtn-del"  onclick="hapusJalan(${p.id})">🗑️ Hapus</button>
      </div>
    </div>`;
}

function editJalan(id) {
  const j = allJalan.find(x=>x.id==id);
  if (!j) return showToast('Data jalan tidak ditemukan', 'er');
  document.getElementById('e-jalan-id').value  = j.id;
  document.getElementById('e-j-nama').value    = j.nama   || '';
  document.getElementById('e-j-status').value  = j.status || 'kabupaten';
  document.getElementById('e-j-panjang').value = j.panjang_meter || '';
  openModal('m-edit-jalan');
}

async function hapusJalan(id) {
  const ok = await showConfirm('Hapus jalan ini? Tindakan tidak dapat dibatalkan.', 'Hapus Jalan');
  if (!ok) return;
  try {
    const res = await fetch(API.jalan, { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({action:'delete',id}) });
    const j = await res.json();
    if (j.status==='success') { loadAllData(); showToast('Jalan berhasil dihapus'); }
    else showToast(j.message||'Gagal hapus', 'er');
  } catch(e) { showToast('Gagal: '+e.message, 'er'); }
}

async function updateJalan() {
  const id           = parseInt(document.getElementById('e-jalan-id').value||0);
  const nama         = document.getElementById('e-j-nama').value;
  const status       = document.getElementById('e-j-status').value;
  const panjang_meter= parseFloat(document.getElementById('e-j-panjang').value);
  try {
    const res = await fetch(API.jalan, { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({action:'update',id,nama,status,panjang_meter}) });
    const j = await res.json();
    if (j.status==='success') { closeModal('m-edit-jalan'); loadAllData(); showToast('Jalan diperbarui'); }
    else showToast(j.message||'Gagal update', 'er');
  } catch(e) { showToast('Gagal: '+e.message, 'er'); }
}

// ===============================
// EDIT GEOMETRI JALAN (drag vertex)
// ===============================
function startEditGeomJalan(id) {
  map.closePopup();
  stopEditGeom(); // clear any existing

  const j = allJalan.find(x => x.id == id);
  if (!j) return;
  const geom = JSON.parse(j.geom);
  let coords = geom.coordinates.map(c => [c[1], c[0]]); // [lat,lng]

  // Highlight line
  const geomLayer = L.polyline(coords, { color: '#f97316', weight: 4, dashArray: '8,5', opacity: 1 }).addTo(map);

  const vms = [];
  const updatePolyline = () => {
    const pts = vms.map(vm => vm.getLatLng());
    geomLayer.setLatLngs(pts);
    // Update panjang preview
    const turfCoords = pts.map(p => [p.lng, p.lat]);
    if (turfCoords.length >= 2) {
      const panjang = turf.length(turf.lineString(turfCoords), { units: 'meters' });
      document.getElementById('geom-edit-info').textContent = `Panjang: ${panjang.toFixed(2)} m`;
    }
  };

  coords.forEach((c, i) => {
    const vm = L.marker(c, {
      draggable: true,
      icon: vertexIcon()
    }).addTo(map);
    vm.on('drag', updatePolyline);
    vms.push(vm);
  });

  editingFeature = { type: 'jalan', id, geomLayer, vms };
  showEditGeomToolbar('Drag titik untuk edit geometri jalan');
}

// ===============================
// RENDER PARSIL (POLYGON)
// ===============================
function renderParsilLayer() {
  if (layers.parsil) map.removeLayer(layers.parsil);

  const geojson = allParsil.map(p => ({
    type: 'Feature',
    geometry: JSON.parse(p.geom),
    properties: p
  }));

  layers.parsil = L.geoJSON(geojson, {
    style: f => {
      const c = COLORS[f.properties.status_kepemilikan] || COLORS.SHM;
      return { color: c.stroke, fillColor: c.fill, weight: 2.5, fillOpacity: 0.45 };
    },
    onEachFeature: (f, layer) => {
      layer.bindPopup(buildParsilPopup(f.properties));
      layer.on('click', e => {
        if (currentGeom) return;
        L.DomEvent.stopPropagation(e);
        layer.openPopup();
      });
    }
  }).addTo(map);
}

function buildParsilPopup(props) {
  const nama   = props.nama || '—';
  const status = props.status_kepemilikan || 'SHM';
  const luas   = props.luas_m2 ? Number(props.luas_m2).toFixed(2)+' m²' : '—';
  const badgeMap = { SHM:'bp-shm', HGB:'bp-hgb', HGU:'bp-hgu', HP:'bp-hp' };
  const badgeClass = badgeMap[status] || 'bp-shm';

  return `
    <div class="pcard-detail">
      <div class="pcd-title" data-type="parsil">${nama}</div>
      <div class="pcd-rows">
        <div class="pcd-row">
          <span class="pcd-label">📋 Kepemilikan</span>
          <span class="badge ${badgeClass}">${status}</span>
        </div>
        <div class="pcd-row">
          <span class="pcd-label">📐 Luas</span>
          <span class="pcd-val">${luas}</span>
        </div>
      </div>
      <div class="pcd-actions">
        <button class="pbtn pbtn-edit" onclick="editParsil(${props.id})">✏️ Edit Atribut</button>
        <button class="pbtn pbtn-move" onclick="startEditGeomParsil(${props.id})">📐 Edit Geometri</button>
        <button class="pbtn pbtn-del"  onclick="hapusParsil(${props.id})">🗑️ Hapus</button>
      </div>
    </div>`;
}

function editParsil(id) {
  const p = allParsil.find(x=>x.id==id);
  if (!p) return showToast('Data parsil tidak ditemukan', 'er');
  document.getElementById('e-parsil-id').value  = p.id;
  document.getElementById('e-p-nama').value     = p.nama   || '';
  document.getElementById('e-p-status').value   = p.status_kepemilikan || 'SHM';
  document.getElementById('e-p-luas').value     = p.luas_m2 || '';
  openModal('m-edit-parsil');
}

async function hapusParsil(id) {
  const ok = await showConfirm('Hapus parsil ini? Tindakan tidak dapat dibatalkan.', 'Hapus Parsil');
  if (!ok) return;
  try {
    const res = await fetch(API.parsil, { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({action:'delete',id}) });
    const j = await res.json();
    if (j.status==='success') { loadAllData(); showToast('Parsil berhasil dihapus'); }
    else showToast(j.message||'Gagal hapus', 'er');
  } catch(e) { showToast('Gagal: '+e.message, 'er'); }
}

async function updateParsil() {
  const id               = parseInt(document.getElementById('e-parsil-id').value||0);
  const nama             = document.getElementById('e-p-nama').value;
  const status_kepemilikan= document.getElementById('e-p-status').value;
  const luas_m2          = parseFloat(document.getElementById('e-p-luas').value);
  try {
    const res = await fetch(API.parsil, { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({action:'update',id,nama,status_kepemilikan,luas_m2}) });
    const j = await res.json();
    if (j.status==='success') { closeModal('m-edit-parsil'); loadAllData(); showToast('Parsil diperbarui'); }
    else showToast(j.message||'Gagal update', 'er');
  } catch(e) { showToast('Gagal: '+e.message, 'er'); }
}

// ===============================
// EDIT GEOMETRI PARSIL (drag vertex)
// ===============================
function startEditGeomParsil(id) {
  map.closePopup();
  stopEditGeom();

  const p = allParsil.find(x => x.id == id);
  if (!p) return;
  const geom = JSON.parse(p.geom);
  // outer ring, drop closing duplicate
  let coords = geom.coordinates[0].slice(0, -1).map(c => [c[1], c[0]]);

  const geomLayer = L.polygon(coords, {
    color: '#8b5cf6', fillColor: '#ede9fe', weight: 2.5,
    dashArray: '8,5', fillOpacity: 0.3
  }).addTo(map);

  const vms = [];
  const updatePolygon = () => {
    const pts = vms.map(vm => vm.getLatLng());
    geomLayer.setLatLngs(pts);
    const turfCoords = [...pts.map(p => [p.lng, p.lat])];
    turfCoords.push(turfCoords[0]);
    if (turfCoords.length >= 4) {
      const luas = turf.area(turf.polygon([turfCoords]));
      document.getElementById('geom-edit-info').textContent = `Luas: ${luas.toFixed(2)} m²`;
    }
  };

  coords.forEach(c => {
    const vm = L.marker(c, { draggable: true, icon: vertexIcon() }).addTo(map);
    vm.on('drag', updatePolygon);
    vms.push(vm);
  });

  editingFeature = { type: 'parsil', id, geomLayer, vms };
  showEditGeomToolbar('Drag titik untuk edit geometri parsil');
}

// ===============================
// VERTEX ICON
// ===============================
function vertexIcon() {
  return L.divIcon({
    html: `<div style="width:14px;height:14px;background:#fff;border:2.5px solid #6366f1;border-radius:50%;box-shadow:0 2px 8px rgba(99,102,241,.4);cursor:grab;"></div>`,
    className: '',
    iconSize: [14, 14],
    iconAnchor: [7, 7]
  });
}

// ===============================
// GEOM EDIT TOOLBAR
// ===============================
function showEditGeomToolbar(hint) {
  const tb = document.getElementById('geom-edit-toolbar');
  document.getElementById('geom-edit-hint').textContent = hint;
  document.getElementById('geom-edit-info').textContent = '';
  tb.classList.add('visible');
}

function stopEditGeom() {
  if (!editingFeature) return;
  if (editingFeature.geomLayer) map.removeLayer(editingFeature.geomLayer);
  editingFeature.vms.forEach(vm => { try { map.removeLayer(vm); } catch(e){} });
  editingFeature = null;
  document.getElementById('geom-edit-toolbar').classList.remove('visible');
}

async function saveEditGeom() {
  if (!editingFeature) return;
  const { type, id, vms } = editingFeature;
  const pts = vms.map(vm => vm.getLatLng());

  try {
    if (type === 'jalan') {
      const coords = pts.map(p => [p.lng, p.lat]);
      const panjang = turf.length(turf.lineString(coords), { units: 'meters' });
      const j = allJalan.find(x => x.id == id);
      const res = await fetch(API.jalan, {
        method: 'POST', headers: {'Content-Type':'application/json'},
        body: JSON.stringify({
          action: 'update', id,
          nama: j.nama, status: j.status,
          panjang_meter: panjang,
          geom: { type: 'LineString', coordinates: coords }
        })
      });
      const data = await res.json();
      if (data.status === 'success') { showToast('Geometri jalan diperbarui'); stopEditGeom(); loadAllData(); }
      else showToast(data.message || 'Gagal simpan', 'er');

    } else if (type === 'parsil') {
      const coords = pts.map(p => [p.lng, p.lat]);
      coords.push(coords[0]);
      const luas = turf.area(turf.polygon([coords]));
      const p = allParsil.find(x => x.id == id);
      const res = await fetch(API.parsil, {
        method: 'POST', headers: {'Content-Type':'application/json'},
        body: JSON.stringify({
          action: 'update', id,
          nama: p.nama, status_kepemilikan: p.status_kepemilikan,
          luas_m2: luas,
          geom: { type: 'Polygon', coordinates: [coords] }
        })
      });
      const data = await res.json();
      if (data.status === 'success') { showToast('Geometri parsil diperbarui'); stopEditGeom(); loadAllData(); }
      else showToast(data.message || 'Gagal simpan', 'er');
    }
  } catch(e) { showToast('Gagal: '+e.message, 'er'); }
}

// ===============================
// HANDLE MAP CLICK (DRAW)
// ===============================
function onMapClick(e) {
  if (isDraggingMarker) return;
  if (!currentGeom) return;

  if (currentGeom === 'point') {
    document.getElementById('spbu-lat').value = e.latlng.lat;
    document.getElementById('spbu-lng').value = e.latlng.lng;
    openModal('m-add-spbu');
    return;
  }

  drawPoints.push({ lat: e.latlng.lat, lng: e.latlng.lng });
  undoStack.push({ lat: e.latlng.lat, lng: e.latlng.lng });
  redoStack = [];
  drawTemp();
}

// ===============================
// GAMBAR SEMENTARA
// ===============================
function drawTemp() {
  if (tempLayer) { map.removeLayer(tempLayer); tempLayer = null; }
  vertexMarkers.forEach(m => { try { map.removeLayer(m); } catch(e){} });
  vertexMarkers = [];

  if (drawPoints.length === 0) { updateCounter(); return; }

  const latlngs = drawPoints.map(p => [p.lat, p.lng]);

  if (currentGeom === 'polyline' && drawPoints.length >= 2) {
    tempLayer = L.polyline(latlngs, { color: COLORS.jalanProvinsi, weight: 3, dashArray:'7,5', opacity:.85 }).addTo(map);
  }
  if (currentGeom === 'polygon' && drawPoints.length >= 3) {
    tempLayer = L.polygon(latlngs, { color: COLORS.SHM.stroke, weight: 2.5, dashArray:'7,5', fillColor: COLORS.SHM.fill, fillOpacity:.25 }).addTo(map);
  }

  drawPoints.forEach(p => {
    const vm = L.circleMarker([p.lat, p.lng], {
      radius: 6, color:'#fff', weight: 2.5,
      fillColor: currentGeom==='polygon' ? COLORS.SHM.stroke : COLORS.jalanProvinsi,
      fillOpacity: 1
    }).addTo(map);
    vertexMarkers.push(vm);
  });

  updateCounter();
}

// ===============================
// UNDO / REDO
// ===============================
function undoDraw() {
  if (!drawPoints.length) return;
  redoStack.push(drawPoints.pop());
  drawTemp();
}

function redoDraw() {
  if (!redoStack.length) return;
  drawPoints.push(redoStack.pop());
  drawTemp();
}

// ===============================
// SELESAI DRAW
// ===============================
function finishDrawing() {
  if (currentGeom === 'polyline') {
    if (drawPoints.length < 2) { showToast('Minimal 2 titik untuk membuat jalan!', 'er'); return; }
    finishJalanDrawing();
  } else if (currentGeom === 'polygon') {
    if (drawPoints.length < 3) { showToast('Minimal 3 titik untuk membuat parsil!', 'er'); return; }
    finishParsilDrawing();
  }
}

function finishJalanDrawing() {
  savedDrawPoints = drawPoints.map(p => ({ lat: p.lat, lng: p.lng }));
  const coords  = savedDrawPoints.map(p => [p.lng, p.lat]);
  const panjang = turf.length(turf.lineString(coords), { units:'meters' });
  document.getElementById('j-nama').value    = '';
  document.getElementById('j-status').value  = 'kabupaten';
  document.getElementById('j-panjang').value = panjang.toFixed(2);
  openModal('m-add-jalan');
}

function finishParsilDrawing() {
  savedDrawPoints = drawPoints.map(p => ({ lat: p.lat, lng: p.lng }));
  const coords = savedDrawPoints.map(p => [p.lng, p.lat]);
  coords.push(coords[0]);
  const luas = turf.area(turf.polygon([coords]));
  document.getElementById('p-nama').value   = '';
  document.getElementById('p-status').value = 'SHM';
  document.getElementById('p-luas').value   = luas.toFixed(2);
  openModal('m-add-parsil');
}

// ===============================
// SAVE SPBU
// ===============================
async function saveSpbu() {
  const lat      = parseFloat(document.getElementById('spbu-lat').value);
  const lng      = parseFloat(document.getElementById('spbu-lng').value);
  const namaspbu = document.getElementById('spbu-nama').value.trim();
  if (!namaspbu) { showToast('Nama SPBU wajib diisi!', 'er'); return; }
  if (isNaN(lat)||isNaN(lng)) { showToast('Koordinat tidak valid!', 'er'); return; }

  try {
    const res  = await fetch(API.spbu, { method:'POST', headers:{'Content-Type':'application/json'},
      body: JSON.stringify({ action:'create', namaspbu, nomorwa:document.getElementById('spbu-wa').value,
        statusbuka:document.getElementById('spbu-status').value, koordinat:{type:'Point',coordinates:[lng,lat]} }) });
    const data = await res.json();
    if (data.status!=='success') { showToast(data.message||'Gagal simpan', 'er'); return; }
    closeModal('m-add-spbu'); deactivateGeom(); loadAllData(); showToast('SPBU berhasil ditambahkan');
  } catch(e) { showToast('Error: '+e.message, 'er'); }
}

// ===============================
// SAVE JALAN
// ===============================
async function saveJalan() {
  const nama = document.getElementById('j-nama').value.trim();
  if (!nama) { showToast('Nama jalan wajib diisi!', 'er'); return; }
  if (savedDrawPoints.length < 2) { showToast('Data koordinat hilang, silakan gambar ulang.', 'er'); return; }

  try {
    const res  = await fetch(API.jalan, { method:'POST', headers:{'Content-Type':'application/json'},
      body: JSON.stringify({ action:'create', nama, status:document.getElementById('j-status').value,
        panjang_meter:parseFloat(document.getElementById('j-panjang').value),
        geom:{ type:'LineString', coordinates:savedDrawPoints.map(p=>[p.lng,p.lat]) } }) });
    const data = await res.json();
    if (data.status!=='success') { showToast(data.message||'Gagal simpan', 'er'); return; }
    closeModal('m-add-jalan'); deactivateGeom(); cancelDraw(); loadAllData(); showToast('Jalan berhasil ditambahkan');
  } catch(e) { showToast('Error: '+e.message, 'er'); }
}

// ===============================
// SAVE PARSIL
// ===============================
async function saveParsil() {
  const nama = document.getElementById('p-nama').value.trim();
  if (!nama) { showToast('Nama parsil wajib diisi!', 'er'); return; }
  if (savedDrawPoints.length < 3) { showToast('Data koordinat hilang, silakan gambar ulang.', 'er'); return; }

  const coords = savedDrawPoints.map(p => [p.lng, p.lat]);
  coords.push(coords[0]);

  try {
    const res  = await fetch(API.parsil, { method:'POST', headers:{'Content-Type':'application/json'},
      body: JSON.stringify({ action:'create', nama, status_kepemilikan:document.getElementById('p-status').value,
        luas_m2:parseFloat(document.getElementById('p-luas').value),
        geom:{ type:'Polygon', coordinates:[coords] } }) });
    const data = await res.json();
    if (data.status!=='success') { showToast(data.message||'Gagal simpan', 'er'); return; }
    closeModal('m-add-parsil'); deactivateGeom(); cancelDraw(); loadAllData(); showToast('Parsil berhasil ditambahkan');
  } catch(e) { showToast('Error: '+e.message, 'er'); }
}

// ===============================
// CONTROL DRAW
// ===============================
function cancelDraw() {
  drawPoints = []; undoStack = []; redoStack = []; savedDrawPoints = [];
  if (tempLayer) { try { map.removeLayer(tempLayer); } catch(e){} tempLayer = null; }
  vertexMarkers.forEach(m => { try { map.removeLayer(m); } catch(e){} });
  vertexMarkers = [];
  updateCounter();
  document.getElementById('draw-toolbar').classList.remove('visible');
}

function deactivateGeom() {
  currentGeom = null;
  document.querySelectorAll('.geom-btn').forEach(b => b.classList.remove('active'));
  document.getElementById('geom-hint').classList.remove('on');
  document.getElementById('map').classList.remove('crosshair-cursor');
  document.getElementById('draw-toolbar').classList.remove('visible');
}

// ===============================
// MODAL
// ===============================
function openModal(id)  { document.getElementById(id).classList.add('open'); }
function closeModal(id) { document.getElementById(id).classList.remove('open'); }

// ===============================
// COUNTER
// ===============================
function updateCounter() {
  const n = drawPoints.length;
  document.getElementById('dt-counter').innerText = n + ' titik';
  document.getElementById('btn-undo').disabled = n === 0;
  document.getElementById('btn-redo').disabled = redoStack.length === 0;
}

// ===============================
// INIT
// ===============================
document.addEventListener('DOMContentLoaded', () => {
  initMap();
  loadAllData();
  setupSearch();

  document.getElementById('btn-finish').onclick = finishDrawing;
  document.getElementById('btn-undo').onclick   = undoDraw;
  document.getElementById('btn-redo').onclick   = redoDraw;
  document.getElementById('btn-cancel-draw').onclick = () => { cancelDraw(); deactivateGeom(); };

  // Geom edit toolbar buttons
  document.getElementById('btn-geom-save').onclick   = saveEditGeom;
  document.getElementById('btn-geom-cancel').onclick = stopEditGeom;

  document.querySelectorAll('.geom-btn').forEach(btn => {
    btn.addEventListener('click', () => {
      const geom = btn.dataset.geom;
      if (currentGeom === geom) { cancelDraw(); deactivateGeom(); return; }
      cancelDraw();
      currentGeom = geom;
      document.querySelectorAll('.geom-btn').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      document.getElementById('map').classList.add('crosshair-cursor');
      const toolbar = document.getElementById('draw-toolbar');
      toolbar.classList.toggle('visible', geom==='polyline'||geom==='polygon');
      const hint     = document.getElementById('geom-hint');
      const hintText = document.getElementById('geom-hint-text');
      hint.classList.add('on');
      if (geom==='point')    hintText.innerText = 'Klik peta untuk tambah SPBU';
      if (geom==='polyline') hintText.innerText = 'Klik peta untuk menambah titik jalan, klik Selesai jika sudah';
      if (geom==='polygon')  hintText.innerText = 'Klik peta untuk menambah titik parsil, klik Selesai jika sudah';
    });
  });

  // Layer toggle
  const ldbtn     = document.getElementById('ldbtn');
  const layerMenu = document.getElementById('layer-menu');
  if (ldbtn && layerMenu) {
    ldbtn.addEventListener('click', e => { e.stopPropagation(); layerMenu.classList.toggle('open'); });
    document.addEventListener('click', () => layerMenu.classList.remove('open'));

    document.getElementById('lm-point').addEventListener('click', function() {
      this.classList.toggle('active');
      if (this.classList.contains('active')) { if (layers.spbu)   layers.spbu.addTo(map); }
      else { if (layers.spbu)   map.removeLayer(layers.spbu); }
    });
    document.getElementById('lm-jalan').addEventListener('click', function() {
      this.classList.toggle('active');
      if (this.classList.contains('active')) { if (layers.jalan)  layers.jalan.addTo(map); }
      else { if (layers.jalan)  map.removeLayer(layers.jalan); }
    });
    document.getElementById('lm-parsil').addEventListener('click', function() {
      this.classList.toggle('active');
      if (this.classList.contains('active')) { if (layers.parsil) layers.parsil.addTo(map); }
      else { if (layers.parsil) map.removeLayer(layers.parsil); }
    });
  }
});