import { AfterViewInit, Component, ElementRef, Input, OnDestroy, ViewChild } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import * as turf from '@turf/turf';

declare const Cesium: any;

/**
 * Cesium component that visualizes Tunisian districts by merging ADM1 governorates.
 * Inputs:
 *  - geoJsonPath: path to ADM1 GeoJSON (default: 'assets/tunisia_adm1.geojson')
 *  - districtsMapping: object where keys are district identifiers and value is { name_ar, name_en, members: [NAME_1 strings] }
 *
 * Note: Requires `npm install @turf/turf` for polygon union and centroid calculations.
 */
@Component({
  selector: 'app-cesium-tunisia-districts',
  templateUrl: './cesium-tunisia-districts.component.html',
  styleUrls: ['./cesium-tunisia-districts.component.css']
})
export class CesiumTunisiaDistrictsComponent implements AfterViewInit, OnDestroy {
  @ViewChild('mapContainer', { static: true }) mapContainer!: ElementRef<HTMLDivElement>;

  @Input() geoJsonPath = 'assets/tunisia_adm1.geojson';

  @Input() districtsMapping: { [id: string]: { name_ar: string; name_en: string; members: string[] } } = {
    first: {
      name_ar: 'الإقليم الأول',
      name_en: 'First District',
      members: ['Bizerte', 'Beja', 'Jendouba', 'El Kef']
    },
    second: {
      name_ar: 'الإقليم الثاني',
      name_en: 'Second District',
      members: ['Tunis', 'Ariana', 'Manouba', 'Ben Arous']
    }
    // Add other districts as needed
  };

  private viewer: any;
  private dataSources: any[] = [];

  constructor(private http: HttpClient) {}

  ngAfterViewInit(): void {
    this.viewer = new Cesium.Viewer(this.mapContainer.nativeElement, {
      timeline: false,
      animation: false,
      baseLayerPicker: true,
      infoBox: false,
      selectionIndicator: false
    });

    this.loadAndRender();
  }

  ngOnDestroy(): void {
    try {
      this.viewer?.destroy();
    } catch (e) {
      // ignore
    }
  }

  private async loadAndRender() {
    try {
      const geojson: any = await this.http.get(this.geoJsonPath).toPromise();

      // Index features by NAME_1 for quick lookup
      const features = geojson.features || [];

      // For each district, collect matching features and perform turf.union
      for (const id of Object.keys(this.districtsMapping)) {
        const meta = this.districtsMapping[id];
        const matched = features.filter((f: any) => {
          const name = f.properties && (f.properties.NAME_1 || f.properties.NAME || f.properties.NAME_EN);
          return meta.members.includes(name);
        });

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

        // Convert matched features to turf features and union them
        let merged: any = null;
        for (const f of matched) {
          const turfFeat = f; // already GeoJSON feature
          if (!merged) merged = turfFeat;
          else merged = turf.union(merged, turfFeat) as any;
        }

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

        // Build a GeoJSON FeatureCollection for this merged district
        const districtFeature = {
          type: 'FeatureCollection',
          features: [
            {
              type: 'Feature',
              properties: {
                id,
                name_en: meta.name_en,
                name_ar: meta.name_ar
              },
              geometry: merged.geometry
            }
          ]
        };

        // Load into Cesium as GeoJsonDataSource so Cesium handles polygon details
        const ds = await Cesium.GeoJsonDataSource.load(districtFeature, { clampToGround: false });
        this.viewer.dataSources.add(ds);
        this.dataSources.push(ds);

        // Style the polygon and add a label at centroid
        ds.entities.values.forEach((ent: any) => {
          if (ent.polygon) {
            ent.polygon.material = Cesium.Color.fromCssColorString('#4caf50').withAlpha(0.35);
            ent.polygon.outline = true;
            ent.polygon.outlineColor = Cesium.Color.BLACK;
          }
        });

        // Arabic first, then English (browser/Cesium will handle RTL rendering if container dir=rtl)
        const labelText = `${meta.name_ar}\n${meta.name_en}`;
        this.viewer.entities.add({
          position: Cesium.Cartesian3.fromDegrees(lon, lat),
          label: {
            text: labelText,
            font: '18px Arial',
            fillColor: Cesium.Color.BLACK,
            style: Cesium.LabelStyle.FILL,
            verticalOrigin: Cesium.VerticalOrigin.CENTER,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            pixelOffset: new Cesium.Cartesian2(0, -10),
            eyeOffset: new Cesium.Cartesian3(0, 0, 0)
          }
        });
      }

      // Zoom to full extent
      this.viewer.zoomTo(this.viewer.entities);

    } catch (err) {
      console.error('Failed loading or rendering GeoJSON', err);
    }
  }
}
