<script setup>
import { ref, reactive, onMounted, 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);

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

// Configuración de colores por estado
const markerColors = {
  sin_avances: "#EF4444", // Rojo
  abiertas: "#F59E0B", // Amarillo
  finalizadas: "#10B981", // Verde
};

// Estadísticas de procesamiento
const processingStats = ref({
  total: 0,
  successful: 0,
  failed: 0,
  outOfBounds: 0,
});

// Contador de marcadores visibles
const visibleMarkersCount = computed(() => {
  return markers.value.filter((marker) => marker.visible).length;
});

// Coordenadas del centro de Comalcalco, Tabasco
const COMALCALCO_CENTER = {
  lat: 18.2669,
  lng: -93.2072,
};

// Límites expandidos de Tabasco (más amplios para capturar todas las obras)
const TABASCO_BOUNDS = {
  north: 18.7, // Expandido hacia el norte
  south: 17.3, // Expandido hacia el sur
  east: -92.0, // Expandido hacia el este
  west: -94.7, // Expandido hacia el oeste
};

// Cache para geocodificación (evitar llamadas duplicadas)
const geocodingCache = new Map();

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",
      libraries: ["places"],
    });

    const google = await loader.load();

    if (!google.maps) {
      throw new Error("Google Maps no se cargó correctamente");
    }

    // Inicializar el mapa con zoom más amplio
    map.value = new google.maps.Map(mapContainer.value, {
      center: COMALCALCO_CENTER,
      zoom: 11, // Zoom más amplio para ver toda la región
      restriction: {
        latLngBounds: TABASCO_BOUNDS,
        strictBounds: false,
      },
      mapTypeControl: true,
      streetViewControl: true,
      fullscreenControl: true,
      zoomControl: true,
    });

    geocoder.value = new google.maps.Geocoder();

    await loadMarkers();
  } catch (err) {
    console.error("Error loading Google Maps:", err);
    error.value = err.message || "Error al cargar Google Maps";
  } finally {
    loading.value = false;
  }
};

const loadMarkers = async () => {
  if (!map.value || !geocoder.value) return;

  // Limpiar marcadores existentes
  clearMarkers();

  // Resetear estadísticas
  processingStats.value = {
    total: 0,
    successful: 0,
    failed: 0,
    outOfBounds: 0,
    duplicates: 0,
  };

  const allObras = [
    ...props.counters.sin_avances.detalles.map((obra) => ({
      ...obra,
      estado: "sin_avances",
    })),
    ...props.counters.abiertas.detalles.map((obra) => ({
      ...obra,
      estado: "abiertas",
    })),
    ...props.counters.finalizadas.detalles.map((obra) => ({
      ...obra,
      estado: "finalizadas",
    })),
  ];

  processingStats.value.total = allObras.length;

  console.table(
    allObras.map((obra) => ({
      proyecto: obra.num_proyecto,
      direccion: obra.direccion_obra,
      estado: obra.estado,
    }))
  );

  // Agrupar obras por dirección
  const obrasPorDireccion = new Map();
  allObras.forEach(obra => {
    const direccion = obra.direccion_obra;
    if (!obrasPorDireccion.has(direccion)) {
      obrasPorDireccion.set(direccion, []);
    }
    obrasPorDireccion.get(direccion).push(obra);
  });

  processingStats.value.total = allObras.length;

  // Procesar grupos de obras por dirección en lotes
  const direcciones = Array.from(obrasPorDireccion.keys());
  const batchSize = 5;

  for (let i = 0; i < direcciones.length; i += batchSize) {
    const batch = direcciones.slice(i, i + batchSize);
    const batchPromises = batch.map(direccion =>
      createMarkerForDireccion(direccion, obrasPorDireccion.get(direccion))
    );

    await Promise.allSettled(batchPromises);

    if (i + batchSize < direcciones.length) {
      await new Promise((resolve) => setTimeout(resolve, 100));
    }
  }
  updateMarkers();
};

