<script setup>
import { ref, reactive, onMounted, onUnmounted, computed, watch } from "vue";
import { Loader } from "@googlemaps/js-api-loader";

const props = defineProps({
  counters: { type: Object, required: true },
});

const mapContainer = ref(null);
const loading = ref(true);
const error = ref(null);
const map = ref(null);
const markers = ref([]);
const geocoder = ref(null);
const isMounted = ref(false);

const filters = reactive({
  sin_avances: true,
  abiertas: true,
  finalizadas: true,
});

const searchQuery = ref("");
const searchResults = ref([]);
const showSearchResults = ref(false);
const searchLoading = ref(false);

const geocodingCache = new Map();
const failedGeocodings = ref([]);

const markerColors = {
  sin_avances: "#EF4444",
  abiertas: "#F59E0B",
  finalizadas: "#10B981",
};
const COMALCALCO_CENTER = { lat: 18.26, lng: -93.25 };

const COMALCALCO_BOUNDS = {
  south: 18.1,
  west: -93.4,
  north: 18.4,
  east: -93.0,
};

const visibleMarkersCount = computed(
  () => markers.value.filter((m) => m.visible).length
);

onMounted(() => {
  isMounted.value = true;
  initMap();
});

onUnmounted(() => {
  isMounted.value = false;
});

watch(
  () => props.counters,
  () => {
    if (map.value && geocoder.value) {
      loadMarkers();
    }
  },
  { deep: true }
);

const initMap = async () => {
  loading.value = true;
  error.value = null;
  try {
    const loader = new Loader({
      apiKey: import.meta.env.VITE_GOOGLE_MAPS_API_KEY,
      version: "weekly",
      // Usar solo librerías básicas por compatibilidad
      libraries: ["places", "geometry"],
    });
    window.google = await loader.load();

    if (!isMounted.value) return;

    map.value = new google.maps.Map(mapContainer.value, {
      center: COMALCALCO_CENTER,
      zoom: 11,
      // Mantener mapId pero para funcionalidad futura
      mapId: "OBRAS_MAP_COMALCALCO",
      mapTypeControl: true,
      streetViewControl: true,
      fullscreenControl: true,
      zoomControl: true,
      // Estilos mejorados
      styles: [
        {
          featureType: "poi",
          elementType: "labels.icon",
          stylers: [{ visibility: "off" }],
        },
        {
          featureType: "transit",
          elementType: "labels.icon",
          stylers: [{ visibility: "off" }],
        },
      ],
    });
    geocoder.value = new google.maps.Geocoder();
    await loadMarkers();
  } catch (err) {
    if (!isMounted.value) return;
    console.error("Error loading map:", err);
    error.value = err.message || "Error al cargar Google Maps";
  } finally {
    if (isMounted.value) loading.value = false;
  }
};

const loadMarkers = async () => {
  if (!map.value || !geocoder.value || !isMounted.value) return;
  loading.value = true;
  clearMarkers();
  failedGeocodings.value = [];

  const allObras = getAllObras();
  console.log("Total obras a procesar:", allObras.length);

  if (allObras.length === 0) {
    if (isMounted.value) loading.value = false;
    return;
  }

  const obrasPorGrupo = groupObrasByAddressAndStatus(allObras);
  const uniqueAddresses = [
    ...new Set(Array.from(obrasPorGrupo.values()).map((g) => g.direccion)),
  ].filter(Boolean);

  console.log("Direcciones únicas a geocodificar:", uniqueAddresses.length);

  await geocodeUniqueAddresses(uniqueAddresses);

  if (!isMounted.value) return;

  createMarkersFromGroups(obrasPorGrupo);
  loading.value = false;
  updateMarkers();

  console.log("Marcadores creados exitosamente:", markers.value.length);
};

const normalizeAddressForGeocoding = (address) => {
  if (!address) return "";
  return address
    .replace(/^RA\.\s*/, "RANCHERÍA ")
    .replace(/(\d+)\s*DA\s*SECCION/i, "$1 SECCION")
    .replace(/\s+/g, " ")
    .trim();
};

