'use client';

import { useEffect, useState, useRef } from 'react';
import { supabase } from '@/lib/supabase';
import Chart from 'chart.js/auto';
import { useRouter } from 'next/navigation';
import SidebarControls from './dashboard/SidebarControls';
import StatsPanel from './dashboard/StatsPanel';
import ApprovalQueueModal from './dashboard/modals/ApprovalQueueModal';
import UserProvisioningModal from './dashboard/modals/UserProvisioningModal';
import DonationModal from './dashboard/modals/DonationModal';
import HubFormModal from './dashboard/modals/HubFormModal';
import HouseholdFormModal from './dashboard/modals/HouseholdFormModal';
import ProfileModal from './dashboard/modals/ProfileModal';
import SurveyMethodModal from './dashboard/modals/SurveyMethodModal';
import CapacityApprovalModal from './dashboard/modals/CapacityApprovalModal';
import DelegationQueueModal from './dashboard/modals/DelegationQueueModal';
import PicListModal from './dashboard/modals/PicListModal';
import kecamatanData from '@/lib/Admin_Kecamatan.json';
import { createHeatLayer } from '@/lib/initLeafletHeat';

// Point-in-Polygon algorithm for dynamic spatial kecamatan calculations
const isPointInPolygon = (point, polygon) => {
  const x = point[0], y = point[1];
  let inside = false;
  for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
    const xi = polygon[i][0], yi = polygon[i][1];
    const xj = polygon[j][0], yj = polygon[j][1];
    const intersect = ((yi > y) !== (yj > y))
        && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
    if (intersect) inside = !inside;
  }
  return inside;
};

const getKecamatanForPoint = (lat, lng) => {
  if (!kecamatanData || !kecamatanData.features) return null;
  for (const feature of kecamatanData.features) {
    const name = feature.properties?.Ket;
    const geom = feature.geometry;
    if (!name || !geom) continue;

    if (geom.type === 'Polygon') {
      if (isPointInPolygon([lng, lat], geom.coordinates[0])) {
        return name;
      }
    } else if (geom.type === 'MultiPolygon') {
      for (const polygonCoords of geom.coordinates) {
        if (isPointInPolygon([lng, lat], polygonCoords[0])) {
          return name;
        }
      }
    }
  }
  return null;
};

const parseLocation = (loc) => {
  if (!loc) return { lat: 0, lng: 0 };
  if (typeof loc === 'string') {
    const match = loc.match(/POINT\(([^ ]+) ([^ ]+)\)/);
    if (match) return { lng: parseFloat(match[1]), lat: parseFloat(match[2]) };
  } else if (loc.coordinates) {
    return { lng: loc.coordinates[0], lat: loc.coordinates[1] };
  }
  return { lat: 0, lng: 0 };
};

export default function Dashboard() {
  const mapRef = useRef(null);
  const mapInstance = useRef(null);
  
  // Charts
  const barChartRef = useRef(null);
  const donutChartRef = useRef(null);
  const barChartInstance = useRef(null);
  const donutChartInstance = useRef(null);

  // Data Stores
  const [hubs, setHubs] = useState([]);
  const [allHubs, setAllHubs] = useState([]);
  const [households, setHouseholds] = useState([]);
  const [activeHubs, setActiveHubs] = useState([]);
  
  // Router & Auth State
  const router = useRouter();
  const [user, setUser] = useState(null);
  const [profile, setProfile] = useState(null);

  // UI Toggles
  const [showTopBar, setShowTopBar] = useState(true);
  const [showControls, setShowControls] = useState(true);
  const [showStats, setShowStats] = useState(true);
  const [showLegend, setShowLegend] = useState(true);
  const [showSubmenu, setShowSubmenu] = useState(false);

  const [onlyMyHub, setOnlyMyHub] = useState(false);

  // State
  
  const [showUserModal, setShowUserModal] = useState(false);
  const [usersList, setUsersList] = useState([]);
  const [userFormData, setUserFormData] = useState({
    email: '',
    password: '',
    full_name: '',
    role: 'pic',
    hub_id: ''
  });
  const [isSubmittingUser, setIsSubmittingUser] = useState(false);

  const fetchUsers = async () => {
    try {
      const res = await fetch('/api/users');
      if (res.ok) {
        const data = await res.json();
        setUsersList(data.users || []);
      }
    } catch (e) { console.error('Error fetching users:', e); }
  };

  const handleCreateUser = async (e) => {
    e.preventDefault();
    setIsSubmittingUser(true);
    try {
      const res = await fetch('/api/users', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(userFormData)
      });
      if (res.ok) {
        showToastNotification('Pengguna berhasil dibuat!');
        fetchUsers();
        setUserFormData({ email: '', password: '', full_name: '', role: 'pic', hub_id: '' });
        setShowUserModal(false);
      } else {
        const data = await res.json();
        showToastNotification('Gagal membuat pengguna: ' + data.error, 'error');
      }
    } catch (e) { showToastNotification('Gagal: ' + e.message, 'error'); }
    setIsSubmittingUser(false);
  };

  const handleDeleteUser = (id) => {
    setConfirmDialog({
      title: 'Hapus Pengguna',
      message: 'Apakah Anda yakin ingin menghapus pengguna ini? Akun mereka di Supabase Authentication juga akan dihapus secara permanen.',
      onCancel: () => setConfirmDialog(null),
      onConfirm: async () => {
        setConfirmDialog(null);
        try {
          const res = await fetch(`/api/users?id=${id}`, { method: 'DELETE' });
          if (res.ok) {
            showToastNotification('Pengguna berhasil dihapus!');
            fetchUsers();
          } else {
            showToastNotification('Gagal menghapus pengguna', 'error');
          }
        } catch (e) { 
          showToastNotification('Error saat menghapus pengguna', 'error'); 
        }
      }
    });
  };

  const handleDeleteHub = (id, name) => {
    setConfirmDialog({
      title: 'Hapus Rumah Ibadah',
      message: `Apakah Anda yakin ingin menghapus "${name}"? Seluruh akun PIC dan Ketua Pengurus yang terikat ke rumah ibadah ini akan ikut dihapus secara permanen dari sistem.`,
      onCancel: () => setConfirmDialog(null),
      onConfirm: async () => {
        setConfirmDialog(null);
        try {
          const res = await fetch(`/api/hubs?id=${id}`, { method: 'DELETE' });
          if (res.ok) {
            showToastNotification('Rumah ibadah dan akun terikat berhasil dihapus!');
            fetchData();
          } else {
            const data = await res.json();
            showToastNotification('Gagal menghapus: ' + (data.error || 'Terjadi kesalahan'), 'error');
          }
        } catch (e) {
          showToastNotification('Error saat menghapus rumah ibadah', 'error');
        }
      }
    });
  };