const createMarkerForDireccion = async (direccion, obrasEnDireccion) => {
  if (!direccion || !geocoder.value) {
    obrasEnDireccion.forEach(() => processingStats.value.failed++);
    return;
  }

  // Construir direcciones alternativas para geocodificación
  const addresses = [
    `${direccion}, Comalcalco, Tabasco, México`,
    `${direccion}, Tabasco, México`,
    `${direccion}, México`,
  ];

  // Verificar cache primero
  const cacheKey = direccion;
  if (geocodingCache.has(cacheKey)) {
    const cachedData = geocodingCache.get(cacheKey);
    processingStats.value.duplicates += obrasEnDireccion.length - 1;
    return createMarkerFromPosition(obrasEnDireccion, cachedData.position, cachedData.formatted_address);
  }

  // Intentar geocodificación con direcciones alternativas
  for (const address of addresses) {
    try {
      const result = await geocodeAddress(address);
      if (result.success) {
        // Guardar en cache
        geocodingCache.set(cacheKey, {
          position: result.position,
          formatted_address: result.formatted_address,
        });

        return createMarkerFromPosition(obrasEnDireccion, result.position, result.formatted_address);
      }
    } catch (err) {
      console.warn(`Error geocodificando ${address}:`, err);
    }
  }

  // Si todas las direcciones fallan, crear marcador fallback
  processingStats.value.failed += obrasEnDireccion.length;

  const randomOffset = {
    lat: (Math.random() - 0.5) * 0.02,
    lng: (Math.random() - 0.5) * 0.02,
  };

  const fallbackPosition = {
    lat: COMALCALCO_CENTER.lat + randomOffset.lat,
    lng: COMALCALCO_CENTER.lng + randomOffset.lng,
  };

  return createMarkerFromPosition(obrasEnDireccion, fallbackPosition, "Ubicación aproximada - Comalcalco, Tabasco");
};

const geocodeAddress = (address) => {
  return new Promise((resolve, reject) => {
    geocoder.value.geocode({ address }, (results, status) => {
      if (status === "OK" && results[0]) {
        const position = results[0].geometry.location;
        const lat = position.lat();
        const lng = position.lng();

        resolve({
          success: true,
          position: { lat, lng },
          formatted_address: results[0].formatted_address,
        });
      } else {
        resolve({
          success: false,
          status,
          address,
        });
      }
    });
  });
};

const createMarkerFromPosition = (obrasEnPosicion, position, formatted_address) => {
  const lat = position.lat;
  const lng = position.lng;

  // Verificar límites expandidos
  if (
    lat < TABASCO_BOUNDS.south ||
    lat > TABASCO_BOUNDS.north ||
    lng < TABASCO_BOUNDS.west ||
    lng > TABASCO_BOUNDS.east
  ) {
    processingStats.value.outOfBounds += obrasEnPosicion.length;
  }

  // Usar la primera obra para definir el marcador principal
  const obraPrincipal = obrasEnPosicion[0];

  const marker = new google.maps.Marker({
    position: new google.maps.LatLng(lat, lng),
    map: map.value,
    title: obrasEnPosicion.length === 1
      ? `${obraPrincipal.num_proyecto} - ${obraPrincipal.direccion_obra}`
      : `${obrasEnPosicion.length} obras en ${obraPrincipal.direccion_obra}`,
    icon: createCustomMarker(obraPrincipal.estado),
    visible: filters[obraPrincipal.estado],
    animation: google.maps.Animation.DROP,
  });

  // Info window con todas las obras en esa posición
  const infoWindow = new google.maps.InfoWindow({
    content: createMultipleInfoWindowContent(obrasEnPosicion, formatted_address),
  });

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

  markers.value.push({
    marker,
    infoWindow,
    estado: obraPrincipal.estado,
    obras: obrasEnPosicion,
    visible: filters[obraPrincipal.estado],
    position: { lat, lng },
  });

  processingStats.value.successful += obrasEnPosicion.length;
};

