<template>
  <k-field v-bind="$props" class="k-map-editor-field">
    <div class="map-editor-container">
      <div class="map-content" :class="{ 'single-mode': mode === 'single' }">
        <!-- Marker list sidebar (only in multi mode) -->
        <MarkerList
          v-if="mode === 'multi'"
          :markers="markers"
          :selected-marker-id="selectedMarkerId"
          :max-markers="maxMarkers"
          @add-marker="handleAddMarker"
          @select-marker="handleSelectMarker"
          @edit-marker="editMarker"
          @delete-marker="deleteMarker"
          @select-location="handleLocationSelect"
        />

        <!-- Map preview -->
        <div class="map-preview-container">
          <MapPreview
            v-if="mapReady"
            ref="mapPreview"
            :center="center"
            :zoom="zoom"
            :markers="markers"
            :selected-marker-id="selectedMarkerId"
            @marker-moved="handleMarkerMoved"
            @map-click="handleMapClick"
            @marker-click="handleSelectMarker"
            @marker-dblclick="editMarker"
          />
        </div>
      </div>
    </div>
  </k-field>
</template>

<script>
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue';
import MapPreview from '../map/MapPreview.vue';
import MarkerList from '../map/MarkerList.vue';
import { useMarkersApi } from '../../composables/useMarkersApi.js';
import { useMapData } from '../../composables/useMapData.js';