const [isEditMode, setIsEditMode] = useState(false);
  const [placementMode, setPlacementMode] = useState(null);
  const [searchQuery, setSearchQuery] = useState('');
  const [filters, setFilters] = useState({
    Mosque: true,
    Church: true,
    Vihara: true,
    Temple: true,
    Other: true,
  });

  // Modal State
  const [showHubModal, setShowHubModal] = useState(false);
  const [showHhModal, setShowHhModal] = useState(false);
  const [showApprovalModal, setShowApprovalModal] = useState(false);
  const [showCapacityModal, setShowCapacityModal] = useState(false);
  const [showDelegationModal, setShowDelegationModal] = useState(false);
  const [showPicListModal, setShowPicListModal] = useState(false);
  const [selectedPhotoUrl, setSelectedPhotoUrl] = useState('');
  const [imageFile, setImageFile] = useState(null);
  const [isUploading, setIsUploading] = useState(false);
  const [hubFormData, setHubFormData] = useState({
    id: '',
    name: '',
    type: 'Mosque',
    radius_meter: 500,
    lat: '',
    lng: '',
    address: '',
    pic_phone: ''
  });
  const [hhFormData, setHhFormData] = useState({
    id: '', head_name: '', nik: '', no_kk: '', family_size: 1, status: 'Pending', photo_url: 'https://via.placeholder.com/150', lat: '', lng: '', assigned_hub_id: null
  });

  // Donations State
  const [showDonationModal, setShowDonationModal] = useState(false);
  const [activeDonationHub, setActiveDonationHub] = useState(null);
  const [donationsList, setDonationsList] = useState([]);
  const [donationFormData, setDonationFormData] = useState({
    amount: '', type: 'IN', description: '', transaction_date: new Date().toISOString().split('T')[0]
  });
  const [isSubmittingDonation, setIsSubmittingDonation] = useState(false);

  // Toast
  const [showToast, setShowToast] = useState(false);
  const [webNotification, setWebNotification] = useState(null);
  const [confirmDialog, setConfirmDialog] = useState(null);

  const showToastNotification = (message, type = 'success') => {
    setWebNotification({ message, type });
    setTimeout(() => {
      setWebNotification(null);
    }, 3500);
  };

  // Profile & Logout Modal State
  const [showProfileModal, setShowProfileModal] = useState(false);
  const [isLoggingOut, setIsLoggingOut] = useState(false);
  const [showSurveyModal, setShowSurveyModal] = useState(false);

  const handleLogout = async () => {
    setIsLoggingOut(true);
    try {
      await supabase.auth.signOut();
      window.location.reload();
    } catch (e) {
      console.error('Error logging out:', e);
      showToastNotification('Gagal keluar dari akun', 'error');
    } finally {
      setIsLoggingOut(false);
    }
  };

  // Stats
  const [stats, setStats] = useState({
    hubsCount: 0,
    coveredCount: 0,
    uncoveredCount: 0,
    equalityIndex: 0
  });

  // Marker & Layer References
  const LeafletRef = useRef(null);
  const hubLayersRef = useRef(null);
  const circleLayersRef = useRef(null);
  const householdLayersRef = useRef(null);
  const hubMarkersRef = useRef({});
  const circleMarkersRef = useRef({});
  const hhMarkersRef = useRef({});

  const heatLayersRef = useRef(null);
  const householdsRef = useRef([]); // Keeps latest households accessible from async CDN callbacks
  const hubsRef = useRef([]); // Keeps latest hubs accessible from Leaflet click handler closure
  const profileRef = useRef(null);
  const isMountedRef = useRef(true);

  // Heatmap + Individual Marker visibility logic per spec
  // Zoom 11-13: heatmap full, markers hidden for ALL
  // Zoom 14:    heatmap visible, markers hidden for ALL
  // Zoom 15-18: heatmap hidden, markers visible ONLY for super_admin & pic (not public)
  const updateMapLayersVisibility = (zoom) => {
    // Retrieve current profile from ref so this works inside Leaflet event listeners
    const currentProfile = profileRef.current;
    const canSeeMarkers = currentProfile &&
      (currentProfile.role === 'super_admin' || currentProfile.role === 'pic' || currentProfile.role === 'hub_head');

    const map = mapInstance.current;
    if (!map) return;

    if (zoom >= 15) {
      // Micro: hide heatmap, show markers only for authorized roles
      if (heatLayersRef.current) {
        heatLayersRef.current.setOptions({ opacity: 0, maxOpacity: 0 });
      }
      
      // Show Worship Hubs and Circles when zoomed in
      if (hubLayersRef.current && !map.hasLayer(hubLayersRef.current)) {
        map.addLayer(hubLayersRef.current);
      }
      if (circleLayersRef.current && !map.hasLayer(circleLayersRef.current)) {
        map.addLayer(circleLayersRef.current);
      }

      // Show/Hide Household markers based on role
      if (householdLayersRef.current) {
        if (canSeeMarkers) {
          if (!map.hasLayer(householdLayersRef.current)) {
            map.addLayer(householdLayersRef.current);
          }
        } else {
          if (map.hasLayer(householdLayersRef.current)) {
            map.removeLayer(householdLayersRef.current);
          }
        }
      }
    } else {
      // Macro/Medium (zoom 11-14): show heatmap, hide all individual markers
      const opacity = zoom <= 13 ? 1.0 : 0.75;
      if (heatLayersRef.current) {
        heatLayersRef.current.setOptions({ opacity, maxOpacity: opacity });
      }
      
      // Hide individual household markers
      if (householdLayersRef.current && map.hasLayer(householdLayersRef.current)) {
        map.removeLayer(householdLayersRef.current);
      }

      // If public user (no logged-in profile / no heatmap), keep Worship Hubs visible even at zoom < 15
      if (!currentProfile) {
        if (hubLayersRef.current && !map.hasLayer(hubLayersRef.current)) {
          map.addLayer(hubLayersRef.current);
        }
        if (circleLayersRef.current && !map.hasLayer(circleLayersRef.current)) {
          map.addLayer(circleLayersRef.current);
        }
      } else {
        // For authenticated users who have the heatmap, hide Worship Hubs when zoomed out
        if (hubLayersRef.current && map.hasLayer(hubLayersRef.current)) {
          map.removeLayer(hubLayersRef.current);
        }
        if (circleLayersRef.current && map.hasLayer(circleLayersRef.current)) {
          map.removeLayer(circleLayersRef.current);
        }
      }
    }
  };

  const hubStyles = {
    'Mosque': { color: '#10b981', iconClass: 'fas fa-mosque' },
    'Church': { color: '#3b82f6', iconClass: 'fas fa-church' },
    'Vihara': { color: '#ec4899', iconClass: 'fas fa-vihara' },
    'Temple': { color: '#f59e0b', iconClass: 'fas fa-torii-gate' },
    'Other':  { color: '#8b5cf6', iconClass: 'fas fa-place-of-worship' }
  };

  // 1. Initial Load of Leaflet, Data, & Auth
  useEffect(() => {
    if (typeof window === 'undefined') return;
    isMountedRef.current = true;

    // Check Auth State
    const checkAuth = async () => {
      const { data: { session } } = await supabase.auth.getSession();
      if (session) {
        setUser(session.user);
        const { data } = await supabase.from('profiles').select('*').eq('id', session.user.id).single();
        setProfile(data);
        // Store profile in ref so Leaflet event closures can read it
        profileRef.current = data;
      }
    };
    checkAuth();

    // Load Leaflet dynamically to prevent SSR errors
    import('leaflet').then((L) => {
      LeafletRef.current = L;

      // Fix Default Leaflet Icons (Just in case, though we use custom HTML divIcons)
      delete L.Icon.Default.prototype._getIconUrl;
      L.Icon.Default.mergeOptions({
        iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/marker-icon-2x.png',
        iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/marker-icon.png',
        shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/images/marker-shadow.png',
      });

      // Init Map
      if (!mapInstance.current && mapRef.current) {
        const map = L.map(mapRef.current, { zoomControl: false }).setView([-0.0263, 109.3425], 13);
        L.control.zoom({ position: 'bottomright' }).addTo(map);

        L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', {
          attribution: '&copy; OpenStreetMap &copy; CARTO',
          subdomains: 'abcd',
          maxZoom: 20
        }).addTo(map);

        hubLayersRef.current = L.layerGroup().addTo(map);
        circleLayersRef.current = L.layerGroup().addTo(map);
        householdLayersRef.current = L.layerGroup().addTo(map);

        map.on('click', (e) => {
          // Use a ref-based check for placementMode to avoid stale closure issues
          const currentPlacementMode = mapRef.current.dataset.placementMode;
          if (currentPlacementMode) {
            handleMapClickPlacement(e.latlng, currentPlacementMode);
          }
        });

        map.on('zoomend', () => {
          updateMapLayersVisibility(map.getZoom());
        });
        // Initialize heatmap layer — using our safe factory helper (avoids ES module mutation issues)
        heatLayersRef.current = createHeatLayer(L, [], {
          radius: 25,
          blur: 15,
          max: 6.0,         // 6+ overlapping points reaches maximum red intensity per spec section 4
          maxZoom: 13,      // Calibrates zoom scale factor so overlap counts are accurate at zoom 11-13
          minOpacity: 0.4,
          gradient: {
            0.4: '#3b82f6',  // Biru - rendah
            0.6: '#06b6d4',  // Sian - menengah-rendah
            0.8: '#eab308',  // Kuning - menengah-tinggi
            1.0: '#ef4444'   // Merah - tinggi / hotspot
          }
        }).addTo(map);

        // Populate from householdsRef in case fetchData() finished first
        const latestHouseholds = householdsRef.current;
        if (latestHouseholds && latestHouseholds.length > 0) {
          const heatPoints = latestHouseholds
            .filter(hh => hh.lat && hh.lng && hh.lat !== 0 && hh.lng !== 0)
            .map(hh => [hh.lat, hh.lng, 1.0]);
          heatLayersRef.current.setLatLngs(heatPoints);
        }

        // Initial visibility call — after heatmap layer exists
        updateMapLayersVisibility(map.getZoom());

        mapInstance.current = map;
        initCharts();
        fetchData();
      }
    });

    return () => {
      isMountedRef.current = false;
      if (mapInstance.current) {
        mapInstance.current.remove();
        mapInstance.current = null;
      }
      if (barChartInstance.current) barChartInstance.current.destroy();
      if (donutChartInstance.current) donutChartInstance.current.destroy();
    };
  }, []);

  // Listen to Auth changes
  useEffect(() => {
    supabase.auth.getUser().then(({ data: { user } }) => {
      setUser(user);
    });

    const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => {
      setUser(session?.user ?? null);
      if (!session?.user) {
        setIsEditMode(false);
      }
    });

    return () => {
      subscription.unsubscribe();
    };
  }, []);

  // Sync placement mode state to DOM dataset to bypass Leaflet click closure issue
  useEffect(() => {
    if (mapRef.current) {
      mapRef.current.dataset.placementMode = placementMode || '';
    }
  }, [placementMode]);

  // Fetch Data from Supabase
  async function fetchData() {
    try {
      const { data: { session } } = await supabase.auth.getSession();
      if (!isMountedRef.current) return;
      let currentProfile = null;
      if (session) {
        const { data } = await supabase.from('profiles').select('*').eq('id', session.user.id).single();
        currentProfile = data;
      }

      const { data: hubsData, error: hubsErr } = await supabase.from('hubs').select('*');
      if (hubsErr) console.error("Error fetching hubs:", hubsErr.message || hubsErr.details || hubsErr);

      const rawParsedHubs = (hubsData || []).map(hub => {
        const { lat, lng } = parseLocation(hub.location);
        return { ...hub, lat, lng, radius: hub.radius_meter };
      });
      setAllHubs(rawParsedHubs);

      let filteredHubs = hubsData || [];

      const parsedHubs = filteredHubs.map(hub => {
        const { lat, lng } = parseLocation(hub.location);
        return { ...hub, lat, lng, radius: hub.radius_meter };
      });
      setHubs(parsedHubs);
      hubsRef.current = parsedHubs;

      if (currentProfile) {
        const { data: hhData, error: hhErr } = await supabase.from('households').select('*');
        if (!isMountedRef.current) return;
        if (hhErr) console.error("Error fetching households:", hhErr.message || hhErr.details || hhErr);

        const parsedHouseholds = (hhData || []).map(hh => {
          const { lat, lng } = parseLocation(hh.location);
          return { ...hh, lat, lng, head_of_family: hh.head_name };
        });

        const subDistrictsList = ['Pontianak Barat', 'Pontianak Kota', 'Pontianak Selatan', 'Pontianak Tenggara', 'Pontianak Timur', 'Pontianak Utara'];
        const formattedHh = parsedHouseholds.map((hh, idx) => {
          
          return {
            ...hh,
            db_assigned_hub_id: hh.assigned_hub_id,
            sub_district: hh.sub_district || 'Belum Terpetakan',
            covered: false,
            assigned_hub_id: null,
            assigned_hub_type: null
          };
        });
        setHouseholds(formattedHh);
      } else {
        setHouseholds([]);
        fetch('/api/stats')
          .then(res => res.json())
          .then(data => {
             if (!isMountedRef.current) return;
             if (data && !data.error) {
               setStats({
                 hubsCount: data.hubsCount,
                 coveredCount: data.coveredCount,
                 uncoveredCount: data.uncoveredCount,
                 equalityIndex: data.equalityIndex
               });
               if (barChartInstance.current && donutChartInstance.current) {
                 const labels = Object.keys(data.subDistrictsMap);
                 const dataCovered = labels.map(l => data.subDistrictsMap[l].covered);
                 const dataUncovered = labels.map(l => data.subDistrictsMap[l].uncovered);
                 barChartInstance.current.data.labels = labels;
                 barChartInstance.current.data.datasets = [
                   { label: 'Terlayani', data: dataCovered, backgroundColor: '#10b981', borderRadius: 4 },
                   { label: 'Belum Terlayani', data: dataUncovered, backgroundColor: '#ef4444', borderRadius: 4 }
                 ];
                 barChartInstance.current.update('none');
                 const dLabels = Object.keys(data.typeCounts);
                 const dData = Object.values(data.typeCounts);
                 const colors = ['#3b82f6', '#8b5cf6', '#ec4899', '#f59e0b', '#10b981'];
                 donutChartInstance.current.data.labels = dLabels;
                 donutChartInstance.current.data.datasets = [{
                   data: dData,
                   backgroundColor: colors.slice(0, dLabels.length),
                   hoverOffset: 4
                 }];
                 donutChartInstance.current.update('none');
               }
             }
          })
          .catch(err => console.error("Error fetching public stats:", err));
      }
    } catch (err) {
      console.error("Data load failed:", err);
    }
  };

  // True Database Synchronization (Unfiltered)
  // This logic is decoupled from map visual filtering so that searching/filtering 
  // doesn't accidentally wipe out database assignments for hidden hubs.
  useEffect(() => {
    if (!mapInstance.current || hubs.length === 0 || households.length === 0) return;

    const dbUpdates = [];
    
    households.forEach(hh => {
      let trueAssignedId = hh.db_assigned_hub_id;
      
      if (!hh.manual_override_assigned_hub) {
        let closestHub = null;
        let minDistance = Infinity;

        hubs.forEach(hub => {
          const dist = mapInstance.current.distance([hh.lat, hh.lng], [hub.lat, hub.lng]);
          const hubRadius = parseInt(hub.radius) || 500;
          if (dist <= hubRadius && dist < minDistance) {
            minDistance = dist;
            closestHub = hub;
          }
        });
        trueAssignedId = closestHub ? closestHub.id : null;
      }

      if (hh.db_assigned_hub_id !== trueAssignedId) {
        dbUpdates.push({ id: hh.id, assigned_hub_id: trueAssignedId });
        // mutate locally to prevent continuous sync loops
        hh.db_assigned_hub_id = trueAssignedId; 
      }
    });

    if (dbUpdates.length > 0) {
      Promise.all(
        dbUpdates.map(upd => 
          supabase.from('households').update({ assigned_hub_id: upd.assigned_hub_id }).eq('id', upd.id)
        )
      ).catch(err => console.error("True silent sync failed:", err));
    }
  }, [hubs, households]);

  // Keep heatmap layer in sync whenever households data changes
  useEffect(() => {
    // Always keep ref up-to-date so async CDN onload can read it
    householdsRef.current = households;

    if (!heatLayersRef.current || !households || households.length === 0) return;
    const validPoints = households
      .filter(hh => hh.lat && hh.lng && hh.lat !== 0 && hh.lng !== 0)
      .map(hh => [hh.lat, hh.lng, 1.0]);
    heatLayersRef.current.setLatLngs(validPoints);
    if (mapInstance.current) {
      updateMapLayersVisibility(mapInstance.current.getZoom());
    }
  }, [households]);

  // Re-run calculations when hubs, households, filters, or search query change
  useEffect(() => {
    if (!LeafletRef.current || !mapInstance.current) return;
    
    // Filter active hubs by visibility checkbox, search query, and "Only My Hub" toggle
    const active = hubs.filter(h => {
      const typeMatch = filters[h.type];
      const queryMatch = searchQuery 
        ? h.name.toLowerCase().includes(searchQuery.toLowerCase()) 
        : true;
      
      let myHubMatch = true;
      if (onlyMyHub && profile) {
        myHubMatch = h.pic_id === profile.id || h.head_id === profile.id;
      }
      
      return typeMatch && queryMatch && myHubMatch;
    });
    setActiveHubs(active);
    
    recalculateCoverageAndRender(active);
  }, [hubs, households, filters, searchQuery, isEditMode, onlyMyHub, profile]);

  // Handle click to place points
  function handleMapClickPlacement(latlng, type) {
    if (type === 'hub') {
      setHubFormData({
        id: '',
        name: '',
        type: 'Mosque',
        radius_meter: 500,
        lat: latlng.lat,
        lng: latlng.lng,
        address: 'Loading address...',
        pic_phone: ''
      });
      setShowHubModal(true);

      // Async reverse geocoding for new Hub
      fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${latlng.lat}&lon=${latlng.lng}`)
        .then(res => res.json())
        .then(data => {
          const resolvedAddress = data.display_name || `${latlng.lat.toFixed(4)}, ${latlng.lng.toFixed(4)}`;
          setHubFormData(prev => ({ ...prev, address: resolvedAddress }));
        })
        .catch(() => {
          setHubFormData(prev => ({ ...prev, address: `${latlng.lat.toFixed(4)}, ${latlng.lng.toFixed(4)}` }));
        });
    } else if (type === 'household') {
      // Spatially pre-calculate assigned hub
      let closestHub = null;
      let minDistance = Infinity;
      const latestHubs = hubsRef.current || [];
      latestHubs.forEach(hub => {
        if (mapInstance.current) {
          const dist = mapInstance.current.distance([latlng.lat, latlng.lng], [hub.lat, hub.lng]);
          const hubRadius = parseInt(hub.radius) || 500;
          if (dist <= hubRadius && dist < minDistance) {
            minDistance = dist;
            closestHub = hub;
          }
        }
      });

      if (profileRef.current?.role !== 'super_admin') {
        const myHub = latestHubs.find(h => h.pic_id === profileRef.current?.id || h.head_id === profileRef.current?.id);
        if (!myHub || !closestHub || closestHub.id !== myHub.id) {
          showToastNotification("Titik KK baru harus berada di dalam radius jangkauan rumah ibadah Anda!", "danger");
          setPlacementMode(null);
          setShowToast(false);
          return;
        }
      }

      setHhFormData({
        id: '',
        head_name: '',
        nik: '',
        no_kk: '',
        family_size: 1,
        status: 'Pending',
        photo_url: '',
        lat: latlng.lat,
        lng: latlng.lng,
        assigned_hub_id: closestHub ? closestHub.id : null
      });
      setImageFile(null);
      setShowHhModal(true);
    }
    setPlacementMode(null);
    setShowToast(false);
  };

  // Custom Leaflet Icons builder
  const getCustomIcon = (color, iconClass, capacityStatus) => {
    const isOverloaded = capacityStatus === 'overloaded';
    const borderStyle = isOverloaded ? '2px dashed #ef4444' : '2px solid white';
    const warningBadge = isOverloaded 
      ? `<div style="position:absolute;top:-4px;right:-4px;background:#ef4444;color:white;width:15px;height:15px;border-radius:50%;border:1px solid white;display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:bold;box-shadow:0 2px 5px rgba(0,0,0,0.3);"><i class="fas fa-exclamation" style="font-size: 8px;"></i></div>` 
      : '';
    const pulseClass = isOverloaded ? 'pulse-border' : '';

    return LeafletRef.current.divIcon({
      className: `custom-div-icon ${pulseClass}`,
      html: `<div style="position:relative;background-color:${color};width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:white;border:${borderStyle};box-shadow:0 4px 10px rgba(0,0,0,0.5);"><i class="${iconClass}"></i>${warningBadge}</div>`,
      iconSize: [32, 32],
      iconAnchor: [16, 16],
      popupAnchor: [0, -16]
    });
  };

  // Coverage Calculations and UI Rendering
  function recalculateCoverageAndRender(currentActiveHubs) {
    const L = LeafletRef.current;
    
    // Clear layers
    hubLayersRef.current.clearLayers();
    circleLayersRef.current.clearLayers();
    householdLayersRef.current.clearLayers();

    hubMarkersRef.current = {};
    circleMarkersRef.current = {};
    hhMarkersRef.current = {};

    let covered = 0;
    
    // 1. Render Hubs and Circles
    currentActiveHubs.forEach(hub => {
      const hubRadius = parseInt(hub.radius) || 500;
      const style = hubStyles[hub.type] || hubStyles['Other'];

      // Circle
      const circle = L.circle([hub.lat, hub.lng], {
        radius: hubRadius,
        color: style.color,
        fillColor: style.color,
        fillOpacity: 0.15,
        weight: 1.5,
        dashArray: '4, 4'
      }).addTo(circleLayersRef.current);
      circleMarkersRef.current[hub.id] = circle;

      // Marker
      const marker = L.marker([hub.lat, hub.lng], {
        icon: getCustomIcon(style.color, style.iconClass, hub.capacity_status),
        draggable: isEditMode && profileRef.current?.role === 'super_admin'
      }).addTo(hubLayersRef.current);
      hubMarkersRef.current[hub.id] = marker;

      // Ownership check for this specific Worship Hub
      const isMyHub = profileRef.current && (
        profileRef.current.role === 'super_admin' ||
        hub.pic_id === profileRef.current.id ||
        hub.head_id === profileRef.current.id
      );

      // Capacity Status Display & Interaction
      const capStatus = hub.capacity_status === 'overloaded' ? 'Kritis / Overloaded' : 'Normal';
      const capColor = hub.capacity_status === 'overloaded' ? '#ef4444' : '#10b981';
      const pendingText = hub.pending_capacity_status 
        ? `<div style="font-size:0.75rem; color:#f59e0b; margin-top:4px; font-weight:600;"><i class="fas fa-clock"></i> Pengajuan: ${hub.pending_capacity_status === 'overloaded' ? 'Kritis' : 'Normal'} (Menunggu Persetujuan)</div>`
        : '';

      // Determine Capacity Button (Only visible if the Hub Head actually owns this hub)
      let capacityButtonHTML = '';
      const isHubHead = profileRef.current && profileRef.current.role === 'hub_head';
      if (isHubHead && isMyHub) {
        if (hub.pending_capacity_status) {
          capacityButtonHTML = `<button class="btn cancel-capacity-btn" style="width: 100%; margin-top: 8px; padding: 6px; background: #64748b; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 0.8rem;"><i class="fas fa-undo"></i> Batalkan Pengajuan</button>`;
        } else if (hub.capacity_status === 'normal') {
          capacityButtonHTML = `<button class="btn request-capacity-btn" data-target="overloaded" style="width: 100%; margin-top: 8px; padding: 6px; background: #ef4444; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 0.8rem;"><i class="fas fa-exclamation-triangle"></i> Ajukan Status Overloaded</button>`;
        } else {
          capacityButtonHTML = `<button class="btn request-capacity-btn" data-target="normal" style="width: 100%; margin-top: 8px; padding: 6px; background: #10b981; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 0.8rem;"><i class="fas fa-check-circle"></i> Ajukan Kembali ke Normal</button>`;
        }
      }

      // Realtime popup slider
      const popupDiv = document.createElement('div');
      popupDiv.innerHTML = `
        <h3 style="margin: 0 0 8px 0; font-size: 1.1rem; border-bottom: 1px solid rgba(0,0,0,0.1); padding-bottom: 8px;">
          <i class="${style.iconClass}" style="color: ${style.color}; margin-right: 8px;"></i>${hub.name}
          <span style="font-size:0.7rem; background:rgba(0,0,0,0.08); padding:2px 6px; border-radius:4px; float:right;">${hub.type}</span>
        </h3>
        <p style="margin: 0 0 4px 0; font-size: 0.8rem; color: #94a3b8;"><i class="fas fa-map-marker-alt"></i> Alamat: <span id="hub-address-${hub.id}" style="font-weight:bold; font-size:0.75rem;">${hub.address || 'Memuat alamat...'}</span></p>
        <p style="margin: 0 0 4px 0; font-size: 0.8rem; color: #94a3b8;"><i class="fas fa-phone"></i> Kontak PIC: <span style="font-weight:bold; font-size:0.75rem; color:var(--text-main);">${hub.pic_phone ? `<a href="https://wa.me/${hub.pic_phone.replace(/\D/g, '')}" target="_blank" style="color:var(--primary); text-decoration:none; font-weight:bold;">${hub.pic_phone} <i class="fab fa-whatsapp" style="color:#25d366;"></i></a>` : 'Belum diatur'}</span></p>
        <p style="margin: 0 0 8px 0; font-size: 0.8rem; color: #94a3b8;"><i class="fas fa-compass"></i> Lat: ${parseFloat(hub.lat).toFixed(4)}, Lng: ${parseFloat(hub.lng).toFixed(4)}</p>
        
        <div style="margin: 8px 0; padding: 8px; background: rgba(0,0,0,0.02); border-radius: 6px; border-left: 3px solid ${capColor};">
          <span style="font-size: 0.8rem; color: var(--text-muted); font-weight: 500;">Status Kapasitas:</span>
          <span style="font-size: 0.8rem; font-weight: bold; color: ${capColor}; float: right;">${capStatus}</span>
          ${pendingText}
          ${capacityButtonHTML}
        </div>

        <div class="popup-slider-container" style="margin-top: 12px; background: rgba(0,0,0,0.05); padding: 10px; border-radius: 8px;">
          <label style="display: block; font-size: 0.8rem; margin-bottom: 6px; color: var(--text-muted);">Radius Jangkauan: <span id="radval_${hub.id}" style="color:var(--text-main); font-weight:bold;">${hubRadius}</span>m</label>
          <input type="range" min="100" max="3000" step="50" value="${hubRadius}" 
            ${isEditMode && isMyHub ? '' : 'disabled'}
            style="width: 100%; accent-color: var(--primary);" />
        </div>
        <div style="margin-top: 12px; display: flex; gap: 8px;">
          ${isEditMode && isMyHub ? `<button class="btn edit-hub-btn" style="flex: 1; padding: 6px; background: #3b82f6; color: white; border: none; border-radius: 4px; cursor: pointer;"><i class="fas fa-edit"></i> Edit</button>` : ''}
          ${profileRef.current && isMyHub ? `<button class="btn manage-donations-btn" style="flex: 1; padding: 6px; background: #10b981; color: white; border: none; border-radius: 4px; cursor: pointer;"><i class="fas fa-wallet"></i> Kas</button>` : ''}
          ${isEditMode && profileRef.current?.role === 'super_admin' ? `<button class="btn delete-hub-btn" style="flex: 1; padding: 6px; background: #ef4444; color: white; border: none; border-radius: 4px; cursor: pointer;"><i class="fas fa-trash-alt"></i> Hapus</button>` : ''}
        </div>
      `;

      // Slider event listeners
      const slider = popupDiv.querySelector('input[type=range]');
      slider.addEventListener('input', (e) => {
        const val = e.target.value;
        popupDiv.querySelector(`#radval_${hub.id}`).textContent = val;
        circle.setRadius(parseInt(val));
        // Dynamically update coordinates mapping
        hub.radius = parseInt(val);
        fastRecalculate(currentActiveHubs);
      });

      slider.addEventListener('change', async (e) => {
        const val = parseInt(e.target.value);
        const { error } = await supabase.from('hubs').update({ radius_meter: val }).eq('id', hub.id);
        if (error) {
          console.error("Error updating radius:", error.message || error.details || error);
          alert(`Error updating radius: ${error.message || error.details || JSON.stringify(error)}`);
        } else {
          fetchData();
        }
      });

      marker.bindPopup(popupDiv, { minWidth: 240 });

      // On-demand reverse geocoding for Worship Hubs
      marker.on('popupopen', async () => {
        const addressEl = popupDiv.querySelector(`#hub-address-${hub.id}`);
        if (addressEl && (addressEl.textContent === 'Loading address...' || !hub.address)) {
          try {
            const res = await fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${hub.lat}&lon=${hub.lng}`);
            const data = await res.json();
            const address = data.display_name || `${hub.lat.toFixed(4)}, ${hub.lng.toFixed(4)}`;
            addressEl.textContent = address;
            
            // Auto cache address to database silently
            if (!hub.address) {
              await supabase.from('hubs').update({ address }).eq('id', hub.id);
              hub.address = address;
            }
          } catch (e) {
            addressEl.textContent = `${hub.lat.toFixed(4)}, ${hub.lng.toFixed(4)}`;
          }
        }

        const editBtn = popupDiv.querySelector('.edit-hub-btn');
        if (editBtn) {
          editBtn.onclick = () => {
            setHubFormData({
              id: hub.id,
              name: hub.name,
              type: hub.type,
              radius_meter: hub.radius,
              lat: hub.lat,
              lng: hub.lng,
              address: hub.address,
              pic_phone: hub.pic_phone || ''
            });
            setShowHubModal(true);
          };
        }

        const donationBtn = popupDiv.querySelector('.manage-donations-btn');
        if (donationBtn) {
          donationBtn.onclick = () => {
            setActiveDonationHub(hub);
            fetchDonations(hub.id);
            setShowDonationModal(true);
          };
        }

        const deleteBtn = popupDiv.querySelector('.delete-hub-btn');
        if (deleteBtn) {
          deleteBtn.onclick = () => {
            handleDeleteHub(hub.id, hub.name);
          };
        }

        const reqBtn = popupDiv.querySelector('.request-capacity-btn');
        if (reqBtn) {
          reqBtn.onclick = async () => {
            const targetStatus = reqBtn.dataset.target;
            const { error } = await supabase.from('hubs').update({ pending_capacity_status: targetStatus }).eq('id', hub.id);
            if (error) {
              alert(`Gagal mengajukan perubahan status: ${error.message}`);
            } else {
              showToastNotification('Pengajuan perubahan status kapasitas berhasil dikirim ke Super Admin!');
              marker.closePopup();
              fetchData();
            }
          };
        }

        const cancelBtn = popupDiv.querySelector('.cancel-capacity-btn');
        if (cancelBtn) {
          cancelBtn.onclick = async () => {
            const { error } = await supabase.from('hubs').update({ pending_capacity_status: null }).eq('id', hub.id);
            if (error) {
              alert(`Gagal membatalkan pengajuan: ${error.message}`);
            } else {
              showToastNotification('Pengajuan perubahan status kapasitas berhasil dibatalkan.');
              marker.closePopup();
              fetchData();
            }
          };
        }
      });

      // Drag listener
      marker.on('drag', (e) => {
        const pos = e.target.getLatLng();
        circle.setLatLng(pos);
        hub.lat = pos.lat;
        hub.lng = pos.lng;
        fastRecalculate(currentActiveHubs);
      });

      marker.on('dragend', async (e) => {
        const pos = e.target.getLatLng();
        const { error } = await supabase.from('hubs').update({ location: `POINT(${pos.lng} ${pos.lat})` }).eq('id', hub.id);
        if (error) {
          console.error("Error updating location:", error.message || error.details || error);
          alert(`Error updating location: ${error.message || error.details || JSON.stringify(error)}`);
        } else {
          fetchData();
        }
      });
    });

    // 2. Render Households
    const isLocalAdmin = profileRef.current && profileRef.current.role === 'pic';
    const myHub = isLocalAdmin ? hubs.find(h => h.pic_id === profileRef.current?.id || h.head_id === profileRef.current?.id) : null;
    const subDistrictsList = ['Pontianak Barat', 'Pontianak Kota', 'Pontianak Selatan', 'Pontianak Tenggara', 'Pontianak Timur', 'Pontianak Utara'];
    const updatedHh = households.map((hh, idx) => {
      let closestHub = null;
      let minDistance = Infinity;

      if (hh.manual_override_assigned_hub) {
        closestHub = currentActiveHubs.find(h => h.id === hh.db_assigned_hub_id);
      } else {
        currentActiveHubs.forEach(hub => {
          const dist = mapInstance.current.distance([hh.lat, hh.lng], [hub.lat, hub.lng]);
          const hubRadius = parseInt(hub.radius) || 500;
          if (dist <= hubRadius && dist < minDistance) {
            minDistance = dist;
            closestHub = hub;
          }
        });
      }

      if (closestHub) {
        hh.assigned_hub_id = closestHub.id;
        hh.assigned_hub_type = closestHub.type;
        hh.covered = true;
        covered++;
      } else {
        hh.assigned_hub_id = null;
        hh.assigned_hub_type = null;
        hh.covered = false;
      }

      // Spatially recalculate kecamatan sub district dynamically
      hh.sub_district = hh.sub_district && hh.sub_district !== 'Belum Terpetakan' 
        ? hh.sub_district 
        : getKecamatanForPoint(hh.lat, hh.lng) || 'Belum Terpetakan';

      // Retrieve assigned hub name (using allHubs database master list)
      const assignedHub = allHubs.find(h => String(h.id) === String(hh.db_assigned_hub_id || hh.assigned_hub_id));
      const assignedHubName = assignedHub ? assignedHub.name : 'Belum Ditugaskan / Mandiri';

      // Marker
      const isVerified = hh.status === 'Verified';
      let markerColor = 'var(--danger)';
      if (isVerified) {
        markerColor = hh.covered ? 'var(--success)' : 'var(--danger)';
      } else {
        markerColor = hh.covered ? '#f59e0b' : '#64748b'; // Orange if inside, Gray if outside
      }
      const icon = getCustomIcon(markerColor, 'fas fa-user');

      const canEditHh = profileRef.current?.role === 'super_admin' || (isLocalAdmin && myHub && (hh.db_assigned_hub_id === myHub.id || hh.surveyor_id === profileRef.current?.id));

      const marker = L.marker([hh.lat, hh.lng], {
        icon: icon,
        draggable: isEditMode && canEditHh
      }).addTo(householdLayersRef.current);
      hhMarkersRef.current[hh.id] = marker;

      const isHttp = hh.photo_url && hh.photo_url.startsWith('http');

      let delegationHTML = '';
      if (isLocalAdmin && myHub && hh.db_assigned_hub_id === myHub.id) {
        if (!hh.pending_transfer_hub_id) {
          const otherHubs = hubs.filter(h => h.id !== myHub.id);
          const optionsHTML = otherHubs.map(h => `<option value="${h.id}">${h.name} (${h.type})</option>`).join('');
          delegationHTML = `
            <div class="delegation-panel" style="margin-top: 12px; padding: 10px; background: rgba(59, 130, 246, 0.05); border-radius: 8px; border: 1px dashed rgba(59, 130, 246, 0.3);">
              <h4 style="margin: 0 0 8px 0; font-size: 0.85rem; color: #1e3a8a; display: flex; align-items: center; gap: 6px;"><i class="fas fa-exchange-alt"></i> Delegasi Lintas Hub</h4>
              <p style="margin: 0 0 8px 0; font-size: 0.75rem; color: #4b5563;">Ajukan bantuan terlayani warga ini ke Hub terdekat lainnya.</p>
              <div style="display: flex; flex-direction: column; gap: 8px;">
                <select id="delegation-target-${hh.id}" style="width: 100%; padding: 6px 8px; font-size: 0.8rem; border-radius: 4px; border: 1px solid #cbd5e1; outline: none; background: white; color: black;">
                  <option value="">-- Pilih Hub Penerima --</option>
                  ${optionsHTML}
                </select>
                <button class="btn send-delegation-btn" data-hh-id="${hh.id}" style="width: 100%; padding: 6px 8px; background: #3b82f6; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 0.8rem; display: flex; align-items: center; justify-content: center; gap: 6px;"><i class="fas fa-paper-plane"></i> Kirim</button>
              </div>
            </div>
          `;
        } else {
          const targetHubName = hubs.find(h => h.id === hh.pending_transfer_hub_id)?.name || 'Hub Lain';
          delegationHTML = `
            <div class="delegation-panel" style="margin-top: 12px; padding: 10px; background: rgba(245, 158, 11, 0.05); border-radius: 8px; border: 1px dashed rgba(245, 158, 11, 0.3);">
              <h4 style="margin: 0 0 8px 0; font-size: 0.85rem; color: #78350f; display: flex; align-items: center; gap: 6px;"><i class="fas fa-clock"></i> Delegasi Tertunda</h4>
              <div style="font-size: 0.75rem; color: #f59e0b; font-weight: 600; margin-bottom: 8px;"><i class="fas fa-info-circle"></i> Menunggu persetujuan: <span style="color:#b45309">${targetHubName}</span></div>
              <button class="btn cancel-delegation-btn" data-hh-id="${hh.id}" style="width: 100%; padding: 4px; background: #ef4444; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 0.8rem; display: flex; align-items: center; justify-content: center; gap: 4px;"><i class="fas fa-times-circle"></i> Batalkan Delegasi</button>
            </div>
          `;
        }
      }

      // Popup
      marker.bindPopup(`
        <div class="citizen-modal" style="display: flex; gap: 20px;">
          <div class="citizen-photo" style="width: 100px; height: 100px; background: rgba(0,0,0,0.05); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: rgba(0,0,0,0.3); font-size: 2rem; overflow: hidden;">
            <img id="hh-photo-${hh.id}" src="${isHttp ? hh.photo_url : ''}" style="width: 100%; height: 100%; object-fit: cover; display: ${isHttp ? 'block' : 'none'};" />
            <i id="hh-photo-icon-${hh.id}" class="fas fa-image" style="display: ${isHttp ? 'none' : 'block'};"></i>
          </div>
          <div class="citizen-details" style="flex: 1;">
            <h3 style="margin: 0 0 8px 0; font-size: 1.1rem; border-bottom: 1px solid rgba(0,0,0,0.1); padding-bottom: 8px;">${hh.head_of_family}</h3>
            <p style="margin: 0 0 8px 0; font-size: 0.9rem; color: var(--text-muted);">Jumlah Anggota KK: ${hh.family_size} Jiwa</p>
            <p style="margin: 0 0 4px 0; font-size: 0.9rem; color: var(--text-muted);">Alamat: <span id="hh-address-${hh.id}" style="font-weight:bold; font-size:0.8rem; display:block; margin-top:2px;">Memuat alamat...</span></p>
            <p style="margin: 0 0 8px 0; font-size: 0.9rem; color: var(--text-muted);">Kecamatan: <span style="font-weight:bold;">${hh.sub_district}</span></p>
            <p style="margin: 0 0 8px 0; font-size: 0.9rem; color: var(--text-muted);">Hub Naungan: <span style="font-weight:bold; color:var(--text-main);">${assignedHubName}</span></p>
            <p style="margin: 0 0 8px 0; font-size: 0.9rem; color: var(--text-muted);">Status: <span style="color: ${hh.covered ? 'var(--success)' : 'var(--danger)'}; font-weight:bold;">
              ${hh.covered ? 'Terlayani' : 'Belum Terlayani'}
            </span></p>
          </div>
        </div>
        ${delegationHTML}
        ${isEditMode && canEditHh ? `
        <div style="margin-top: 12px;">
          <button class="btn edit-hh-btn" style="width: 100%; padding: 6px; background: #3b82f6; color: white; border: none; border-radius: 4px; cursor: pointer;"><i class="fas fa-edit"></i> Edit Detail Warga</button>
        </div>` : ''}
      `, { minWidth: 280 });

      // On-demand reverse geocoding for Citizens
      marker.on('popupopen', async () => {
        const addressEl = document.getElementById(`hh-address-${hh.id}`);
        if (addressEl && (addressEl.textContent === 'Loading address...' || addressEl.textContent === 'Memuat alamat...')) {
          try {
            const res = await fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${hh.lat}&lon=${hh.lng}`);
            const data = await res.json();
            addressEl.textContent = data.display_name || `${hh.lat.toFixed(4)}, ${hh.lng.toFixed(4)}`;
          } catch (e) {
            addressEl.textContent = `${hh.lat.toFixed(4)}, ${hh.lng.toFixed(4)}`;
          }
        }

        const imgEl = document.getElementById(`hh-photo-${hh.id}`);
        const iconEl = document.getElementById(`hh-photo-icon-${hh.id}`);
        if (imgEl && iconEl && hh.photo_url && !hh.photo_url.startsWith('http')) {
          const { data } = await supabase.storage.from('geotagging-photo').createSignedUrl(hh.photo_url, 3600);
          if (data && data.signedUrl) {
            imgEl.src = data.signedUrl;
            imgEl.style.display = 'block';
            iconEl.style.display = 'none';
          }
        }

        const editBtn = document.querySelector('.edit-hh-btn');
        if (editBtn) {
          editBtn.onclick = () => {
            setHhFormData({
              id: hh.id,
              head_name: hh.head_of_family || hh.head_name || '',
              nik: hh.nik || '',
              no_kk: hh.no_kk || '',
              family_size: hh.family_size,
              status: hh.status || 'Pending',
              photo_url: hh.photo_url || 'https://via.placeholder.com/150',
              lat: hh.lat,
              lng: hh.lng,
              assigned_hub_id: hh.db_assigned_hub_id || hh.assigned_hub_id
            });
            setImageFile(null);
            setShowHhModal(true);
          };
        }

        const sendBtn = document.querySelector(`.send-delegation-btn[data-hh-id="${hh.id}"]`);
        if (sendBtn) {
          sendBtn.onclick = async () => {
            const targetSelect = document.getElementById(`delegation-target-${hh.id}`);
            const targetHubId = targetSelect?.value;
            if (!targetHubId) {
              alert("Silakan pilih Hub penerima terlebih dahulu.");
              return;
            }
            const { error } = await supabase.from('households').update({
              pending_transfer_hub_id: targetHubId
            }).eq('id', hh.id);
            
            if (error) {
              alert(`Gagal mengirim permohonan delegasi: ${error.message}`);
            } else {
              showToastNotification('Permohonan delegasi berhasil dikirim ke Hub penerima!');
              marker.closePopup();
              fetchData();
            }
          };
        }

        const cancelBtn = document.querySelector(`.cancel-delegation-btn[data-hh-id="${hh.id}"]`);
        if (cancelBtn) {
          cancelBtn.onclick = async () => {
            const { error } = await supabase.from('households').update({
              pending_transfer_hub_id: null
            }).eq('id', hh.id);
            
            if (error) {
              alert(`Gagal membatalkan permohonan delegasi: ${error.message}`);
            } else {
              showToastNotification('Permohonan delegasi berhasil dibatalkan.');
              marker.closePopup();
              fetchData();
            }
          };
        }
      });

      // Drag events
      let originalLatLng = null;
      marker.on('dragstart', (e) => {
        originalLatLng = e.target.getLatLng();
      });

      marker.on('drag', (e) => {
        const pos = e.target.getLatLng();
        hh.lat = pos.lat;
        hh.lng = pos.lng;
        fastRecalculate(currentActiveHubs);
      });

      marker.on('dragend', async (e) => {
        const pos = e.target.getLatLng();
        
        let closestHub = null;
        let minDistance = Infinity;

        if (hh.manual_override_assigned_hub) {
          closestHub = hubs.find(h => h.id === hh.db_assigned_hub_id);
        } else {
          // Calculate true closest hub on drag end against ALL hubs
          hubs.forEach(hub => {
            const dist = mapInstance.current.distance([pos.lat, pos.lng], [hub.lat, hub.lng]);
            const hubRadius = parseInt(hub.radius) || 500;
            if (dist <= hubRadius && dist < minDistance) {
              minDistance = dist;
              closestHub = hub;
            }
          });
        }

        // For non-admin, target must be inside their managed hub's radius OR the household must be assigned to their hub
        let isManualOverrideApplied = hh.manual_override_assigned_hub;
        if (profileRef.current?.role !== 'super_admin') {
          const myHub = hubsRef.current.find(h => h.pic_id === profileRef.current?.id || h.head_id === profileRef.current?.id);
          const isInsideRadius = closestHub && myHub && closestHub.id === myHub.id;
          const isMyHousehold = myHub && hh.db_assigned_hub_id === myHub.id;
          
          if (!isInsideRadius && !isMyHousehold) {
            showToastNotification("Titik KK harus berada di dalam radius jangkauan atau merupakan warga yang terdaftar pada Hub Anda!", "danger");
            if (originalLatLng) {
              e.target.setLatLng(originalLatLng);
              hh.lat = originalLatLng.lat;
              hh.lng = originalLatLng.lng;
              fastRecalculate(currentActiveHubs);
            }
            return;
          }

          // If the household belongs to the user's hub, but is dragged outside the radius or into another hub's radius,
          // we force it to stay assigned to the user's hub and apply the manual override flag!
          if (isMyHousehold && !isInsideRadius) {
            closestHub = myHub;
            isManualOverrideApplied = true;
          }
        }

        const matchedKec = getKecamatanForPoint(pos.lat, pos.lng) || 'Belum Terpetakan';
        const { error } = await supabase.from('households').update({ 
          location: `POINT(${pos.lng} ${pos.lat})`,
          assigned_hub_id: closestHub ? closestHub.id : null,
          sub_district: matchedKec,
          manual_override_assigned_hub: isManualOverrideApplied
        }).eq('id', hh.id);
        if (error) {
          console.error("Error updating location:", error.message || error.details || error);
          alert(`Error updating location: ${error.message || error.details || JSON.stringify(error)}`);
        } else {
          fetchData();
        }
      });

      return hh;
    });

    // Update Stats
    const total = updatedHh.length;
    const uncovered = total - covered;
    const equality = total > 0 ? Math.round((covered / total) * 100) : 0;

    // Update Stats only if authenticated (public stats come from API)
    if (profile) {
      setStats({
        hubsCount: currentActiveHubs.length,
        coveredCount: covered,
        uncoveredCount: uncovered,
        equalityIndex: equality
      });

      updateChartsData(updatedHh);
    }
  };

  // Perform quick visual updates without fully recreating layers (prevents marker flicker on drag)
  function fastRecalculate(currentActiveHubs) {
    let covered = 0;
    const subDistrictsList = ['Pontianak Barat', 'Pontianak Kota', 'Pontianak Selatan', 'Pontianak Tenggara', 'Pontianak Timur', 'Pontianak Utara'];
    const updatedHh = households.map((hh, idx) => {
      let closestHub = null;
      let minDistance = Infinity;

      if (hh.manual_override_assigned_hub) {
        closestHub = currentActiveHubs.find(h => h.id === hh.db_assigned_hub_id);
      } else {
        currentActiveHubs.forEach(hub => {
          const dist = mapInstance.current.distance([hh.lat, hh.lng], [hub.lat, hub.lng]);
          const hubRadius = parseInt(hub.radius) || 500;
          if (dist <= hubRadius && dist < minDistance) {
            minDistance = dist;
            closestHub = hub;
          }
        });
      }

      const wasCovered = hh.covered;
      hh.covered = !!closestHub;
      hh.assigned_hub_type = closestHub ? closestHub.type : null;
      if (hh.covered) covered++;

      // Spatially recalculate kecamatan sub district on the fly during drag
      hh.sub_district = getKecamatanForPoint(hh.lat, hh.lng) || 'Belum Terpetakan';

      // Visually toggle icon colors on drag without re-rendering everything
      if (wasCovered !== hh.covered && hhMarkersRef.current[hh.id]) {
        const isVerified = hh.status === 'Verified';
        let markerColor = 'var(--danger)';
        if (isVerified) {
          markerColor = hh.covered ? 'var(--success)' : 'var(--danger)';
        } else {
          markerColor = hh.covered ? '#f59e0b' : '#64748b'; // Orange if inside, Gray if outside
        }
        const icon = getCustomIcon(markerColor, 'fas fa-user');
        hhMarkersRef.current[hh.id].setIcon(icon);
      }

      return hh;
    });

    const total = updatedHh.length;
    const uncovered = total - covered;
    const equality = total > 0 ? Math.round((covered / total) * 100) : 0;

    if (profile) {
      setStats({
        hubsCount: currentActiveHubs.length,
        coveredCount: covered,
        uncoveredCount: uncovered,
        equalityIndex: equality
      });

      updateChartsData(updatedHh);
    }
  };

  // Initialize Statistics Charts
  function initCharts() {
    const barCtx = barChartRef.current.getContext('2d');
    barChartInstance.current = new Chart(barCtx, {
      type: 'bar',
      data: { labels: [], datasets: [] },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        scales: {
          y: { beginAtZero: true, grid: { color: 'rgba(0,0,0,0.05)' } },
          x: { grid: { display: false } }
        },
        plugins: { legend: { position: 'bottom', labels: { boxWidth: 12 } } }
      }
    });

    const donutCtx = donutChartRef.current.getContext('2d');
    donutChartInstance.current = new Chart(donutCtx, {
      type: 'doughnut',
      data: { labels: [], datasets: [] },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: { legend: { position: 'right', labels: { boxWidth: 12 } } },
        cutout: '70%',
        borderWidth: 0
      }
    });
  };

  // Update Data inside Chart Instances
  function updateChartsData(currentHouseholds) {
    if (!barChartInstance.current || !donutChartInstance.current) return;

    // 1. Update Bar Chart (Sub-Districts) using Pontianak's exact 6 kecamatan
    const subDistrictsList = ['Pontianak Barat', 'Pontianak Kota', 'Pontianak Selatan', 'Pontianak Tenggara', 'Pontianak Timur', 'Pontianak Utara'];
    const subDistrictsMap = {};
    subDistrictsList.forEach(sub => {
      subDistrictsMap[sub] = { covered: 0, uncovered: 0 };
    });

    currentHouseholds.forEach(hh => {
      const sub = hh.sub_district || 'Other';
      if(!subDistrictsMap[sub]) subDistrictsMap[sub] = { covered: 0, uncovered: 0 };
      if(hh.covered) subDistrictsMap[sub].covered++;
      else subDistrictsMap[sub].uncovered++;
    });

    const labels = Object.keys(subDistrictsMap);
    const dataCovered = labels.map(l => subDistrictsMap[l].covered);
    const dataUncovered = labels.map(l => subDistrictsMap[l].uncovered);

    barChartInstance.current.data.labels = labels;
    barChartInstance.current.data.datasets = [
      { label: 'Terlayani', data: dataCovered, backgroundColor: '#10b981', borderRadius: 4 },
      { label: 'Belum Terlayani', data: dataUncovered, backgroundColor: '#ef4444', borderRadius: 4 }
    ];
    barChartInstance.current.update('none');

    // 2. Update Donut Chart (Hub types)
    const typeCounts = {};
    currentHouseholds.forEach(hh => {
      if(hh.covered && hh.assigned_hub_type) {
        typeCounts[hh.assigned_hub_type] = (typeCounts[hh.assigned_hub_type] || 0) + 1;
      }
    });

    const dLabels = Object.keys(typeCounts);
    const dData = Object.values(typeCounts);
    const colors = ['#3b82f6', '#8b5cf6', '#ec4899', '#f59e0b', '#10b981'];

    donutChartInstance.current.data.labels = dLabels;
    donutChartInstance.current.data.datasets = [{
      data: dData,
      backgroundColor: colors.slice(0, dLabels.length),
      hoverOffset: 4
    }];
    donutChartInstance.current.update('none');
  };

  const fetchDonations = async (hubId) => {
    const { data, error } = await supabase
      .from('donations')
      .select('*, profiles(full_name)')
      .eq('hub_id', hubId)
      .order('transaction_date', { ascending: false });
    
    if (error) {
      console.error("Error fetching donations", error);
    } else {
      setDonationsList(data || []);
    }
  };

  const handleSaveDonation = async (e) => {
    e.preventDefault();
    if (!activeDonationHub) return;
    if (isSubmittingDonation) return;
    setIsSubmittingDonation(true);
    
    const data = {
      hub_id: activeDonationHub.id,
      transaction_date: donationFormData.transaction_date,
      amount: parseFloat(donationFormData.amount),
      type: donationFormData.type,
      description: donationFormData.description,
      recorded_by: user?.id
    };

    try {
      const { error } = await supabase.from('donations').insert([data]);
      if (error) {
        alert(`Error saving donation: ${error.message}`);
        return;
      }

      setDonationFormData({ amount: '', type: 'IN', description: '', transaction_date: new Date().toISOString().split('T')[0] });
      fetchDonations(activeDonationHub.id);
    } finally {
      setIsSubmittingDonation(false);
    }
  };

  // Save new hub
  const handleSaveHub = async (e) => {
    e.preventDefault();
    const data = {
      name: hubFormData.name,
      type: hubFormData.type,
      radius_meter: parseInt(hubFormData.radius_meter) || 500,
      location: `POINT(${hubFormData.lng} ${hubFormData.lat})`,
      address: hubFormData.address,
      pic_phone: hubFormData.pic_phone || null
    };

    let error;
    if (hubFormData.id) {
      const res = await supabase.from('hubs').update(data).eq('id', hubFormData.id);
      error = res.error;
    } else {
      const res = await supabase.from('hubs').insert([data]);
      error = res.error;
    }

    if (error) {
      console.error("Error saving hub:", error.message || error.details || error);
      alert(`Error saving hub: ${error.message || error.details || JSON.stringify(error)}`);
    } else {
      setShowHubModal(false);
      fetchData();
    }
  };

  const handleVerifyAction = async (id, status) => {
    const { error } = await supabase.from('households').update({ status }).eq('id', id);
    if (error) {
      alert(`Error updating status: ${error.message}`);
    } else {
      fetchData();
    }
  };

  const handleFocusHousehold = (hh) => {
    if (!mapInstance.current) return;
    
    // 1. Close modal
    setShowApprovalModal(false);
    
    // 2. Set view to coordinate with high zoom
    mapInstance.current.setView([hh.lat, hh.lng], 18);
    
    // 3. Auto-open marker popup after small timeout
    setTimeout(() => {
      const marker = hhMarkersRef.current[hh.id];
      if (marker) {
        marker.openPopup();
      }
    }, 400);
  };

  const handleFocusHub = (hub) => {
    if (!mapInstance.current || !hub) return;
    mapInstance.current.setView([hub.lat, hub.lng], 17);
    setTimeout(() => {
      const marker = hubMarkersRef.current[hub.id];
      if (marker) {
        marker.openPopup();
      }
    }, 400);
  };

  const handleOpenKas = (hub) => {
    if (!hub) return;
    setActiveDonationHub(hub);
    fetchDonations(hub.id);
    setShowDonationModal(true);
  };

  const handleSaveHh = async (e) => {
    e.preventDefault();
    setIsUploading(true);
    let finalPhotoUrl = hhFormData.photo_url || 'https://via.placeholder.com/150';

    if (imageFile) {
      const fileName = `public/${Date.now()}_${imageFile.name}`;
      const { data: uploadData, error: uploadError } = await supabase.storage
        .from('geotagging-photo')
        .upload(fileName, imageFile);

      if (uploadError) {
        alert(`Error uploading image: ${uploadError.message}`);
        setIsUploading(false);
        return;
      }
      finalPhotoUrl = uploadData.path;
    }

    // Determine sub-district dynamically
    let subDistrictName = 'Belum Terpetakan';
    if (hhFormData.lat && hhFormData.lng) {
      const matched = getKecamatanForPoint(parseFloat(hhFormData.lat), parseFloat(hhFormData.lng));
      if (matched) subDistrictName = matched;
    }

    const data = {
      head_name: hhFormData.head_name,
      nik: hhFormData.nik || null,
      no_kk: hhFormData.no_kk || null,
      family_size: parseInt(hhFormData.family_size) || 1,
      status: hhFormData.status || 'Pending',
      photo_url: finalPhotoUrl,
      assigned_hub_id: hhFormData.assigned_hub_id || null,
      sub_district: subDistrictName,
      manual_override_assigned_hub: hhFormData.assigned_hub_id ? true : false
    };

    if (hhFormData.id) {
      // If Super Admin is editing and changes the hub assignment, instead of immediately shifting the hub,
      // we route it to the target Hub's "Delegasi Masuk" pending transfer queue!
      const originalHh = households.find(h => h.id === hhFormData.id);
      const isSuperAdmin = profileRef.current?.role === 'super_admin';
      
      if (isSuperAdmin && originalHh && hhFormData.assigned_hub_id !== originalHh.db_assigned_hub_id) {
        if (hhFormData.assigned_hub_id !== null) {
          data.assigned_hub_id = originalHh.db_assigned_hub_id;
          data.pending_transfer_hub_id = hhFormData.assigned_hub_id;
          data.manual_override_assigned_hub = originalHh.manual_override_assigned_hub;
        }
      }

      const { error } = await supabase.from('households').update(data).eq('id', hhFormData.id);
      if (error) {
        alert(`Gagal menyimpan data warga: ${error.message}`);
      } else {
        setShowHhModal(false);
        setImageFile(null);
        fetchData();
      }
    } else {
      // It's a new household, construct PostGIS POINT geometry and determine default status
      const defaultStatus = profileRef.current?.role === 'super_admin' ? 'Verified' : 'Pending';
      const insertData = {
        ...data,
        status: defaultStatus,
        location: `POINT(${hhFormData.lng} ${hhFormData.lat})`,
        surveyor_id: user ? user.id : null
      };

      const { error } = await supabase.from('households').insert([insertData]);
      if (error) {
        alert(`Gagal menambah data warga: ${error.message || JSON.stringify(error)}`);
      } else {
        setShowHhModal(false);
        setImageFile(null);
        fetchData();
      }
    }
    setIsUploading(false);
  };

  return (
    <>
      <div 
        id="map" 
        ref={mapRef} 
        style={{ 
          height: '100vh', 
          width: '100vw', 
          position: 'absolute', 
          top: 0, 
          left: 0, 
          zIndex: 1, 
          cursor: placementMode ? 'crosshair' : '' 
        }}
      ></div>

      {/* Show Panel Buttons */}
      <button className={`show-panel-btn ${!showTopBar ? '' : 'hidden'}`} id="showTopBarBtn" onClick={() => setShowTopBar(true)}>
        <i className="fas fa-chevron-down"></i> Tampilkan Header
      </button>
      <button className={`show-panel-btn ${!showControls ? '' : 'hidden'}`} id="showControlsBtn" onClick={() => setShowControls(true)}>
        <i className="fas fa-sliders-h"></i> Tampilkan Menu Kontrol
      </button>
      <button className={`show-panel-btn ${!showStats ? '' : 'hidden'}`} id="showStatsBtn" onClick={() => setShowStats(true)}>
        <i className="fas fa-chart-pie"></i> Tampilkan Statistik
      </button>
      <button className={`show-panel-btn ${!showLegend ? '' : 'hidden'}`} id="showLegendBtn" onClick={() => setShowLegend(true)}>
        <i className="fas fa-list-ul"></i> Tampilkan Legenda
      </button>

      {/* Top Header */}
      <header className={`top-bar glass-panel ${showTopBar ? '' : 'hidden'}`} id="topBar">
        <div className="logo">
          <i className="fas fa-hands-holding-circle"></i> <span>Sinergi Umat</span>
        </div>
        <div className="search-container">
          <i className="fas fa-search" style={{ color: 'rgba(0,0,0,0.4)' }}></i>
          <input 
            type="text" 
            placeholder="Cari lokasi rumah ibadah..." 
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
          />
        </div>
        <div className="top-bar-right" style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
          {!user ? (
            <button 
              className="login-btn" 
              onClick={() => router.push('/login')}
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: '8px',
                padding: '8px 20px',
                borderRadius: '20px',
                fontSize: '0.9rem',
                fontWeight: '600',
                background: 'linear-gradient(135deg, var(--primary), #6366f1)',
                color: 'white',
                border: 'none',
                cursor: 'pointer',
                boxShadow: '0 4px 10px rgba(59, 130, 246, 0.3)',
                transition: 'all 0.2s'
              }}
              onMouseOver={(e) => e.currentTarget.style.transform = 'translateY(-1px)'}
              onMouseOut={(e) => e.currentTarget.style.transform = 'translateY(0)'}
            >
              <i className="fas fa-sign-in-alt"></i> Login
            </button>
          ) : (
            <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
              <span style={{ fontSize: '0.85rem', color: 'var(--text-muted)', fontWeight: '500' }}>
                Halo, <strong style={{ color: 'var(--text-main)' }}>{profile?.full_name || user.email}</strong>
              </span>
              <div 
                className="avatar" 
                title="Klik untuk melihat Profil & Logout" 
                onClick={() => setShowProfileModal(true)} 
                style={{ 
                  cursor: 'pointer', 
                  display: 'flex', 
                  alignItems: 'center', 
                  justifyContent: 'center', 
                  background: 'linear-gradient(135deg, var(--primary), #6366f1)', 
                  color: 'white',
                  width: '36px', 
                  height: '36px', 
                  borderRadius: '50%', 
                  fontWeight: 'bold',
                  boxShadow: '0 4px 10px rgba(59, 130, 246, 0.3)',
                  transition: 'transform 0.2s'
                }}
                onMouseOver={(e) => e.currentTarget.style.transform = 'scale(1.05)'}
                onMouseOut={(e) => e.currentTarget.style.transform = 'scale(1)'}
              >
                {profile?.full_name ? profile.full_name.substring(0, 2).toUpperCase() : 'US'}
              </div>
            </div>
          )}
          <button className="btn-toggle-panel" onClick={() => setShowTopBar(false)} title="Sembunyikan Header">
            <i className="fas fa-chevron-up"></i>
          </button>
        </div>
      </header>

      {/* Left Panel (Controls) */}
      <div className={`left-panel glass-panel ${showControls ? '' : 'hidden'}`} id="controlsPanel">
        <div className="panel-title">
          <span className="title-text"><i className="fas fa-sliders-h"></i> Menu Kontrol</span>
          <button className="btn-toggle-panel" onClick={() => setShowControls(false)} title="Sembunyikan Kontrol">
            <i className="fas fa-chevron-left"></i>
          </button>
        </div>
        
        <SidebarControls 
          user={user} profile={profile} router={router}
          isEditMode={isEditMode} setIsEditMode={setIsEditMode}
          setShowApprovalModal={setShowApprovalModal} setShowUserModal={setShowUserModal}
          fetchUsers={fetchUsers} setPlacementMode={setPlacementMode}
          setShowToast={setShowToast} filters={filters} setFilters={setFilters}
          hubStyles={hubStyles}
          setShowSurveyModal={setShowSurveyModal}
          setShowCapacityModal={setShowCapacityModal}
          pendingCapacityCount={hubs.filter(h => h.pending_capacity_status !== null && h.pending_capacity_status !== undefined).length}
          setShowDelegationModal={setShowDelegationModal}
          pendingDelegationsCount={profile && profile.role === 'hub_head' ? households.filter(hh => hh.pending_transfer_hub_id === (hubs.find(h => h.head_id === profile.id)?.id)).length : 0}
          hubs={hubs}
          onFocusHub={handleFocusHub}
          onOpenKas={handleOpenKas}
          setShowPicListModal={setShowPicListModal}
          onlyMyHub={onlyMyHub}
          setOnlyMyHub={setOnlyMyHub}
        />
      </div>

      {/* Right Panel (Stats) */}
      <div className={`right-panel glass-panel ${showStats ? '' : 'hidden'}`} id="statsPanel">
        <div className="panel-title">
          <span className="title-text"><i className="fas fa-chart-pie"></i> {profile?.role === 'hub_head' || profile?.role === 'pic' ? 'Statistik Mikro (Wilayah Anda)' : 'Statistik Makro (Tingkat Kota)'}</span>
          <button className="btn-toggle-panel" onClick={() => setShowStats(false)}><i className="fas fa-chevron-right"></i> Sembunyikan</button>
        </div>
        
        <div className="kpi-container">
          <div className="kpi-box">
            <div className="kpi-value text-primary">{stats.hubsCount}</div>
            <div className="kpi-label">Hub Rumah Ibadah</div>
          </div>
          <div className="kpi-box">
            <div className="kpi-value text-success">{stats.coveredCount}</div>
            <div className="kpi-label">Warga Terlayani</div>
          </div>
          <div className="kpi-box">
            <div className="kpi-value text-danger">{stats.uncoveredCount}</div>
            <div className="kpi-label">Belum Terlayani</div>
          </div>
        </div>

        <div className="chart-box">
          <h4>Cakupan per Kecamatan</h4>
          <div style={{ position: 'relative', height: '180px', width: '100%' }}>
            <canvas ref={barChartRef}></canvas>
          </div>
        </div>

        <div className="chart-box">
          <h4>Penyebaran Bantuan per Tipe Hub</h4>
          <div style={{ position: 'relative', height: '180px', width: '100%' }}>
            <canvas ref={donutChartRef}></canvas>
          </div>
        </div>

        <div className="chart-box">
          <h4>Indeks Pemerataan Bantuan</h4>
          <div className="gauge-container">
            <div className="gauge" style={{ background: 'rgba(0,0,0,0.1)' }}>
              <div 
                className="gauge-fill" 
                style={{ 
                  transform: `rotate(${stats.equalityIndex / 200}turn)`,
                  background: 'linear-gradient(to right, var(--danger), #f59e0b, var(--success))'
                }}
              ></div>
              <div className="gauge-cover" style={{ background: 'white' }}>{stats.equalityIndex}%</div>
            </div>
          </div>
        </div>
      </div>

      {/* Legend */}
      <div 
        className={`legend glass-panel ${showLegend ? '' : 'hidden'}`} 
        id="legendPanel"
        style={{
          display: 'flex',
          flexDirection: 'row',
          alignItems: 'center',
          gap: '14px',
          padding: '8px 16px',
          width: 'auto',
          height: '42px',
          bottom: '20px',
          left: '2%',
          borderRadius: '24px',
          fontSize: '0.8rem',
          fontWeight: '500'
        }}
      >
        <div style={{ display: 'flex', alignItems: 'center', gap: '8px', color: 'var(--text-muted)', fontWeight: '600', marginRight: '4px' }}>
          <i className="fas fa-list-ul" style={{ color: 'var(--primary)' }}></i>
          <span>LEGENDA</span>
        </div>

        <div style={{ width: '1px', height: '16px', background: 'rgba(0,0,0,0.15)' }}></div>

        {profile && (
          <>
            <div className="legend-item" style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
              <div className="legend-color" style={{ background: 'var(--success)', width: '12px', height: '12px', borderRadius: '50%', border: 'none' }}></div> 
              <span>Terverifikasi & Terlayani</span>
            </div>
            
            <div className="legend-item" style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
              <div className="legend-color" style={{ background: 'var(--danger)', width: '12px', height: '12px', borderRadius: '50%', border: 'none' }}></div> 
              <span>Terverifikasi & Belum Terlayani</span>
            </div>

            <div className="legend-item" style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
              <div className="legend-color" style={{ background: '#f59e0b', width: '12px', height: '12px', borderRadius: '50%', border: 'none' }}></div> 
              <span>Pending & Terlayani</span>
            </div>

            <div className="legend-item" style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
              <div className="legend-color" style={{ background: '#64748b', width: '12px', height: '12px', borderRadius: '50%', border: 'none' }}></div> 
              <span>Pending & Belum Terlayani</span>
            </div>

            <div style={{ width: '1px', height: '16px', background: 'rgba(0,0,0,0.15)' }}></div>

            <div className="legend-item" style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
              <div style={{ 
                width: '48px', height: '10px', borderRadius: '5px',
                background: 'linear-gradient(to right, #3b82f6, #06b6d4, #eab308, #ef4444)',
                border: 'none'
              }}></div>
              <span>Kepadatan KK</span>
            </div>

            <div style={{ width: '1px', height: '16px', background: 'rgba(0,0,0,0.15)' }}></div>
          </>
        )}

        <div className="legend-item" style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
          <div className="pulse-border" style={{ 
            width: '16px', 
            height: '16px', 
            borderRadius: '50%', 
            border: '2px dashed #ef4444',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            background: '#ef4444',
            color: 'white',
            fontSize: '8px',
            position: 'relative'
          }}>
            <i className="fas fa-exclamation" style={{ fontSize: '7px' }}></i>
          </div>
          <span>Hub Overloaded / Kritis</span>
        </div>

        <div style={{ width: '1px', height: '16px', background: 'rgba(0,0,0,0.15)' }}></div>

        <button 
          className="btn-toggle-panel" 
          onClick={() => setShowLegend(false)} 
          title="Hide Legend"
          style={{
            background: 'none',
            border: 'none',
            color: 'var(--text-muted)',
            cursor: 'pointer',
            padding: '2px',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            fontSize: '0.85rem'
          }}
        >
          <i className="fas fa-times"></i>
        </button>
      </div>

      {/* Placement Toast */}
      {showToast && (
        <div className="placement-toast glass-panel" style={{ display: 'flex' }}>
          <span><i className="fas fa-info-circle text-primary"></i> Klik pada peta untuk menempatkan <strong>{placementMode === 'hub' ? 'Hub Rumah Ibadah' : 'Data KK Warga'}</strong></span>
          <button onClick={() => { setPlacementMode(null); setShowToast(false); }}>Batal</button>
        </div>
      )}

      {/* Hub Modal */}
      <HubFormModal 
        showHubModal={showHubModal} setShowHubModal={setShowHubModal}
        hubFormData={hubFormData} setHubFormData={setHubFormData}
        handleSaveHub={handleSaveHub} isEditMode={isEditMode}
      />

      <HouseholdFormModal 
        showHhModal={showHhModal} setShowHhModal={setShowHhModal}
        hhFormData={hhFormData} setHhFormData={setHhFormData}
        handleSaveHh={handleSaveHh} hubs={hubs}
        imageFile={imageFile} setImageFile={setImageFile}
        isUploading={isUploading} isEditMode={isEditMode}
        profile={profile}
      />

      <DonationModal 
        showDonationModal={showDonationModal} setShowDonationModal={setShowDonationModal}
        donationFormData={donationFormData} setDonationFormData={setDonationFormData}
        hubs={hubs} isSubmittingDonation={isSubmittingDonation}
        handleSaveDonation={handleSaveDonation} donationsList={donationsList}
        profile={profile}
      />

      <ApprovalQueueModal 
        showApprovalModal={showApprovalModal} setShowApprovalModal={setShowApprovalModal}
        households={households} selectedPhotoUrl={selectedPhotoUrl}
        setSelectedPhotoUrl={setSelectedPhotoUrl} handleVerifyAction={handleVerifyAction}
        onFocusHousehold={handleFocusHousehold}
      />

      <CapacityApprovalModal 
        showApprovalModal={showCapacityModal} setShowApprovalModal={setShowCapacityModal}
        hubs={hubs} households={households}
        showToastNotification={showToastNotification}
        onSuccess={fetchData}
      />

      <DelegationQueueModal 
        showDelegationModal={showDelegationModal}
        setShowDelegationModal={setShowDelegationModal}
        households={households}
        hubs={allHubs}
        myHub={profile && (profile.role === 'pic' || profile.role === 'hub_head') ? allHubs.find(h => h.pic_id === profile.id || h.head_id === profile.id) : null}
        selectedPhotoUrl={selectedPhotoUrl}
        setSelectedPhotoUrl={setSelectedPhotoUrl}
        onFocusHousehold={handleFocusHousehold}
        fetchData={fetchData}
        showToastNotification={showToastNotification}
      />

      <UserProvisioningModal 
        showUserModal={showUserModal} setShowUserModal={setShowUserModal}
        usersList={usersList} profile={profile}
        userFormData={userFormData} setUserFormData={setUserFormData}
        handleCreateUser={handleCreateUser} isSubmittingUser={isSubmittingUser}
        handleDeleteUser={handleDeleteUser}
        hubs={hubs}
      />

      <ProfileModal 
        showProfileModal={showProfileModal}
        setShowProfileModal={setShowProfileModal}
        profile={profile}
        user={user}
        handleLogout={handleLogout}
        isLoggingOut={isLoggingOut}
      />

      <PicListModal 
        showPicListModal={showPicListModal}
        setShowPicListModal={setShowPicListModal}
        myHub={profile && (profile.role === 'pic' || profile.role === 'hub_head') ? hubs.find(h => h.pic_id === profile.id || h.head_id === profile.id) : null}
        usersList={usersList}
      />

      <SurveyMethodModal 
        showSurveyModal={showSurveyModal}
        setShowSurveyModal={setShowSurveyModal}
        setPlacementMode={setPlacementMode}
        setShowToast={setShowToast}
        hubs={hubs}
        mapInstance={mapInstance}
        setHhFormData={setHhFormData}
        setImageFile={setImageFile}
        setShowHhModal={setShowHhModal}
        showToastNotification={showToastNotification}
        profile={profile}
      />

      {/* Custom Toast Notification */}
      {webNotification && (
        <div 
          style={{
            position: 'fixed',
            top: '24px',
            right: '24px',
            zIndex: 9999,
            display: 'flex',
            alignItems: 'center',
            gap: '12px',
            padding: '16px 24px',
            borderRadius: '16px',
            background: webNotification.type === 'success' ? 'rgba(16, 185, 129, 0.95)' : 'rgba(239, 68, 68, 0.95)',
            backdropFilter: 'blur(10px)',
            color: 'white',
            fontWeight: '600',
            fontSize: '0.9rem',
            boxShadow: '0 10px 25px rgba(0, 0, 0, 0.25)',
            border: webNotification.type === 'success' ? '1px solid rgba(16, 185, 129, 0.3)' : '1px solid rgba(239, 68, 68, 0.3)',
            animation: 'slideInRight 0.3s cubic-bezier(0.4, 0, 0.2, 1)'
          }}
        >
          <i className={webNotification.type === 'success' ? 'fas fa-circle-check' : 'fas fa-triangle-exclamation'} style={{ fontSize: '1.2rem' }}></i>
          <span>{webNotification.message}</span>
        </div>
      )}

      {/* Custom Confirmation Modal */}
      {confirmDialog && (
        <div 
          className="modal-overlay active" 
          style={{ zIndex: 9999 }}
        >
          <div 
            className="modal-content"
            style={{
              maxWidth: '400px',
              width: '95%',
              padding: '24px',
              animation: 'fadeInScale 0.2s ease-out'
            }}
          >
            <div style={{ display: 'flex', gap: '16px', marginBottom: '20px' }}>
              <div 
                style={{ 
                  background: 'rgba(239, 68, 68, 0.1)', 
                  color: 'var(--danger)', 
                  width: '48px', 
                  height: '48px', 
                  borderRadius: '50%', 
                  display: 'flex', 
                  alignItems: 'center', 
                  justifyContent: 'center',
                  fontSize: '1.5rem',
                  flexShrink: 0
                }}
              >
                <i className="fas fa-trash-alt"></i>
              </div>
              <div style={{ textAlign: 'left' }}>
                <h3 style={{ margin: '0 0 8px 0', fontSize: '1.2rem', fontWeight: '700', color: 'var(--text-main)' }}>
                  {confirmDialog.title}
                </h3>
                <p style={{ margin: 0, fontSize: '0.9rem', color: 'var(--text-muted)', lineHeight: '1.5' }}>
                  {confirmDialog.message}
                </p>
              </div>
            </div>
            <div style={{ display: 'flex', gap: '12px', justifyContent: 'flex-end' }}>
              <button 
                className="btn btn-outline" 
                onClick={confirmDialog.onCancel}
                style={{ flex: 1, padding: '10px' }}
              >
                Batal
              </button>
              <button 
                className="btn btn-danger" 
                onClick={confirmDialog.onConfirm}
                style={{ 
                  flex: 1, 
                  padding: '10px', 
                  background: 'var(--danger)', 
                  color: 'white',
                  border: 'none',
                  borderRadius: '12px',
                  fontWeight: '600',
                  cursor: 'pointer'
                }}
              >
                Hapus
              </button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}