



import { Component, OnInit, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { MapService } from '../Services/map.service';
import { LocationsService } from '../Services/locations.service';
import { SectorService } from '../Services/sector.service';
import { DefaultMapDTO } from '../Models/map.model';
import { LocationDTO, LocationType } from '../Models/location.model';
import { SectorDTO } from '../Models/sector.model';
import { I18nService, SupportedLanguage } from '../Services/i18n.service';
import { SidebarAnimationStyle, SidebarConfig, SidebarConfigService, SidebarPosition } from '../Services/sidebar-config.service';
import Swal from 'sweetalert2';
import * as Cesium from 'cesium';
import * as turf from '@turf/turf';
import { forkJoin } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { MatDialog } from '@angular/material/dialog';
import { PolygonContentDialogComponent } from '../polygon-content-dialog/polygon-content-dialog.component';
// @ts-ignore
import { reshape } from 'arabic-persian-reshaper';
import { TextStyleService } from '../Services/text-style.service';
import { SettingsService } from '../Services/settings.service';
import {  LocationContentDTO, } from '../Models/location.model';
@Component({
  selector: 'app-map-settings',
  templateUrl: './map-settings.component.html',
  styleUrls: ['./map-settings.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MapSettingsComponent implements OnInit, AfterViewInit {
   zoneChildEntities: Map<number, Cesium.Entity[]> = new Map();
    maps: DefaultMapDTO[] = [];
  filteredMaps: DefaultMapDTO[] = [];
  searchQuery: string = '';
  selectedDefaultMapId: number | null = null;
  newMap: DefaultMapDTO = {
    countryName: '',
    borderColor: '#FFFF00',
    fillOpacity: 0.3,
    borderWidth: 2
  };
  zoneChildMap: Map<number, LocationDTO[]> = new Map();
  showCreateForm: boolean = false;
  selectedName: string | null = null;
    selectedContents: LocationContentDTO[] = [];
    selectedLocation: LocationDTO | null = null;
    currentZoneChildPoints: LocationDTO[] = []; // Child points of the selected zone
    currentZoneId: number | null = null;
 currentZoneProjectZoneId: number | string | null = null;
 showSidebarCustomization: boolean = false;
  // Country selection from GeoJSON
  availableCountries: string[] = [];
  filteredCountries: string[] = [];
  countrySearchQuery: string = '';
  showCountryDropdown: boolean = false;
 currentZoneProjectEntities: Cesium.Entity[] = [];
  // Cesium viewer
  viewer!: Cesium.Viewer;
  currentLoadedMap: DefaultMapDTO | null = null;
  currentMap: any; // Active map from MapService (for creating locations)
  countryLocationId: number | null = null; // backend country node id when available
 filteredSectors: SectorDTO[] = [];
  sidebarConfig: SidebarConfig;
  readonly sidebarPositions: SidebarPosition[] = ['inside-right', 'inside-left', 'left', 'right', 'top', 'bottom'];
  readonly sidebarAnimations: SidebarAnimationStyle[] = ['slide', 'fade', 'expand'];
  // Right sidebar for location details
  //selectedLocation: LocationDTO | null = null;
  showRightSidebar: boolean = false;
  showLocationsList: boolean = true;
  //selectedName: string | null = null;
 // selectedContents: any[] = [];
  filteredLocations: LocationDTO[] = [];
  allLocations: LocationDTO[] = [];
  navigableLocations: LocationDTO[] = [];
  currentLocationIndex: number = 0;
  countryBorders: any[] = [];
  selectedRightSidebarTab: string = 'ALL'; // 'ALL', 'DISTRICTS', 'GOVERNORATES'
  filteredDistricts: any[] = []; // Districts for sidebar list
  filteredGovernorates: any[] = []; // Governorates for sidebar list
  allDistricts: any[] = []; // All districts
  allGovernorates: any[] = []; // All governorates

  // Drawing functionality
  drawingPolygon = false;
  drawingPoint = false;
  polygonPoints: number[][] = [];
  tempPolygonEntity: Cesium.Entity | null = null;
  tempPointEntities: Cesium.Entity[] = [];
  displayedCountryBorders: Cesium.Entity[] = [];

  // Districts (zones) support
  currentLanguage: SupportedLanguage = 'en';
  districtLabelEntities: Cesium.Entity[] = [];
  districtLabelData: Map<string, { lon: number; lat: number; meta: any }> = new Map();
  selectedDistrict: { id: string; meta: any } | null = null;
  tunisiaDistrictMatchedFeatures: { [districtId: string]: any[] } = {}; // Store matched governorate features per district
  displayedDistrictEntities: Cesium.Entity[] = []; // Track currently displayed district governorate entities

  // Sectors and Projects support
  allSectors: SectorDTO[] = [];
  selectedSector: SectorDTO | null = null;
  selectedProject: LocationDTO | null = null;
  allProjects: LocationDTO[] = [];
  isCreatingProject: boolean = false; // Flag to indicate if user is creating a project vs regular point
  displayedProjectEntities: Cesium.Entity[] = [];
  showBrief: boolean = false;
  briefLayoutMode: 'split' | 'full' = 'full';
  // brief panel customization bindings
  briefBgColor: string = '#CFE8FF';
  briefText: string = '';
  briefTextColor: string = '#032b38';
  // sidebar overlay customization
  sidebarOverlayEffect: string = 'none';
  sidebarOverlayOpacity: number = 0.5;

  constructor(
    private mapService: MapService,
    private locationsService: LocationsService,
    private sectorService: SectorService,
    private http: HttpClient,
    private dialog: MatDialog,
    private i18nService: I18nService,
    private sidebarConfigService: SidebarConfigService,
    private textStyleService: TextStyleService,
    public settingsService: SettingsService,
    private cdr: ChangeDetectorRef
  ) {
    this.sidebarConfig = this.sidebarConfigService.getConfig();
  }

  toggleBrief(value: boolean) {
    this.showBrief = !!value;
    this.briefLayoutMode = this.showBrief ? 'split' : 'full';
    try {
      this.settingsService.updateSettings({
        showBrief: !!value,
        layoutMode: value ? 'split' : 'full'
      });
    } catch (e) {
      console.warn('toggleBrief failed', e);
    }
  }

  onBriefLayoutModeChanged(mode: 'split' | 'full'): void {
    this.briefLayoutMode = mode;
    this.toggleBrief(mode === 'split');
  }
  openSectorIds: Set<number> = new Set<number>();
  isSectorOpen(sector: SectorDTO | any): boolean {
    const id = Number(sector.id ?? sector.sectorId ?? sector.id);
    return this.openSectorIds.has(id);
  }
    toggleSector(sector: SectorDTO | any) {
      const id = Number(sector.id ?? sector.sectorId ?? sector.id);
      if (this.openSectorIds.has(id)) {
        this.openSectorIds.delete(id);
      } else {
        this.openSectorIds.add(id);
      }
    }
    toggleSidebarCustomization(): void {
  this.showSidebarCustomization = !this.showSidebarCustomization;
}
    onSectorProjectClick(project: LocationDTO): void {
        console.log('🖱️ Sector project clicked:', project);
    
        // First show the projects for the parent zone (so pin is visible)
        if ((project as any).parentId) {
          this.showProjectsForZone((project as any).parentId);
        }
    
        // Then select the project to show info
        this.selectProject(project);
      }
       showProjectsForZone(zoneId: number | string): void {
    // Toggle off if same zone clicked again
    if (String(this.currentZoneProjectZoneId) === String(zoneId)) {
      this.clearZoneProjects();
      return;
    }
    this.clearZoneProjects();
    this.currentZoneProjectZoneId = zoneId;

    // Always coerce both sides to string for comparison — avoids number/string mismatch
    const zoneIdStr = String(zoneId);
    const zoneProjects = this.allProjects.filter((p: any) =>
      p.parentId != null && String(p.parentId) === zoneIdStr
    );

    console.log(`🔍 showProjectsForZone(${zoneId}): ${zoneProjects.length} projects found`);
    console.log('🔍 All project parentIds:', this.allProjects.map((p: any) => String(p.parentId)));

    if (!zoneProjects.length) {
      console.warn(`⚠️ No projects for zone ${zoneId} — check that project parentId matches this zone's backend ID`);
      return;
    }

    this.renderZoneProjectPins(zoneProjects);
  }
    private async renderZoneProjectPins(projects: any[]): Promise<void> {
      for (const project of projects) {
        try {
          // If geometry is missing, fetch full project details from backend
          let fullProject = project;
          if (!project.geometry || !project.geometry.coordinates) {
            console.log(`📡 Fetching full details for project "${project.name}" (id: ${project.id})...`);
            try {
              fullProject = await this.locationsService.getLocationDetails(project.id).toPromise();
              console.log(`✅ Got full project:`, fullProject);
            } catch (fetchErr) {
              console.warn(`❌ Could not fetch details for project ${project.id}:`, fetchErr);
              continue; // skip this project if we can't get its geometry
            }
          }
  
          if (!fullProject.geometry || !fullProject.geometry.coordinates) {
            console.warn(`⚠️ Project "${fullProject.name}" still has no geometry after fetch — skipping`);
            continue;
          }
  
          const lon = Number(fullProject.geometry.coordinates[0]);
          const lat = Number(fullProject.geometry.coordinates[1]);
  
          if (isNaN(lon) || isNaN(lat)) {
            console.warn(`⚠️ Invalid coordinates for project "${fullProject.name}": lon=${lon}, lat=${lat}`);
            continue;
          }
  
          // Remove any existing entity with this id to avoid conflicts
          const entityId = `project-pin-${fullProject.id}`;
          const existing = this.viewer.entities.getById(entityId);
          if (existing) {
            this.viewer.entities.remove(existing);
          }
  
          const pinImage = this.createProjectDiamondPin();
          const entity = this.viewer.entities.add({
            id: entityId,
            position: Cesium.Cartesian3.fromDegrees(lon, lat),
            billboard: {
              image: pinImage,
              verticalOrigin: Cesium.VerticalOrigin.CENTER,
              horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
              disableDepthTestDistance: Number.POSITIVE_INFINITY,
              scaleByDistance: new Cesium.NearFarScalar(1.0e3, 1.3, 1.0e7, 0.5),
              width: 52,
              height: 52
            },
           /* label: {
              text: fullProject.name,
              font: 'bold 13px sans-serif',
              fillColor: Cesium.Color.fromCssColorString('#00FFFF'),
              outlineColor: Cesium.Color.BLACK,
              outlineWidth: 2,
              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
              verticalOrigin: Cesium.VerticalOrigin.TOP,
              horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
              pixelOffset: new Cesium.Cartesian2(0, 30),
              showBackground: true,
              backgroundColor: Cesium.Color.BLACK.withAlpha(0.75),
              backgroundPadding: new Cesium.Cartesian2(8, 5),
              disableDepthTestDistance: Number.POSITIVE_INFINITY,
              scaleByDistance: new Cesium.NearFarScalar(1.0e3, 1.0, 1.0e6, 0.5)
            },*/
            properties: { type: 'project', projectData: fullProject }
          });
  
          console.log(`✅ Rendered project pin: "${fullProject.name}" at (${lon}, ${lat})`);
          this.currentZoneProjectEntities.push(entity);
          this.displayedProjectEntities.push(entity);
  
        } catch (e) {
          console.error(`Failed to render project pin for "${project.name}":`, e);
        }
      }
  
      // Fly camera to show all rendered project pins
      if (this.currentZoneProjectEntities.length > 0) {
        this.viewer.flyTo(this.currentZoneProjectEntities, {
          duration: 1.5,
          offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-45), 0)
        });
      }
    }
    private createProjectDiamondPin(): string {
  return this.createDiamondPinIcon('#0b57d0', 52);
}
selectProject(project: LocationDTO | null): void {
  this.selectedProject = project;
  this.selectedDistrict = null;

  if (!project || !this.viewer) return;

  this.selectedLocation = project as any;
  this.selectedContents = (project as any).contents || [];
  this.selectedName = project.name;
  this.showLocationsList = false;
  this.showRightSidebar = true;

  // Find and select the entity — Cesium sticks the green box to it
  const entityId = `project-pin-${project.id}`;
  const entity = this.viewer.entities.getById(entityId);
  if (entity) {
    this.viewer.selectedEntity = entity;
    // flyTo the entity itself — Cesium calculates exact position, no drift
    this.viewer.flyTo(entity, {
      duration: 0.8,
      offset: new Cesium.HeadingPitchRange(
        this.viewer.camera.heading,
        this.viewer.camera.pitch,
        this.viewer.camera.positionCartographic.height
      )
    });
  }

  if (project.id) {
    this.locationsService.getLocationDetails(project.id).subscribe({
      next: (location: LocationDTO) => {
        this.selectedLocation = location;
        this.selectedContents = location.contents || [];
        this.selectedName = location.name;
      },
      error: (err) => console.warn('Could not fetch project details:', err)
    });
  }
}
  getFirstImage(): string | null {
    if (!this.selectedContents || this.selectedContents.length === 0) {
      return null;
    }
    for (const c of this.selectedContents) {
      const content = (c && (c.content || c)) || {};
      const type = String(content['type'] || '').toUpperCase();
      if (type === 'IMAGE') {
        return content['value'] || content['url'] || content['src'] || null;
      }
    }
    return null;
  }
  shouldDisablePrevious(): boolean {
    // Project navigation
    if (this.selectedProject && this.currentZoneProjectEntities.length > 0) {
      const zoneProjects = this.currentZoneProjectEntities
        .map(e => {
          const now = Cesium.JulianDate.now();
          const props = e.properties;
          if (!props) return null;
          const d = props['projectData']?.getValue ? props['projectData'].getValue(now) : props['projectData'];
          return d as LocationDTO;
        })
        .filter(Boolean) as LocationDTO[];
      const idx = zoneProjects.findIndex(p => p.id === this.selectedProject?.id);
      return idx <= 0;
    }
  
    // Districts tab
    if (this.selectedRightSidebarTab === 'DISTRICTS' || (this.selectedDistrict && !this.selectedLocation)) {
      const idx = this.filteredDistricts.findIndex((d: any) => d.id === this.selectedDistrict?.id);
      // Nothing selected → can't go previous
      if (idx < 0) return true;
      return idx <= 0;
    }
  
    // Governorates tab
    if (this.selectedRightSidebarTab === 'GOVERNORATES' || this.selectedLocation?.category === 'GOVERNORATE') {
      const normalize = (s: string) =>
        (s || '').toLowerCase().replace(/\s+/g, '').normalize('NFD').replace(/\p{Diacritic}/gu, '');
      const idx = this.filteredGovernorates.findIndex(
        (g: any) => normalize(g.displayName || g.name) === normalize(this.selectedLocation?.name || '')
      );
      if (idx < 0) return true;
      return idx <= 0;
    }
  
    return this.currentLocationIndex <= 0;
  }
  shouldDisableNext(): boolean {
    // Project navigation
    if (this.selectedProject && this.currentZoneProjectEntities.length > 0) {
      const zoneProjects = this.currentZoneProjectEntities
        .map(e => {
          const now = Cesium.JulianDate.now();
          const props = e.properties;
          if (!props) return null;
          const d = props['projectData']?.getValue ? props['projectData'].getValue(now) : props['projectData'];
          return d as LocationDTO;
        })
        .filter(Boolean) as LocationDTO[];
      const idx = zoneProjects.findIndex(p => p.id === this.selectedProject?.id);
      return idx >= zoneProjects.length - 1;
    }
  
    // Districts tab
    if (this.selectedRightSidebarTab === 'DISTRICTS' || (this.selectedDistrict && !this.selectedLocation)) {
      const idx = this.filteredDistricts.findIndex((d: any) => d.id === this.selectedDistrict?.id);
      // If nothing selected, we can still go next (to first)
      if (idx < 0) return this.filteredDistricts.length === 0;
      return idx >= this.filteredDistricts.length - 1;
    }
  
    // Governorates tab
    if (this.selectedRightSidebarTab === 'GOVERNORATES' || this.selectedLocation?.category === 'GOVERNORATE') {
      const normalize = (s: string) =>
        (s || '').toLowerCase().replace(/\s+/g, '').normalize('NFD').replace(/\p{Diacritic}/gu, '');
      const idx = this.filteredGovernorates.findIndex(
        (g: any) => normalize(g.displayName || g.name) === normalize(this.selectedLocation?.name || '')
      );
      if (idx < 0) return this.filteredGovernorates.length === 0;
      return idx >= this.filteredGovernorates.length - 1;
    }
  
    return this.currentLocationIndex >= this.filteredLocations.length - 1;
  }
 hasImage(): boolean {
    return this.getFirstImage() !== null;
  }
  ngOnInit(): void {
    this.loadMaps();
    this.loadSectors();

    this.settingsService.settings$.subscribe(settings => {
      const resolvedMode = settings?.layoutMode ?? (settings?.showBrief ? 'split' : 'full');
      this.briefLayoutMode = resolvedMode;
      this.showBrief = resolvedMode === 'split' && !!settings?.showBrief;
      // apply customization bindings
      this.briefBgColor = settings?.briefBgColor ?? this.briefBgColor;
      this.briefText = settings?.briefText ?? this.briefText;
      this.briefTextColor = settings?.briefTextColor ?? this.briefTextColor;
      // overlay bindings
      this.sidebarOverlayEffect = settings?.sidebarOverlayEffect ?? this.sidebarOverlayEffect;
      this.sidebarOverlayOpacity = (typeof settings?.sidebarOverlayOpacity === 'number') ? settings.sidebarOverlayOpacity : this.sidebarOverlayOpacity;
      this.cdr.markForCheck();
    });

    // Keep sidebar config reactive for both default and map-specific values.
    this.sidebarConfigService.getConfig$().subscribe(() => {
      this.applyResolvedSidebarConfig();
    });

      // Load all locations for navigation and filtering (mimic cesium-map)
      // Use getLocationsByMapWithGeometry for the current map if available
      this.mapService.getActiveMap$().subscribe(map => {
        this.currentMap = map;
        this.sidebarConfigService.setActiveMapId(map?.id ?? null);
        this.applyResolvedSidebarConfig();
        if (map && map.id) {
          this.locationsService.getLocationsByMapWithGeometry(map.id, true).subscribe({
            next: (locations) => {
              this.allLocations = locations;
              this.filteredLocations = locations;
            },
            error: (err) => {
              console.error('Error loading all locations:', err);
            }
          });
        }
      });

    // Subscribe to active map (for creating locations)
    this.mapService.getActiveMap$().subscribe(map => {
      this.currentMap = map;
      if (map && map.id) {
        this.loadProjects();
      }
    });

    this.locationsService.locationCreated$.subscribe(() => {
      if (!this.currentMap?.id) return;
      this.locationsService.getLocationsByMapWithGeometry(this.currentMap.id, true).subscribe({
        next: (locations) => {
          this.allLocations = locations;
          this.filteredLocations = locations;
          this.cdr.markForCheck();
        },
        error: () => {}
      });
      this.loadProjects();
    });

    this.locationsService.locationUpdated$.subscribe(() => {
      if (!this.currentMap?.id) return;
      this.locationsService.getLocationsByMapWithGeometry(this.currentMap.id, true).subscribe({
        next: (locations) => {
          this.allLocations = locations;
          this.filteredLocations = locations;
          this.cdr.markForCheck();
        },
        error: () => {}
      });
      this.loadProjects();
    });

    this.locationsService.locationDeleted$.subscribe(() => {
      if (!this.currentMap?.id) return;
      this.locationsService.getLocationsByMapWithGeometry(this.currentMap.id, true).subscribe({
        next: (locations) => {
          this.allLocations = locations;
          this.filteredLocations = locations;
          this.cdr.markForCheck();
        },
        error: () => {}
      });
      this.loadProjects();
    });

    // Load country borders GeoJSON and extract country names
    this.http.get('assets/countries.geojson').subscribe((geojson: any) => {
      this.countryBorders = geojson.features || [];

      // Extract unique country names from GeoJSON
      const countryNames = new Set<string>();
      this.countryBorders.forEach((feature: any) => {
        const name = feature.properties?.ADMIN || feature.properties?.name;
        if (name) {
          countryNames.add(name);
        }
      });

      // Sort countries alphabetically
      this.availableCountries = Array.from(countryNames).sort();
      this.filteredCountries = this.availableCountries;
    });

    // Subscribe to language changes to update district labels
    this.i18nService.currentLanguage$.subscribe(language => {
      this.currentLanguage = language;
      this.updateDistrictLabels();
    });

    // Close dropdown when clicking outside
    document.addEventListener('click', (event: MouseEvent) => {
      const target = event.target as HTMLElement;
      if (!target.closest('.country-dropdown-wrapper')) {
        this.showCountryDropdown = false;
      }
    });
  }

  /** Scroll the left Map Settings column to the Sidebar Customization section. */
  openSidebarCustomization(): void {
    try {
      const left = document.querySelector('.left-sidebar') as HTMLElement | null;
      const target = document.getElementById('sidebar-customization');
      if (!left || !target) return;
      // Compute offset of target relative to left sidebar's scroll container
      const leftRect = left.getBoundingClientRect();
      const targetRect = target.getBoundingClientRect();
      const currentScroll = left.scrollTop || 0;
      const offset = (targetRect.top - leftRect.top) + currentScroll - 16;
      left.scrollTo({ top: Math.max(0, offset), behavior: 'smooth' });
      // focus first focusable control inside the target for keyboard users
      const focusable = target.querySelector('input, select, button, textarea') as HTMLElement | null;
      if (focusable) focusable.focus();
    } catch (e) {
      console.warn('openSidebarCustomization failed', e);
    }
  }

  private applyResolvedSidebarConfig(): void {
    const resolved = this.currentMap?.id
      ? this.sidebarConfigService.getConfigForMap(this.currentMap.id)
      : this.sidebarConfigService.getConfig();
    this.sidebarConfig = { ...resolved };
    this.cdr.markForCheck();
  }

  private buildSidebarConfigDraft(): SidebarConfig {
    const resolved = this.currentMap?.id
      ? this.sidebarConfigService.getConfigForMap(this.currentMap.id)
      : this.sidebarConfigService.getConfig();

    return {
      ...resolved,
      ...this.sidebarConfig,
      textColor: this.sidebarConfig?.textColor ?? resolved.textColor,
      fontSizePx: this.sidebarConfig?.fontSizePx ?? resolved.fontSizePx,
    } as SidebarConfig;
  }

  onSidebarConfigChanged(): void {
    // Update live preview in memory only; explicit Save persists to backend.
    const cloned = this.buildSidebarConfigDraft();
    if (this.currentMap && this.currentMap.id) {
      this.sidebarConfigService.updateConfigForMap(this.currentMap.id, cloned);
    } else {
      this.sidebarConfigService.updateConfig(cloned);
    }

    // Push font style updates immutably so CesiumMap receives latest values instantly
    this.textStyleService.updateSettings({
      fontColor: cloned.textColor,
      fontSize: cloned.fontSizePx,
      fontWeight: (cloned as any).fontWeight || 'normal'
    });

    this.cdr.markForCheck();
  }

  saveSidebarCustomization(): void {
    const cloned = this.buildSidebarConfigDraft();

    if (this.currentMap && this.currentMap.id) {
      this.sidebarConfigService.saveConfigForMap(this.currentMap.id, cloned).subscribe({
        next: (savedConfig) => {
          this.sidebarConfig = { ...savedConfig };
          this.textStyleService.updateSettings({
            fontColor: savedConfig.textColor,
            fontSize: savedConfig.fontSizePx,
            fontWeight: (savedConfig as any).fontWeight || 'normal'
          });
          this.cdr.markForCheck();
          Swal.fire({ toast: true, position: 'top-end', icon: 'success', title: 'Sidebar saved for this map', showConfirmButton: false, timer: 1500, background: '#1f2937', color: '#ffffff' });
        },
        error: () => {
          Swal.fire({ toast: true, position: 'top-end', icon: 'warning', title: 'Saved locally only. Server save failed.', showConfirmButton: false, timer: 2200, background: '#7c2d12', color: '#ffffff' });
        }
      });
      return;
    }

    this.sidebarConfigService.setConfig(cloned);
    this.textStyleService.updateSettings({
      fontColor: cloned.textColor,
      fontSize: cloned.fontSizePx,
      fontWeight: (cloned as any).fontWeight || 'normal'
    });
    this.cdr.markForCheck();
    Swal.fire({ toast: true, position: 'top-end', icon: 'success', title: 'Sidebar default updated', showConfirmButton: false, timer: 1500, background: '#1f2937', color: '#ffffff' });
  }

  onSidebarBackgroundImageUpload(event: Event): void {
    const input = event.target as HTMLInputElement;
    const file = input?.files?.[0];
    if (!file) return;

    const reader = new FileReader();
    reader.onload = () => {
      const base64 = String(reader.result || '');
      this.sidebarConfig.backgroundType = 'image';
      this.sidebarConfig.backgroundImage = base64;
      if (this.sidebarConfig.backgroundImageOpacity == null) this.sidebarConfig.backgroundImageOpacity = 0.9;
      this.onSidebarConfigChanged();
    };
    reader.readAsDataURL(file);
  }

  resetSidebarConfig(): void {
    if (this.currentMap && this.currentMap.id) {
      this.sidebarConfigService.resetConfigForMap(this.currentMap.id);
    } else {
      this.sidebarConfigService.resetConfig();
    }
    this.applyResolvedSidebarConfig();
  }

  getSidebarPanelClassMap(): Record<string, boolean> {
    return {
      'position-inside-right': this.sidebarConfig.position === 'inside-right',
      'position-inside-left': this.sidebarConfig.position === 'inside-left',
      'position-left': this.sidebarConfig.position === 'left',
      'position-right': this.sidebarConfig.position === 'right',
      'position-top': this.sidebarConfig.position === 'top',
      'position-bottom': this.sidebarConfig.position === 'bottom',
      'anim-slide': this.sidebarConfig.animationStyle === 'slide',
      'anim-fade': this.sidebarConfig.animationStyle === 'fade',
      'anim-expand': this.sidebarConfig.animationStyle === 'expand',
    };
  }

  getSidebarPanelStyle(): Record<string, string> {
    const style: Record<string, string> = {
      '--panel-overlay-width': `${this.sidebarConfig.widthVw}vw`,
      'font-family': this.sidebarConfig.fontFamily,
      'font-size': `${this.sidebarConfig.fontSizePx}px`,
      'color': this.sidebarConfig.textColor,
    };

    if (this.sidebarConfig.backgroundType === 'solid') {
      style['background'] = this.sidebarConfig.backgroundColor;
    } else if (this.sidebarConfig.backgroundImage) {
      const opacity = this.sidebarConfig.backgroundImageOpacity ?? 0.9;
      // overlay to simulate opacity (darken to reveal background color underneath)
      style['background-image'] = `linear-gradient(rgba(0,0,0,${1 - opacity}), rgba(0,0,0,${1 - opacity})), url(${this.sidebarConfig.backgroundImage})`;
      style['background-size'] = 'cover';
      style['background-position'] = 'center';
    }

    return style;
  }


  ngAfterViewInit(): void {
    this.initializeCesiumViewer();
  }

  async initializeCesiumViewer() {
    (window as any).CESIUM_BASE_URL = 'assets/cesium';

    this.viewer = new Cesium.Viewer('mapSettingsCesiumContainer', {
      terrainProvider: new Cesium.EllipsoidTerrainProvider(),
      animation: false,
      timeline: false,
      baseLayerPicker: true,
      geocoder: true,
      homeButton: true,
      navigationHelpButton: false,
      sceneModePicker: false,
      fullscreenButton: false,
      creditContainer: document.createElement('div'),
      creditViewport: document.createElement('div'),
      // Performance optimizations
      requestRenderMode: true,
      targetFrameRate: 30,
    });

    this.viewer.imageryLayers.removeAll();
    const satProvider = new Cesium.UrlTemplateImageryProvider({
      url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
      credit: new Cesium.Credit('Esri'),
      minimumLevel: 0,
      maximumLevel: 19,
    });
    const satLayer = this.viewer.imageryLayers.addImageryProvider(satProvider);
    satLayer.alpha = 1.0;
    satLayer.brightness = 0.28;
    satLayer.contrast = 1.6;
    satLayer.saturation = 0.4;
    satLayer.hue = 0.55;

    this.hideCesiumBranding();
    setTimeout(() => this.hideCesiumBranding(), 0);
    setTimeout(() => this.hideCesiumBranding(), 500);

    // Apply additional performance settings
    this.viewer.scene.maximumRenderTimeChange = Infinity;
    this.viewer.resolutionScale = 0.75;
    this.viewer.scene.globe.maximumScreenSpaceError = 7;

    // Initialize globe effects
    this.viewer.scene.globe.enableLighting = true;
    this.viewer.scene.globe.dynamicAtmosphereLighting = true;

    if (this.viewer.scene.skyAtmosphere) {
      this.viewer.scene.skyAtmosphere.show = true;
      this.viewer.scene.skyAtmosphere.hueShift = 0.0;
      this.viewer.scene.skyAtmosphere.saturationShift = 0.2;
      this.viewer.scene.skyAtmosphere.brightnessShift = 0.1;
    }

    // Enable click handler for locations
    this.enableClickHandler();

    // Allow page scrolling when wheel events occur over the Cesium container
    try {
      const container = document.getElementById('mapSettingsCesiumContainer');
      if (container) {
        container.addEventListener('wheel', (evt: WheelEvent) => {
          if (evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) return; // allow Cesium zoom with modifier
          try { evt.stopImmediatePropagation(); } catch (e) {}
        }, { capture: true, passive: true } as AddEventListenerOptions);
      }
    } catch (e) { /* ignore */ }

    // Auto-load default map and its locations on startup
    this.loadDefaultMapOnStartup();
  }

  loadDefaultMapOnStartup(): void {
    // Use MapService to fetch the default map (keeps base URL consistent)
    this.mapService.getDefaultMap().subscribe({
      next: (defaultMap: any) => {
        if (defaultMap && defaultMap.id) {
          console.log('Auto-loading default map:', defaultMap.countryName);
          this.loadDefaultMapOnViewer(defaultMap);
        } else {
          console.log('No default map found on startup');
        }
      },
      error: (error) => {
        console.warn('No default map set yet or failed to contact backend:', error.status, error.message || error);
      }
    });
  }

  private hideCesiumBranding(): void {
    if (!this.viewer) return;

    try {
      const widget = (this.viewer as any)?._cesiumWidget;
      if (widget?._creditContainer) {
        widget._creditContainer.style.display = 'none';
      }
      if (widget?._creditViewport) {
        widget._creditViewport.style.display = 'none';
      }
    } catch {
      // ignore
    }

    const selectors = [
      '.cesium-credit-container',
      '.cesium-credit-logoContainer',
      '.cesium-credit-expand-link',
      '.cesium-credit-textContainer',
      '.cesium-widget-credits',
      '.cesium-credit-lightbox-overlay',
      '.cesium-credit-lightbox',
    ];

    selectors.forEach((selector) => {
      document.querySelectorAll(selector).forEach((node) => {
        const el = node as HTMLElement;
        el.style.setProperty('display', 'none', 'important');
        el.style.setProperty('visibility', 'hidden', 'important');
        el.style.setProperty('opacity', '0', 'important');
        el.style.setProperty('pointer-events', 'none', 'important');
      });
    });
  }

  enableClickHandler() {
    const handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);

    handler.setInputAction((event: any) => {
      // Check if in drawing mode first
      if (this.drawingPoint || this.drawingPolygon) {
        this.handleMapClick(event);
        return;
      }

      // Otherwise handle entity selection (existing logic)
      const picked = this.viewer.scene.pick(event.position);

      // Check if clicked on a district first
      if (Cesium.defined(picked) && picked.id?.properties) {
        const now = Cesium.JulianDate.now();
        
        // Check for district label
        const districtId = picked.id.properties.districtId?.getValue ? picked.id.properties.districtId.getValue(now) : picked.id.properties.districtId;
        const labelType = picked.id.properties.labelType?.getValue ? picked.id.properties.labelType.getValue(now) : picked.id.properties.labelType;
        
        if (districtId && labelType === 'district') {
            // Clicked on a district label - show district info in sidebar and render governorates
            const data = this.districtLabelData.get(districtId);
            if (data) {
              // Use async flow to attempt loading saved district content first
              (async () => {
                this.selectedDistrict = { id: districtId, meta: data.meta };
                this.selectedLocation = null; // Clear any previous location
                this.showRightSidebar = true;
                this.showLocationsList = false;
                console.log('Selected district:', this.selectedDistrict);

                try {
                  const districtLocation = await this.getDistrictAsLocation();
                  if (districtLocation && districtLocation.id && districtLocation.id > 0) {
                    this.selectedLocation = districtLocation;
                    this.selectedName = districtLocation.name;
                    this.selectedContents = districtLocation.contents || [];
                  }
                } catch (e) {
                  console.warn('Could not load district location from backend', e);
                }

                // If no saved location, synthesize minimal LocationDTO so UI shows image/text
                if (!this.selectedLocation) {
                  const synthesized: any = {
                    id: 0,
                    name: data.meta?.name_en || districtId,
                    category: 'DISTRICT',
                    type: 'ZONE',
                    mapId: this.currentMap?.id || 0,
                    parentId: this.countryLocationId || undefined,
                    geometry: this.tunisiaDistrictGeometries[districtId] || null,
                    contents: []
                  };

                  const img = this.getDistrictImage(districtId);
                  if (img) synthesized.contents.push({ content: { type: 'IMAGE', value: img } });
                  const members = (data.meta?.members || []).join(', ');
                  synthesized.contents.push({ content: { type: 'TEXT', value: `${data.meta?.name_en || districtId} — administrative district containing: ${members}.` } });

                  this.selectedLocation = synthesized as any;
                  this.selectedName = this.selectedLocation.name;
                  this.selectedContents = this.selectedLocation.contents || [];
                }

                // Render governorates for this district
                try {
                  await this.showDistrict(districtId);
                } catch (e) {
                  console.warn('Error rendering district governorates:', e);
                }
              })();
              return;
            }
        }

        // Check for project point selection
        const entityType = picked.id.properties.type?.getValue ? picked.id.properties.type.getValue(now) : picked.id.properties.type;
        if (entityType === 'project') {
          const projectData = picked.id.properties.projectData?.getValue
            ? picked.id.properties.projectData.getValue(now)
            : picked.id.properties.projectData;

          if (projectData) {
            this.showRightSidebar = true;
            this.showLocationsList = false;
            this.selectProject(projectData);
            return;
          }
        }

        // Check for regular location
        if (picked.id?.properties?.location) {
          const rawLocation = picked.id.properties.location;
          const location: LocationDTO = rawLocation?.getValue ? rawLocation.getValue(now) : rawLocation;

          this.openLocationDetails(location, picked.id as Cesium.Entity);
          return;
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  }

  private openLocationDetails(location: LocationDTO, entity?: Cesium.Entity): void {
    if (!location) return;

    // Deep clone to avoid Cesium wrapper side effects
    const safeLocation = JSON.parse(JSON.stringify(location)) as LocationDTO;

    this.selectedProject = null;
    this.selectedDistrict = null;
    this.selectedLocation = safeLocation;
    this.selectedName = safeLocation.name;
    this.selectedContents = safeLocation.contents || [];
    this.showRightSidebar = true;
    this.showLocationsList = false;

    if (entity) {
      this.viewer.selectedEntity = entity;
      this.viewer.flyTo(entity, {
        duration: 1.1,
        offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-40), 85000)
      });
    }

    if (safeLocation.id && safeLocation.id > 0) {
      this.locationsService.getLocationDetails(safeLocation.id).subscribe({
        next: (fullLocation: LocationDTO) => {
          this.selectedLocation = fullLocation;
          this.selectedName = fullLocation.name;
          this.selectedContents = fullLocation.contents || [];
          this.showRightSidebar = true;
          this.showLocationsList = false;
          this.cdr.markForCheck();
        },
        error: (err) => {
          console.warn('Could not load full location details from backend', err);
        }
      });
    }

    this.cdr.markForCheck();
  }

  loadMaps(): void {
    this.mapService.getAllDefaultMaps().subscribe({
      next: (maps) => {
        this.maps = maps;
        this.filteredMaps = maps;
        // Try to initialize selectedDefaultMapId from backend default
        this.mapService.getDefaultMap().subscribe({
          next: (def) => {
            if (def && def.id) this.selectedDefaultMapId = def.id;
          },
          error: () => { /* ignore */ }
        });
      },
      error: (error) => {
        console.error('Error loading maps:', error);
        Swal.fire('Error', 'Failed to load maps', 'error');
      }
    });
  }

  /**
   * Load all sectors
   */
loadSectors(): void {
    this.sectorService.getAllSectors().subscribe({
      next: (sectors) => {
        this.allSectors = sectors;
        this.filteredSectors = sectors;
        console.log('Loaded sectors:', sectors);
      },
      error: (err) => {
        console.error('Error loading sectors:', err);
      }
    });
  }

  /**
   * Load all projects for current map
   */
  loadProjects(): void {
    if (!this.currentMap || !this.currentMap.id) {
      return;
    }

    const mapId = this.currentMap.id;
    // Request geometry so projects can be rendered as points
    this.locationsService.getLocationsByMapWithGeometry(mapId, true).subscribe({
      next: (locations) => {
        this.allProjects = locations.filter(l => l.category === 'PROJECT');
        console.log('Loaded projects (as locations) for map:', mapId, this.allProjects);
        this.renderProjectsOnMap();
      },
      error: (err) => {
        console.error('Error loading projects (locations):', err);
      }
    });
  }

  /**
   * Render all projects as cyan points on the map
   */
  renderProjectsOnMap(): void {
    if (!this.viewer) return;

    // Clear existing project entities
    this.displayedProjectEntities.forEach(entity => {
      this.viewer.entities.remove(entity);
    });
    this.displayedProjectEntities = [];

    this.allProjects.forEach(project => {
      if (!project.geometry || !project.geometry.coordinates) {
        return;
      }

      const [lon, lat] = project.geometry.coordinates;

      const entity = this.viewer.entities.add({
        id: `project-${project.id}`,
        position: Cesium.Cartesian3.fromDegrees(lon, lat),
        point: {
          pixelSize: 10,
          color: Cesium.Color.CYAN,
          outlineColor: Cesium.Color.WHITE,
          outlineWidth: 2
        },
      /*  label: {
          text: project.name,
          font: '12px sans-serif',
          fillColor: Cesium.Color.WHITE,
          outlineColor: Cesium.Color.BLACK,
          outlineWidth: 2,
          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          pixelOffset: new Cesium.Cartesian2(0, -12)
        },*/
        properties: {
          type: 'project',
          projectData: project
        }
      });

      this.displayedProjectEntities.push(entity);
    });

    console.log(`Rendered ${this.displayedProjectEntities.length} project entities on map`);
  }

  searchMaps(): void {
    if (!this.searchQuery.trim()) {
      this.filteredMaps = this.maps;
    } else {
      this.filteredMaps = this.maps.filter(map =>
        map.countryName.toLowerCase().includes(this.searchQuery.toLowerCase())
      );
    }
  }

  // Country dropdown methods
  filterCountries(): void {
    if (!this.countrySearchQuery.trim()) {
      this.filteredCountries = this.availableCountries;
    } else {
      this.filteredCountries = this.availableCountries.filter(country =>
        country.toLowerCase().includes(this.countrySearchQuery.toLowerCase())
      );
    }
  }

  selectCountry(country: string): void {
    this.newMap.countryName = country;
    this.countrySearchQuery = country;
    this.showCountryDropdown = false;
  }

  toggleCountryDropdown(): void {
    this.showCountryDropdown = !this.showCountryDropdown;
    if (this.showCountryDropdown) {
      this.countrySearchQuery = this.newMap.countryName;
      this.filterCountries();
    }
  }

  // Load default map from backend
  loadDefaultMap(): void {
    // Use MapService.getDefaultMap() — avoids hard-coded host and CORS mismatches
    this.mapService.getDefaultMap().subscribe({
      next: (response: any) => {
        if (response) {
          Swal.fire({
            title: 'Default Map Found',
            text: `Loading ${response.countryName}`,
            icon: 'success',
            timer: 2000,
            showConfirmButton: false,
            toast: true,
            position: 'top-end',
            background: '#1f2937',
            color: '#ffffff'
          });
          this.loadDefaultMapOnViewer(response);
        }
      },
      error: (error) => {
        console.error('Error loading default map:', error.status, error.message || error);
        Swal.fire({
          title: 'No Default Map',
          text: 'No default map has been set yet or the server could not be reached',
          icon: 'info',
          background: '#1f2937',
          color: '#ffffff'
        });
      }
    });
  }

  loadDefaultMapOnViewer(map: DefaultMapDTO): void {
    if (!this.viewer) return;

    // Clear existing entities
    this.viewer.entities.removeAll();
    this.displayedCountryBorders = []; // Reset country borders array

    // Find country borders
    const features = this.countryBorders.filter(f =>
      f.properties && (f.properties.ADMIN === map.countryName || f.properties.name === map.countryName)
    );

    features.forEach(feature => {
      if (feature.geometry.type === 'Polygon') {
        feature.geometry.coordinates.forEach((ring: any) => {
          const positions: number[] = [];
          ring.forEach((coord: any) => {
            positions.push(coord[0], coord[1]);
          });

          const entity = this.viewer.entities.add({
            polygon: {
              hierarchy: Cesium.Cartesian3.fromDegreesArray(positions),
              material: Cesium.Color.fromCssColorString(map.borderColor || '#FFFF00').withAlpha(0.15),
              outline: true,
              outlineColor: Cesium.Color.fromCssColorString(map.borderColor || '#FFFF00'),
              outlineWidth: 2,
        
              fill: true
            }
          });
          this.displayedCountryBorders.push(entity);
        });
      } else if (feature.geometry.type === 'MultiPolygon') {
        feature.geometry.coordinates.forEach((polygon: any) => {
          polygon.forEach((ring: any) => {
            const positions: number[] = [];
            ring.forEach((coord: any) => {
              positions.push(coord[0], coord[1]);
            });

            const entity = this.viewer.entities.add({
              polygon: {
                hierarchy: Cesium.Cartesian3.fromDegreesArray(positions),
                material: Cesium.Color.fromCssColorString(map.borderColor || '#FFFF00').withAlpha(0.15),
                outline: true,
                outlineColor: Cesium.Color.fromCssColorString(map.borderColor || '#FFFF00'),
                outlineWidth: 2,

                fill: true
              }
            });
            this.displayedCountryBorders.push(entity);
          });
        });
      }
    });

    // Fly to borders
    if (this.displayedCountryBorders.length > 0) {
      setTimeout(() => {
        this.viewer.flyTo(this.displayedCountryBorders, {
          duration: 2,
          offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-45), 0)
        });
      }, 100);
    }

    this.currentLoadedMap = map;

    // Determine and store the country location node id (if present in GeoJSON properties)
    if (features.length > 0 && features[0].properties && features[0].properties.id) {
      this.countryLocationId = features[0].properties.id;
    } else {
      this.countryLocationId = null;
    }

    // Load all locations for this default map (don't filter by parent country)
    this.mapService.getActiveMap().subscribe(activeMap => {
      if (activeMap && activeMap.id) {
        console.log('Loading all locations for default map, mapId:', activeMap.id);
        this.locationsService.getLocationsByMap(activeMap.id).subscribe((locations: LocationDTO[]) => {
          console.log('Loaded', locations.length, 'locations for default map');
          this.allLocations = locations;
          this.displayLocationsOnMap(locations);
        }, err => {
          console.error('Failed to load locations for default map:', err);
        });
      } else {
        console.warn('No active map found for loading locations');
      }
    });

    Swal.fire({
      title: 'Map Loaded!',
      text: `Loaded ${map.countryName}`,
      icon: 'success',
      timer: 2000,
      showConfirmButton: false,
      toast: true,
      position: 'top-end',
      background: '#1f2937',
      color: '#ffffff'
    });

    // If loading Tunisia, also display districts
    if (map.countryName.toLowerCase().includes('tunisia') || map.countryName.toLowerCase().includes('tunisie')) {
      console.log('Detected Tunisia map, displaying districts');
      this.displayTunisiaDistricts();
    }
  }

  displayLocationsOnMap(locations: LocationDTO[]): void {
    // Populate navigable locations for explore more
    this.navigableLocations = locations;
    this.currentLocationIndex = 0;

    console.log('displayLocationsOnMap called with', locations.length, 'locations');

    // Clear all location entities (keep country borders and temp drawing entities)
    const entitiesToRemove = this.viewer.entities.values.filter((entity: any) => {
      return !this.displayedCountryBorders.includes(entity) && 
             !this.tempPointEntities.includes(entity) &&
             entity !== this.tempPolygonEntity;
    });
    console.log('Removing', entitiesToRemove.length, 'old entities');
    entitiesToRemove.forEach((entity: any) => {
      this.viewer.entities.remove(entity);
    });

    locations.forEach((loc: LocationDTO) => {
      console.log('Processing location:', loc.name, 'type:', loc.geometry?.type);
      if (loc.geometry?.type === 'Point' && loc.geometry.coordinates) {
        const [lon, lat] = loc.geometry.coordinates;
        this.viewer.entities.add({
          name: loc.name,
          position: Cesium.Cartesian3.fromDegrees(Number(lon), Number(lat)),
          point: {
            pixelSize: 10,
            color: Cesium.Color.fromCssColorString('#10b981'),
            outlineColor: Cesium.Color.WHITE,
            outlineWidth: 2
          },
          label: {
            text: loc.name,
            font: 'bold 12px sans-serif',
            fillColor: Cesium.Color.WHITE,
            backgroundColor: Cesium.Color.BLACK.withAlpha(0.9),
            backgroundPadding: new Cesium.Cartesian2(8, 6),
            style: Cesium.LabelStyle.FILL,
            pixelOffset: new Cesium.Cartesian2(0, -20),
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            showBackground: true
          },
          properties: { location: loc }
        });
      } else if (loc.geometry?.type === 'Polygon' && loc.geometry.coordinates) {
        // Handle Polygon/Zone rendering with robust error handling
        try {
          // Validate and extract coordinates array
          if (!Array.isArray(loc.geometry.coordinates)) {
            console.warn(`Invalid polygon structure for ${loc.name}: coordinates is not an array`);
            return;
          }

          // Get first ring (outer boundary)
          let ring = loc.geometry.coordinates[0];

          // Handle extra nesting: sometimes coordinates come as [[[lon, lat]]] instead of [[lon, lat]]
          while (Array.isArray(ring) && ring.length === 1 && Array.isArray(ring[0]) && Array.isArray(ring[0][0])) {
            console.log(`Unwrapping extra nesting level for ${loc.name}`);
            ring = ring[0];
          }

          if (!Array.isArray(ring) || ring.length < 3) {
            console.warn(`Invalid polygon ring for ${loc.name}: need at least 3 points, got ${ring?.length || 0}`);
            return;
          }

          const positions: number[] = [];
          let sumLon = 0, sumLat = 0;
          let validCoordCount = 0;

          // Process each coordinate with multiple format support
          ring.forEach((coord: any, index: number) => {
            let lon: number, lat: number;

            // Handle different coordinate formats
            if (Array.isArray(coord) && coord.length >= 2) {
              // Standard array format: [lon, lat]
              lon = Number(coord[0]);
              lat = Number(coord[1]);
            } else if (coord && typeof coord === 'object') {
              // Object format: {lon, lat} or {lng, lat} or {longitude, latitude}
              lon = Number(coord.lon ?? coord.lng ?? coord.longitude);
              lat = Number(coord.lat ?? coord.latitude);
            } else {
              console.warn(`Invalid coordinate format at index ${index} for ${loc.name}:`, coord);
              return;
            }

            // Validate coordinate values
            if (isNaN(lon) || isNaN(lat)) {
              console.warn(`Invalid coordinate values (NaN) at index ${index} for ${loc.name}:`, coord);
              return;
            }

            // Check for reasonable coordinate ranges
            if (lon < -180 || lon > 180 || lat < -90 || lat > 90) {
              console.warn(`Coordinate out of valid range at index ${index} for ${loc.name}: lon=${lon}, lat=${lat}`);
              return;
            }

            positions.push(lon, lat);
            sumLon += lon;
            sumLat += lat;
            validCoordCount++;
          });

          // Need at least 3 valid coordinates (6 values in positions array)
          if (positions.length < 6) {
            console.warn(`Not enough valid coordinates for polygon ${loc.name}: got ${validCoordCount} valid points, need at least 3`);
            return;
          }

          // Calculate centroid for label
          const centerLon = sumLon / validCoordCount;
          const centerLat = sumLat / validCoordCount;

          // Add polygon entity with 3D walls
          this.viewer.entities.add({
            name: loc.name,
            polygon: {
              hierarchy: Cesium.Cartesian3.fromDegreesArray(positions),
              material: Cesium.Color.fromCssColorString('#8b5cf6').withAlpha(0.5),
              outline: true,
              outlineColor: Cesium.Color.fromCssColorString('#8b5cf6'),
              outlineWidth: 3,
        // 5km tall 3D walls
              perPositionHeight: false
            },
            position: Cesium.Cartesian3.fromDegrees(centerLon, centerLat),
            label: {
              text: loc.name,
              font: 'bold 14px sans-serif',
              fillColor: Cesium.Color.WHITE,
              backgroundColor: Cesium.Color.BLACK.withAlpha(0.9),
              backgroundPadding: new Cesium.Cartesian2(10, 8),
              style: Cesium.LabelStyle.FILL,
              pixelOffset: new Cesium.Cartesian2(0, -20),
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
              horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
              showBackground: true
            },
            properties: { location: loc }
          });
          console.log('Successfully added polygon entity for:', loc.name);
        } catch (error) {
          console.error(`Failed to render polygon for ${loc.name}:`, error);
          console.error('Polygon data:', JSON.stringify(loc.geometry, null, 2));
        }
      }
    });
    console.log('displayLocationsOnMap completed');
  }

  /**
   * Delete all locations currently loaded in this viewer.
   * Uses multiple delete requests and waits for them to finish, then clears the UI.
   */
  clearAllData(): void {
    if (!this.currentLoadedMap) {
      Swal.fire('Error', 'No map loaded to clear.', 'error');
      return;
    }

    if (!this.allLocations || this.allLocations.length === 0) {
      Swal.fire('Nothing to clear', 'There are no locations loaded for this map.', 'info');
      return;
    }

    Swal.fire({
      title: 'Are you sure?',
      text: `This will delete all ${this.allLocations.length} locations for ${this.currentLoadedMap.countryName}. This action cannot be undone!`,
      icon: 'warning',
      showCancelButton: true,
      confirmButtonColor: '#ef4444',
      cancelButtonColor: '#6b7280',
      confirmButtonText: 'Yes, delete all',
      background: '#1f2937',
      color: '#ffffff'
    }).then(result => {
      if (!result.isConfirmed) return;

      // If we have a backend country node id available, call the single bulk-delete endpoint
      if (this.countryLocationId) {
        this.locationsService.clearAllCountryData(this.countryLocationId).subscribe({
          next: () => {
            Swal.fire({
              title: 'Cleared!',
              text: 'All locations have been deleted.',
              icon: 'success',
              confirmButtonColor: '#10b981',
              background: '#1f2937',
              color: '#ffffff'
            });
            // Clear UI state
            this.allLocations = [];
            this.navigableLocations = [];
            this.currentLocationIndex = 0;
            this.selectedLocation = null;
            this.showRightSidebar = false;
            // Remove all non-border entities
            const toRemove = this.viewer.entities.values.filter((e: any) => !this.displayedCountryBorders.includes(e));
            toRemove.forEach((e: any) => this.viewer.entities.remove(e));
          },
          error: (err) => {
            console.error('Failed to clear all locations via bulk API:', err);
            Swal.fire('Error', 'Failed to clear locations on server.', 'error');
          }
        });
      } else {
        // Fallback: delete each location individually
        const deletes = this.allLocations
          .filter(l => l.id != null)
          .map(l => this.locationsService.deleteLocation(l.id!));

        if (deletes.length === 0) {
          Swal.fire('No deletable locations', '', 'info');
          return;
        }

        forkJoin(deletes).subscribe({
          next: () => {
            Swal.fire({
              title: 'Cleared!',
              text: 'All locations have been deleted.',
              icon: 'success',
              confirmButtonColor: '#10b981',
              background: '#1f2937',
              color: '#ffffff'
            });
            // Clear UI state
            this.allLocations = [];
            this.navigableLocations = [];
            this.currentLocationIndex = 0;
            this.selectedLocation = null;
            this.showRightSidebar = false;
            // Remove all non-border entities
            const toRemove = this.viewer.entities.values.filter((e: any) => !this.displayedCountryBorders.includes(e));
            toRemove.forEach((e: any) => this.viewer.entities.remove(e));
          },
          error: (err) => {
            console.error('Failed to clear all locations:', err);
            Swal.fire('Error', 'Failed to delete some locations.', 'error');
          }
        });
      }
    });
  }

  // Add a single location to the map without clearing existing entities
  addSingleLocationToMap(loc: LocationDTO): void {
    console.log('Adding single location to map:', loc.name, 'type:', loc.geometry?.type);
    
    if (loc.geometry?.type === 'Point' && loc.geometry.coordinates) {
      const [lon, lat] = loc.geometry.coordinates;
      this.viewer.entities.add({
        name: loc.name,
        position: Cesium.Cartesian3.fromDegrees(Number(lon), Number(lat)),
        point: {
          pixelSize: 10,
          color: Cesium.Color.fromCssColorString('#10b981'),
          outlineColor: Cesium.Color.WHITE,
          outlineWidth: 2
        },
        label: {
          text: loc.name,
          font: 'bold 12px sans-serif',
          fillColor: Cesium.Color.WHITE,
          backgroundColor: Cesium.Color.BLACK.withAlpha(0.9),
          backgroundPadding: new Cesium.Cartesian2(8, 6),
          style: Cesium.LabelStyle.FILL,
          pixelOffset: new Cesium.Cartesian2(0, -20),
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          showBackground: true
        },
        properties: { location: loc }
      });
      console.log('Successfully added point:', loc.name);
    } else if (loc.geometry?.type === 'Polygon' && loc.geometry.coordinates) {
      try {
        if (!Array.isArray(loc.geometry.coordinates)) {
          console.warn(`Invalid polygon structure for ${loc.name}`);
          return;
        }

        let ring = loc.geometry.coordinates[0];
        while (Array.isArray(ring) && ring.length === 1 && Array.isArray(ring[0]) && Array.isArray(ring[0][0])) {
          ring = ring[0];
        }

        if (!Array.isArray(ring) || ring.length < 3) {
          console.warn(`Invalid polygon ring for ${loc.name}`);
          return;
        }

        const positions: number[] = [];
        let sumLon = 0, sumLat = 0;
        let validCoordCount = 0;

        ring.forEach((coord: any) => {
          let lon: number, lat: number;
          if (Array.isArray(coord) && coord.length >= 2) {
            lon = Number(coord[0]);
            lat = Number(coord[1]);
          } else if (coord && typeof coord === 'object') {
            lon = Number(coord.lon ?? coord.lng ?? coord.longitude);
            lat = Number(coord.lat ?? coord.latitude);
          } else {
            return;
          }

          if (isNaN(lon) || isNaN(lat) || lon < -180 || lon > 180 || lat < -90 || lat > 90) {
            return;
          }

          positions.push(lon, lat);
          sumLon += lon;
          sumLat += lat;
          validCoordCount++;
        });

        if (positions.length < 6) {
          console.warn(`Not enough valid coordinates for polygon ${loc.name}`);
          return;
        }

        const centerLon = sumLon / validCoordCount;
        const centerLat = sumLat / validCoordCount;

        this.viewer.entities.add({
          name: loc.name,
          polygon: {
            hierarchy: Cesium.Cartesian3.fromDegreesArray(positions),
            material: Cesium.Color.fromCssColorString('#8b5cf6').withAlpha(0.5),
            outline: true,
            outlineColor: Cesium.Color.fromCssColorString('#8b5cf6'),
            outlineWidth: 3,
            perPositionHeight: false
          },
          position: Cesium.Cartesian3.fromDegrees(centerLon, centerLat),
          label: {
            text: loc.name,
            font: 'bold 14px sans-serif',
            fillColor: Cesium.Color.WHITE,
            backgroundColor: Cesium.Color.BLACK.withAlpha(0.9),
            backgroundPadding: new Cesium.Cartesian2(10, 8),
            style: Cesium.LabelStyle.FILL,
            pixelOffset: new Cesium.Cartesian2(0, -20),
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            showBackground: true
          },
          properties: { location: loc }
        });
        console.log('Successfully added polygon:', loc.name);
      } catch (error) {
        console.error(`Failed to render polygon for ${loc.name}:`, error);
      }
    }
  }

  createMap(): void {
    if (!this.newMap.countryName.trim()) {
      Swal.fire('Error', 'Please enter a country name', 'warning');
      return;
    }

    this.mapService.saveDefaultMap(this.newMap).subscribe({
      next: (savedMap) => {
        this.maps.push(savedMap);
        this.filteredMaps = this.maps;
        this.resetForm();
        Swal.fire({
          title: 'Success',
          text: 'Map created successfully',
          icon: 'success',
          background: '#1f2937',
          color: '#ffffff'
        });
      },
      error: (error) => {
        console.error('Error creating map:', error);
        Swal.fire('Error', 'Failed to create map', 'error');
      }
    });
  }

  deleteMap(mapId: number): void {
    Swal.fire({
      title: 'Are you sure?',
      text: 'This will delete the default map configuration',
      icon: 'warning',
      showCancelButton: true,
      confirmButtonText: 'Yes, delete it!',
      background: '#1f2937',
      color: '#ffffff'
    }).then((result) => {
      if (result.isConfirmed) {
        this.mapService.deleteDefaultMap(mapId).subscribe({
          next: () => {
            this.maps = this.maps.filter(m => m.id !== mapId);
            this.filteredMaps = this.maps;
            Swal.fire({
              title: 'Deleted!',
              text: 'Map has been deleted.',
              icon: 'success',
              background: '#1f2937',
              color: '#ffffff'
            });
          },
          error: (error) => {
            console.error('Error deleting map:', error);
            Swal.fire('Error', 'Failed to delete map', 'error');
          }
        });
      }
    });
  }

  setAsActive(mapId: number): void {
    this.mapService.setActiveMap(mapId).subscribe({
      next: () => {
        // Refresh list
        this.loadMaps();

        // Also set the active map as the default map in the backend so it becomes the default
        const mapObj = this.maps.find(m => m.id === mapId);
        if (mapObj) {
          this.mapService.saveDefaultMap(mapObj).subscribe({
            next: () => {
              // Refresh shared active map observable so other components (like Cesium) update
              this.mapService.refreshActiveMap();
              Swal.fire({
                title: 'Success',
                text: 'Active map updated and set as default',
                icon: 'success',
                background: '#1f2937',
                color: '#ffffff'
              });
            },
            error: (err) => {
              console.warn('Active map updated but failed to set as default:', err);
              // Still attempt to refresh active map
              this.mapService.refreshActiveMap();
              Swal.fire({
                title: 'Partial Success',
                text: 'Active map updated but failed to set as default',
                icon: 'warning',
                background: '#1f2937',
                color: '#ffffff'
              });
            }
          });
        } else {
          Swal.fire({
            title: 'Success',
            text: 'Active map updated',
            icon: 'success',
            background: '#1f2937',
            color: '#ffffff'
          });
        }
      },
      error: (error) => {
        console.error('Error setting active map:', error.status, error.message || error);
        Swal.fire('Error', 'Failed to set active map', 'error');
      }
    });
  }

  toggleCreateForm(): void {
    this.showCreateForm = !this.showCreateForm;
    if (!this.showCreateForm) {
      this.resetForm();
    }
  }

  resetForm(): void {
    this.newMap = {
      countryName: '',
      borderColor: '#FFFF00',
      fillOpacity: 0.3,
      borderWidth: 2
    };
    this.showCreateForm = false;
  }

  closeRightSidebar(): void {
    this.showRightSidebar = false;
    this.selectedLocation = null;
    this.selectedDistrict = null; // Clear district selection
    if (this.viewer) {
      this.viewer.selectedEntity = undefined;
    }
    // Clear displayed governorates when closing sidebar
    this.clearDisplayedDistricts();
  }

  getLocationImage(location: LocationDTO): string | null {
    if (!location.contents || location.contents.length === 0) {
      return null;
    }
    const imageContent = (location.contents as any[]).find((c: any) => c.content?.type === 'IMAGE');
    return imageContent ? imageContent.content.value : null;
  }

  /**
   * Get image for a district by fetching from backend/cache
   */
  getDistrictImage(districtId: string): string | null {
    if (!this.currentMap?.id) return null;
    const districtMeta = this.tunisiaDistrictsMapping[districtId];
    if (!districtMeta) return null;

    const districtName = districtMeta.name_en;
    const districtMatches = this.allLocations
      .filter(loc => loc.category === 'DISTRICT' && (loc.name === districtName || loc.name === districtMeta.name_ar || loc.name === districtMeta.name_fr))
      .sort((a, b) => {
        const score = (loc: LocationDTO) => ((Array.isArray(loc.contents) && loc.contents.length > 0) ? 2 : 0) + (loc.id ? 1 : 0);
        const byScore = score(b) - score(a);
        if (byScore !== 0) return byScore;
        return Number(b.id || 0) - Number(a.id || 0);
      });

    const districtLocation = districtMatches[0];

    if (districtLocation && districtLocation.contents) {
      return this.getLocationImage(districtLocation);
    }
    return null;
  }

  // ==================== DRAWING FUNCTIONALITY ====================

  startPointDrawing(): void {
    this.drawingPoint = true;
    this.drawingPolygon = false;
    Swal.fire({
      title: 'Point Mode Active',
      text: 'Click on the map to create a point',
      icon: 'info',
      timer: 2000,
      showConfirmButton: false,
      toast: true,
      position: 'top-end',
      background: '#1f2937',
      color: '#ffffff'
    });
  }

  startPolygonDrawing(): void {
    this.drawingPolygon = true;
    this.drawingPoint = false;
    this.polygonPoints = [];

    // Remove previous temp entities
    if (this.tempPolygonEntity) {
      this.viewer.entities.remove(this.tempPolygonEntity);
    }
    this.tempPointEntities.forEach(e => this.viewer.entities.remove(e));
    this.tempPointEntities = [];

    Swal.fire({
      title: 'Zone Drawing Mode',
      text: 'Click points on the map, then click "Finish Zone"',
      icon: 'info',
      timer: 3000,
      showConfirmButton: false,
      toast: true,
      position: 'top-end',
      background: '#1f2937',
      color: '#ffffff'
    });
  }

  async finishPolygon(): Promise<void> {
    if (this.polygonPoints.length < 3) {
      Swal.fire({
        title: 'Not enough points',
        text: 'Zone needs at least 3 points',
        icon: 'warning',
        background: '#1f2937',
        color: '#ffffff'
      });
      return;
    }

    const { value: zoneName } = await Swal.fire({
      title: 'Enter Zone Name',
      input: 'text',
      inputPlaceholder: 'Enter a name for this zone',
      showCancelButton: true,
      confirmButtonText: 'Next',
      background: '#1f2937',
      color: '#ffffff',
      inputValidator: (value) => {
        if (!value) {
          return 'Please enter a name!';
        }
        return null;
      }
    });

    if (!zoneName) return;

    // Open content dialog
    const dialogRef = this.dialog.open(PolygonContentDialogComponent, {
      width: '600px',
      maxHeight: '80vh',
      panelClass: 'dark-dialog',
      backdropClass: 'dialog-backdrop',
      disableClose: false,
      data: {
        name: zoneName,
        isCreating: true,
        contents: []
      }
    });

    dialogRef.afterClosed().subscribe((contents) => {
      if (contents !== null && contents !== undefined) {
        // Close polygon
        const first = this.polygonPoints[0];
        const last = this.polygonPoints[this.polygonPoints.length - 1];
        const coordsCopy = [...this.polygonPoints];
        if (Math.abs(first[0] - last[0]) > 1e-6 || Math.abs(first[1] - last[1]) > 1e-6) {
          coordsCopy.push([...first]);
        }

        // Get country ID if loading a default map
        let countryId: number | undefined = undefined;
        if (this.currentLoadedMap && this.countryBorders.length > 0) {
          const features = this.countryBorders.filter(f =>
            f.properties && (f.properties.ADMIN === this.currentLoadedMap.countryName || f.properties.name === this.currentLoadedMap.countryName)
          );
          if (features.length > 0 && features[0].properties?.id) {
            countryId = features[0].properties.id;
          }
        }

        if (!this.currentMap || !this.currentMap.id) {
          Swal.fire({
            title: 'Error',
            text: 'No map selected. Please select a map first.',
            icon: 'error',
            background: '#1f2937',
            color: '#ffffff'
          });
          return;
        }

        const locationDTO: any = {
          name: zoneName,
          category: 'USER_ZONE',
          type: 'ZONE',
          mapId: this.currentMap.id, // Use active map ID
          parentId: countryId, // Set parent if in default map context
          geometry: { type: 'Polygon', coordinates: [coordsCopy] }
        };

        // Create location with contents
        const request: any = {
          location: locationDTO,
          contents: contents || []
        };

        // Debug logging: log the request payload
        console.log('Creating zone with request:', JSON.stringify(request, null, 2));
        console.log('Polygon coordinates:', coordsCopy);
        console.log('Number of points:', coordsCopy.length);

        this.locationsService.createLocation(request).subscribe({
          next: (response) => {
            console.log('Zone created successfully:', response);
            Swal.fire({
              title: 'Success!',
              text: `Zone "${zoneName}" created successfully`,
              icon: 'success',
              background: '#1f2937',
              color: '#ffffff'
            });

            this.drawingPolygon = false;
            this.polygonPoints = [];

            if (this.tempPolygonEntity) {
              this.viewer.entities.remove(this.tempPolygonEntity);
            }
            this.tempPointEntities.forEach(e => this.viewer.entities.remove(e));
            this.tempPointEntities = [];

            // Immediately add the created zone to the map without clearing existing locations
            if (response && response.geometry) {
              this.allLocations.push(response);
              this.addSingleLocationToMap(response);
            }
          },
          error: (err) => {
            console.error('Zone creation error:', err);
            console.error('Error details:', err.error);
            console.error('Status:', err.status);
            console.error('Request that failed:', JSON.stringify(request, null, 2));
            Swal.fire({
              title: 'Error!',
              text: `Failed to create zone: ${err.error?.message || err.message || 'Unknown error'}`,
              icon: 'error',
              background: '#1f2937',
              color: '#ffffff'
            });
          }
        });
      }
      // If user cancels the content dialog, polygon stays in drawing mode
    });
  }

  handleMapClick(event: any): void {
    const cartesian = this.viewer.scene.pickPosition(event.position);
    if (!cartesian) return;

    const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
    const lon = Cesium.Math.toDegrees(cartographic.longitude);
    const lat = Cesium.Math.toDegrees(cartographic.latitude);

    if (this.drawingPoint) {
      this.createPointAtLocation(lon, lat);
    } else if (this.drawingPolygon) {
      this.addPolygonPoint(lon, lat);
    }
  }

  async createPointAtLocation(lon: number, lat: number): Promise<void> {
    // Check if point is inside the country
    if (!this.isPointInsideCountry(lon, lat)) {
      Swal.fire({
        title: 'Invalid Location',
        text: 'You must draw the point inside the zone boundaries!',
        icon: 'warning',
        background: '#1f2937',
        color: '#ffffff'
      });
      this.drawingPoint = false;
      return;
    }

    // Step 1: Ask if creating a project or regular point
    const { value: pointType } = await Swal.fire({
      title: 'Select Point Type',
      html: `
        <div style="display: flex; flex-direction: column; gap: 15px; margin-top: 20px;">
          <button id="project-btn" style="padding: 15px; background: linear-gradient(135deg, #00D9FF 0%, #0099CC 100%); border: none; border-radius: 8px; color: white; font-size: 16px; font-weight: bold; cursor: pointer; transition: all 0.3s; box-shadow: 0 4px 15px rgba(0, 217, 255, 0.3);">
            <div style="display: flex; align-items: center; justify-content: center; gap: 10px;">
              <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
                <line x1="8" y1="21" x2="16" y2="21"></line>
                <line x1="12" y1="17" x2="12" y2="21"></line>
              </svg>
              <span>Create Project</span>
            </div>
            <p style="margin: 8px 0 0 0; font-size: 12px; opacity: 0.9;">Add a project linked to a sector</p>
          </button>
          <button id="regular-btn" style="padding: 15px; background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 8px; color: white; font-size: 16px; font-weight: bold; cursor: pointer; transition: all 0.3s;">
            <div style="display: flex; align-items: center; justify-content: center; gap: 10px;">
              <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
                <circle cx="12" cy="10" r="3"></circle>
              </svg>
              <span>Regular Point</span>
            </div>
            <p style="margin: 8px 0 0 0; font-size: 12px; opacity: 0.7;">Create a standard location point</p>
          </button>
        </div>
      `,
      showConfirmButton: false,
      showCancelButton: true,
      cancelButtonText: 'Cancel',
      background: '#1f2937',
      color: '#ffffff',
      didOpen: () => {
        const projectBtn = document.getElementById('project-btn');
        const regularBtn = document.getElementById('regular-btn');
        
        projectBtn?.addEventListener('mouseover', () => {
          projectBtn.style.transform = 'scale(1.05)';
          projectBtn.style.boxShadow = '0 6px 20px rgba(0, 217, 255, 0.5)';
        });
        projectBtn?.addEventListener('mouseout', () => {
          projectBtn.style.transform = 'scale(1)';
          projectBtn.style.boxShadow = '0 4px 15px rgba(0, 217, 255, 0.3)';
        });
        regularBtn?.addEventListener('mouseover', () => {
          regularBtn.style.background = 'rgba(255, 255, 255, 0.15)';
          regularBtn.style.transform = 'scale(1.05)';
        });
        regularBtn?.addEventListener('mouseout', () => {
          regularBtn.style.background = 'rgba(255, 255, 255, 0.1)';
          regularBtn.style.transform = 'scale(1)';
        });
        
        projectBtn?.addEventListener('click', () => {
          Swal.clickConfirm();
          Swal.close();
          (window as any)._swalResult = 'project';
        });
        regularBtn?.addEventListener('click', () => {
          Swal.clickConfirm();
          Swal.close();
          (window as any)._swalResult = 'regular';
        });
      }
    });

    const selectedType = (window as any)._swalResult;
   delete (window as any)._swalResult;

    if (!selectedType) {
      this.drawingPoint = false;
      return;
    }

    if (selectedType === 'project') {
      await this.createProjectAtLocation(lon, lat);
    } else {
      await this.createRegularPointAtLocation(lon, lat);
    }
  }

  /**
   * Create a project at the specified location
   */
 async createProjectAtLocation(lon: number, lat: number): Promise<void> {
    // Step 1: Select sector
    if (this.allSectors.length === 0) {
      Swal.fire({
        title: 'No Sectors Available',
        text: 'Please create sectors first before adding projects.',
        icon: 'warning',
        background: '#1f2937',
        color: '#ffffff'
      });
      this.drawingPoint = false;
      return;
    }

    const sectorOptions = this.allSectors.reduce((acc, sector) => {
      const displayName = this.currentLanguage === 'ar' ? sector.nameAr :
                         (this.currentLanguage === 'fr' ? sector.nameFr : sector.nameEn);
      acc[sector.id!.toString()] = displayName || sector.nameEn;
      return acc;
    }, {} as any);

    const { value: sectorId } = await Swal.fire({
      title: '🏢 Select Sector',
      input: 'select',
      inputOptions: sectorOptions,
      inputPlaceholder: 'Choose a sector',
      showCancelButton: true,
      confirmButtonText: 'Next',
      cancelButtonText: 'Cancel',
      background: '#1f2937',
      color: '#ffffff',
      inputValidator: (value) => {
        if (!value) return 'Please select a sector!';
        return null;
      }
    });

    if (!sectorId) { this.drawingPoint = false; return; }

    // Step 2: Get project name
    const { value: projectName } = await Swal.fire({
      title: '📝 Enter Project Name',
      input: 'text',
      inputPlaceholder: 'e.g., Solar Energy Plant, Highway Construction',
      showCancelButton: true,
      confirmButtonText: 'Next',
      background: '#1f2937',
      color: '#ffffff',
      inputValidator: (value) => {
        if (!value) return 'Please enter a project name!';
        return null;
      }
    });

    if (!projectName) { this.drawingPoint = false; return; }

    // ─── Step 3: Auto-detect parent (governorate or district) by spatial lookup ───
    let parentId: number | null = null;

    // 3a. Prefer sidebar selection if already active
    if (this.selectedLocation?.category === 'GOVERNORATE' && this.selectedLocation.id) {
      parentId = this.selectedLocation.id as number;
    } else if (this.selectedLocation?.category === 'DISTRICT' && this.selectedLocation.id) {
      parentId = this.selectedLocation.id as number;
    } else {
      // 3b. Spatial lookup: find which governorate polygon contains this point
      let matchedGovName: string | null = null;
      let matchedDistrictId: string | null = null;

      outer: for (const districtId of Object.keys(this.tunisiaDistrictMatchedFeatures)) {
        const features = this.tunisiaDistrictMatchedFeatures[districtId];
        for (const feature of (features || [])) {
          let inside = false;
          if (feature.geometry?.type === 'Polygon') {
            for (const ring of feature.geometry.coordinates) {
              if (this.pointInPolygon(lon, lat, ring)) { inside = true; break; }
            }
          } else if (feature.geometry?.type === 'MultiPolygon') {
            for (const poly of feature.geometry.coordinates) {
              for (const ring of poly) {
                if (this.pointInPolygon(lon, lat, ring)) { inside = true; break; }
              }
              if (inside) break;
            }
          }
          if (inside) {
            matchedGovName = (feature.properties?.NAME_1 || feature.properties?.NAME || feature.properties?.ADMIN) as string;
            matchedDistrictId = districtId;
            break outer;
          }
        }
      }

      // 3c. Look up the matched governorate's backend ID
      if (matchedGovName && this.currentMap?.id) {
        try {
          const normalize = (s: string) =>
            s.toLowerCase().replace(/\s+/g, '').normalize('NFD').replace(/\p{Diacritic}/gu, '');
          const locations = await this.locationsService.getLocationsByMap(this.currentMap.id).toPromise();

          // First priority: find saved governorate by name
          const govLoc = locations?.find((l: any) =>
            l.category === 'GOVERNORATE' && normalize(l.name) === normalize(matchedGovName!)
          );

          if (govLoc?.id) {
            parentId = govLoc.id as number;
            console.log(`✅ Matched governorate: ${matchedGovName} (id: ${parentId})`);
          } else {
            // Governorate not yet saved → fall back to its specific district
            if (matchedDistrictId) {
              const meta = this.tunisiaDistrictsMapping[matchedDistrictId];
              const districtLoc = locations?.find((l: any) =>
                l.category === 'DISTRICT' &&
                normalize(l.name) === normalize(meta?.name_en || '')
              );
              if (districtLoc?.id) {
                parentId = districtLoc.id as number;
                console.log(`⚠️ Governorate "${matchedGovName}" not saved yet. Using district: "${meta?.name_en}" (id: ${parentId})`);
              }
            }
          }
        } catch (e) {
          console.warn('Could not fetch parent from backend during spatial lookup', e);
        }
      }

      // 3d. Still no parent — ask the user to pick
      if (!parentId && this.currentMap?.id) {
        try {
          const locations = await this.locationsService.getLocationsByMap(this.currentMap.id).toPromise();
          const parents = (locations || []).filter((l: any) =>
            l.category === 'GOVERNORATE' || l.category === 'DISTRICT'
          );
          if (parents.length > 0) {
            const options = parents.reduce((acc: any, l: any) => {
              acc[l.id] = `${l.category === 'GOVERNORATE' ? '🏛' : '🗺'} ${l.name}`;
              return acc;
            }, {});
            const { value: chosenParentId } = await Swal.fire({
              title: 'Select Parent Location',
              text: 'Which governorate or district does this project belong to?',
              input: 'select',
              inputOptions: options,
              inputPlaceholder: 'Choose a governorate or district',
              showCancelButton: true,
              confirmButtonText: 'Confirm',
              background: '#1f2937',
              color: '#ffffff',
              inputValidator: (value) => value ? null : 'Please select a parent location!'
            });
            if (!chosenParentId) { this.drawingPoint = false; return; }
            parentId = parseInt(chosenParentId);
          }
        } catch (e) {
          console.warn('Parent selection failed', e);
        }
      }
    }

    if (!this.currentMap || !this.currentMap.id) {
      Swal.fire({
        title: 'Error',
        text: 'No map selected. Please select a map first.',
        icon: 'error',
        background: '#1f2937',
        color: '#ffffff'
      });
      this.drawingPoint = false;
      return;
    }

    // Step 4: Open content dialog
    const dialogRef = this.dialog.open(PolygonContentDialogComponent, {
      width: '600px',
      maxHeight: '80vh',
      panelClass: 'dark-dialog',
      backdropClass: 'dialog-backdrop',
      disableClose: false,
      data: { name: projectName, isCreating: true, contents: [] }
    });

    dialogRef.afterClosed().subscribe((contents) => {
      if (contents === null || contents === undefined) {
        contents = [];
      }

      const locationRequest = {
        location: {
          name: projectName,
          parentId: parentId,         // ← always correctly set now
          sectorId: parseInt(sectorId),
          geometry: { type: 'Point', coordinates: [lon, lat] },
          mapId: this.currentMap.id,
          type: LocationType.POINT,
          category: 'PROJECT'
        },
        contents: contents || []
      };

      console.log('Creating project with request:', JSON.stringify(locationRequest, null, 2));

      this.locationsService.createLocation(locationRequest).subscribe({
        next: (response) => {
          console.log('Project created successfully:', response);
          Swal.fire({
            title: 'Success!',
            html: `<div style="text-align:center;">
                     <div style="font-size:48px;margin-bottom:10px;">🎉</div>
                     <p style="font-size:16px;margin-bottom:5px;">Project created successfully!</p>
                     <p style="font-size:14px;opacity:0.8;color:#00FFFF;">"${projectName}"</p>
                   </div>`,
            icon: 'success',
            timer: 3000,
            showConfirmButton: false,
            background: '#1f2937',
            color: '#ffffff'
          });
          this.drawingPoint = false;
          this.loadProjects();
        },
        error: (err) => {
          console.error('Project creation error:', err);
          Swal.fire({
            title: 'Error!',
            text: `Failed to create project: ${err.error?.message || err.message || 'Unknown error'}`,
            icon: 'error',
            background: '#1f2937',
            color: '#ffffff'
          });
          this.drawingPoint = false;
        }
      });
    });
  }

  /**
   * Create a regular location point (original behavior)
   */
  async createRegularPointAtLocation(lon: number, lat: number): Promise<void> {
    const { value: pointName } = await Swal.fire({
      title: 'Enter Point Name',
      input: 'text',
      inputPlaceholder: 'Enter a name for this point',
      showCancelButton: true,
      confirmButtonText: 'Next',
      background: '#1f2937',
      color: '#ffffff',
      inputValidator: (value) => {
        if (!value) {
          return 'Please enter a name!';
        }
        return null;
      }
    });

    if (!pointName) {
      this.drawingPoint = false;
      return;
    }

    // Open content dialog
    const dialogRef = this.dialog.open(PolygonContentDialogComponent, {
      width: '600px',
      maxHeight: '80vh',
      panelClass: 'dark-dialog',
      backdropClass: 'dialog-backdrop',
      disableClose: false,
      data: {
        name: pointName,
        isCreating: true,
        contents: []
      }
    });

    dialogRef.afterClosed().subscribe((contents) => {
      if (contents !== null && contents !== undefined) {
        // Get country ID if loading a default map
        let countryId: number | undefined = undefined;
        if (this.currentLoadedMap && this.countryBorders.length > 0) {
          const features = this.countryBorders.filter(f =>
            f.properties && (f.properties.ADMIN === this.currentLoadedMap.countryName || f.properties.name === this.currentLoadedMap.countryName)
          );
          if (features.length > 0 && features[0].properties?.id) {
            countryId = features[0].properties.id;
          }
        }

        if (!this.currentMap || !this.currentMap.id) {
          Swal.fire({
            title: 'Error',
            text: 'No map selected. Please select a map first.',
            icon: 'error',
            background: '#1f2937',
            color: '#ffffff'
          });
          return;
        }

        const locationDTO: any = {
          name: pointName,
          category: 'USER_POINT',
          type: 'POINT',
          mapId: this.currentMap.id, // Use active map ID
          parentId: countryId, // Set parent if in default map context
          geometry: { type: 'Point', coordinates: [lon, lat] }
        };

        const request: any = {
          location: locationDTO,
          contents: contents || []
        };

        // Debug logging
        console.log('Creating point with request:', JSON.stringify(request, null, 2));

        this.locationsService.createLocation(request).subscribe({
          next: (response) => {
            console.log('Point created successfully:', response);
            Swal.fire({
              title: 'Success!',
              text: `Point "${pointName}" created successfully`,
              icon: 'success',
              timer: 2000,
              showConfirmButton: false,
              background: '#1f2937',
              color: '#ffffff'
            });

            this.drawingPoint = false;

            // Immediately add the created point to the map without clearing existing locations
            if (response && response.geometry) {
              this.allLocations.push(response);
              this.addSingleLocationToMap(response);
            }
          },
          error: (err) => {
            console.error('Point creation error:', err);
            console.error('Error details:', err.error);
            console.error('Request that failed:', JSON.stringify(request, null, 2));
           Swal.fire({
              title: 'Error!',
              text: `Failed to create point: ${err.error?.message || err.message || 'Unknown error'}`,
              icon: 'error',
              background: '#1f2937',
              color: '#ffffff'
            });
            this.drawingPoint = false;
          }
        });
      } else {
        // User cancelled the content dialog
        this.drawingPoint = false;
      }
    });
  }

  addPolygonPoint(lon: number, lat: number): void {
    this.polygonPoints.push([lon, lat]);

    // Draw temp point
    const pointEntity = this.viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(lon, lat),
      point: { pixelSize: 8, color: Cesium.Color.RED },
      label: {
        text: (this.polygonPoints.length).toString(),
        font: '14px sans-serif',
        fillColor: Cesium.Color.WHITE
      }
    });
    this.tempPointEntities.push(pointEntity);

    if (this.polygonPoints.length >= 2) {
      this.drawTempPolygon();
    }
  }

  drawTempPolygon(): void {
    if (this.tempPolygonEntity) {
      this.viewer.entities.remove(this.tempPolygonEntity);
    }

    const flatCoords = this.polygonPoints.flat();

    this.tempPolygonEntity = this.viewer.entities.add({
      polygon: {
        hierarchy: Cesium.Cartesian3.fromDegreesArray(flatCoords),
        material: Cesium.Color.fromCssColorString('beige').withAlpha(0.6),
        height: 0,
        outline: true,
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 2
      }
    });
  }

  isPointInsideCountry(lon: number, lat: number): boolean {
    // If no map is loaded or no country borders, allow the point
    if (!this.currentLoadedMap) {
      console.log('No map loaded, allowing point');
      return true;
    }

    if (this.countryBorders.length === 0) {
      console.log('No country borders loaded, allowing point');
      return true;
    }

    // Find country borders matching the loaded map
    const features = this.countryBorders.filter(f =>
      f.properties &&
      (f.properties.ADMIN === this.currentLoadedMap?.countryName ||
       f.properties.name === this.currentLoadedMap?.countryName)
    );

    console.log(`Checking point (${lon}, ${lat}) against ${features.length} country features for ${this.currentLoadedMap?.countryName}`);

    if (features.length === 0) {
      console.log('No matching country features found, allowing point');
      return true; // If no borders found, allow
    }

    // Check if point is inside any of the country's polygons
    for (const feature of features) {
      if (feature.geometry.type === 'Polygon') {
        for (const ring of feature.geometry.coordinates) {
          if (this.pointInPolygon(lon, lat, ring)) {
            console.log('Point is inside country boundary');
            return true;
          }
        }
      } else if (feature.geometry.type === 'MultiPolygon') {
        for (const polygon of feature.geometry.coordinates) {
          for (const ring of polygon) {
            if (this.pointInPolygon(lon, lat, ring)) {
              console.log('Point is inside country boundary (MultiPolygon)');
              return true;
            }
          }
        }
      }
    }

    console.log('Point is OUTSIDE country boundary');
    return false;
  }

  pointInPolygon(lon: number, lat: number, ring: number[][]): boolean {
    let inside = false;
    for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
      const xi = ring[i][0], yi = ring[i][1];
      const xj = ring[j][0], yj = ring[j][1];
      const intersect = ((yi > lat) !== (yj > lat)) && (lon < (xj - xi) * (lat - yi) / (yj - yi) + xi);
      if (intersect) inside = !inside;
    }
    return inside;
  }

  // Basic geometry validation to avoid sending malformed geometries to backend
  validateGeometry(geometry: any): { valid: boolean; message?: string } {
    if (!geometry || !geometry.type) return { valid: false, message: 'Missing geometry or type' };
    const type = (geometry.type || '').toLowerCase();

    if (type === 'point') {
      const c = geometry.coordinates;
      if (!Array.isArray(c) || c.length < 2) return { valid: false, message: 'Point must have 2 coordinates [lon, lat]' };
      if (isNaN(Number(c[0])) || isNaN(Number(c[1]))) return { valid: false, message: 'Point coordinates must be numbers' };
      return { valid: true };
    }

    if (type === 'linestring') {
      const c = geometry.coordinates;
      if (!Array.isArray(c) || c.length < 2) return { valid: false, message: 'LineString needs at least 2 points' };
      return { valid: true };
    }

    if (type === 'polygon') {
      const c = geometry.coordinates;
      if (!Array.isArray(c) || c.length === 0) return { valid: false, message: 'Polygon coordinates missing' };
      const outer = c[0];
      if (!Array.isArray(outer) || outer.length < 3) return { valid: false, message: 'Polygon outer ring must have at least 3 points' };
      return { valid: true };
    }

    // For other geometry types, perform a minimal check
    if (Array.isArray(geometry.coordinates)) return { valid: true };
    return { valid: false, message: 'Unsupported or malformed geometry' };
  }

  // Attempt to normalize common GeoJSON formatting issues (extra nesting, object points)
  normalizeGeometry(geometry: any): any {
    if (!geometry) return geometry;
    const type = (geometry.type || '').toLowerCase();

    const toNumberPair = (pt: any) => {
      if (Array.isArray(pt) && pt.length >= 2) return [Number(pt[0]), Number(pt[1])];
      if (pt && typeof pt === 'object') return [Number(pt.lon ?? pt.lng ?? pt.longitude), Number(pt.lat ?? pt.latitude)];
      return pt;
    };

    if (type === 'point') {
      const c = geometry.coordinates;
      if (Array.isArray(c)) geometry.coordinates = toNumberPair(c);
      return geometry;
    }

    if (type === 'linestring') {
      let c = geometry.coordinates;
      // unwrap extra nesting
      while (Array.isArray(c) && c.length === 1 && Array.isArray(c[0])) c = c[0];
      if (Array.isArray(c) && typeof c[0] === 'number') c = [c];
      geometry.coordinates = (c || []).map((p: any) => toNumberPair(p));
      return geometry;
    }

    if (type === 'polygon') {
      let c = geometry.coordinates;
      // Unwrap common extra nesting levels: [[[...]]] -> [[...]]
      while (Array.isArray(c) && c.length === 1 && Array.isArray(c[0]) && Array.isArray(c[0][0])) {
        c = c[0];
      }

      // If coordinates look like a flat list of numbers, wrap as single ring
      if (Array.isArray(c) && c.length > 0 && typeof c[0] === 'number') {
        c = [c];
      }

      // Ensure each ring is an array of [lon,lat]
      if (Array.isArray(c)) {
        c = c.map((ring: any) => {
          // If ring is a single point wrapped, try to unwrap
          if (Array.isArray(ring) && ring.length === 1 && Array.isArray(ring[0])) ring = ring[0];
          if (!Array.isArray(ring)) return ring;
          return ring.map((pt: any) => toNumberPair(pt));
        });
      }

      geometry.coordinates = c;
      return geometry;
    }

    // Default: try minimal normalization
    if (geometry.coordinates) {
      geometry.coordinates = JSON.parse(JSON.stringify(geometry.coordinates));
    }
    return geometry;
  }

  editLocation(): void {
    if (!this.selectedLocation) return;

    // First, show a dialog to edit the name
    Swal.fire({
      title: 'Edit Location Name',
      input: 'text',
      inputValue: this.selectedLocation.name,
      inputPlaceholder: 'Enter location name',
      showCancelButton: true,
      confirmButtonText: 'Next',
      cancelButtonText: 'Cancel',
      background: '#1f2937',
      color: '#ffffff',
      inputValidator: (value) => {
        if (!value) {
          return 'Please enter a name!';
        }
        return null;
      }
    }).then((result) => {
      if (result.isConfirmed) {
        const newName = result.value;
        
        // Then open the content dialog to edit contents
        const dialogRef = this.dialog.open(PolygonContentDialogComponent, {
          width: '600px',
          maxHeight: '80vh',
          panelClass: 'dark-dialog',
          backdropClass: 'dialog-backdrop',
          disableClose: false,
          data: { 
            name: newName, 
            contents: this.selectedLocation.contents || [],
            isCreating: false 
          }
        });

        dialogRef.afterClosed().subscribe((contents) => {
          if (contents !== null && contents !== undefined) {
            // Build the location update object with all required fields
            const updatedLocation: any = {
              id: this.selectedLocation!.id,
              name: newName,
              category: this.selectedLocation!.category,
              type: this.selectedLocation!.type,
              mapId: this.selectedLocation!.mapId || (this.currentMap ? this.currentMap.id : undefined),
              parentId: this.selectedLocation!.parentId,
              geometry: this.selectedLocation!.geometry
            };

            // Ensure we have all required fields
            if (!updatedLocation.mapId && this.currentMap) {
              updatedLocation.mapId = this.currentMap.id;
            }

            // Ensure geometry is preserved
            if (!updatedLocation.geometry) {
              console.error('Location geometry is missing!', updatedLocation);
              Swal.fire({
                title: 'Error!',
                text: 'Location geometry is missing. Cannot update.',
                icon: 'error',
                background: '#1f2937',
                color: '#ffffff'
              });
              return;
            }

            const request: any = {
              location: updatedLocation,
              contents: contents || []
            };

            // Validate geometry before sending to backend to avoid server conversion errors
            updatedLocation.geometry = this.normalizeGeometry(updatedLocation.geometry);
            const validation = this.validateGeometry(updatedLocation.geometry);
            if (!validation.valid) {
              // Try to auto-repair by extracting coordinates from the selected Cesium entity
              console.warn('Initial validation failed, attempting repair:', validation.message, updatedLocation.geometry);
              const repaired = this.attemptRepairPolygonFromSelectedEntity();
              if (repaired) {
                // Ask user to confirm using repaired geometry
                Swal.fire({
                  title: 'Repair Polygon?',
                  text: 'The polygon geometry looked malformed. Use repaired polygon geometry from the viewer?',
                  icon: 'question',
                  showCancelButton: true,
                  confirmButtonText: 'Use Repaired',
                  cancelButtonText: 'Cancel',
                  background: '#1f2937',
                  color: '#ffffff'
                }).then(choice => {
                  if (choice.isConfirmed) {
                    // Update both the location object and the request
                    updatedLocation.geometry = repaired;
                    const repairedRequest: any = {
                      location: updatedLocation,
                      contents: contents || []
                    };

                    console.log('Updating location with repaired geometry:', JSON.stringify(repairedRequest, null, 2));
                    this.locationsService.updateLocation(this.selectedLocation!.id!, repairedRequest).subscribe({
                      next: () => {
                        Swal.fire({
                          title: 'Updated!',
                          text: 'Location updated successfully with repaired geometry',
                          icon: 'success',
                          background: '#1f2937',
                          color: '#ffffff'
                        });
                        this.closeRightSidebar();
                        if (this.currentLoadedMap) {
                          this.loadDefaultMapOnViewer(this.currentLoadedMap);
                        }
                      },
                      error: (err) => {
                        console.error('Update error:', err);
                        console.error('Error response:', err.error);
                        Swal.fire({
                          title: 'Error!',
                          text: `Failed to update location: ${err.error?.message || err.message || 'Unknown error'}`,
                          icon: 'error',
                          background: '#1f2937',
                          color: '#ffffff'
                        });
                      }
                    });
                  }
                });
                return;
              }

              console.error('Invalid geometry, aborting update:', validation.message, updatedLocation.geometry);
              Swal.fire({
                title: 'Invalid Geometry',
                text: validation.message,
                icon: 'error',
                background: '#1f2937',
                color: '#ffffff'
              });
              return;
            }

            // Update request with normalized geometry
            request.location.geometry = updatedLocation.geometry;

            console.log('Updating location with request:', JSON.stringify(request, null, 2));
            this.locationsService.updateLocation(this.selectedLocation!.id!, request).subscribe({
              next: () => {
                Swal.fire({
                  title: 'Updated!',
                  text: 'Location updated successfully',
                  icon: 'success',
                  background: '#1f2937',
                  color: '#ffffff'
                });
                this.closeRightSidebar();
                if (this.currentLoadedMap) {
                  this.loadDefaultMapOnViewer(this.currentLoadedMap);
                }
              },
              error: (err) => {
                console.error('Update error:', err);
                console.error('Error response:', err.error);
                Swal.fire({
                  title: 'Error!',
                  text: `Failed to update location: ${err.error?.message || err.message || 'Unknown error'}`,
                  icon: 'error',
                  background: '#1f2937',
                  color: '#ffffff'
                });
              }
            });
          }
        });
      }
    });
  }

  // Try to build a valid Polygon geometry from the currently selected Cesium entity
  attemptRepairPolygonFromSelectedEntity(): any | null {
    try {
      const entity = this.viewer?.selectedEntity;
      if (!entity || !entity.polygon) return null;

      // Retrieve hierarchy (may be a Property)
      const hierarchy = entity.polygon.hierarchy && (entity.polygon.hierarchy.getValue ? entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()) : entity.polygon.hierarchy);
      if (!hierarchy) return null;

      const positions: Cesium.Cartesian3[] = hierarchy.positions || hierarchy; // sometimes hierarchy is array
      if (!positions || positions.length < 3) return null;

      const coords: number[][] = positions.map((c: Cesium.Cartesian3) => {
        const carto = Cesium.Cartographic.fromCartesian(c);
        return [Cesium.Math.toDegrees(carto.longitude), Cesium.Math.toDegrees(carto.latitude)];
      });

      if (coords.length < 3) return null;

      // Ensure closed ring
      const first = coords[0];
      const last = coords[coords.length - 1];
      if (Math.abs(first[0] - last[0]) > 1e-6 || Math.abs(first[1] - last[1]) > 1e-6) coords.push([first[0], first[1]]);

      return { type: 'Polygon', coordinates: [coords] };
    } catch (e) {
      console.error('Repair extraction failed', e);
      return null;
    }
  }

  deleteLocation(): void {
    if (!this.selectedLocation) return;

    Swal.fire({
      title: 'Are you sure?',
      text: `Delete ${this.selectedLocation.geometry?.type === 'Point' ? 'point' : 'zone'} "${this.selectedLocation.name}"?`,
      icon: 'warning',
      showCancelButton: true,
      confirmButtonText: 'Yes, delete it!',
      background: '#1f2937',
      color: '#ffffff'
    }).then((result) => {
      if (result.isConfirmed && this.selectedLocation) {
        this.locationsService.deleteLocation(this.selectedLocation.id!).subscribe({
          next: () => {
            // Instantly refresh the map by reloading
            this.closeRightSidebar();
            if (this.currentLoadedMap) {
              this.loadDefaultMapOnViewer(this.currentLoadedMap);
            }
          },
          error: (err) => {
            console.error(err);
            Swal.fire({
              title: 'Error!',
              text: 'Failed to delete location',
              icon: 'error',
              background: '#1f2937',
              color: '#ffffff'
            });
          }
        });
      }
    });
  }

  /**
   * Edit district (opens dialog to edit/create district contents)
   */
  async editDistrict(): Promise<void> {
    const districtLocation = await this.getDistrictAsLocation();
    if (!districtLocation) return;

    const dialogRef = this.dialog.open(PolygonContentDialogComponent, {
      width: '600px',
      maxHeight: '80vh',
      panelClass: 'dark-dialog',
      backdropClass: 'dialog-backdrop',
      disableClose: false,
      data: {
        name: districtLocation.name,
        contents: districtLocation.contents || [],
        isCreating: districtLocation.id === 0 || !districtLocation.id
      }
    });

    dialogRef.afterClosed().subscribe(async (result) => {
      if (result !== null && result !== undefined && districtLocation) {
        if (!this.currentMap || !this.currentMap.id) {
          Swal.fire({ title: 'Error', text: 'No map selected. Please select a map first.', icon: 'error', background: '#1f2937', color: '#ffffff' });
          return;
        }

        const locationDTO: LocationDTO = {
          ...districtLocation,
          mapId: this.currentMap.id,
          parentId: this.countryLocationId || undefined
        };

        const normalizedContents = Array.isArray(result) ? result : ((result as any)?.contents || []);
        const requestBody = { location: locationDTO, contents: normalizedContents };

        try {
          const saved = await this.locationsService.createOrUpdateDistrict(requestBody, this.countryLocationId || undefined).toPromise();

          Swal.fire({ title: 'Success', text: 'District saved successfully', icon: 'success', timer: 2000, showConfirmButton: false, toast: true, position: 'top-end', background: '#1f2937', color: '#ffffff' });

          // Refresh UI
          if (this.currentLoadedMap) {
            this.loadDefaultMapOnViewer(this.currentLoadedMap);
          } else {
            this.loadProjects();
          }

          this.selectedLocation = saved;
          this.selectedContents = saved.contents || [];
        } catch (error) {
          console.error('Error saving district', error);
          Swal.fire({ title: 'Error', text: 'Failed to save district', icon: 'error', background: '#1f2937', color: '#ffffff' });
        }
      }
    });
  }

  /**
   * Delete district
   */
  deleteDistrict(): void {
    if (!this.selectedLocation) return;

    Swal.fire({
      title: 'Are you sure?',
      text: `Delete district "${this.selectedLocation.name}"? This will remove all associated content.`,
      icon: 'warning',
      showCancelButton: true,
      confirmButtonColor: '#f44336',
      cancelButtonColor: '#6b7280',
      confirmButtonText: 'Yes, delete it!',
      cancelButtonText: 'Cancel',
      background: '#1f2937',
      color: '#ffffff'
    }).then((result) => {
      if (result.isConfirmed && this.selectedLocation && this.selectedLocation.id) {
        this.locationsService.deleteLocation(this.selectedLocation.id).subscribe(() => {
          Swal.fire({ title: 'Deleted!', text: 'District has been deleted.', icon: 'success', timer: 2000, showConfirmButton: false, toast: true, position: 'top-end', background: '#1f2937', color: '#ffffff' });
          this.clearSelection?.();
          if (this.currentLoadedMap) {
            this.loadDefaultMapOnViewer(this.currentLoadedMap);
          }
        }, err => {
          console.error('Error deleting district', err);
          Swal.fire({ title: 'Error!', text: 'Failed to delete district', icon: 'error', confirmButtonColor: '#f44336', background: '#1f2937', color: '#ffffff' });
        });
      }
    });
  }

  clearSelection() {
    this.clearZoneProjects();
    this.selectedName = null;
    this.selectedContents = [];
    this.selectedLocation = null;
    this.selectedDistrict = null; // Clear district selection
    // Hide zone child points if they're displayed
    if (this.currentZoneId !== null && this.zoneChildEntities.has(this.currentZoneId)) {
      this.toggleZonePoints(this.currentZoneId); // Toggle off (hide)
    }
    this.currentZoneChildPoints = []; // Clear child points
    this.currentZoneId = null;
    this.showLocationsList = true;
    this.showRightSidebar = false;
    this.viewer.selectedEntity = undefined;
    // Stop tracking any entity so camera is free to move
    try { this.viewer.trackedEntity = undefined; } catch (e) {}
  }
  
  backToList() {
    // Return the right sidebar to the list view and clear any transient detail state
    this.showLocationsList = true;
    this.showRightSidebar = true;
    this.selectedName = null;
    this.selectedContents = [];
    this.selectedLocation = null;
    this.selectedDistrict = null;
    this.currentZoneChildPoints = [];
    this.currentZoneId = null;
    try { this.viewer.trackedEntity = undefined; } catch (e) {}
    this.cdr.detectChanges();
  }
  // Navigation methods for exploring locations
  navigatePrevious(): void {
    if (this.currentLocationIndex > 0) {
      this.currentLocationIndex--;
      this.selectLocationByIndex(this.currentLocationIndex);
    }
  }
  clearZoneProjects(): void {
    this.currentZoneProjectEntities.forEach(entity => {
      try { this.viewer.entities.remove(entity); } catch (e) {}
    });
    this.displayedProjectEntities = this.displayedProjectEntities.filter(
      e => !this.currentZoneProjectEntities.includes(e)
    );
    this.currentZoneProjectEntities = [];
    this.currentZoneProjectZoneId = null;
  }
  navigateNext(): void {
    if (this.currentLocationIndex < this.navigableLocations.length - 1) {
      this.currentLocationIndex++;
      this.selectLocationByIndex(this.currentLocationIndex);
    }
  }
