#!/usr/bin/env python3
"""
Build orari bus database from TPER GTFS for the HTTP server.
Produces: /home/alina/aNavigator/server/orari_db.json
"""
import csv
import json
import os
import sys
from collections import defaultdict

GTFS_DIR = "/tmp/gtfs_tper_raw"
OUTPUT_DIR = "/home/alina/aNavigator/server"

os.makedirs(OUTPUT_DIR, exist_ok=True)

# ─── 1. Routes ───
print("Reading routes...")
routes = {}
with open(os.path.join(GTFS_DIR, "routes.txt"), encoding="utf-8") as f:
    for row in csv.DictReader(f):
        routes[row["route_id"]] = row["route_short_name"].strip()

# ─── 2. Trips ───
print("Reading trips...")
trips = {}
trips_by_route = defaultdict(list)
with open(os.path.join(GTFS_DIR, "trips.txt"), encoding="utf-8") as f:
    for row in csv.DictReader(f):
        tid = row["trip_id"]
        trips[tid] = {
            "route_id": row["route_id"],
            "direction_id": row["direction_id"],
            "service_id": row["service_id"],
            "headsign": row.get("trip_headsign", "").strip()
        }
        trips_by_route[row["route_id"]].append(tid)

# ─── 3. Calendar ───
print("Reading calendar...")
calendar = {}
with open(os.path.join(GTFS_DIR, "calendar.txt"), encoding="utf-8") as f:
    for row in csv.DictReader(f):
        days = []
        for d in ['monday','tuesday','wednesday','thursday','friday','saturday','sunday']:
            if row.get(d) == '1':
                days.append(d[:3])
        calendar[row["service_id"]] = days

# Also check calendar_dates for exceptions
with open(os.path.join(GTFS_DIR, "calendar_dates.txt"), encoding="utf-8") as f:
    for row in csv.DictReader(f):
        pass  # We skip date-specific exceptions for now

def service_label(days):
    """Returns a label for the service."""
    if not days:
        return ""
    week = {'mon','tue','wed','thu','fri'}
    if week.issubset(set(days)):
        return "Feriale"
    if days == ['sat']:
        return "Sabato"
    if days == ['sun']:
        return "Domenica"
    if 'sat' in days and 'sun' in days and all(d in days for d in week):
        return "Tutti i giorni"
    if 'sat' in days and 'sun' in days:
        return "Sabato e Domenica"
    # Mixed - figure out
    has_weekday = any(d in week for d in days)
    has_weekend = 'sat' in days or 'sun' in days
    if has_weekday and not has_weekend:
        return "Feriale"
    if not has_weekday and has_weekend:
        return "Weekend"
    return ", ".join(days[:3])

# ─── 4. Stops ───
print("Reading stops...")
stops = {}
with open(os.path.join(GTFS_DIR, "stops.txt"), encoding="utf-8") as f:
    for row in csv.DictReader(f):
        stops[row["stop_id"]] = row["stop_name"].strip()

# ─── 5. Stop times (the big one - 48MB) ───
print("Reading stop_times (48MB)...")
# Structure: line_short_name -> stop_name -> {dir: {service: [times]}}
db = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(list))))

count = 0
with open(os.path.join(GTFS_DIR, "stop_times.txt"), encoding="utf-8") as f:
    for row in csv.DictReader(f):
        trip_id = row["trip_id"]
        stop_id = row["stop_id"]
        arrival = row["arrival_time"]  # HH:MM:SS
        
        trip = trips.get(trip_id)
        if not trip:
            continue
        
        route_id = trip["route_id"]
        line_num = routes.get(route_id, "")
        if not line_num:
            continue
        
        stop_name = stops.get(stop_id, stop_id)
        dir_id = trip["direction_id"]
        days = calendar.get(trip["service_id"], [])
        label = service_label(days)
        
        # Store time in compact format (HH:MM)
        time_compact = arrival[:5] if len(arrival) >= 5 else arrival
        
        db[line_num][stop_name][dir_id][label].append(time_compact)
        
        count += 1
        if count % 500000 == 0:
            print(f"  Processed {count} stop_times...")

print(f"  Total stop_times processed: {count}")

# ─── 6. Sort times and deduplicate ───
print("Sorting and deduplicating...")
result = {}
for line_num in sorted(db.keys(), key=lambda x: (int(x) if x.isdigit() else 999, x)):
    line_data = {}
    for stop_name in sorted(db[line_num].keys()):
        dirs = {}
        for dir_id in sorted(db[line_num][stop_name].keys()):
            services = {}
            for label in sorted(db[line_num][stop_name][dir_id].keys()):
                times = sorted(set(db[line_num][stop_name][dir_id][label]))
                services[label] = times
            dirs[dir_id] = services
        line_data[stop_name] = dirs
    result[line_num] = line_data

# ─── 7. Write output ───
output_path = os.path.join(OUTPUT_DIR, "orari_db.json")
with open(output_path, "w", encoding="utf-8") as f:
    json.dump(result, f, ensure_ascii=False)

size_mb = os.path.getsize(output_path) / 1024 / 1024
print(f"Written to {output_path} ({size_mb:.1f} MB)")
print(f"Lines: {len(result)}")
sample_stops = sum(len(v) for v in result.values())
print(f"Stop entries: ~{sample_stops}")
print("Done!")