const geocodeAndCacheAddress = (address) => {
  if (!address || geocodingCache.has(address)) {
    return Promise.resolve();
  }

  return new Promise((resolve) => {
    const normalizedAddress = normalizeAddressForGeocoding(address);

    const request = {
      address: normalizedAddress,
      componentRestrictions: {
        country: "MX",
        administrativeArea: "Tabasco",
      },
      bounds: new google.maps.LatLngBounds(
        { lat: COMALCALCO_BOUNDS.south, lng: COMALCALCO_BOUNDS.west },
        { lat: COMALCALCO_BOUNDS.north, lng: COMALCALCO_BOUNDS.east }
      ),
    };

    geocoder.value.geocode(request, (results, status) => {
      if (status === "OK" && results?.length) {
        // Con la búsqueda sesgada, el primer resultado es ahora mucho más confiable
        const bestResult = results[0];
        geocodingCache.set(address, {
          success: true,
          position: {
            lat: bestResult.geometry.location.lat(),
            lng: bestResult.geometry.location.lng(),
          },
          formatted_address: bestResult.formatted_address,
        });
      } else {
        geocodingCache.set(address, { success: false, status });
      }
      resolve();
    });
  });
};

const groupObrasByAddressAndStatus = (obras) => {
  const grouped = new Map();
  obras.forEach((obra) => {
    const key = `${obra.direccion_obra}|${obra.estado}`;
    if (!grouped.has(key)) {
      grouped.set(key, {
        direccion: obra.direccion_obra,
        estado: obra.estado,
        obras: [],
      });
    }
    grouped.get(key).obras.push(obra);
  });
  return grouped;
};

const geocodeUniqueAddresses = async (addresses) => {
  const geocodingPromises = addresses.map((addr) =>
    geocodeAndCacheAddress(addr)
  );
  await Promise.all(geocodingPromises);
};

const createMarkersFromGroups = (obrasPorGrupo) => {
  const statusOffsets = {
    sin_avances: { lat: 0.00008, lng: -0.00005 },
    abiertas: { lat: 0, lng: 0.0001 },
    finalizadas: { lat: -0.00004, lng: -0.00005 },
  };

  for (const grupo of obrasPorGrupo.values()) {
    const geocodedResult = geocodingCache.get(grupo.direccion);
    if (geocodedResult?.success) {
      const offset = statusOffsets[grupo.estado] || { lat: 0, lng: 0 };
      const position = {
        lat: geocodedResult.position.lat + offset.lat,
        lng: geocodedResult.position.lng + offset.lng,
      };
      createMarker(
        position,
        grupo.estado,
        grupo.obras,
        geocodedResult.formatted_address
      );
    } else {
      failedGeocodings.value.push({
        direccion: grupo.direccion,
        motivo: geocodedResult?.status || "NOT_FOUND",
        obras: grupo.obras,
      });
    }
  }
};

const createMarker = (position, estado, obras, formatted_address) => {
  try {
    const svgIcon = createSVGIcon(estado, obras.length);

    const marker = new google.maps.Marker({
      position: new google.maps.LatLng(position.lat, position.lng),
      map: map.value,
      title: `${obras.length} obra(s) en ${obras[0].direccion_obra}`,
      icon: {
        url: svgIcon,
        scaledSize: new google.maps.Size(32, 40),
        anchor: new google.maps.Point(16, 40),
      },
      animation: google.maps.Animation.DROP,
      optimized: false,
    });

    const infoWindow = new google.maps.InfoWindow({
      content: createMultipleInfoWindowContent(obras, formatted_address),
      maxWidth: 400,
    });

    marker.addListener("click", () => {
      markers.value.forEach((m) => m.infoWindow?.close());
      infoWindow.open(map.value, marker);
    });

    markers.value.push({
      marker,
      infoWindow,
      estado,
      obras,
      visible: filters[estado],
      position,
    });
  } catch (error) {
    console.error("Error creando marcador:", error);
  }
};