export default {
  components: {
    MapPreview,
    MarkerList,
  },

  props: {
    value: String,
    name: String,
    label: String,
    help: String,
    disabled: Boolean,
    defaultCenter: {
      type: Array,
      default: () => [43.836699, 4.360054],
    },
    defaultZoom: {
      type: Number,
      default: 13,
    },
    maxMarkers: {
      type: Number,
      default: 50,
    },
    mode: {
      type: String,
      default: 'multi',
      validator: (value) => ['multi', 'single'].includes(value),
    },
    latitude: {
      type: [Number, String],
      default: null,
    },
    longitude: {
      type: [Number, String],
      default: null,
    },
  },

  setup(props, { emit }) {
    const mapReady = ref(false);
    const mapPreview = ref(null);
    const selectedMarkerId = ref(null);

    // Extract page ID from field name
    // For single mode, we don't need the API
    const pageId = computed(() => {
      if (props.mode === 'single') return null;

      // In Kirby Panel, the field name contains the page context
      // We need to get the current page ID from the Panel context
      // Try to extract from the current URL
      const urlMatch = window.location.pathname.match(/\/panel\/pages\/(.+)/);
      if (urlMatch) {
        // Convert URL format (map+carte) to page ID format (map/carte)
        return urlMatch[1].replace(/\+/g, '/');
      }

      // Fallback: try to extract from props.name if available
      // Format might be "pages/map+carte/fields/mapdata"
      const nameMatch = props.name?.match(/pages\/([^/]+)/);
      if (nameMatch) {
        return nameMatch[1].replace(/\+/g, '/');
      }

      console.warn('Could not extract page ID, using default');
      return 'map/carte';
    });

    // Initialize API composable (only for multi mode)
    const markersApi = props.mode === 'multi'
      ? useMarkersApi(pageId.value)
      : { markers: ref([]), loading: ref(false), error: ref(null) };

    const { center, zoom, loadMapData, debouncedSave } = useMapData({
      defaultCenter: {
        lat: props.defaultCenter[0],
        lon: props.defaultCenter[1],
      },
      defaultZoom: props.defaultZoom,
      onSave: (yamlString) => emit('input', yamlString),
    });

    // Computed: markers based on mode
    const markers = computed(() => {
      if (props.mode === 'single') {
        // Single mode: create one marker from form values
        const lat = singleLat.value;
        const lon = singleLon.value;

        // Only create marker if we have valid coordinates
        if (!isNaN(lat) && !isNaN(lon) && lat !== null && lon !== null && lat !== 0 && lon !== 0) {
          return [{
            id: 'single-marker',
            position: { lat, lon },
            title: 'Current position',
          }];
        }
        return [];
      }
      return markersApi.markers.value;
    });

    const canAddMarker = computed(() => {
      if (props.mode === 'single') return false;
      return markers.value.length < props.maxMarkers;
    });

    // Single mode: reactive references for coordinates from form fields
    const singleLat = ref(null);
    const singleLon = ref(null);

    // Function to get coordinates from Panel form fields (single mode)
    function getCoordinatesFromForm() {
      // Find the latitude and longitude input fields in the same form
      const form = document.querySelector('.k-form');
      if (!form) return { lat: null, lon: null };

      const latInput = form.querySelector('input[name*="latitude"]');
      const lonInput = form.querySelector('input[name*="longitude"]');

      return {
        lat: latInput ? parseFloat(latInput.value) : null,
        lon: lonInput ? parseFloat(lonInput.value) : null
      };
    }

    // Load data on mount
    onMounted(async () => {
      if (props.mode === 'multi') {
        // Multi mode: load from API
        try {
          await markersApi.fetchMarkers();
        } catch (error) {
          console.error('Failed to load markers:', error);
        }
      } else if (props.mode === 'single') {
        // Single mode: get coordinates from form
        const coords = getCoordinatesFromForm();
        singleLat.value = coords.lat;
        singleLon.value = coords.lon;

        if (!isNaN(coords.lat) && !isNaN(coords.lon) && coords.lat !== 0 && coords.lon !== 0) {
          center.value = { lat: coords.lat, lon: coords.lon };
        }

        // Watch for changes in the form fields
        const form = document.querySelector('.k-form');
        if (form) {
          // Listen to input events
          form.addEventListener('input', (e) => {
            if (e.target.name && (e.target.name.includes('latitude') || e.target.name.includes('longitude'))) {
              const newCoords = getCoordinatesFromForm();
              singleLat.value = newCoords.lat;
              singleLon.value = newCoords.lon;
            }
          });

          // Also use MutationObserver to detect value changes (e.g., from "Supprimer" button)
          const latInput = form.querySelector('input[name*="latitude"]');
          const lonInput = form.querySelector('input[name*="longitude"]');

          if (latInput && lonInput) {
            const observer = new MutationObserver(() => {
              const newCoords = getCoordinatesFromForm();
              if (newCoords.lat !== singleLat.value || newCoords.lon !== singleLon.value) {
                singleLat.value = newCoords.lat;
                singleLon.value = newCoords.lon;
              }
            });

            // Observe attribute changes (value attribute)
            observer.observe(latInput, { attributes: true, attributeFilter: ['value'] });
            observer.observe(lonInput, { attributes: true, attributeFilter: ['value'] });

            // Also poll periodically as a fallback
            const pollInterval = setInterval(() => {
              const newCoords = getCoordinatesFromForm();
              if (newCoords.lat !== singleLat.value || newCoords.lon !== singleLon.value) {
                singleLat.value = newCoords.lat;
                singleLon.value = newCoords.lon;
              }
            }, 500);

            // Cleanup on unmount
            onBeforeUnmount(() => {
              observer.disconnect();
              clearInterval(pollInterval);
            });
          }
        }
      }

      // Load map data (center, zoom, background)
      if (props.value && props.mode === 'multi') {
        loadMapData(props.value);
      }

      await nextTick();
      mapReady.value = true;
    });

    // Watch center and zoom for automatic save (multi mode only)
    watch(
      [center, zoom],
      () => {
        if (props.mode === 'multi') {
          debouncedSave();
        }
      },
      { deep: true }
    );

    // Watch form coordinates in single mode
    watch(
      () => [singleLat.value, singleLon.value],
      ([lat, lon]) => {
        if (props.mode === 'single') {
          // Center map on new position if valid
          if (!isNaN(lat) && !isNaN(lon) && lat !== null && lon !== null && lat !== 0 && lon !== 0) {
            // Force immediate reactivity
            nextTick(() => {
              if (mapPreview.value && mapPreview.value.centerOnPosition) {
                mapPreview.value.centerOnPosition(lat, lon);
              }
            });
          } else {
            // Coordinates are invalid/cleared - reset to default center
            center.value = {
              lat: props.defaultCenter[0],
              lon: props.defaultCenter[1]
            };
            nextTick(() => {
              if (mapPreview.value && mapPreview.value.centerOnPosition) {
                mapPreview.value.centerOnPosition(center.value.lat, center.value.lon);
              }
            });
          }
        }
      }
    );

    /**
     * Get current map center or fallback to state center
     */
    function getCurrentCenter() {
      if (mapPreview.value && mapPreview.value.getCurrentCenter) {
        return mapPreview.value.getCurrentCenter();
      }
      return { lat: center.value.lat, lon: center.value.lon };
    }

    /**
     * Handle add marker button click (multi mode only)
     */
    async function handleAddMarker() {
      if (!canAddMarker.value || props.mode === 'single') {
        return;
      }

      const currentCenter = getCurrentCenter();

      // Normalize position format (ensure lon, not lng)
      const position = {
        lat: currentCenter.lat,
        lon: currentCenter.lon || currentCenter.lng
      };

      try {
        await markersApi.createMarker(position);
      } catch (error) {
        console.error('Failed to create marker:', error);
      }
    }

    /**
     * Handle map click to add marker (multi mode only)
     */
    async function handleMapClick(position) {
      if (!canAddMarker.value || props.mode === 'single') {
        return;
      }

      try {
        await markersApi.createMarker({ lat: position.lat, lon: position.lng });
      } catch (error) {
        console.error('Failed to create marker:', error);
      }
    }

    /**
     * Handle marker selection
     */
    function handleSelectMarker(markerId) {
      selectedMarkerId.value = markerId;

      // Center map on marker
      const marker = markers.value.find((m) => m.id === markerId);
      if (marker && mapPreview.value && mapPreview.value.centerOnPosition) {
        mapPreview.value.centerOnPosition(marker.position.lat, marker.position.lon);
      }
    }

    /**
     * Handle marker drag end
     */
    async function handleMarkerMoved({ markerId, position }) {
      if (props.mode === 'single') {
        // Single mode: update form fields directly
        const form = document.querySelector('.k-form');
        if (form) {
          const latInput = form.querySelector('input[name*="latitude"]');
          const lonInput = form.querySelector('input[name*="longitude"]');

          if (latInput && lonInput) {
            latInput.value = position.lat;
            lonInput.value = position.lng;

            // Trigger input event to update Vue/Kirby state
            latInput.dispatchEvent(new Event('input', { bubbles: true }));
            lonInput.dispatchEvent(new Event('input', { bubbles: true }));

            // Update local refs
            singleLat.value = position.lat;
            singleLon.value = position.lng;
          }
        }
      } else {
        // Multi mode: update via API
        try {
          await markersApi.updateMarkerPosition(markerId, {
            lat: position.lat,
            lon: position.lng,
          });
        } catch (error) {
          console.error('Failed to update marker position:', error);
        }
      }
    }

    /**
     * Edit marker - redirect to Panel
     */
    function editMarker(markerId) {
      if (props.mode === 'single') return;

      const marker = markers.value.find(m => m.id === markerId);
      if (marker && marker.panelUrl) {
        window.top.location.href = marker.panelUrl;
      }
    }

    /**
     * Delete marker (multi mode only)
     */
    async function deleteMarker(markerId) {
      if (props.mode === 'single') return;

      if (!confirm('Supprimer ce marqueur ?')) {
        return;
      }

      try {
        await markersApi.deleteMarker(markerId);
        if (selectedMarkerId.value === markerId) {
          selectedMarkerId.value = null;
        }
      } catch (error) {
        console.error('Failed to delete marker:', error);
      }
    }

    /**
     * Handle location selection from geocoding
     */
    function handleLocationSelect(location) {
      if (mapPreview.value && mapPreview.value.centerOnPosition) {
        mapPreview.value.centerOnPosition(location.lat, location.lon);
      }
    }

    return {
      // State
      center,
      zoom,
      markers,
      selectedMarkerId,
      mapReady,
      mapPreview,
      canAddMarker,
      loading: markersApi.loading,
      error: markersApi.error,

      // Methods
      handleAddMarker,
      handleMapClick,
      handleSelectMarker,
      handleMarkerMoved,
      handleLocationSelect,
      deleteMarker,
      editMarker,
    };
  },
};
</script>

<style>
.k-map-editor-field {
  --marker-list-width: 250px;
}

.map-editor-container {
  border: 1px solid var(--color-border);
  border-radius: var(--rounded);
  overflow: hidden;
  background: var(--color-white);
}

.map-content {
  display: flex;
  height: 600px;
  background: var(--color-white);
}

.map-content.single-mode {
  height: 400px;
}

.map-preview-container {
  flex: 1;
  position: relative;
  background: #f0f0f0;
  min-width: 0;
}
</style>
