"""Script to import bus stop coordinates from Supabase that follow actual roads."""
import os
from pathlib import Path
from supabase import create_client, Client
from sqlmodel import Session, select, create_engine
import sys

from app.core.config import settings, get_env_file
from app.models.bus_stop import BusStop
from app.models.route import Route
from app.models.route_stop import RouteStop


def load_env_file():
    """Load environment variables from .env.development file."""
    env_file = get_env_file()
    env_path = Path(env_file)
    
    # If relative path, make it relative to backend directory
    if not env_path.is_absolute():
        backend_dir = Path(__file__).parent.parent.parent
        env_path = backend_dir / env_file
    
    if env_path.exists():
        from dotenv import load_dotenv
        load_dotenv(env_path)
        print(f"✓ Loaded environment from {env_path}")
    else:
        print(f"⚠️  Warning: {env_path} not found, using system environment variables")


def get_supabase_client() -> Client:
    """Create Supabase client from environment variables."""
    # Load .env.development file first
    load_env_file()
    
    supabase_url = os.getenv("SUPABASE_URL")
    supabase_key = os.getenv("SUPABASE_ANON_KEY")
    
    if not supabase_url or not supabase_key:
        raise ValueError(
            "SUPABASE_URL and SUPABASE_ANON_KEY must be set in environment or .env.development file.\n"
            f"Checked file: {get_env_file()}"
        )
    
    return create_client(supabase_url, supabase_key)


