#!/usr/bin/env python
"""
Test script for the unified map service.
This script tests the map service with real location data.
"""

import os
import sys
import django

# Ensure project root is on sys.path so imports like `core.services.*` resolve.
# This inserts the parent directory of the tests folder (project root).
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if PROJECT_ROOT not in sys.path:
    sys.path.insert(0, PROJECT_ROOT)

# Setup Django environment before importing app modules that depend on settings.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.django.test")
django.setup()

# Now import project modules
from apps.core.services.data_structures import GeoBounds, MapFilters, LocationType  # noqa: E402
from apps.core.services.map_service import unified_map_service  # noqa: E402


def test_basic_map_service():
    """Test basic map service functionality."""
    print("=" * 60)
    print("TESTING UNIFIED MAP SERVICE")
    print("=" * 60)

    try:
        # Test 1: Get all locations (no filters)
        print("\n1. Testing get_map_data() with no filters:")
        response = unified_map_service.get_map_data(zoom_level=10, cluster=False)
        print(f"   Total locations found: {len(response.locations)}")
        print(f"   Clusters: {len(response.clusters)}")
        print(f"   Query time: {response.query_time_ms}ms")
        print(f"   Cache hit: {response.cache_hit}")

        if response.locations:
            print(
                f"   Sample location: {
                    response.locations[0].name} ({
                    response.locations[0].type.value})"
            )

        # Test 2: Get locations with bounds (Ohio area - Cedar Point region)
        print("\n2. Testing get_map_data() with bounds (Ohio):")
        ohio_bounds = GeoBounds(north=42.0, south=40.0, east=-80.5, west=-84.5)
        response = unified_map_service.get_map_data(
            bounds=ohio_bounds, zoom_level=8, cluster=False
        )
        print(f"   Locations in Ohio bounds: {len(response.locations)}")
        print(f"   Query time: {response.query_time_ms}ms")

        # Test 3: Test clustering
        print("\n3. Testing clustering functionality:")
        response = unified_map_service.get_map_data(
            bounds=ohio_bounds,
            zoom_level=6,  # Lower zoom should trigger clustering
            cluster=True,
        )
        print(f"   Locations (unclustered): {len(response.locations)}")
        print(f"   Clusters: {len(response.clusters)}")
        print(f"   Clustered: {response.clustered}")

        if response.clusters:
            cluster = response.clusters[0]
            print(
                f"   Sample cluster: {
                    cluster.count} points at {
                    cluster.coordinates}"
            )

        # Test 4: Test filtering by type
        print("\n4. Testing location type filtering:")
        filters = MapFilters(location_types={LocationType.PARK})
        response = unified_map_service.get_map_data(
            filters=filters, zoom_level=10, cluster=False
        )
        print(f"   Parks only: {len(response.locations)}")

        # Test 5: Test search functionality
        print("\n5. Testing search functionality:")
        results = unified_map_service.search_locations(query="Cedar Point", limit=5)
        print(f"   Search results for 'Cedar Point': {len(results)}")
        if results:
            print(
                f"   First result: {
                    results[0].name} ({
                    results[0].type.value})"
            )

        # Test 6: Test location detail retrieval
        print("\n6. Testing location detail retrieval:")
        if response.locations:
            location = response.locations[0]
            location_type, location_id = location.id.split("_", 1)
            detail = unified_map_service.get_location_details(
                location_type, int(location_id)
            )
            if detail:
                print(f"   Retrieved details for: {detail.name}")
                print(f"   Coordinates: {detail.coordinates}")
                print(f"   Metadata keys: {list(detail.metadata.keys())}")
            else:
                print("   No details found")

        # Test 7: Test service statistics
        print("\n7. Testing service statistics:")
        stats = unified_map_service.get_service_stats()
        print(
            f"   Cache hit rate: {
                stats['cache_performance']['hit_rate_percent']}%"
        )
        print(
            f"   Supported location types: {
                stats['supported_location_types']}"
        )
        print(f"   Max unclustered points: {stats['max_unclustered_points']}")

        print("\n" + "=" * 60)
        print("✅ ALL TESTS PASSED!")
        print("The unified map service is working correctly.")
        print("=" * 60)

    except Exception as e:
        print(f"\n❌ ERROR: {str(e)}")
        import traceback

        traceback.print_exc()
        return False

    return True


