"""
Генератор тестовых данных для прототипа карты шумового загрязнения.
Создаёт реалистичные траектории вылетов/посадок из Шереметьево (SVO),
Домодедово (DME) и Внуково (VKO).
"""

import json
import math
import random
from datetime import datetime, timedelta, timezone

# Аэропорты Московской области
AIRPORTS = {
    "SVO": {"lat": 55.9726, "lon": 37.4146, "name": "Шереметьево"},
    "DME": {"lat": 55.4088, "lon": 37.9063, "name": "Домодедово"},
    "VKO": {"lat": 55.5914, "lon": 37.2615, "name": "Внуково"},
    "ZIA": {"lat": 55.5531, "lon": 38.1500, "name": "Жуковский"},
}

# Типичные направления вылета/захода (азимуты взлётно-посадочных полос)
RUNWAY_HEADINGS = {
    "SVO": [75, 255, 100, 280],
    "DME": [50, 230, 60, 240],
    "VKO": [120, 300, 130, 310],
    "ZIA": [85, 265],
}

AIRCRAFT_TYPES = [
    "B738", "A320", "A321", "B77W", "A333", "SU95",
    "B763", "A319", "E170", "B737", "A350",
]

AIRLINES = [
    "Aeroflot", "S7 Airlines", "Pobeda", "Rossiya",
    "UTair", "Ural Airlines", "Azur Air", "NordWind",
]


def generate_departure_track(airport_code: str, flight_id: int) -> dict:
    """Генерация трека вылета из аэропорта"""
    airport = AIRPORTS[airport_code]
    heading = random.choice(RUNWAY_HEADINGS.get(airport_code, [90]))
    heading_rad = math.radians(heading)

    aircraft_type = random.choice(AIRCRAFT_TYPES)
    callsign = f"{''.join(random.choices('ABCDEFGHIJKLMNOPQRSTUVWXYZ', k=3))}{random.randint(100,999)}"

    # Генерация точек трека вылета
    # Фазы: разбег (0ft), отрыв → набор высоты → крейсер
    points = []
    base_time = datetime(2026, 3, 20, random.randint(6, 22), random.randint(0, 59),
                         tzinfo=timezone.utc)

    lat, lon = airport["lat"], airport["lon"]
    altitude = 0
    speed = 0

    num_points = random.randint(20, 40)

    for i in range(num_points):
        dt = base_time + timedelta(minutes=i * 2)

        # Фазы полёта
        progress = i / num_points
        if progress < 0.05:
            # Руление
            altitude = 0
            speed = random.randint(20, 60)
        elif progress < 0.2:
            # Набор высоты
            altitude = int(progress * 15000 / 0.2)
            speed = random.randint(180, 280)
        elif progress < 0.5:
            # Начальный набор
            altitude = int(5000 + progress * 20000)
            speed = random.randint(280, 380)
        else:
            # Крейсер
            altitude = random.randint(28000, 38000)
            speed = random.randint(420, 480)

        # Движение по направлению взлёта
        dist_km = (i * 2) * (speed / 60) / 1.852  # в км
        lat_offset = (dist_km / 111.32) * math.cos(heading_rad)
        lon_offset = (dist_km / (111.32 * math.cos(math.radians(lat)))) * math.sin(heading_rad)

        point_lat = airport["lat"] + lat_offset + random.gauss(0, 0.005)
        point_lon = airport["lon"] + lon_offset + random.gauss(0, 0.005)

        points.append({
            "lat": round(point_lat, 5),
            "lon": round(point_lon, 5),
            "altitude": altitude,
            "speed": speed,
            "heading": heading + random.randint(-10, 10),
            "timestamp": dt.isoformat(),
        })

    return {
        "id": f"DEMO{flight_id:04d}",
        "callsign": callsign,
        "flight_number": f"{''.join(random.choices('ABCDEFGHIJKLMNOPQRSTUVWXYZ', k=2))}{random.randint(100,999)}",
        "aircraft_type": aircraft_type,
        "airline": random.choice(AIRLINES),
        "origin": airport_code,
        "destination": random.choice([k for k in AIRPORTS if k != airport_code]),
        "origin_name": airport["name"],
        "registration": f"RA-{random.randint(10000,99999)}",
        "points": points,
        "type": "departure",
    }