const createCustomMarker = (estado) => {
  const color = markerColors[estado];
  const width = 32;
  const height = 48;

  return {
    url: `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(`
      <svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg">
        <defs>
          <!-- Sombra para el marcador -->
          <filter id="dropshadow-${estado}" x="-50%" y="-50%" width="200%" height="200%">
            <feDropShadow dx="0" dy="2" stdDeviation="3" flood-color="rgba(0,0,0,0.3)" flood-opacity="0.5"/>
          </filter>

          <!-- Gradiente para dar volumen -->
          <radialGradient id="gradient-${estado}" cx="30%" cy="20%" r="70%">
            <stop offset="0%" style="stop-color:white;stop-opacity:0.3" />
            <stop offset="100%" style="stop-color:${color};stop-opacity:1" />
          </radialGradient>
        </defs>

        <!-- Forma principal del marcador (gota/pin) -->
        <path d="M ${width / 2} ${height - 4}
                 C ${width / 2} ${height - 4},
                   ${width * 0.125} ${height * 0.58},
                   ${width * 0.125} ${height * 0.375}
                 C ${width * 0.125} ${height * 0.167},
                   ${width * 0.292} 2,
                   ${width / 2} 2
                 C ${width * 0.708} 2,
                   ${width * 0.875} ${height * 0.167},
                   ${width * 0.875} ${height * 0.375}
                 C ${width * 0.875} ${height * 0.58},
                   ${width / 2} ${height - 4},
                   ${width / 2} ${height - 4} Z"
              fill="url(#gradient-${estado})"
              stroke="white"
              stroke-width="1.5"
              filter="url(#dropshadow-${estado})"/>

        <!-- Borde interior más oscuro -->
        <path d="M ${width / 2} ${height - 4}
                 C ${width / 2} ${height - 4},
                   ${width * 0.125} ${height * 0.58},
                   ${width * 0.125} ${height * 0.375}
                 C ${width * 0.125} ${height * 0.167},
                   ${width * 0.292} 2,
                   ${width / 2} 2
                 C ${width * 0.708} 2,
                   ${width * 0.875} ${height * 0.167},
                   ${width * 0.875} ${height * 0.375}
                 C ${width * 0.875} ${height * 0.58},
                   ${width / 2} ${height - 4},
                   ${width / 2} ${height - 4} Z"
              fill="none"
              stroke="${color}"
              stroke-width="1"
              opacity="0.8"/>

        <!-- Círculo interior blanco -->
        <circle cx="${width / 2}"
                cy="${height * 0.375}"
                r="${width * 0.25}"
                fill="white"
                stroke="${color}"
                stroke-width="1"/>
      </svg>
    `)}`,
    scaledSize: new google.maps.Size(width, height),
    anchor: new google.maps.Point(width / 2, height - 4),
    origin: new google.maps.Point(0, 0),
  };
};

const createMultipleInfoWindowContent = (obras, formatted_address = null) => {
  if (obras.length === 1) {
    return createInfoWindowContent(obras[0], formatted_address);
  }

  const direccion = obras[0].direccion_obra;

  let obrasHtml = '';
  obras.forEach(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";

    obrasHtml += `
      <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 transition-all duration-300 ${
              obra.estado === "finalizadas" ? "bg-green-500" : obra.estado === "abiertas" ? "bg-yellow-500" : "bg-red-500"
            }" style="width: ${Number(obra.cumplimiento_total) || 0}%"></div>
          </div>
          <span class="text-xs font-medium text-gray-700 min-w-[35px]">${cumplimiento}</span>
        </div>
      </div>
    `;
  });

  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} Obras 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>
  `;
};

const createInfoWindowContent = (obra, formatted_address = null) => {
  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="p-4 max-w-sm">
      <div class="flex items-center justify-between mb-3">
        <h3 class="font-bold text-gray-900 text-lg">${
          obra.num_proyecto || "N/A"
        }</h3>
        <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
          config.color
        }">
          ${config.label}
        </span>
      </div>

      <div class="space-y-3 text-sm">
        <div>
          <p class="font-medium text-gray-700 mb-1">Dirección Original:</p>
          <p class="text-gray-600 text-xs">${obra.direccion_obra || "N/A"}</p>
        </div>

        ${
          formatted_address
            ? `
        <div>
          <p class="font-medium text-gray-700 mb-1">Ubicación Encontrada:</p>
          <p class="text-gray-500 text-xs">${formatted_address}</p>
        </div>
        `
            : ""
        }

        <div>
          <p class="font-medium text-gray-700 mb-1">Cumplimiento:</p>
          <div class="flex items-center space-x-2">
            <div class="flex-1 bg-gray-200 rounded-full h-2">
              <div class="h-2 rounded-full transition-all duration-300 ${
                obra.estado === "finalizadas"
                  ? "bg-green-500"
                  : obra.estado === "abiertas"
                  ? "bg-yellow-500"
                  : "bg-red-500"
              }"
                   style="width: ${
                     Number(obra.cumplimiento_total) || 0
                   }%"></div>
            </div>
            <span class="text-xs font-medium text-gray-700 min-w-[40px]">${cumplimiento}</span>
          </div>
        </div>
      </div>
    </div>
  `;
};