// Crear icono SVG
const createSVGIcon = (estado, count) => {
  const color = markerColors[estado];
  const svg = `
    <svg width="32" height="40" viewBox="0 0 32 40" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <filter id="shadow" x="-50%" y="-50%" width="200%" height="200%">
          <feDropShadow dx="0" dy="2" stdDeviation="2" flood-opacity="0.3"/>
        </filter>
      </defs>
      <path d="M16 0C7.163 0 0 7.163 0 16c0 12 16 24 16 24s16-12 16-24c0-8.837-7.163-16-16-16z"
            fill="${color}"
            stroke="white"
            stroke-width="2"
            filter="url(#shadow)"/>
      <circle cx="16" cy="16" r="10" fill="white"/>
      <circle cx="16" cy="16" r="7" fill="${color}"/>
      <text x="16" y="21" text-anchor="middle" fill="white" font-size="10" font-weight="bold" font-family="Arial">${count}</text>
    </svg>
  `;
  return `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(svg)}`;
};

const updateMarkers = () => {
  markers.value.forEach((m) => {
    const shouldShow = filters[m.estado];
    m.marker.setVisible(shouldShow);
    m.visible = shouldShow;
  });
  console.log("Marcadores actualizados. Visibles:", visibleMarkersCount.value);
};

const clearMarkers = () => {
  markers.value.forEach(({ marker, infoWindow }) => {
    try {
      infoWindow?.close();
      marker.setMap(null);
    } catch (error) {
      console.error("Error limpiando marcador:", error);
    }
  });
  markers.value = [];
  // No limpiar cache para mejorar rendimiento
};

const fitMapToMarkers = () => {
  if (!map.value || markers.value.length === 0) return;

  const bounds = new google.maps.LatLngBounds();
  const visibleMarkers = markers.value.filter((m) => m.visible);

  if (visibleMarkers.length === 0) return;

  visibleMarkers.forEach(({ position }) => {
    bounds.extend(new google.maps.LatLng(position.lat, position.lng));
  });

  map.value.fitBounds(bounds);

  const listener = google.maps.event.addListener(map.value, "idle", () => {
    if (map.value.getZoom() > 15) map.value.setZoom(15);
    google.maps.event.removeListener(listener);
  });
};

const getAllObras = () => {
  try {
    return [
      ...props.counters.sin_avances.detalles.map((o) => ({
        ...o,
        estado: "sin_avances",
      })),
      ...props.counters.abiertas.detalles.map((o) => ({
        ...o,
        estado: "abiertas",
      })),
      ...props.counters.finalizadas.detalles.map((o) => ({
        ...o,
        estado: "finalizadas",
      })),
    ];
  } catch (error) {
    console.error("Error obteniendo obras:", error);
    return [];
  }
};

const searchAddresses = () => {
  if (!searchQuery.value.trim()) {
    searchResults.value = [];
    showSearchResults.value = false;
    return;
  }
  const query = searchQuery.value.toLowerCase();
  const allObras = getAllObras();
  searchResults.value = allObras
    .filter(
      (obra) =>
        obra.direccion_obra?.toLowerCase().includes(query) ||
        obra.num_proyecto?.toLowerCase().includes(query)
    )
    .slice(0, 10);
  showSearchResults.value = true;
};

const goToObra = (obra) => {
  searchQuery.value = "";
  searchResults.value = [];
  showSearchResults.value = false;

  const markerData = markers.value.find((m) =>
    m.obras.some((o) => o.num_proyecto === obra.num_proyecto)
  );

  if (markerData) {
    map.value.setCenter(markerData.position);
    map.value.setZoom(16);
    markers.value.forEach((m) => m.infoWindow?.close());
    markerData.infoWindow.open(map.value, markerData.marker);
  }
};

const clearSearch = () => {
  searchQuery.value = "";
  searchResults.value = [];
  showSearchResults.value = false;
};

