/**
 * Utility functions to parse map URLs from various sources
 * Supports: mapy.cz, Google Maps
 */

export interface MapCoordinates {
  latitude: number;
  longitude: number;
  zoom?: number;
  address?: string;
  source: 'mapy.cz' | 'google-maps' | 'unknown';
  // Detailed address components from reverse geocoding
  street?: string;
  city?: string;
  zip?: string;
  country?: string;
}

/**
 * Parse mapy.cz URL
 * Example: mapy.cz/en/letecka?q=krnov%20stadion&source=firm&id=12954454&ds=2&x=17.6996859&y=50.0947150&z=19
 */
export function parseMapyCzUrl(url: string): MapCoordinates | null {
  try {
    const urlObj = new URL(url);
    
    // Check if it's a mapy.cz domain
    if (!urlObj.hostname.includes('mapy.cz') && !urlObj.hostname.includes('mapy.com')) {
      return null;
    }

    const params = urlObj.searchParams;
    const xParam = params.get('x');
    const yParam = params.get('y');
    const zParam = params.get('z');
    const qParam = params.get('q');

    if (xParam && yParam) {
      const longitude = parseFloat(xParam);
      const latitude = parseFloat(yParam);
      const zoom = zParam ? parseInt(zParam) : undefined;

      if (isNaN(latitude) || isNaN(longitude)) {
        return null;
      }

      return {
        latitude,
        longitude,
        zoom,
        address: qParam ? decodeURIComponent(qParam) : undefined,
        source: 'mapy.cz',
      };
    }

    return null;
  } catch (error) {
    console.error('Error parsing mapy.cz URL:', error);
    return null;
  }
}

/**
 * Parse Google Maps URL
 * Supports various formats:
 * - /maps/place/.../@lat,lng,zoom
 * - /maps?q=lat,lng
 * - /maps/@lat,lng,zoom
 */
export function parseGoogleMapsUrl(url: string): MapCoordinates | null {
  try {
    const urlObj = new URL(url);
    
    // Check if it's a Google Maps domain
    if (!urlObj.hostname.includes('google.com') && !urlObj.hostname.includes('google.cz')) {
      return null;
    }

    // Try to extract from pathname (/@lat,lng,zoom format)
    const pathMatch = urlObj.pathname.match(/@(-?\d+\.\d+),(-?\d+\.\d+),(\d+)z/);
    if (pathMatch) {
      const latitude = parseFloat(pathMatch[1]);
      const longitude = parseFloat(pathMatch[2]);
      const zoom = parseInt(pathMatch[3]);

      if (!isNaN(latitude) && !isNaN(longitude)) {
        // Try to extract place name from pathname
        const placeMatch = urlObj.pathname.match(/\/place\/([^/]+)/);
        const address = placeMatch ? decodeURIComponent(placeMatch[1].replace(/\+/g, ' ')) : undefined;

        return {
          latitude,
          longitude,
          zoom: !isNaN(zoom) ? zoom : undefined,
          address,
          source: 'google-maps',
        };
      }
    }

    // Try to extract from query parameters
    const params = urlObj.searchParams;
    const qParam = params.get('q');
    
    if (qParam) {
      // Check if q parameter contains coordinates (lat,lng format)
      const coordMatch = qParam.match(/(-?\d+\.\d+),(-?\d+\.\d+)/);
      if (coordMatch) {
        const latitude = parseFloat(coordMatch[1]);
        const longitude = parseFloat(coordMatch[2]);

        if (!isNaN(latitude) && !isNaN(longitude)) {
          return {
            latitude,
            longitude,
            address: qParam.includes(',') ? undefined : qParam,
            source: 'google-maps',
          };
        }
      }
    }

    // Try data parameter (some Google Maps links use this)
    const dataMatch = urlObj.pathname.match(/!3d(-?\d+\.\d+)!4d(-?\d+\.\d+)/);
    if (dataMatch) {
      const latitude = parseFloat(dataMatch[1]);
      const longitude = parseFloat(dataMatch[2]);

      if (!isNaN(latitude) && !isNaN(longitude)) {
        return {
          latitude,
          longitude,
          source: 'google-maps',
        };
      }
    }

    return null;
  } catch (error) {
    console.error('Error parsing Google Maps URL:', error);
    return null;
  }
}

/**
 * Main function to parse any supported map URL
 */
export function parseMapUrl(url: string): MapCoordinates | null {
  if (!url || typeof url !== 'string') {
    return null;
  }

  // Normalize the URL (add protocol if missing)
  let normalizedUrl = url.trim();
  if (!normalizedUrl.startsWith('http://') && !normalizedUrl.startsWith('https://')) {
    normalizedUrl = 'https://' + normalizedUrl;
  }

  // Try parsing as mapy.cz
  const mapyCzResult = parseMapyCzUrl(normalizedUrl);
  if (mapyCzResult) {
    return mapyCzResult;
  }

  // Try parsing as Google Maps
  const googleMapsResult = parseGoogleMapsUrl(normalizedUrl);
  if (googleMapsResult) {
    return googleMapsResult;
  }

  return null;
}

/**
 * Validate if coordinates are within valid ranges
 */
export function validateCoordinates(lat: number, lng: number): boolean {
  return (
    !isNaN(lat) &&
    !isNaN(lng) &&
    lat >= -90 &&
    lat <= 90 &&
    lng >= -180 &&
    lng <= 180
  );
}

/**
 * Reverse geocode coordinates to get detailed address information
 * Uses Nominatim API (OpenStreetMap)
 */
export async function reverseGeocode(lat: number, lng: number): Promise<Partial<MapCoordinates>> {
  try {
    const response = await fetch(
      `https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&addressdetails=1&accept-language=cs`,
      {
        headers: {
          'User-Agent': 'FotbalClub/1.0',
        },
      }
    );

    if (!response.ok) {
      throw new Error('Reverse geocoding failed');
    }

    const data = await response.json();
    const addr = data.address || {};

    return {
      address: data.display_name,
      street: addr.road || addr.street || addr.pedestrian || addr.footway,
      city: addr.city || addr.town || addr.village || addr.municipality,
      zip: addr.postcode,
      country: addr.country || 'Česká republika',
    };
  } catch (error) {
    console.error('Reverse geocoding error:', error);
    return {};
  }
}