def generate_arrival_track(airport_code: str, flight_id: int) -> dict:
    """Генерация трека захода на посадку"""
    airport = AIRPORTS[airport_code]
    heading = random.choice(RUNWAY_HEADINGS.get(airport_code, [90]))
    # Заход с противоположного направления
    approach_heading = (heading + 180) % 360
    heading_rad = math.radians(approach_heading)

    aircraft_type = random.choice(AIRCRAFT_TYPES)
    callsign = f"{''.join(random.choices('ABCDEFGHIJKLMNOPQRSTUVWXYZ', k=3))}{random.randint(100,999)}"

    points = []
    base_time = datetime(2026, 3, 20, random.randint(6, 22), random.randint(0, 59),
                         tzinfo=timezone.utc)

    num_points = random.randint(25, 45)
    start_dist_km = random.randint(80, 150)

    # Начало трека далеко от аэропорта
    start_lat = airport["lat"] + (start_dist_km / 111.32) * math.cos(heading_rad)
    start_lon = airport["lon"] + (start_dist_km / (111.32 * math.cos(
        math.radians(airport["lat"])))) * math.sin(heading_rad)

    for i in range(num_points):
        dt = base_time + timedelta(minutes=i * 2)
        progress = i / num_points

        # Снижение от крейсерской до посадочной
        if progress < 0.2:
            altitude = random.randint(28000, 35000)
            speed = random.randint(420, 470)
        elif progress < 0.5:
            altitude = int(30000 * (1 - (progress - 0.2) / 0.5))
            speed = random.randint(320, 420)
        elif progress < 0.8:
            altitude = int(10000 * (1 - (progress - 0.5) / 0.5))
            speed = random.randint(200, 280)
        elif progress < 0.95:
            altitude = int(3000 * (1 - (progress - 0.8) / 0.2))
            speed = random.randint(150, 180)
        else:
            altitude = 0
            speed = random.randint(20, 80)

        # Движение к аэропорту
        dist_km = start_dist_km * (1 - progress)
        point_lat = airport["lat"] + (dist_km / 111.32) * math.cos(heading_rad) + random.gauss(0, 0.004)
        point_lon = airport["lon"] + (dist_km / (111.32 * math.cos(
            math.radians(airport["lat"])))) * math.sin(heading_rad) + random.gauss(0, 0.004)

        points.append({
            "lat": round(point_lat, 5),
            "lon": round(point_lon, 5),
            "altitude": max(0, altitude),
            "speed": speed,
            "heading": (approach_heading + 180) % 360 + random.randint(-5, 5),
            "timestamp": dt.isoformat(),
        })

    return {
        "id": f"DEMO{flight_id:04d}",
        "callsign": callsign,
        "flight_number": f"{''.join(random.choices('ABCDEFGHIJKLMNOPQRSTUVWXYZ', k=2))}{random.randint(100,999)}",
        "aircraft_type": aircraft_type,
        "airline": random.choice(AIRLINES),
        "origin": random.choice([k for k in AIRPORTS if k != airport_code]),
        "destination": airport_code,
        "destination_name": airport["name"],
        "registration": f"RA-{random.randint(10000,99999)}",
        "points": points,
        "type": "arrival",
    }


def generate_sample_data(num_flights: int = 50) -> dict:
    """Генерация тестового датасета"""
    random.seed(42)  # воспроизводимость
    flights = []

    airports = list(AIRPORTS.keys())
    flight_id = 1

    for i in range(num_flights):
        airport = airports[i % len(airports)]
        if i % 2 == 0:
            flight = generate_departure_track(airport, flight_id)
        else:
            flight = generate_arrival_track(airport, flight_id)
        flights.append(flight)
        flight_id += 1

    return {
        "generated_at": datetime.now(timezone.utc).isoformat(),
        "description": "Тестовые данные для прототипа карты шумового загрязнения",
        "region": "Московская область",
        "airports": AIRPORTS,
        "flights_count": len(flights),
        "flights": flights,
    }


if __name__ == "__main__":
    print("🎲 Генерация тестовых данных...")
    data = generate_sample_data(50)

    output_path = "data/sample_flights.json"
    with open(output_path, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

    print(f"✅ Сгенерировано {data['flights_count']} рейсов → {output_path}")

    # Статистика
    total_points = sum(len(f["points"]) for f in data["flights"])
    print(f"   Всего точек трека: {total_points}")
    print(f"   Аэропорты: {', '.join(AIRPORTS.keys())}")
