"""
Seed transport data for the SCHOOL database: vehicles, real Chennai-area
routes with ordered stops + pickup timings, and student/teacher assignments.

Also fixes up two categories of pre-existing test data:
  * The placeholder "mappedu" route (junk driver/stops, destination
    "Arakkonam") is corrected into a real Sriperumbudur <-> Mappedu
    corridor route, in place — its existing student/teacher assignments
    are preserved since we update the Route/Stop rows rather than
    replace them.
  * Any TransportVehicle that has no Route yet (Route is a
    OneToOneField) gets a real route + stops created for it.

Idempotent — safe to re-run.  Usage:
  .venv\\Scripts\\python.exe seed_transport_data.py
"""

import os
import random
import sys
from datetime import time, timedelta, datetime, date
from decimal import Decimal

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings")

import django

django.setup()

from academics.models import AcademicYear, StudentEnrollment
from people.models import Teacher
from transport.models import (
    Route,
    Stop,
    StudentTransport,
    TeacherTransport,
    TransportType,
    TransportVehicle,
)

random.seed(2027)

# ─── Transport types ─────────────────────────────────────────────────────────
bus_type, _ = TransportType.objects.get_or_create(name="Bus")
van_type, _ = TransportType.objects.get_or_create(name="Van")

created = {
    "vehicles": 0, "routes": 0, "stops": 0, "students": 0, "teachers": 0,
    "routes updated": 0,
}


def seed_route_for_vehicle(vehicle, name, ttype, dist, start_loc, first_pick, stop_names):
    """Create (idempotent) a Route + ordered Stops for an existing vehicle."""
    route, was_created = Route.objects.get_or_create(
        vehicle=vehicle,
        defaults={
            "route_name": name,
            "start_location": start_loc,
            "destination": "School Campus",
            "distance_km": Decimal(str(dist)),
        },
    )
    if was_created:
        created["routes"] += 1

    cursor = datetime.combine(date(2026, 1, 1), first_pick)
    for order, stop_name in enumerate(stop_names, start=1):
        _, was_created = Stop.objects.get_or_create(
            route=route,
            stop_order=order,
            defaults={"stop_name": stop_name, "arrival_time": cursor.time()},
        )
        if was_created:
            created["stops"] += 1
        cursor += timedelta(minutes=7)
    return route


# ═══════════════════════════════════════════════════════════════════════════
# 1. New vehicles + real Chennai-area routes (13 total: 8 pre-existing + 5 new)
# (route_name, type, distance_km, start, first_pickup, [stops...])
# ═══════════════════════════════════════════════════════════════════════════
ROUTES = [
    ("Route 1 - Avadi & Ambattur", bus_type, 18.5, "Avadi", time(6, 50), [
        "Avadi Bus Terminus", "Avadi Checkpost", "Pattabiram Railway Gate",
        "Thirumullaivoyal", "Ambattur OT Bus Stand", "Ambattur Industrial Estate",
        "Padi Junction", "Anna Nagar West Depot",
    ]),
    ("Route 2 - Tiruvallur", bus_type, 36.0, "Tiruvallur", time(6, 30), [
        "Tiruvallur Bus Stand", "Manavalan Nagar", "Kakkalur Bypass",
        "Thiruninravur", "Veppampattu", "Sevvapet Road", "Pattabiram",
        "Avadi Checkpost",
    ]),
    ("Route 3 - Poonamallee & Porur", bus_type, 16.0, "Poonamallee", time(7, 0), [
        "Poonamallee Bus Terminus", "Kumananchavadi", "Karayanchavadi",
        "Iyyappanthangal", "Porur Junction", "Valasaravakkam",
        "Virugambakkam", "Vadapalani Signal",
    ]),
    ("Route 4 - Velachery & Adyar", bus_type, 14.5, "Velachery", time(7, 0), [
        "Velachery Bus Terminus", "Vijayanagar Junction", "Taramani Link Road",
        "Thiruvanmiyur RTO", "Adyar Depot", "Kotturpuram Bridge",
        "Saidapet Court", "Guindy Kathipara",
    ]),
    ("Route 5 - Tambaram & Guindy", bus_type, 17.0, "Tambaram", time(6, 45), [
        "Tambaram Sanatorium", "Chromepet Bus Stop", "Pallavaram Bridge",
        "Meenambakkam Metro", "Alandur Junction", "Guindy Race Course",
        "Little Mount",
    ]),
    ("Route 6 - Central & T Nagar", bus_type, 12.0, "Broadway", time(7, 5), [
        "Broadway Bus Terminus", "Chennai Central", "Egmore Station",
        "Chetpet Signal", "Nungambakkam High Road", "T Nagar Bus Terminus",
        "Saidapet Bridge",
    ]),
    ("Route 7 - Anna Nagar (Van)", van_type, 10.0, "Anna Nagar", time(7, 15), [
        "Anna Nagar West Depot", "Anna Nagar Roundtana", "Shanthi Colony",
        "Aminjikarai Market", "Chetpet Signal",
    ]),
    ("Route 8 - Mogappair & Koyambedu (Van)", van_type, 13.0, "Mogappair", time(7, 10), [
        "Mogappair East", "Mogappair West Depot", "Nolambur Phase 2",
        "Maduravoyal Erikarai", "Koyambedu CMBT", "Arumbakkam Metro",
    ]),
    # ── 5 new routes ──
    ("Route 9 - Perambur & Villivakkam", bus_type, 15.0, "Perambur", time(7, 0), [
        "Perambur Barracks Road", "Perambur Railway Station", "Perambur Market",
        "Villivakkam Bus Depot", "Villivakkam Railway Station", "Korattur Signal",
        "Ambattur Estate",
    ]),
    ("Route 10 - Red Hills & Madhavaram", bus_type, 22.0, "Red Hills", time(6, 40), [
        "Red Hills Bus Stand", "Puzhal Checkpost", "Madhavaram Milk Colony",
        "Madhavaram Bus Depot", "Kolathur Signal", "Villivakkam Junction",
        "Anna Nagar West Depot",
    ]),
    ("Route 11 - Sholinganallur & OMR IT Corridor", bus_type, 20.0, "Sholinganallur", time(6, 55), [
        "Sholinganallur Junction", "Perungudi Signal", "Thoraipakkam OMR",
        "Kandanchavadi", "Adyar Signal", "Saidapet Bridge", "Guindy Kathipara",
    ]),
    ("Route 12 - Medavakkam & Pallikaranai (Van)", van_type, 11.0, "Medavakkam", time(7, 10), [
        "Medavakkam Junction", "Pallikaranai Bus Stop", "Madipakkam Signal",
        "Velachery Bypass", "Guindy Kathipara",
    ]),
    ("Route 13 - Kundrathur & Mangadu", bus_type, 19.0, "Kundrathur", time(6, 50), [
        "Kundrathur Signal", "Mangadu Junction", "Nazarethpet",
        "Kumananchavadi", "Iyyappanthangal", "Porur Junction",
    ]),
]