def test_api_endpoints():
    """Test the API endpoints."""
    print("\n" + "=" * 60)
    print("TESTING API ENDPOINTS")
    print("=" * 60)

    try:
        from django.test import Client

        client = Client()

        # Test 1: Main locations endpoint
        print("\n1. Testing /api/map/locations/")
        response = client.get("/api/map/locations/")
        print(f"   Status: {response.status_code}")
        if response.status_code == 200:
            data = response.json()
            print(f"   Response status: {data.get('status')}")
            print(f"   Locations: {len(data.get('data', {}).get('locations', []))}")

        # Test 2: Bounds endpoint
        print("\n2. Testing /api/map/bounds/")
        response = client.get("/api/map/bounds/?north=42&south=40&east=-80&west=-84")
        print(f"   Status: {response.status_code}")
        if response.status_code == 200:
            data = response.json()
            print(
                f"   Locations in bounds: {len(data.get('data', {}).get('locations', []))}"
            )

        # Test 3: Search endpoint
        print("\n3. Testing /api/map/search/")
        response = client.get("/api/map/search/?q=park")
        print(f"   Status: {response.status_code}")
        if response.status_code == 200:
            data = response.json()
            print(
                f"   Search results: {len(data.get('data', {}).get('locations', []))}"
            )

        # Test 4: Stats endpoint
        print("\n4. Testing /api/map/stats/")
        response = client.get("/api/map/stats/")
        print(f"   Status: {response.status_code}")
        if response.status_code == 200:
            data = response.json()
            print(
                f"   Service version: {
                    data.get(
                        'data',
                        {}).get('service_version')}"
            )

        print("\n✅ API ENDPOINTS WORKING!")

    except Exception as e:
        print(f"\n❌ API ERROR: {str(e)}")
        import traceback

        traceback.print_exc()
        return False

    return True


def test_performance():
    """Test performance characteristics."""
    print("\n" + "=" * 60)
    print("TESTING PERFORMANCE")
    print("=" * 60)

    import time

    try:
        # Test response times
        times = []
        for i in range(5):
            start = time.time()
            unified_map_service.get_map_data(zoom_level=10, cluster=True)
            end = time.time()
            times.append((end - start) * 1000)  # Convert to ms

        avg_time = sum(times) / len(times)
        print(f"\n   Average response time: {avg_time:.2f}ms")
        print(f"   Min time: {min(times):.2f}ms")
        print(f"   Max time: {max(times):.2f}ms")

        # Test cache performance
        print("\n   Testing cache performance:")
        start = time.time()
        response1 = unified_map_service.get_map_data(zoom_level=10, use_cache=True)
        time1 = time.time() - start

        start = time.time()
        response2 = unified_map_service.get_map_data(zoom_level=10, use_cache=True)
        time2 = time.time() - start

        print(
            f"   First call: {
                time1 *
                1000:.2f}ms (cache miss: {
                not response1.cache_hit})"
        )
        print(
            f"   Second call: {
                time2 *
                1000:.2f}ms (cache hit: {
                response2.cache_hit})"
        )

        if response2.cache_hit and time2 < time1:
            print("   ✅ Cache is working and providing performance benefit!")

        print("\n✅ PERFORMANCE TESTS COMPLETED!")

    except Exception as e:
        print(f"\n❌ PERFORMANCE ERROR: {str(e)}")
        import traceback

        traceback.print_exc()
        return False

    return True


if __name__ == "__main__":
    print("Starting unified map service tests...")

    success = True
    success &= test_basic_map_service()
    success &= test_api_endpoints()
    success &= test_performance()

    if success:
        print("\n🎉 ALL TESTS COMPLETED SUCCESSFULLY!")
        print("The unified map service implementation is working correctly.")
    else:
        print("\n💥 SOME TESTS FAILED!")
        sys.exit(1)
