import { Component, OnInit } from '@angular/core';
import { LocationsService, DynamicImportRequest } from './src/app/Services/locations.service';
import { LocationDTO } from './src/app/Models/location.model';

/**
 * Example component demonstrating the dynamic district/governorate system.
 * 
 * This shows how to:
 * 1. Define district mapping dynamically
 * 2. Import districts to backend
 * 3. Load and display hierarchical data efficiently
 * 4. Handle user interactions with lazy loading
 */
@Component({
  selector: 'app-dynamic-districts-example',
  templateUrl: './EXAMPLE_dynamic-districts.component.html',
  styleUrls: []
})
export class DynamicDistrictsExampleComponent implements OnInit {

  currentMapId = 1; // Your map ID
  currentLanguage = 'en'; // 'ar', 'en', or 'fr'
  
  districts: LocationDTO[] = [];
  selectedDistrict: LocationDTO | null = null;
  selectedGovernorate: LocationDTO | null = null;
  
  loading = false;
  importStatus = '';

  /**
   * DYNAMIC DISTRICT MAPPING
   * 
   * This is the ONLY place you define your districts and governorates.
   * No backend code changes needed to add/modify districts!
   */
  private tunisiaDistrictsMapping: any = {
    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: ['قابس', 'مدنين', 'تطاوين', 'قبلي']
    }
  };

  constructor(private locationsService: LocationsService) {}

  ngOnInit(): void {
    // Load districts when component initializes
    this.loadDistricts();
  }

  /**
   * STEP 1: Import districts dynamically to backend
   * 
   * This only needs to be run once (or when you update the mapping).
   * The backend will create parent/child relationships automatically.
   */
  async importDistricts(): Promise<void> {
    this.loading = true;
    this.importStatus = 'Importing districts...';

    try {
      // Build request from mapping
      const request: DynamicImportRequest = this.locationsService.buildDynamicImportRequest(
        this.currentMapId,
        this.tunisiaDistrictsMapping
      );

      // Send to backend
      const result = await this.locationsService.importDynamicDistricts(request).toPromise();
      
      this.importStatus = result || 'Import successful!';
      console.log('Import completed:', result);

      // Reload districts
      await this.loadDistricts();

    } catch (error) {
      this.importStatus = 'Import failed: ' + error;
      console.error('Import error:', error);
    } finally {
      this.loading = false;
    }
  }

  /**
   * STEP 2: Load districts with governorates (hierarchical data)
   * 
   * Uses includeGeometry=false for performance.
   * Geometry is loaded on-demand when user clicks.
   */
  async loadDistricts(): Promise<void> {
    this.loading = true;

    try {
      // Load hierarchy without geometry (fast)
      this.districts = await this.locationsService
        .getDistrictsHierarchy(this.currentMapId, false)
        .toPromise() || [];
      
      console.log('Loaded districts:', this.districts);

    } catch (error) {
      console.error('Failed to load districts:', error);
    } finally {
      this.loading = false;
    }
  }

  /**
   * STEP 3: Handle user selection (lazy load full details)
   * 
   * When user clicks a district, load full details with geometry.
   */
  async selectDistrict(district: LocationDTO): Promise<void> {
    this.loading = true;
    this.selectedDistrict = null;
    this.selectedGovernorate = null;

    try {
      // Load full details with geometry
      this.selectedDistrict = await this.locationsService
        .getLocationDetails(district.id!)
        .toPromise() || null;
      
      console.log('Selected district:', this.selectedDistrict);

      // TODO: Zoom camera to district on map
      // this.viewer.flyTo(districtEntity);

    } catch (error) {
      console.error('Failed to load district details:', error);
    } finally {
      this.loading = false;
    }
  }

  /**
   * STEP 4: Handle governorate selection
   */
  async selectGovernorate(governorate: LocationDTO): Promise<void> {
    this.loading = true;
    this.selectedGovernorate = null;

    try {
      // Load full details with geometry
      this.selectedGovernorate = await this.locationsService
        .getLocationDetails(governorate.id!)
        .toPromise() || null;
      
      console.log('Selected governorate:', this.selectedGovernorate);

      // TODO: Zoom camera to governorate on map
      // this.viewer.flyTo(governorateEntity);

    } catch (error) {
      console.error('Failed to load governorate details:', error);
    } finally {
      this.loading = false;
    }
  }

  /**
   * UTILITY: Get localized name based on current language
   */
  getLocalizedName(location: LocationDTO): string {
    if (!location.translations) {
      return location.name;
    }

    switch (this.currentLanguage) {
      case 'ar': return location.translations.ar;
      case 'fr': return location.translations.fr;
      default: return location.translations.en;
    }
  }

  /**
   * UTILITY: Change display language
   */
  changeLanguage(lang: 'ar' | 'en' | 'fr'): void {
    this.currentLanguage = lang;
  }

  /**
   * UTILITY: Get first image from contents
   */
  getFirstImage(location: LocationDTO): string | null {
    if (!location.contents || location.contents.length === 0) {
      return null;
    }

    for (const content of location.contents) {
      if (content.content['type'] === 'image' && content.content['url']) {
        return content.content['url'];
      }
    }

    return null;
  }

  /**
   * UTILITY: Check if location has content
   */
  hasContent(location: LocationDTO): boolean {
    return !!(location.contents && location.contents.length > 0);
  }

  /**
   * Example: Update governorate content
   */
  async updateGovernorateContent(governorate: LocationDTO, newContent: any): Promise<void> {
    try {
      const request = {
        location: {
          id: governorate.id,
          name: governorate.name,
          type: governorate.type,
          mapId: this.currentMapId,
          geometry: governorate.geometry
        },
        contents: [{ content: newContent }]
      };

      await this.locationsService.updateLocation(governorate.id!, request).toPromise();
      
      // Reload details
      this.selectedGovernorate = await this.locationsService
        .getLocationDetails(governorate.id!)
        .toPromise() || null;

      console.log('Content updated successfully');

    } catch (error) {
      console.error('Failed to update content:', error);
    }
  }

  /**
   * Example: Add new district dynamically
   * 
   * Just add to the mapping and re-import!
   */
  addNewDistrict(): void {
    // Add new district to mapping
    this.tunisiaDistrictsMapping['district6'] = {
      name_ar: 'الإقليم السادس',
      name_en: 'Sixth District',
      name_fr: 'Sixième District',
      members: ['NewGov1', 'NewGov2'],
      members_ar: ['محافظة جديدة 1', 'محافظة جديدة 2']
    };

    // Re-import (idempotent - won't duplicate existing)
    this.importDistricts();
  }
}