DRIVERS = [
    ("Murugan S", "9840012301"), ("Rajendran K", "9840012302"),
    ("Selvam P", "9840012303"), ("Kumar V", "9840012304"),
    ("Ganesh R", "9840012305"), ("Prabhu M", "9840012306"),
    ("Sathish B", "9840012307"), ("Elumalai D", "9840012308"),
    ("Anbarasu N", "9840012309"), ("Palani M", "9840012310"),
    ("Vasu R", "9840012311"), ("Ilango S", "9840012312"),
    ("Chezhian T", "9840012313"),
]

routes = []
for i, (name, ttype, dist, start_loc, first_pick, stop_names) in enumerate(ROUTES):
    vehicle, was_created = TransportVehicle.objects.get_or_create(
        vehicle_number=f"TN 09 SC {2301 + i}",
        defaults={
            "transport_type": ttype,
            "bus_number": f"BUS-{i + 1:02d}",
            "driver_name": DRIVERS[i][0],
            "driver_phone": DRIVERS[i][1],
            "capacity": 40 if ttype == bus_type else 14,
        },
    )
    if was_created:
        created["vehicles"] += 1
    route = seed_route_for_vehicle(vehicle, name, ttype, dist, start_loc, first_pick, stop_names)
    routes.append(route)

# ═══════════════════════════════════════════════════════════════════════════
# 2. Give every OTHER existing vehicle (manually created test rows with no
#    route yet — Route is a one-to-one) a real route too.
# ═══════════════════════════════════════════════════════════════════════════
ORPHAN_VEHICLE_ROUTES = {
    # vehicle_number -> (name, type, distance, start, first_pickup, stops)
    "BH2": (
        "Route 14 - Perungalathur & Vandalur", bus_type, 26.0, "Vandalur", time(6, 35),
        [
            "Vandalur Zoo Junction", "Perungalathur Bus Stop", "Urapakkam Signal",
            "Tambaram West", "Chromepet Bus Stop", "Pallavaram Bridge",
            "Meenambakkam Metro",
        ],
    ),
    "JI0": (
        "Route 15 - Kilpauk & Purasawalkam", bus_type, 9.0, "Kilpauk", time(7, 15),
        [
            "Kilpauk Garden Road", "Purasawalkam High Road", "Aminjikarai Signal",
            "Chetpet Railway Station", "Nungambakkam High Road",
        ],
    ),
}
for vehicle_number, (name, ttype, dist, start_loc, first_pick, stop_names) in ORPHAN_VEHICLE_ROUTES.items():
    vehicle = TransportVehicle.objects.filter(vehicle_number=vehicle_number).first()
    if not vehicle:
        continue
    if hasattr(vehicle, "route"):
        route = vehicle.route  # already seeded in an earlier run — still track it
    else:
        route = seed_route_for_vehicle(vehicle, name, ttype, dist, start_loc, first_pick, stop_names)
    routes.append(route)