const createMultipleInfoWindowContent = (obras, formatted_address) => {
  const direccion = obras[0].direccion_obra;
  let obrasHtml = obras
    .map((obra) => {
      const estadoConfig = {
        sin_avances: { color: "bg-red-100 text-red-800", label: "Sin avances" },
        abiertas: {
          color: "bg-yellow-100 text-yellow-800",
          label: "En proceso",
        },
        finalizadas: {
          color: "bg-green-100 text-green-800",
          label: "Finalizada",
        },
      };
      const config = estadoConfig[obra.estado];
      const cumplimiento = obra.cumplimiento_total
        ? `${Number(obra.cumplimiento_total).toFixed(1)}%`
        : "N/A";
      return `<div class="border-b border-gray-200 pb-3 mb-3 last:border-b-0 last:pb-0 last:mb-0"><div class="flex items-center justify-between mb-2"><h4 class="font-semibold text-gray-900">${
        obra.num_proyecto || "N/A"
      }</h4><span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${
        config.color
      }">${
        config.label
      }</span></div><div class="flex items-center space-x-2"><div class="flex-1 bg-gray-200 rounded-full h-1.5"><div class="h-1.5 rounded-full" style="width: ${
        Number(obra.cumplimiento_total) || 0
      }%; background-color: ${
        markerColors[obra.estado]
      };"></div></div><span class="text-xs font-medium text-gray-700 min-w-[35px]">${cumplimiento}</span></div></div>`;
    })
    .join("");
  return `<div class="p-4 max-w-sm"><div class="mb-3"><h3 class="font-bold text-gray-900 text-lg mb-1">${
    obras.length
  } Obra(s) en esta ubicación</h3><p class="text-xs text-gray-600">${direccion}</p>${
    formatted_address
      ? `<p class="text-xs text-gray-500 mt-1">${formatted_address}</p>`
      : ""
  }</div><div class="space-y-3 text-sm max-h-60 overflow-y-auto">${obrasHtml}</div></div>`;
};
</script>
<template>
  <div class="bg-white rounded-lg shadow-lg overflow-hidden">
    <div
      class="px-6 py-4 bg-gradient-to-r from-gray-50 to-gray-100 border-b border-gray-200"
    >
      <div class="flex items-center justify-between">
        <div>
          <h3 class="text-lg font-medium text-gray-900">Mapa de Obras</h3>
          <p class="text-sm text-gray-600 mt-1">
            Ubicación geográfica de proyectos en Comalcalco, Tabasco
          </p>
        </div>

        <div class="flex items-center space-x-4">
          <div class="relative">
            <div class="relative">
              <input
                v-model="searchQuery"
                @input="searchAddresses"
                @focus="showSearchResults = true"
                type="text"
                placeholder="Buscar obra o dirección..."
                class="w-64 px-3 py-1 text-sm border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500"
              />
              <div
                class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none"
              >
                <svg
                  v-if="searchLoading"
                  class="animate-spin h-4 w-4 text-gray-400"
                  fill="none"
                  viewBox="0 0 24 24"
                >
                  <circle
                    class="opacity-25"
                    cx="12"
                    cy="12"
                    r="10"
                    stroke="currentColor"
                    stroke-width="4"
                  ></circle>
                  <path
                    class="opacity-75"
                    fill="currentColor"
                    d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
                  ></path>
                </svg>
                <svg
                  v-else-if="searchQuery"
                  @click="clearSearch"
                  class="h-4 w-4 text-gray-400 cursor-pointer hover:text-gray-600 pointer-events-auto"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                >
                  <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="2"
                    d="M6 18L18 6M6 6l12 12"
                  />
                </svg>
                <svg
                  v-else
                  class="h-4 w-4 text-gray-400"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                >
                  <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    stroke-width="2"
                    d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
                  />
                </svg>
              </div>
            </div>
            <div
              v-if="showSearchResults && searchResults.length > 0"
              class="absolute z-50 w-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg max-h-60 overflow-y-auto"
            >
              <div
                v-for="obra in searchResults"
                :key="obra.num_proyecto"
                @click="goToObra(obra)"
                class="px-3 py-2 hover:bg-gray-50 cursor-pointer"
              >
                <p class="text-sm font-medium text-gray-900 truncate">
                  {{ obra.num_proyecto || "N/A" }}
                </p>
                <p class="text-xs text-gray-500 truncate">
                  {{ obra.direccion_obra }}
                </p>
              </div>
            </div>
            <div
              v-else-if="
                showSearchResults &&
                searchResults.length === 0 &&
                searchQuery.trim()
              "
              class="absolute z-50 w-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg"
            >
              <div class="px-3 py-2 text-sm text-gray-500 text-center">
                No se encontraron resultados
              </div>
            </div>
          </div>
          <div class="flex items-center space-x-2">
            <input
              id="sin-avances"
              v-model="filters.sin_avances"
              @change="updateMarkers"
              type="checkbox"
              class="rounded border-gray-300 text-red-600 focus:ring-red-500"
            />
            <label
              for="sin-avances"
              class="flex items-center text-sm text-gray-700"
            >
              <div class="w-3 h-3 bg-red-500 rounded-full mr-2"></div>
              Sin avances ({{ counters.sin_avances.count }})
            </label>
          </div>
          <div class="flex items-center space-x-2">
            <input
              id="abiertas"
              v-model="filters.abiertas"
              @change="updateMarkers"
              type="checkbox"
              class="rounded border-gray-300 text-yellow-600 focus:ring-yellow-500"
            />
            <label
              for="abiertas"
              class="flex items-center text-sm text-gray-700"
            >
              <div class="w-3 h-3 bg-yellow-500 rounded-full mr-2"></div>
              Abiertas ({{ counters.abiertas.count }})
            </label>
          </div>
          <div class="flex items-center space-x-2">
            <input
              id="finalizadas"
              v-model="filters.finalizadas"
              @change="updateMarkers"
              type="checkbox"
              class="rounded border-gray-300 text-green-600 focus:ring-green-500"
            />
            <label
              for="finalizadas"
              class="flex items-center text-sm text-gray-700"
            >
              <div class="w-3 h-3 bg-green-500 rounded-full mr-2"></div>
              Finalizadas ({{ counters.finalizadas.count }})
            </label>
          </div>
        </div>
      </div>
      <div class="flex items-center justify-between mt-3">
        <div class="text-sm text-gray-600">
          Marcadores visibles: {{ visibleMarkersCount }} de {{ markers.length }}
        </div>
        <div class="flex items-center space-x-2">
          <button
            @click="fitMapToMarkers"
            class="px-3 py-1 text-xs bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors"
          >
            Ajustar Vista
          </button>
          <button
            @click="loadMarkers"
            class="px-3 py-1 text-xs bg-gray-600 text-white rounded hover:bg-gray-700 transition-colors"
          >
            Recargar
          </button>
        </div>
      </div>
    </div>

    <div ref="mapContainer" class="w-full h-[600px] relative">
      <div
        v-if="loading"
        class="absolute inset-0 bg-gray-100/80 flex items-center justify-center z-10 backdrop-blur-sm"
      >
        <div class="text-center">
          <div
            class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto"
          ></div>
          <p class="mt-2 text-sm text-gray-600">
            Cargando mapa y geocodificando direcciones...
          </p>
        </div>
      </div>
      <div
        v-if="error"
        class="absolute inset-0 bg-red-50 flex items-center justify-center z-10"
      >
        <div class="text-center">
          <h3 class="text-sm font-medium text-red-800">
            Error al cargar el mapa
          </h3>
          <p class="mt-1 text-sm text-red-600">{{ error }}</p>
          <button
            @click="initMap"
            class="mt-4 bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700"
          >
            Reintentar
          </button>
        </div>
      </div>
    </div>

    <div
      v-if="!loading && failedGeocodings.length > 0"
      class="px-6 py-4 bg-yellow-50 border-t border-yellow-200"
    >
      <h4 class="text-sm font-semibold text-yellow-800">
        {{ failedGeocodings.flatMap((f) => f.obras).length }} obra(s) no
        pudieron ser ubicadas
      </h4>
      <p class="text-xs text-yellow-700 mb-2">
        Las siguientes direcciones no fueron encontradas o la coincidencia era
        de baja calidad. Considera revisarlas en la base de datos.
      </p>
      <ul class="text-xs text-gray-700 list-disc pl-5 max-h-32 overflow-y-auto">
        <li v-for="item in failedGeocodings" :key="item.direccion">
          <strong>{{ item.direccion }}</strong> ({{ item.obras.length }} obra/s)
          - Motivo:
          <span class="font-mono text-red-600">{{ item.motivo }}</span>
        </li>
      </ul>
    </div>
  </div>
</template>