def import_coordinates_from_supabase(route_name: str = "Boquete>David", supabase_route_name: str = None):
    """Import bus stop coordinates from Supabase for a specific route.
    
    Args:
        route_name: Route name in local database format (e.g., "Boquete>David")
        supabase_route_name: Route name in Supabase format (e.g., "Boquete – David"). 
                            If None, will try to find it automatically.
    """
    supabase = get_supabase_client()
    
    # If supabase_route_name is provided, use it directly
    if supabase_route_name:
        route_response = supabase.table("routes").select("*").eq("name", supabase_route_name).execute()
    else:
        # Get route from Supabase - try exact match first, then try variations
        route_response = supabase.table("routes").select("*").eq("name", route_name).execute()
        
        # If not found, try with different separators (Supabase uses " – " em dash)
        if not route_response.data:
            # Try with different separators
            variations = [
                route_name.replace(">", " – "),  # Em dash (Supabase format)
                route_name.replace(">", "-"),     # Regular dash
                route_name.replace(">", " to "),  # " to "
                route_name.replace(">", " -> "),  # " -> "
            ]
            for variant in variations:
                route_response = supabase.table("routes").select("*").eq("name", variant).execute()
                if route_response.data:
                    print(f"Found route with name variation: '{variant}'")
                    break
    
    # If still not found, list available routes
    if not route_response.data:
        all_routes = supabase.table("routes").select("name").execute()
        available = [r["name"] for r in all_routes.data] if all_routes.data else []
        raise ValueError(
            f"Route '{route_name}' not found in Supabase.\n"
            f"Available routes: {', '.join(available) if available else 'None found'}"
        )
    
    supabase_route = route_response.data[0]
    supabase_route_id = supabase_route["id"]
    
    # Get all route stops with stop details from Supabase
    # Old app uses 'stops' table with 'lat' and 'lng' columns, and 'seq' for order
    # Try different query formats to match Supabase schema
    try:
        # Try the format used by old Flutter app: stops:stop_id with seq
        route_stops_response = supabase.table("route_stops").select(
            "seq, stops:stop_id(id, name, lat, lng)"
        ).eq("route_id", supabase_route_id).order("seq").execute()

    except Exception as e1:
        try:
            # Try with stop_order instead of seq
            route_stops_response = supabase.table("route_stops").select(
                "stop_order, stops:stop_id(id, name, lat, lng)"
            ).eq("route_id", supabase_route_id).order("stop_order").execute()

        except Exception as e2:
            try:
                # Try bus_stops table (new schema)
                route_stops_response = supabase.table("route_stops").select(
                    "stop_order, bus_stops(*)"
                ).eq("route_id", supabase_route_id).order("stop_order").execute()

            except Exception as e3:
                raise Exception(f"Could not query Supabase: {e1}, {e2}, {e3}")
    
    if not route_stops_response.data:
        print(f"No stops found for route '{route_name}' in Supabase")
        return
    
    # Connect to local database
    sync_database_url = settings.database_url.replace("+asyncpg", "+psycopg2")
    sync_engine = create_engine(sync_database_url, echo=False)
    
    with Session(sync_engine) as session:
        # Find the route in local database
        local_route = session.exec(select(Route).where(Route.name == route_name)).first()
        if not local_route:
            print(f"Route '{route_name}' not found in local database. Please create it first.")
            return
        
        print(f"Found route '{route_name}' in local database (ID: {local_route.id})")
        
        # Get local route stops ordered by stop_order
        local_route_stops = session.exec(
            select(RouteStop, BusStop)
            .join(BusStop, RouteStop.stop_id == BusStop.id)
            .where(RouteStop.route_id == local_route.id)
            .order_by(RouteStop.stop_order)
        ).all()
        
        if len(local_route_stops) != len(route_stops_response.data):
            print(f"⚠️  Warning: Local database has {len(local_route_stops)} stops, Supabase has {len(route_stops_response.data)} stops")
            print("   Updating coordinates for matching stops...")
        
        # Update coordinates for each stop
        updated_count = 0
        for i, supabase_stop_data in enumerate(route_stops_response.data):
            if i >= len(local_route_stops):
                break
                
            # Try different possible field names for the stop data
            supabase_stop = (
                supabase_stop_data.get("bus_stops") or 
                supabase_stop_data.get("stops") or
                supabase_stop_data  # If the stop data is directly in the response
            )
            if not supabase_stop or not isinstance(supabase_stop, dict):
                continue
            
            # Get the local stop
            local_route_stop, local_bus_stop = local_route_stops[i]
            
            # Update coordinates from Supabase
            # Supabase may use 'lat'/'lng' (old schema) or 'latitude'/'longitude' (new schema)
            new_latitude = supabase_stop.get("latitude") or supabase_stop.get("lat")
            new_longitude = supabase_stop.get("longitude") or supabase_stop.get("lng")
            
            if new_latitude is None or new_longitude is None:
                print(f"⚠️  Skipping stop {i+1}: missing coordinates in Supabase")
                continue
            
            # Check if coordinates are different
            if abs(local_bus_stop.latitude - new_latitude) > 0.0001 or \
               abs(local_bus_stop.longitude - new_longitude) > 0.0001:
                local_bus_stop.latitude = new_latitude
                local_bus_stop.longitude = new_longitude
                session.add(local_bus_stop)
                updated_count += 1
                print(f"✓ Updated stop {i+1} ({local_bus_stop.name}): "
                      f"({new_latitude:.6f}, {new_longitude:.6f})")
        
        session.commit()
        print(f"\n✅ Successfully updated {updated_count} stops with coordinates from Supabase")


def import_all_routes():
    """Import coordinates for all routes from Supabase."""
    supabase = get_supabase_client()
    
    # Get all routes from Supabase
    routes_response = supabase.table("routes").select("*").execute()
    routes = routes_response.data
    
    print(f"Found {len(routes)} routes in Supabase")
    
    for route in routes:
        supabase_route_name = route["name"]  # Format: "Boquete – David"
        # Convert Supabase format to local format for matching
        local_route_name = supabase_route_name.replace(" – ", ">").replace(" - ", ">").replace(" to ", ">").replace(" -> ", ">")
        
        print(f"\n{'='*60}")
        print(f"Importing coordinates for route: {supabase_route_name}")
        print(f"Looking for local route: {local_route_name}")
        print(f"{'='*60}")
        try:
            import_coordinates_from_supabase(local_route_name, supabase_route_name=supabase_route_name)
        except Exception as e:
            print(f"❌ Error importing route '{supabase_route_name}': {e}")
            continue


if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] == "--all":
        # Import all routes
        import_all_routes()
    else:
        # Import specific route
        route_name = sys.argv[1] if len(sys.argv) > 1 else "Boquete>David"
        import_coordinates_from_supabase(route_name)

