from __future__ import annotations

"""Application services for combined track operations."""

from sqlalchemy.orm import Session

from backend.app.models import CombinedTrackCreate, CombinedTrackModel
from backend.app.repositories import CombinedTrackRepository, TrackRepository


def create_combined_track(
    session: Session, start_station_id: str, end_station_id: str
) -> CombinedTrackModel | None:
    """Create a combined track between two stations using pathfinding.

    Returns the created combined track, or None if no path exists or
    a combined track already exists between these stations.
    """
    combined_track_repo = CombinedTrackRepository(session)
    track_repo = TrackRepository(session)

    # Check if combined track already exists
    if combined_track_repo.exists_between_stations(start_station_id, end_station_id):
        return None

    # Find path between stations
    path_tracks = track_repo.find_path_between_stations(
        start_station_id, end_station_id)
    if not path_tracks:
        return None

    # Combine geometries
    combined_coords = track_repo.combine_track_geometries(path_tracks)
    if len(combined_coords) < 2:
        return None

    # Calculate total length
    total_length = sum(track.length_meters or 0 for track in path_tracks)

    # Get max speed (use the minimum speed of all tracks)
    max_speeds = [
        track.max_speed_kph for track in path_tracks if track.max_speed_kph]
    max_speed = min(max_speeds) if max_speeds else None

    # Get constituent track IDs
    constituent_track_ids = [str(track.id) for track in path_tracks]

    # Create combined track
    create_data = CombinedTrackCreate(
        start_station_id=start_station_id,
        end_station_id=end_station_id,
        coordinates=combined_coords,
        constituent_track_ids=constituent_track_ids,
        length_meters=total_length if total_length > 0 else None,
        max_speed_kph=max_speed,
        status="operational",
    )

    combined_track = combined_track_repo.create(create_data)
    session.commit()

    return CombinedTrackModel.model_validate(combined_track)


def get_combined_track(session: Session, combined_track_id: str) -> CombinedTrackModel | None:
    """Get a combined track by ID."""
    try:
        combined_track_repo = CombinedTrackRepository(session)
        combined_track = combined_track_repo.get(combined_track_id)
        return CombinedTrackModel.model_validate(combined_track)
    except LookupError:
        return None


def list_combined_tracks(session: Session) -> list[CombinedTrackModel]:
    """List all combined tracks."""
    combined_track_repo = CombinedTrackRepository(session)
    combined_tracks = combined_track_repo.list_all()
    return [CombinedTrackModel.model_validate(ct) for ct in combined_tracks]