const updateMarkers = () => {
  let visibleCount = 0;
  markers.value.forEach(({ marker, estado }) => {
    const shouldShow = filters[estado];
    marker.setVisible(shouldShow);

    if (shouldShow) visibleCount++;

    // Actualizar el estado visible del marcador
    const markerIndex = markers.value.findIndex((m) => m.marker === marker);
    if (markerIndex !== -1) {
      markers.value[markerIndex].visible = shouldShow;
    }
  });
};

const clearMarkers = () => {
  markers.value.forEach(({ marker, infoWindow }) => {
    infoWindow?.close();
    marker.setMap(null);
  });
  markers.value = [];
  geocodingCache.clear(); // Limpiar cache al recargar
};

// Función para ajustar el viewport del mapa a todos los marcadores visibles
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);

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

// Recargar marcadores cuando cambien los contadores
watch(
  () => props.counters,
  () => {
    if (map.value) {
      loadMarkers();
    }
  },
  { deep: true }
);

onMounted(() => {
  initMap();
});
</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>

        <!-- Filtros por estado -->
        <div class="flex items-center space-x-4">
          <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>

      <!-- Controles adicionales -->
      <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>

    <!-- Mapa -->
    <div ref="mapContainer" class="w-full h-96 relative">
      <div
        v-if="loading"
        class="absolute inset-0 bg-gray-100 flex items-center justify-center z-10"
      >
        <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>
          <p class="mt-1 text-xs text-gray-500">
            Esto puede tomar unos segundos
          </p>
        </div>
      </div>

      <div
        v-if="error"
        class="absolute inset-0 bg-gray-100 flex items-center justify-center z-10"
      >
        <div class="text-center">
          <svg
            class="mx-auto h-12 w-12 text-red-400"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              stroke-linecap="round"
              stroke-linejoin="round"
              stroke-width="2"
              d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
            />
          </svg>
          <h3 class="mt-2 text-sm font-medium text-gray-900">
            Error al cargar el mapa
          </h3>
          <p class="mt-1 text-sm text-gray-500">{{ error }}</p>
          <button
            @click="initMap"
            class="mt-4 bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition-colors"
          >
            Reintentar
          </button>
        </div>
      </div>
    </div>

    <!-- Leyenda mejorada -->
    <div class="px-6 py-4 bg-gray-50 border-t border-gray-200">
      <div class="flex items-center justify-between text-xs text-gray-600">
        <div class="flex items-center space-x-4">
          <span class="flex items-center">
            <div class="w-2 h-2 bg-red-500 rounded-full mr-1"></div>
            Sin avances
          </span>
          <span class="flex items-center">
            <div class="w-2 h-2 bg-yellow-500 rounded-full mr-1"></div>
            En proceso
          </span>
          <span class="flex items-center">
            <div class="w-2 h-2 bg-green-500 rounded-full mr-1"></div>
            Finalizadas
          </span>
        </div>
      </div>
    </div>
  </div>
</template>
