<template>
  <div ref="mapContainer" class="map-container"></div>
</template>

<script>
import { config } from '@/config';
// Annahme: Sie haben bereits MSAL oder ähnliche Entra ID Integration
// import { msalInstance } from '@/auth/msal'; // Ihr MSAL Setup

export default {
  name: 'AzureMapsComponent',

  props: {
    coordinates: {
      type: Object,
      required: true,
      validator(value) {
        return value &&
            typeof value.latitude === 'number' &&
            typeof value.longitude === 'number';
      }
    },
    draggable: {
      type: Boolean,
      default: false
    }
  },

  data() {
    return {
      map: null,
      marker: null,
      datasource: null,
      azureMapsClientId: null // Wird vom Backend geholt
    };
  },

  mounted() {
    this.initializeMap();
  },

  beforeUnmount() {
    if (this.map) {
      this.map.dispose();
    }
  },

  watch: {
    coordinates: {
      handler(newCoords) {
        if (this.marker && this.map) {
          this.updateMarkerPosition(newCoords);
        }
      },
      deep: true
    },

    draggable(newValue) {
      if (this.marker) {
        this.updateMarkerDraggable(newValue);
      }
    }
  },

  methods: {
    async initializeMap() {
      try {
        // Azure Maps SDK laden
        if (!window.atlas) {
          await this.loadAzureMapsSDK();
        }

        // Azure Maps Client ID vom Backend abrufen
        await this.fetchAzureMapsConfig();

        // Karte mit Entra ID-Authentifizierung initialisieren
        this.map = new window.atlas.Map(this.$refs.mapContainer, {
          center: [this.coordinates.longitude, this.coordinates.latitude],
          zoom: 15,
          authOptions: {
            authType: 'aad',
            clientId: this.azureMapsClientId,
            aadAppId: this.azureMapsClientId,
            aadTenant: 'common', // oder Ihre spezifische Tenant ID
            getToken: this.getEntraIdTokenForMaps
          }
        });

        // Warten bis die Karte geladen ist
        this.map.events.add('ready', () => {
          this.setupMap();
        });

      } catch (error) {
        console.error('Fehler beim Initialisieren der Karte:', error);
        this.$emit('error', error);
      }
    },

    /**
     * Azure Maps Konfiguration vom Backend abrufen
     */
    async fetchAzureMapsConfig() {
      try {
        const response = await fetch(`${config.backendUrl}/maps/config`, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${await this.getCurrentUserToken()}`
          }
        });

        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }

        const configData = await response.json();
        this.azureMapsClientId = configData.clientId;

        console.debug('Azure Maps Konfiguration erfolgreich abgerufen');

      } catch (error) {
        console.error('Fehler beim Abrufen der Azure Maps Konfiguration:', error);
        throw new Error('Konnte Azure Maps Konfiguration nicht abrufen');
      }
    },

    /**
     * Entra ID Token für Azure Maps abrufen
     */
    async getEntraIdTokenForMaps() {
      try {
        // Azure Maps spezifischen Scope verwenden
        const tokenRequest = {
          scopes: ['https://atlas.microsoft.com/user_impersonation'],
          account: msalInstance.getActiveAccount()
        };

        const response = await msalInstance.acquireTokenSilent(tokenRequest);
        return response.accessToken;

      } catch (error) {
        console.error('Fehler beim Abrufen des Azure Maps Tokens:', error);

        // Fallback: Interactive Token Acquisition
        try {
          const response = await msalInstance.acquireTokenPopup(tokenRequest);
          return response.accessToken;
        } catch (popupError) {
          console.error('Interactive Token-Abruf fehlgeschlagen:', popupError);
          throw new Error('Konnte kein Token für Azure Maps abrufen');
        }
      }
    },

    /**
     * Aktuelles Benutzer-Token für Backend-Aufrufe
     */
    async getCurrentUserToken() {
      try {
        const account = msalInstance.getActiveAccount();
        if (!account) {
          throw new Error('Kein aktiver Benutzer gefunden');
        }

        const tokenRequest = {
          scopes: [`${config.backendUrl}/.default`], // Backend API Scope
          account: account
        };

        const response = await msalInstance.acquireTokenSilent(tokenRequest);
        return response.accessToken;

      } catch (error) {
        console.error('Fehler beim Abrufen des Backend-Tokens:', error);
        throw new Error('Konnte Backend-Token nicht abrufen');
      }
    },

    loadAzureMapsSDK() {
      return new Promise((resolve, reject) => {
        if (window.atlas) {
          resolve();
          return;
        }

        // CSS laden
        const linkElement = document.createElement('link');
        linkElement.rel = 'stylesheet';
        linkElement.href = 'https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css';
        document.head.appendChild(linkElement);

        // JavaScript SDK laden
        const scriptElement = document.createElement('script');
        scriptElement.src = 'https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js';
        scriptElement.onload = resolve;
        scriptElement.onerror = reject;
        document.head.appendChild(scriptElement);
      });
    },

    setupMap() {
      // Datenquelle für den Marker erstellen
      this.datasource = new window.atlas.source.DataSource();
      this.map.sources.add(this.datasource);

      // Symbol-Layer für den Marker hinzufügen
      this.map.layers.add(new window.atlas.layer.SymbolLayer(this.datasource, null, {
        iconOptions: {
          allowOverlap: true,
          ignorePlacement: true
        }
      }));

      // Marker erstellen
      this.createMarker();

      // Event-Listener für draggable Funktionalität
      if (this.draggable) {
        this.enableMarkerDrag();
      }
    },

    createMarker() {
      const point = new window.atlas.data.Point([
        this.coordinates.longitude,
        this.coordinates.latitude
      ]);

      this.marker = new window.atlas.data.Feature(point, {
        id: 'marker',
        draggable: this.draggable
      });

      this.datasource.add(this.marker);
    },

    updateMarkerPosition(coords) {
      if (this.marker && this.datasource) {
        this.marker.geometry.coordinates = [coords.longitude, coords.latitude];
        this.datasource.setShapes([this.marker]);
        this.map.setCamera({
          center: [coords.longitude, coords.latitude]
        });
      }
    },

    updateMarkerDraggable(isDraggable) {
      if (isDraggable) {
        this.enableMarkerDrag();
      } else {
        this.disableMarkerDrag();
      }
    },

    enableMarkerDrag() {
      this.map.events.add('mousedown', this.datasource, this.onMarkerMouseDown);
      this.map.events.add('mousemove', this.onMarkerMouseMove);
      this.map.events.add('mouseup', this.onMarkerMouseUp);
      this.map.events.add('touchstart', this.datasource, this.onMarkerTouchStart);
      this.map.events.add('touchmove', this.onMarkerTouchMove);
      this.map.events.add('touchend', this.onMarkerTouchEnd);
      this.map.getCanvasContainer().style.cursor = 'pointer';
    },

    disableMarkerDrag() {
      this.map.events.remove('mousedown', this.datasource, this.onMarkerMouseDown);
      this.map.events.remove('mousemove', this.onMarkerMouseMove);
      this.map.events.remove('mouseup', this.onMarkerMouseUp);
      this.map.events.remove('touchstart', this.datasource, this.onMarkerTouchStart);
      this.map.events.remove('touchmove', this.onMarkerTouchMove);
      this.map.events.remove('touchend', this.onMarkerTouchEnd);
      this.map.getCanvasContainer().style.cursor = 'default';
    },

    onMarkerMouseDown(e) {
      if (e.shapes && e.shapes.length > 0) {
        this.isDragging = true;
        this.map.getCanvasContainer().style.cursor = 'grabbing';
      }
    },

    onMarkerMouseMove(e) {
      if (this.isDragging) {
        this.marker.geometry.coordinates = [e.position[0], e.position[1]];
        this.datasource.setShapes([this.marker]);
        this.$emit('coordinates-changed', {
          latitude: e.position[1],
          longitude: e.position[0]
        });
      }
    },

    onMarkerMouseUp() {
      if (this.isDragging) {
        this.isDragging = false;
        this.map.getCanvasContainer().style.cursor = 'pointer';
      }
    },

    onMarkerTouchStart(e) {
      if (e.shapes && e.shapes.length > 0) {
        this.isDragging = true;
      }
    },

    onMarkerTouchMove(e) {
      if (this.isDragging && e.position) {
        this.marker.geometry.coordinates = [e.position[0], e.position[1]];
        this.datasource.setShapes([this.marker]);
        this.$emit('coordinates-changed', {
          latitude: e.position[1],
          longitude: e.position[0]
        });
      }
    },

    onMarkerTouchEnd() {
      this.isDragging = false;
    },

    // Öffentliche Methoden
    setCenter(coords) {
      if (this.map) {
        this.map.setCamera({
          center: [coords.longitude, coords.latitude]
        });
      }
    },

    setZoom(zoom) {
      if (this.map) {
        this.map.setCamera({ zoom });
      }
    }
  }
};
</script>

<style scoped>
.map-container {
  width: 100%;
  height: 250px;
  min-height: 150px;
}
</style>