toggleZonePoints(zoneId: number) {
  if (this.zoneChildEntities.has(zoneId)) {
    const ents = this.zoneChildEntities.get(zoneId) || [];
    ents.forEach(e => { try { this.viewer.entities.remove(e); } catch (err) {} });
    this.zoneChildEntities.delete(zoneId);
    return;
  }

  const children = this.zoneChildMap.get(zoneId) || [];
  if (!children || children.length === 0) return;

  const created: Cesium.Entity[] = [];
  const pinImage = this.createUserPointDiamondPin();

  children.forEach((loc: any) => {
    let [lon, lat] = loc.geometry.coordinates;
    lon = Number(lon); lat = Number(lat);

    const ent = this.viewer.entities.add({
      name: loc.name,
      position: Cesium.Cartesian3.fromDegrees(lon, lat),
      billboard: {
        image: pinImage,
        verticalOrigin: Cesium.VerticalOrigin.CENTER,
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
        scaleByDistance: new Cesium.NearFarScalar(1.0e3, 1.2, 1.0e6, 0.6),
        width: 52,
        height: 52
      },
      label: {
        text: loc.name,
        font: 'bold 13px sans-serif',
        fillColor: Cesium.Color.fromCssColorString('#39FF14'),
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 2,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        pixelOffset: new Cesium.Cartesian2(0, 34),
        verticalOrigin: Cesium.VerticalOrigin.TOP,
        showBackground: true,
        backgroundColor: Cesium.Color.BLACK.withAlpha(0.8),
        backgroundPadding: new Cesium.Cartesian2(8, 6),
        disableDepthTestDistance: Number.POSITIVE_INFINITY
      },
      properties: { contents: loc.contents || [], location: loc, parentZoneId: zoneId }
    });
    created.push(ent);
  });

  this.zoneChildEntities.set(zoneId, created);
}
  selectLocationByIndex(index: number): void {
    const location = this.navigableLocations[index];
    if (!location) return;

    this.currentLocationIndex = index;

    // Find the entity for this location in the viewer
    const entity = this.viewer.entities.values.find((e: Cesium.Entity) => e.name === location.name);

    if (entity) {
      this.openLocationDetails(location, entity);
      return;
    }

    this.openLocationDetails(location);

    // Fallback camera movement when entity is not found in the scene
    if (location.geometry?.type === 'Point') {
      const coords = location.geometry.coordinates;
      this.viewer.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(coords[0], coords[1], 100000),
        duration: 2
      });
    } else if (location.geometry?.type === 'Polygon') {
      const coords = location.geometry.coordinates[0];
      const avgLon = coords.reduce((sum: number, c: number[]) => sum + c[0], 0) / coords.length;
      const avgLat = coords.reduce((sum: number, c: number[]) => sum + c[1], 0) / coords.length;
      this.viewer.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(avgLon, avgLat, 100000),
        duration: 2
      });
    }
  }

  // ==================== DISTRICTS (ZONES) SUPPORT ====================

  /**
   * Mapping of Tunisia districts: Arabic, English, French names, and member governorates
   */
  private tunisiaDistrictsMapping: { [id: string]: { name_ar: string; name_en: string; name_fr: string; members: string[]; members_ar?: string[] } } = {
    district1: { name_ar: 'الإقليم الأول', name_en: 'First District', name_fr: 'Premier District', members: ['Bizerte', 'Beja', 'Jendouba', 'Le Kef'], members_ar: ['بنزرت', 'باجة', 'جندوبة', 'الكاف'] },
    district2: { name_ar: 'الإقليم الثاني', name_en: 'Second District', name_fr: 'Deuxième District', members: ['Tunis', 'Ariana', 'Manubah', 'Ben Arous','Nabeul','Zaghouan'], members_ar: ['تونس', 'أريانة', 'منوبة', 'بن عروس', 'نابل', 'زغوان'] },
    district3: { name_ar: 'الإقليم الثالث', name_en: 'Third District', name_fr: 'Troisième District', members: ['Sousse', 'Kasserine', 'Siliana', 'Kairouan','Monastir', 'Mahdia'], members_ar: ['سوسة', 'القصرين', 'سليانة', 'القيروان', 'المنستير', 'المهدية'] },
    district4: { name_ar: 'الإقليم الرابع', name_en: 'Fourth District', name_fr: 'Quatrième District', members: ['Tozeur', 'Sfax Governorate','Gafsa' ,'Sidi Bou Zid'], members_ar: ['توزر', 'صفاقس', 'قفصة', 'سيدي بوزيد'] },
    district5: { name_ar: 'الإقليم الخامس', name_en: 'Fifth District', name_fr: 'Cinquième District', members: ['Gabes', 'Medenine', 'Tataouine','Kebili'], members_ar: ['قابس', 'مدنين', 'تطاوين', 'قبلي'] },
  };

  private tunisiaDistrictGeometries: { [id: string]: any } = {};

  /**
   * Load Tunisia ADM1 GeoJSON and render merged district polygons with labels
   */
  private async displayTunisiaDistricts() {
    try {
      const geojson: any = await this.http.get('assets/tunisia_adm1.geojson').toPromise();
      const features = geojson.features || [];

      const normalize = (s: string) => (s || '').normalize ? s.normalize('NFD').replace(/\p{Diacritic}/gu, '').toLowerCase() : (s || '').toLowerCase();

      for (const id of Object.keys(this.tunisiaDistrictsMapping)) {
        const meta = this.tunisiaDistrictsMapping[id];

        const matched = features.filter((f: any) => {
          const name = (f.properties && (f.properties.NAME_1 || f.properties.NAME || f.properties.ADMIN)) || '';
          const nname = normalize(name);
          return meta.members.some(m => normalize(m) === nname || nname.includes(normalize(m)) || normalize(m).includes(nname));
        });

        if (!matched.length) {
          console.warn(`No governorates matched for ${id} (${meta.name_en})`);
          continue;
        }

        // Store matched governorate features for on-demand rendering when district is clicked
        this.tunisiaDistrictMatchedFeatures[id] = matched;
        console.log(`Stored ${matched.length} features for district ${id}:`, matched.map((f: any) => f.properties?.NAME_1 || f.properties?.NAME));

        let merged: any = null;
        for (const f of matched) {
          const featureCopy = JSON.parse(JSON.stringify(f));
          if (!merged) merged = featureCopy;
          else {
            try {
              merged = turf.union(merged, featureCopy);
            } catch (e) {
              console.warn('turf.union failed, using fallback', e);
              if (merged.geometry.type === 'Polygon') merged.geometry = { type: 'MultiPolygon', coordinates: [merged.geometry.coordinates] };
              if (featureCopy.geometry.type === 'Polygon') featureCopy.geometry = { type: 'MultiPolygon', coordinates: [featureCopy.geometry.coordinates] };
              merged.geometry.coordinates = merged.geometry.coordinates.concat(featureCopy.geometry.coordinates || []);
            }
          }
        }

        if (!merged) continue;

        const ctr = turf.centroid(merged);
        const [lon, lat] = ctr.geometry.coordinates;

        this.tunisiaDistrictGeometries[id] = merged.geometry;

        const districtFeature = {
          type: 'FeatureCollection',
          features: [
            {
              type: 'Feature',
              properties: { id, name_en: meta.name_en, name_ar: meta.name_ar },
              geometry: merged.geometry
            }
          ]
        };

        const ds = await Cesium.GeoJsonDataSource.load(districtFeature, { clampToGround: false });
        this.viewer.dataSources.add(ds);

        const districtIndex = Object.keys(this.tunisiaDistrictsMapping).indexOf(id);
        const totalDistricts = Object.keys(this.tunisiaDistrictsMapping).length || 5;
        const hue = Math.round((districtIndex / totalDistricts) * 360);
        const fillHex = this.hslToHex(hue, 70, 50);
        const fillAlpha = 0.28;

        ds.entities.values.forEach((ent: any) => {
          if (ent.polygon) {
            ent.polygon.material = Cesium.Color.fromCssColorString(fillHex).withAlpha(fillAlpha);
            ent.polygon.outline = true;
            ent.polygon.outlineColor = Cesium.Color.fromCssColorString('#000000');
            ent.polygon.outlineWidth = 2;
          }
        });

        this.districtLabelData.set(id, { lon, lat, meta });

        const labelText = this.getDistrictLabelText(meta);
        
        let label: Cesium.Entity;
        
        if (this.currentLanguage === 'ar') {
          const imageUrl = this.createArabicTextImage(meta.name_ar, 18);
          label = this.viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(lon, lat),
            billboard: {
              image: imageUrl,
              verticalOrigin: Cesium.VerticalOrigin.CENTER,
              horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
              disableDepthTestDistance: Number.POSITIVE_INFINITY,
              scaleByDistance: new Cesium.NearFarScalar(1.0e5, 1.0, 2.0e7, 0.45)
            },
            properties: { districtId: id, labelType: 'district' }
          });
        } else {
          label = this.viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(lon, lat),
            label: {
              text: new Cesium.ConstantProperty(labelText),
              font: 'bold 18px sans-serif',
              fillColor: Cesium.Color.WHITE,
              outlineColor: Cesium.Color.BLACK,
              outlineWidth: 2,
              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
              verticalOrigin: Cesium.VerticalOrigin.CENTER,
              horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
              disableDepthTestDistance: Number.POSITIVE_INFINITY,
              scaleByDistance: new Cesium.NearFarScalar(1.0e5, 1.0, 2.0e7, 0.45)
            },
            properties: { districtId: id, labelType: 'district' }
          });
        }
        
        this.districtLabelEntities.push(label);
        ds.entities.values.forEach((ent: any) => this.displayedCountryBorders.push(ent));
      }

      if (this.displayedCountryBorders.length > 0) {
        this.viewer.flyTo(this.displayedCountryBorders, { duration: 2 });
      }

      // Populate districts and governorates for right sidebar
      this.applyRightSidebarFilter();
      
      // Show right sidebar with districts/governorates list
      this.showRightSidebar = true;
      this.showLocationsList = true;

    } catch (err) {
      console.error('Error rendering Tunisia districts', err);
    }
  }

  private getDistrictLabelText(meta: any): string {
    let labelText = meta.name_en;
    if (this.currentLanguage === 'ar') {
      labelText = this.reverseArabicText(meta.name_ar);
    } else if (this.currentLanguage === 'fr') {
      labelText = meta.name_fr;
    }
    return labelText;
  }

  private reverseArabicText(text: string): string {
    if (!text) return text;
    try {
      const reshaped = reshape(text);
      return reshaped;
    } catch (error) {
      console.error('Error processing Arabic text (reshape):', error);
      return text;
    }
  }

  private createArabicTextImage(text: string, fontSize: number = 18): string {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    if (!ctx) return '';

    const processedText = this.reverseArabicText(text);
    const fontSpec = `bold ${fontSize}px Amiri, "Noto Naskh Arabic", Arial, sans-serif`;

    ctx.font = fontSpec;
    try { ctx.direction = 'rtl'; } catch (e) { /* ignore if unsupported */ }
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';

    const metrics = ctx.measureText(processedText || text);
    const textWidth = Math.ceil(metrics.width || (fontSize * (processedText.length || 1)));
    const textHeight = Math.ceil(fontSize * 1.6);

    const paddingX = 16;
    const paddingY = 8;
    canvas.width = textWidth + paddingX * 2;
    canvas.height = textHeight + paddingY * 2;

    ctx.font = fontSpec;
    try { ctx.direction = 'rtl'; } catch (e) { /* ignore */ }
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';

    ctx.shadowColor = 'rgba(0,0,0,0.6)';
    ctx.shadowOffsetX = 1;
    ctx.shadowOffsetY = 1;
    ctx.shadowBlur = 2;

    ctx.lineWidth = Math.max(2, Math.round(fontSize / 8));
    ctx.strokeStyle = 'black';
    ctx.strokeText(processedText, canvas.width / 2, canvas.height / 2);

    ctx.fillStyle = 'white';
    ctx.fillText(processedText, canvas.width / 2, canvas.height / 2);

    return canvas.toDataURL('image/png');
  }

  private updateDistrictLabels(): void {
    // Remove old district label entities
    this.districtLabelEntities.forEach(entity => {
      this.viewer.entities.remove(entity);
    });
    this.districtLabelEntities = [];

    // Recreate labels with current language
    this.districtLabelData.forEach((data, id) => {
      const { lon, lat, meta } = data;
      const labelText = this.getDistrictLabelText(meta);
      
      let label: Cesium.Entity;
      
      if (this.currentLanguage === 'ar') {
        const imageUrl = this.createArabicTextImage(meta.name_ar, 18);
        label = this.viewer.entities.add({
          position: Cesium.Cartesian3.fromDegrees(lon, lat),
          billboard: {
            image: imageUrl,
            verticalOrigin: Cesium.VerticalOrigin.CENTER,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            disableDepthTestDistance: Number.POSITIVE_INFINITY,
            scaleByDistance: new Cesium.NearFarScalar(1.0e5, 1.0, 2.0e7, 0.45)
          },
          properties: { districtId: id, labelType: 'district' }
        });
      } else {
        label = this.viewer.entities.add({
          position: Cesium.Cartesian3.fromDegrees(lon, lat),
          label: {
            text: new Cesium.ConstantProperty(labelText),
            font: 'bold 18px sans-serif',
            fillColor: Cesium.Color.WHITE,
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 2,
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            verticalOrigin: Cesium.VerticalOrigin.CENTER,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            disableDepthTestDistance: Number.POSITIVE_INFINITY,
            scaleByDistance: new Cesium.NearFarScalar(1.0e5, 1.0, 2.0e7, 0.45)
          },
          properties: { districtId: id, labelType: 'district' }
        });
      }
      
      this.districtLabelEntities.push(label);
    });
  }

  /**
   * Clear currently displayed district governorates
   */
  private clearDisplayedDistricts(): void {
    // Remove all displayed district entities (governorate borders and labels)
    this.displayedDistrictEntities.forEach(entity => {
      try {
        this.viewer.entities.remove(entity);
      } catch (e) {
        // Entity may already be removed
      }
    });
    this.displayedDistrictEntities = [];
  }

  /**
   * Show governorates for a specific district (on-demand rendering)
   */
  private async showDistrict(districtId: string): Promise<void> {
    console.log('=== showDistrict called for:', districtId);
    
    // Clear any previously displayed district governorates
    this.clearDisplayedDistricts();

    const matched = this.tunisiaDistrictMatchedFeatures[districtId];
    console.log('Matched governorate features:', matched?.length || 0);
    
    if (!matched || !matched.length) {
      console.warn(`No governorates found for district ${districtId}`);
      console.warn('Available districts:', Object.keys(this.tunisiaDistrictMatchedFeatures));
      return;
    }

    const meta = this.tunisiaDistrictsMapping[districtId];
    if (!meta) {
      console.warn(`No metadata found for district ${districtId}`);
      return;
    }

    console.log(`Rendering ${matched.length} governorates for ${meta.name_en}:`, meta.members);

    // Helper to normalize names for fuzzy matching
    const normalize = (s: string) => (s || '').normalize ? s.normalize('NFD').replace(/\p{Diacritic}/gu, '').toLowerCase() : (s || '').toLowerCase();

    // Render governorate borders and labels
    for (const govFeature of matched) {
      try {
        // Compute centroid for label placement
        const gCtr = turf.centroid(govFeature);
        const [glon, glat] = gCtr.geometry.coordinates;

        // Derive governorate display names for each language
        const baseName = (govFeature.properties && (govFeature.properties.NAME_1 || govFeature.properties.NAME || govFeature.properties.ADMIN)) || '';
        const govNameEn = baseName;
        let govNameAr = govFeature.properties?.NAME_1_AR || baseName;
        const govNameFr = govFeature.properties?.NAME_1_FR || baseName;

        try {
          // Find index of matching English member to map to provided Arabic member name
          const baseNormalized = normalize(baseName);
          const idx = meta.members.findIndex((m: any) => {
            const mNorm = normalize(m);
            return mNorm === baseNormalized || baseNormalized.includes(mNorm) || mNorm.includes(baseNormalized);
          });
          if (idx >= 0 && meta.members_ar && meta.members_ar[idx]) {
            govNameAr = meta.members_ar[idx];
          }
        } catch (e) {
          // ignore; fallback already set
        }

        console.log(`Rendering governorate: ${govNameEn}`);

        // Build per-governorate outline(s) with bright cyan color for visibility
        const outlineColor = Cesium.Color.fromCssColorString('#00FFFF').withAlpha(0.9); // Bright cyan
        
        if (govFeature.geometry.type === 'Polygon') {
          const positions: number[] = [];
          govFeature.geometry.coordinates.forEach((ring: any) => {
            ring.forEach((coord: any) => positions.push(coord[0], coord[1]));
          });
          const outlineEnt = this.viewer.entities.add({
            polygon: {
              hierarchy: Cesium.Cartesian3.fromDegreesArray(positions),
              material: Cesium.Color.TRANSPARENT,
              height: 500,  // Elevate well above ground and terrain
              outline: true,
              outlineColor: outlineColor,
              outlineWidth: 3,  // Thicker line for visibility
              fill: false,
              perPositionHeight: false
            },
            name: govNameEn,
            // Give outline a non-colliding id (label will carry canonical id)
            id: `GOV_${districtId}_${normalize((govFeature.properties && (govFeature.properties.NAME_1 || govFeature.properties.NAME || govFeature.properties.ADMIN)) || '')}_outline`,
            properties: { isGovernorate: true, govProps: govFeature.properties }
          });
          this.displayedDistrictEntities.push(outlineEnt);
          console.log(`Added governorate polygon entity for ${govNameEn}`);
        } else if (govFeature.geometry.type === 'MultiPolygon') {
          govFeature.geometry.coordinates.forEach((polygon: any) => {
            polygon.forEach((ring: any) => {
              const positions: number[] = [];
              ring.forEach((coord: any) => positions.push(coord[0], coord[1]));
              const outlineEnt = this.viewer.entities.add({
                polygon: {
                  hierarchy: Cesium.Cartesian3.fromDegreesArray(positions),
                  material: Cesium.Color.TRANSPARENT,
                  height: 500,  // Elevate well above ground and terrain
                  outline: true,
                  outlineColor: outlineColor,
                  outlineWidth: 3,  // Thicker line for visibility
                  fill: false,
                  perPositionHeight: false
                },
                name: govNameEn,
                properties: { isGovernorate: true, govProps: govFeature.properties }
              });
              this.displayedDistrictEntities.push(outlineEnt);
            });
          });
        }

        // Governorate labels removed: show outlines only to reduce clutter.
        // If labels are needed later, enable via a config flag and recreate label entities here.
      } catch (e) {
        console.warn('Failed to render governorate outline/label for a matched feature', e);
      }
    }
    
    console.log(`✓ Finished rendering district ${districtId}: ${this.displayedDistrictEntities.length} entities added (borders + labels)`);
    
    // Fly camera to view the rendered governorates
    if (this.displayedDistrictEntities.length > 0) {
      try {
        await this.viewer.flyTo(this.displayedDistrictEntities, {
          duration: 2,
          offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-45), 800000)
        });
        console.log('Camera flew to governorates');
      } catch (e) {
        console.warn('Failed to fly to governorates', e);
      }
    }
  }

  private hslToHex(h: number, s: number, l: number): string {
    s /= 100;
    l /= 100;
    const k = (n: number) => (n + h / 30) % 12;
    const a = s * Math.min(l, 1 - l);
    const f = (n: number) => {
      const color = l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
      return Math.round(255 * color).toString(16).padStart(2, '0');
    };
    return `#${f(0)}${f(8)}${f(4)}`;
  }

  getDistrictName(): string {
    if (!this.selectedDistrict) return '';
    const meta = this.selectedDistrict.meta;
    if (this.currentLanguage === 'ar') return meta.name_ar;
    if (this.currentLanguage === 'fr') return meta.name_fr;
    return meta.name_en;
  }

  /**
   * Get governorate display name based on current language
   */
  getGovernorateDisplayName(districtId: string, index: number): string {
    const meta = this.tunisiaDistrictsMapping[districtId];
    if (!meta) return '';
    
    if (this.currentLanguage === 'ar' && meta.members_ar && meta.members_ar[index]) {
      return meta.members_ar[index];
    }
    return meta.members[index];
  }

  /**
   * Fly camera to a specific governorate
   */
  async flyToGovernorate(districtId: string, governorateIndex: number): Promise<void> {
    // Ensure governorates for this district are rendered so entities exist
    if (!this.displayedDistrictEntities || this.displayedDistrictEntities.length === 0) {
      try {
        await this.showDistrict(districtId);
      } catch (e) {
        console.warn('Could not render district before flyToGovernorate', e);
      }
    }

    // Derive canonical governorate name from metadata and build entity id
    const meta = this.tunisiaDistrictsMapping[districtId];
    if (!meta || !meta.members || governorateIndex < 0 || governorateIndex >= meta.members.length) {
      console.warn(`Invalid governorate index ${governorateIndex} for district ${districtId}`);
      return;
    }

    const normalizeFn = (s: string) => (s || '').normalize ? s.normalize('NFD').replace(/\p{Diacritic}/gu, '').toLowerCase() : (s || '').toLowerCase();
    const baseName = meta.members[governorateIndex] || '';
    const entId = `GOV_${districtId}_${normalizeFn(baseName)}`;

    const ent = this.viewer.entities.getById(entId);
    if (ent) {
      try {
        await this.viewer.flyTo(ent, {
          duration: 1.3,
          offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-40), 110000)
        });
        console.log(`Flew to governorate entity ${entId}`);
      } catch (e) {
        console.warn('Failed to fly to governorate entity', e);
      }
    } else {
      console.warn(`Governorate entity not found for id ${entId}`);
    }
  }

  /**
   * Get governorate image path for thumbnails
   */

  /**
   * Set right sidebar tab
   */
  setRightSidebarTab(tab: string): void {
    this.selectedRightSidebarTab = tab;
    this.applyRightSidebarFilter();
  }

  /**
   * Apply filter based on selected tab
   */
  applyRightSidebarFilter(): void {
    // Populate districts and governorates lists
    this.allDistricts = Object.keys(this.tunisiaDistrictsMapping).map(id => ({
      id,
      ...this.tunisiaDistrictsMapping[id]
    }));

    this.allGovernorates = [];
    Object.keys(this.tunisiaDistrictsMapping).forEach(districtId => {
      const meta = this.tunisiaDistrictsMapping[districtId];
      meta.members.forEach((memberName: string, idx: number) => {
        this.allGovernorates.push({
          districtId,
          index: idx,
          name: memberName,
          name_ar: meta.members_ar ? meta.members_ar[idx] : memberName,
          displayName: this.getGovernorateDisplayName(districtId, idx)
        });
      });
    });

    if (this.selectedRightSidebarTab === 'DISTRICTS') {
      this.filteredDistricts = this.allDistricts;
      this.filteredGovernorates = [];
      this.filteredSectors = [];
    } else if (this.selectedRightSidebarTab === 'GOVERNORATES') {
      this.filteredDistricts = [];
      this.filteredGovernorates = this.allGovernorates;
      this.filteredSectors = [];
    } else if (this.selectedRightSidebarTab === 'SECTORS') {
      this.filteredDistricts = [];
      this.filteredGovernorates = [];
      this.filteredSectors = this.allSectors;
    } else {
      // ALL
      this.filteredDistricts = this.allDistricts;
      this.filteredGovernorates = this.allGovernorates;
      this.filteredSectors = [];
    }
  }

  /**
   * Get district name by ID based on current language
   */
  getDistrictNameById(id: string): string {
    const meta = this.tunisiaDistrictsMapping[id];
    if (!meta) return '';
    if (this.currentLanguage === 'ar') return meta.name_ar;
    if (this.currentLanguage === 'fr') return meta.name_fr;
    return meta.name_en;
  }

  /**
   * Select district from list
   */
  async selectDistrictFromList(district: any): Promise<void> {
    this.selectedDistrict = { id: district.id, meta: district.meta || district };
    this.selectedLocation = null;
    this.showRightSidebar = true;
    this.showLocationsList = false;

    // Load district contents from backend
    try {
      const districtLocation = await this.getDistrictAsLocation();
      if (districtLocation && districtLocation.id && districtLocation.id > 0) {
        this.selectedLocation = districtLocation;
        this.selectedName = districtLocation.name;
        this.selectedContents = districtLocation.contents || [];
      }
    } catch (err) {
      console.error('Failed to load district contents', err);
    }

    // If backend has no saved LocationDTO for this district, synthesize a basic selectedLocation
    if (!this.selectedLocation) {
      const synthesized: any = {
        id: 0,
        name: district.meta?.name_en || district.name_en || district.name,
        category: 'DISTRICT',
        type: 'ZONE',
        mapId: this.currentMap?.id || 0,
        parentId: this.countryLocationId || undefined,
        geometry: this.tunisiaDistrictGeometries[district.id] || null,
        contents: []
      };
      const img = this.getDistrictImage(district.id);
      if (img) {
        synthesized.contents.push({ content: { type: 'IMAGE', value: img } });
      }
      const members = (district.meta?.members || district.members || []).join(', ');
      const desc = `${district.meta?.name_en || district.name_en || district.name} — administrative district containing: ${members}.`;
      synthesized.contents.push({ content: { type: 'TEXT', value: desc } });
      this.selectedLocation = synthesized as LocationDTO;
      this.selectedName = synthesized.name;
      this.selectedContents = synthesized.contents || [];
    }

    // Render governorates on-demand for this district
    try {
      await this.showDistrict(district.id);
    } catch (e) {
      console.warn('Error rendering district governorates:', e);
    }
    // Optionally: fly to district pin if needed (see cesium-map for details)
  }

  /**
   * Select governorate from list
   */
  async selectGovernorateFromList(governorate: any): Promise<void> {
    await this.flyToGovernorate(governorate.districtId, governorate.index);
    // Prefer flying to the pre-registered Cesium entity for the governorate (if available)
    // (Optional: mimic cesium-map fly logic if needed)
    this.selectedDistrict = null;
    this.showLocationsList = false;
    this.showRightSidebar = true;
    // Store selected governorate for edit/delete operations
    try {
      const govName = governorate.displayName || governorate.name || governorate.nameEn;
      this.selectedLocation = await this.getGovernorateAsLocation({
        ...governorate,
        nameEn: govName
      });
      this.selectedName = this.selectedLocation.name;
      this.selectedContents = this.selectedLocation.contents || [];
    } catch (err) {
      console.error('Failed to load governorate as location', err);
      // Even if backend fetch fails, create a basic location object for editing
      this.selectedLocation = {
        id: 0,
        name: governorate.displayName || governorate.name || governorate.nameEn,
        category: 'GOVERNORATE',
        type: LocationType.ZONE,
        mapId: this.currentMap?.id || 0,
        parentId: this.countryLocationId || undefined,
        geometry: null,
        contents: []
      };
      this.selectedName = this.selectedLocation.name;
      this.selectedContents = [];
    }
  }

  /**
   * Convert governorate to LocationDTO for editing
   */
  private async getGovernorateAsLocation(governorate: any): Promise<LocationDTO> {
    const matched = this.tunisiaDistrictMatchedFeatures[governorate.districtId];
    if (!matched || !matched[governorate.index]) {
      throw new Error('Governorate feature not found');
    }

    if (!this.currentMap || !this.currentMap.id) {
      throw new Error('No map selected. Please select a map first.');
    }

    const govFeature = matched[governorate.index];
    const meta = this.tunisiaDistrictsMapping[governorate.districtId];
    
    // Create a LocationDTO representing this governorate as a ZONE
    const locationDTO: LocationDTO = {
      id: 0, // Will be set when fetched from backend
      name: governorate.nameEn,
      category: 'GOVERNORATE',
      type: LocationType.ZONE,
      mapId: this.currentMap.id,
      parentId: this.countryLocationId || undefined,
      geometry: govFeature.geometry,
      contents: [] // Will be populated when editing
    };

    // Try to fetch existing governorate from backend
    if (this.currentMap.id) {
      try {
        const locations = await this.locationsService.getLocationsByMap(this.currentMap.id).toPromise();
        const normalize = (s: string) => s.toLowerCase().replace(/\s+/g, '').normalize('NFD').replace(/\p{Diacritic}/gu, '');
        const existing = locations?.find((loc: any) => {
          return normalize(loc.name) === normalize(governorate.nameEn) && loc.category === 'GOVERNORATE';
        });
        if (existing) {
          if (existing.id && existing.id > 0) {
            try {
              return await this.locationsService.getLocationDetails(existing.id).toPromise();
            } catch (detailError) {
              return existing;
            }
          }
          return existing;
        }
      } catch (e) {
        console.warn('Could not fetch governorate from backend', e);
      }
    }

    return locationDTO;
  }

  /**
   * Convert district to LocationDTO for editing / display
   */
  async getDistrictAsLocation(): Promise<LocationDTO | null> {
    if (!this.selectedDistrict) return null;

    const districtId = this.selectedDistrict.id;
    const meta = this.selectedDistrict.meta;
    const geometry = this.tunisiaDistrictGeometries[districtId];

    if (!geometry) {
      console.error('District geometry not found');
      return null;
    }

    if (!this.currentMap || !this.currentMap.id) {
      Swal.fire({
        title: 'Error',
        text: 'No map selected. Please select a map first.',
        icon: 'error',
        background: '#1f2937',
        color: '#ffffff'
      });
      return null;
    }

    const locationDTO: LocationDTO = {
      id: 0,
      name: meta.name_en,
      category: 'DISTRICT',
      type: LocationType.ZONE,
      mapId: this.currentMap.id,
      parentId: this.countryLocationId || undefined,
      geometry: geometry,
      contents: []
    };

    // Try to fetch existing district from backend
    if (this.currentMap?.id) {
      try {
        const locations = await this.locationsService.getLocationsByMap(this.currentMap.id).toPromise();
        const normalize = (s: string) => s.toLowerCase().replace(/\s+/g, '').normalize('NFD').replace(/\p{Diacritic}/gu, '');
        const existing = locations?.find((loc: any) => normalize(loc.name) === normalize(meta.name_en) && loc.category === 'DISTRICT');
        if (existing) {
          if (existing.id && existing.id > 0) {
            try {
              return await this.locationsService.getLocationDetails(existing.id).toPromise();
            } catch (detailError) {
              return existing;
            }
          }
          return existing;
        }
      } catch (e) {
        console.warn('Could not fetch district from backend', e);
      }
    // ...existing code...
    }

    return locationDTO;
  }

  /**
   * Edit governorate (opens dialog like for zones/points)
   */
  async editGovernorate(): Promise<void> {
    if (!this.selectedLocation) return;

    if (this.selectedLocation.id && this.selectedLocation.id > 0) {
      try {
        const fullLocation = await this.locationsService.getLocationDetails(this.selectedLocation.id).toPromise();
        if (fullLocation) {
          this.selectedLocation = { ...(this.selectedLocation as any), ...(fullLocation as any) };
          this.selectedContents = this.selectedLocation.contents || [];
        }
      } catch (e) {
        console.warn('Could not load full governorate details before edit', e);
      }
    }

    const dialogRef = this.dialog.open(PolygonContentDialogComponent, {
      width: '600px',
      maxHeight: '80vh',
      panelClass: 'dark-dialog',
      backdropClass: 'dialog-backdrop',
      disableClose: false,
      data: {
        name: this.selectedLocation.name,
        contents: this.selectedLocation.contents || [],
        isCreating: this.selectedLocation.id === 0 || !this.selectedLocation.id
      }
    });

    dialogRef.afterClosed().subscribe(async (result) => {
      if (result !== null && result !== undefined && this.selectedLocation) {
        if (!this.currentMap || !this.currentMap.id) {
          Swal.fire({
            title: 'Error',
            text: 'No map selected. Please select a map first.',
            icon: 'error',
            background: '#1f2937',
            color: '#ffffff'
          });
          return;
        }

        const locationDTO: LocationDTO = {
          ...this.selectedLocation,
          mapId: this.currentMap.id,
          parentId: this.countryLocationId || undefined
        };

        const normalizedContents = Array.isArray(result) ? result : ((result as any)?.contents || []);
        const requestBody = {
          location: locationDTO,
          contents: normalizedContents
        };

        try {
          // Validate required fields
          if (!locationDTO.mapId) {
            throw new Error('Map ID is required. Please ensure a map is selected.');
          }

          // Use the new createOrUpdate endpoint that handles find-or-create logic
          const saved = await this.locationsService.createOrUpdateGovernorate(
            requestBody,
            this.countryLocationId || undefined
          ).toPromise();
          
          Swal.fire({
            title: 'Success',
            text: 'Governorate saved successfully',
            icon: 'success',
            timer: 2000,
            showConfirmButton: false,
            toast: true,
            position: 'top-end',
            background: '#1f2937',
            color: '#ffffff'
          });
          
          // Update selected location with saved data
          this.selectedLocation = saved;
          
          // Reload the current map to refresh locations
          if (this.currentLoadedMap) {
            this.loadDefaultMapOnViewer(this.currentLoadedMap);
          }
        } catch (error: any) {
          console.error('Error saving governorate', error);
          const errorMessage = error?.message || error?.error?.message || 'Failed to save governorate';
          Swal.fire({
            title: 'Error',
            text: errorMessage,
            icon: 'error',
            background: '#1f2937',
            color: '#ffffff'
          });
        }
      }
    });
  }

  /**
   * Delete governorate
   */
  async deleteGovernorate(): Promise<void> {
    if (!this.selectedLocation || !this.selectedLocation.id) return;

    const result = await Swal.fire({
      title: 'Delete Governorate?',
      text: `Are you sure you want to delete ${this.selectedLocation.name}?`,
      icon: 'warning',
      showCancelButton: true,
      confirmButtonColor: '#ef4444',
      cancelButtonColor: '#6b7280',
      confirmButtonText: 'Yes, delete it',
      cancelButtonText: 'Cancel',
      background: '#1f2937',
      color: '#ffffff'
    });

    if (result.isConfirmed) {
      try {
        await this.locationsService.deleteLocation(this.selectedLocation.id).toPromise();
        Swal.fire({
          title: 'Deleted',
          text: 'Governorate deleted successfully',
          icon: 'success',
          timer: 2000,
          showConfirmButton: false,
          toast: true,
          position: 'top-end',
          background: '#1f2937',
          color: '#ffffff'
        });
        this.closeRightSidebar();
        // Reload the current map to refresh locations
        if (this.currentLoadedMap) {
          this.loadDefaultMapOnViewer(this.currentLoadedMap);
        }
      } catch (error) {
        console.error('Error deleting governorate', error);
        Swal.fire({
          title: 'Error',
          text: 'Failed to delete governorate',
          icon: 'error',
          background: '#1f2937',
          color: '#ffffff'
        });
      }
    }
  }

  /**
   * Get all projects for a specific sector
   */
  getProjectsBySector(sectorId: number | undefined): LocationDTO[] {
    if (!sectorId) return [];
    return this.allProjects.filter(p => (p as any).sectorId === sectorId);
  }

  /**
   * Edit selected project (placeholder)
   */
  editProject(): void {
    if (!this.selectedProject) return;

    Swal.fire({
      title: 'Edit Project',
      text: 'Project editing UI will be implemented soon.',
      icon: 'info',
      confirmButtonText: 'OK',
      background: '#1f2937',
      color: '#ffffff'
    });
  }

  /**
   * Delete selected project
   */
  deleteProject(): void {
    if (!this.selectedProject || !this.selectedProject.id) return;

    Swal.fire({
      title: 'Are you sure?',
      text: `Delete project "${this.selectedProject.name}"?`,
      icon: 'warning',
      showCancelButton: true,
      confirmButtonColor: '#f44336',
      cancelButtonColor: '#6b7280',
      confirmButtonText: 'Yes, delete it!',
      cancelButtonText: 'Cancel',
      background: '#1f2937',
      color: '#ffffff'
    }).then((result) => {
      if (result.isConfirmed && this.selectedProject && this.selectedProject.id) {
        this.locationsService.deleteLocation(this.selectedProject.id).subscribe({
          next: () => {
            Swal.fire({ title: 'Deleted!', text: 'Project has been deleted.', icon: 'success', timer: 2000, showConfirmButton: false, toast: true, position: 'top-end', background: '#1f2937', color: '#ffffff' });
            this.selectedProject = null;
            this.showLocationsList = true;
            this.loadProjects();
            if (this.currentLoadedMap) this.loadDefaultMapOnViewer(this.currentLoadedMap);
          },
          error: (err) => {
            console.error('Error deleting project', err);
            Swal.fire({ title: 'Error!', text: 'Failed to delete project', icon: 'error', confirmButtonColor: '#f44336', background: '#1f2937', color: '#ffffff' });
          }
        });
      }
    });
  }

  /**
   * Open a native file picker to select an image for a sector and upload/update it.
   */
  openSectorImagePicker(sector: SectorDTO): void {
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = 'image/*';
    input.onchange = (ev: any) => {
      const file = ev.target.files && ev.target.files[0];
      if (!file) return;
      // show a quick preview immediately
      const reader = new FileReader();
      reader.onload = () => {
        (sector as any).imageUrl = reader.result as string;
      };
      reader.readAsDataURL(file);

      // upload the binary file via multipart to backend
      if (sector.id) {
        this.sectorService.uploadSectorImage(sector.id, file).subscribe({
          next: (updated: SectorDTO) => {
            (sector as any).imageUrl = (updated as any).imageUrl || (sector as any).imageUrl;
            Swal.fire({ title: 'Saved', text: 'Sector image uploaded', icon: 'success', timer: 1400, toast: true, position: 'top-end', background: '#1f2937', color: '#ffffff' });
          },
          error: (err) => {
            console.error('Image upload failed', err);
            Swal.fire({ title: 'Upload failed', text: 'Could not upload image to server', icon: 'error', timer: 2000, toast: true, position: 'top-end', background: '#1f2937', color: '#ffffff' });
          }
        });
      }
    };
    input.click();
  }

  getSectorImage(sector: SectorDTO): string {
    return (sector as any).imageUrl || sector['image'] || 'assets/district-images/placeholder.png';
  }

  /**
   * Select a project from the list and show its details
   */
  selectProjectFromList(project: LocationDTO): void {
    // Mimic cesium-map: show projects for parent zone if available, then select project
    if ((project as any).parentId) {
      // Optionally: showProjectsForZone((project as any).parentId); // Implement if needed
    }
    // Then select the project to show info
    this.selectedProject = project;
    this.locationsService.getLocationDetails(project.id!).subscribe({
      next: (location: LocationDTO) => {
        this.selectedLocation = location;
        this.selectedDistrict = null;
        this.showRightSidebar = true;
        this.showLocationsList = false;
      },
      error: (err) => {
        console.warn('Failed to fetch project details as LocationDTO:', err);
        if (project.geometry && project.geometry.coordinates && this.currentMap && this.currentMap.id) {
          const [plon, plat] = project.geometry.coordinates;
          this.locationsService.getLocationsByMap(this.currentMap.id).subscribe((locations: LocationDTO[]) => {
            const match = locations.find(loc => {
              const coords = loc.geometry?.coordinates;
              if (!coords) return false;
              const lon = coords[0];
              const lat = coords[1];
              const eps = 1e-6;
              return Math.abs(lon - plon) <= eps && Math.abs(lat - plat) <= eps;
            });
            if (match) {
              this.selectedLocation = match;
              this.selectedDistrict = null;
              this.showRightSidebar = true;
              this.showLocationsList = false;
            } else {
              Swal.fire('Info', 'Project details not available as a Location; showing basic info', 'info');
            }
          }, (err2) => {
            console.error('Fallback getLocationsByMap failed:', err2);
            Swal.fire('Error', 'Failed to load project details', 'error');
          });
        } else {
          Swal.fire('Error', 'Failed to load project details', 'error');
        }
      }
    });

  }

  /**
   * Select a sector from the list and show its projects
   */
  selectSectorFromList(sector: SectorDTO): void {
    this.selectedSector = sector;
    this.selectedLocation = null;
    this.selectedDistrict = null;
    this.showLocationsList = false;
    this.showRightSidebar = true;
    // Optionally set selectedName/contents if you want a sector detail panel
  }
  getProjectImage(project: LocationDTO): string | null {
    if (!project) return null;
    
    // If the project already has contents loaded, extract image directly
    if (project.contents && project.contents.length > 0) {
      return this.getLocationImage(project);
    }
    
    // Fallback: search allProjects cache by id
    const cached = this.allProjects.find(p => p.id === project.id);
    if (cached && cached.contents && cached.contents.length > 0) {
      return this.getLocationImage(cached as any);
    }
    
    return null;
  }
  getGovernorateImage(govName: string): string | null {
    if (!this.currentMap?.id) return null;
    
    // Normalize function for fuzzy comparison
    const normalize = (s: string) => s.toLowerCase().replace(/\s+/g, '').normalize('NFD').replace(/\p{Diacritic}/gu, '');
    const targetNorm = normalize(govName);
    
    // Try to find the governorate location in allLocations cache
    const govMatches = this.allLocations.filter(loc => {
      if (loc.category !== 'GOVERNORATE') return false;
      const locNorm = normalize(loc.name);
      return locNorm === targetNorm || locNorm.includes(targetNorm) || targetNorm.includes(locNorm);
    });

    govMatches.sort((a, b) => {
      const score = (loc: LocationDTO) => ((Array.isArray(loc.contents) && loc.contents.length > 0) ? 2 : 0) + (loc.id ? 1 : 0);
      const byScore = score(b) - score(a);
      if (byScore !== 0) return byScore;
      return Number(b.id || 0) - Number(a.id || 0);
    });

    const govLocation = govMatches[0];
    
    if (govLocation && govLocation.contents) {
      return this.getLocationImage(govLocation);
    }
    
    return null;
  }
  private createUserPointDiamondPin(): string {
  return this.createDiamondPinIcon('#39FF14', 52);
}
private createDiamondPinIcon(color: string, size: number = 56): string {
  const canvas = document.createElement('canvas');
  canvas.width = size;
  canvas.height = size;
  const ctx = canvas.getContext('2d');
  if (!ctx) return '';

  const cx = size / 2;
  const cy = size / 2;
  const half = size * 0.38;

  // Drop shadow
  ctx.save();
  ctx.shadowColor = 'rgba(0,0,0,0.45)';
  ctx.shadowBlur = 6;
  ctx.shadowOffsetX = 2;
  ctx.shadowOffsetY = 3;

  // Outer diamond (border)
  ctx.beginPath();
  ctx.moveTo(cx, cy - half);         // top
  ctx.lineTo(cx + half, cy);         // right
  ctx.lineTo(cx, cy + half);         // bottom
  ctx.lineTo(cx - half, cy);         // left
  ctx.closePath();
  ctx.fillStyle = '#FFFFFF';
  ctx.fill();
  ctx.restore();

  // Inner diamond (colored fill) - slightly smaller
  const inner = half * 0.78;
  ctx.beginPath();
  ctx.moveTo(cx, cy - inner);
  ctx.lineTo(cx + inner, cy);
  ctx.lineTo(cx, cy + inner);
  ctx.lineTo(cx - inner, cy);
  ctx.closePath();
  ctx.fillStyle = color;
  ctx.fill();

  // Subtle inner glow / shine
  const gradient = ctx.createRadialGradient(cx - inner * 0.2, cy - inner * 0.3, 1, cx, cy, inner);
  gradient.addColorStop(0, 'rgba(255,255,255,0.35)');
  gradient.addColorStop(1, 'rgba(0,0,0,0.0)');
  ctx.beginPath();
  ctx.moveTo(cx, cy - inner);
  ctx.lineTo(cx + inner, cy);
  ctx.lineTo(cx, cy + inner);
  ctx.lineTo(cx - inner, cy);
  ctx.closePath();
  ctx.fillStyle = gradient;
  ctx.fill();

  return canvas.toDataURL('image/png');
}

}