# ═══════════════════════════════════════════════════════════════════════════
# 3. Fix up the pre-existing placeholder "mappedu" route in place — real
#    Sriperumbudur/Mappedu corridor (NH48), keeps its Stop/Route row ids so
#    existing StudentTransport/TeacherTransport assignments stay valid.
# ═══════════════════════════════════════════════════════════════════════════
mappedu_vehicle = TransportVehicle.objects.filter(vehicle_number="42").first()
if mappedu_vehicle and hasattr(mappedu_vehicle, "route"):
    route = mappedu_vehicle.route
    target_name = "Route 16 - Mappedu & Sriperumbudur"
    if route.route_name != target_name:
        route.route_name = target_name
        route.start_location = "Sriperumbudur"
        route.destination = "School Campus"
        route.distance_km = Decimal("28.0")
        route.save()

        mappedu_vehicle.driver_name = "Anbu K"
        mappedu_vehicle.driver_phone = "9840012320"
        mappedu_vehicle.save(update_fields=["driver_name", "driver_phone"])

        mappedu_stops = [
            (1, "Sriperumbudur Bus Stand", time(6, 30)),
            (2, "Mappedu", time(6, 37)),
            (3, "Kunnavakkam", time(6, 44)),
            (4, "Walajabad Road", time(6, 51)),
            (5, "Poonamallee Bypass", time(6, 58)),
            (6, "Iyyappanthangal", time(7, 5)),
        ]
        for order, stop_name, arrival in mappedu_stops:
            _, was_created = Stop.objects.update_or_create(
                route=route, stop_order=order,
                defaults={"stop_name": stop_name, "arrival_time": arrival},
            )
            if was_created:
                created["stops"] += 1
        created["routes updated"] += 1
    if route not in routes:
        routes.append(route)

# ═══════════════════════════════════════════════════════════════════════════
# 4. Assign students (current year 26-27) to routes — topped up PER ROUTE so
#    every route (including newly added/fixed ones) ends up with riders,
#    rather than stopping once the fleet-wide total looks big enough.
# ═══════════════════════════════════════════════════════════════════════════
year_26 = AcademicYear.objects.get(name="26-27")
already_transported_ids = set(
    StudentTransport.objects.values_list("student_id", flat=True)
)
enrollments = list(
    StudentEnrollment.objects.filter(
        academic_class__academic_year=year_26, is_active=True
    )
    .exclude(student_id__in=already_transported_ids)
    .select_related("student", "academic_class")
)
random.shuffle(enrollments)
pool = iter(enrollments)

TARGET_PER_ROUTE = 15

for route in routes:
    stops = list(route.stops.all())
    if not stops:
        continue
    current = StudentTransport.objects.filter(route=route, is_active=True).count()
    capacity = route.vehicle.capacity or TARGET_PER_ROUTE
    need = max(0, min(TARGET_PER_ROUTE, capacity) - current)
    for _ in range(need):
        e = next(pool, None)
        if e is None:
            break
        stop = random.choice(stops)
        StudentTransport.objects.create(
            student=e.student,
            enrollment=e,
            vehicle=route.vehicle,
            route=route,
            stop=stop,
            pickup_point=stop.stop_name,
            fee_amount=Decimal(random.choice([800, 1000, 1200, 1500])),
            enrollment_number=f"ENR-{e.id}",   # model.save reads a missing
            academic_year=year_26.name,        # field unless this is pre-set
        )
        created["students"] += 1

# ═══════════════════════════════════════════════════════════════════════════
# 5. A few teachers use the buses too
# ═══════════════════════════════════════════════════════════════════════════
if TeacherTransport.objects.count() < 20:
    for t in Teacher.objects.filter(is_active=True).order_by("id")[:24]:
        route = random.choice(routes)
        stops = list(route.stops.all())
        if not stops:
            continue
        stop = random.choice(stops)
        _, was_created = TeacherTransport.objects.get_or_create(
            teacher=t,
            vehicle=route.vehicle,
            route=route,
            defaults={"stop": stop, "pickup_point": stop.stop_name},
        )
        if was_created:
            created["teachers"] += 1

print("======== TRANSPORT SEED SUMMARY ========")
for k, v in created.items():
    print(f"  {k}: {v}")
print("totals -> vehicles:", TransportVehicle.objects.count(),
      "| routes:", Route.objects.count(),
      "| stops:", Stop.objects.count())
print("student transport:", StudentTransport.objects.count(),
      "| teacher transport:", TeacherTransport.objects.count())
print("DONE")
