#!/usr/bin/env python3
"""
ADSB Web Server v2
Serves the web app and data API with FAA enrichment support.
"""

import http.server
import json
import os
import shutil
import threading
from datetime import date
from urllib.parse import urlparse, parse_qs

DATA_DIR = '/home/pi/adsb-analyzer/data'
AIRCRAFT_FILE = '/run/readsb/aircraft.json'
MAX_STORAGE_BYTES = 4 * 1024 * 1024 * 1024
lock = threading.Lock()

os.makedirs(DATA_DIR, exist_ok=True)

def get_data_size():
    total = 0
    for fn in os.listdir(DATA_DIR):
        fp = os.path.join(DATA_DIR, fn)
        if os.path.isfile(fp):
            total += os.path.getsize(fp)
    return total

def get_available_dates():
    return sorted([f.replace('.json','') for f in os.listdir(DATA_DIR) if f.endswith('.json')])

def load_date(d):
    fp = os.path.join(DATA_DIR, d + '.json')
    if os.path.exists(fp):
        try:
            with open(fp, 'r') as f:
                return json.load(f)
        except:
            pass
    return {}

class Handler(http.server.SimpleHTTPRequestHandler):

    def send_json(self, data, status=200):
        body = json.dumps(data).encode()
        self.send_response(status)
        self.send_header('Content-Type', 'application/json')
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Content-Length', len(body))
        self.end_headers()
        self.wfile.write(body)

    def do_OPTIONS(self):
        self.send_response(200)
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
        self.end_headers()

    def do_GET(self):
        parsed = urlparse(self.path)
        path = parsed.path
        params = parse_qs(parsed.query)

        if path == '/aircraft':
            try:
                with open(AIRCRAFT_FILE, 'rb') as f:
                    data = f.read()
                self.send_response(200)
                self.send_header('Content-Type', 'application/json')
                self.send_header('Access-Control-Allow-Origin', '*')
                self.end_headers()
                self.wfile.write(data)
            except Exception as e:
                self.send_json({'error': str(e)}, 500)

        elif path == '/data':
            start = params.get('start', [None])[0]
            end = params.get('end', [None])[0]
            today = date.today().isoformat()
            if not start: start = today
            if not end: end = today

            merged = {}
            for d in get_available_dates():
                if d < start or d > end:
                    continue
                day_data = load_date(d)
                for hex_id, rec in day_data.items():
                    if hex_id not in merged:
                        merged[hex_id] = dict(rec)
                    else:
                        merged[hex_id]['total_sightings'] = merged[hex_id].get('total_sightings', 0) + rec.get('total_sightings', 0)
                        merged[hex_id]['visits'] = merged[hex_id].get('visits', 0) + rec.get('visits', 0)
                        if rec.get('first_seen', '') < merged[hex_id].get('first_seen', ''):
                            merged[hex_id]['first_seen'] = rec['first_seen']
                        if rec.get('last_seen', '') > merged[hex_id].get('last_seen', ''):
                            merged[hex_id]['last_seen'] = rec['last_seen']
                            for field in ['alt_baro','gs','track','r_dst','r_dir','baro_rate',
                                         'rssi','squawk','emergency','category','flight',
                                         'make','model','owner','n_number']:
                                if field in rec:
                                    merged[hex_id][field] = rec[field]
            self.send_json(merged)

        elif path == '/status':
            available = get_available_dates()
            data_size = get_data_size()
            disk_total, disk_used, disk_free = shutil.disk_usage('/')
            faa_path = '/home/pi/adsb-analyzer/faa/hex_lookup.json'
            faa_ready = os.path.exists(faa_path)
            faa_age_days = None
            faa_updated = None
            if faa_ready:
                import time as _time
                mtime = os.path.getmtime(faa_path)
                faa_age_days = int((_time.time() - mtime) / 86400)
                from datetime import datetime as _dt
                faa_updated = _dt.fromtimestamp(mtime).strftime('%Y-%m-%d')
            self.send_json({
                'data_size_bytes': data_size,
                'max_bytes': MAX_STORAGE_BYTES,
                'disk_total': disk_total,
                'disk_used': disk_used,
                'disk_free': disk_free,
                'available_dates': available,
                'oldest_date': available[0] if available else None,
                'newest_date': available[-1] if available else None,
                'days_stored': len(available),
                'faa_ready': faa_ready,
                'faa_age_days': faa_age_days,
                'faa_updated': faa_updated,
            })

        elif path == '/ksea':
            ksea_log = '/home/pi/adsb-analyzer/data/ksea_config.json'
            try:
                with open(ksea_log, 'r') as f:
                    self.send_json(json.load(f))
            except:
                self.send_json([])

        elif path == '/ksea/csv':
            ksea_log = '/home/pi/adsb-analyzer/data/ksea_config.json'
            try:
                with open(ksea_log, 'r') as f:
                    entries = json.load(f)
                cols = ['timestamp','config','config_changed','aircraft_sampled',
                        'wind_dir','wind_spd','wind_gust','visibility','ceiling',
                        'altimeter','temp','dewpoint','wx','metar_raw']
                lines = [','.join(cols)]
                for e in entries:
                    row = []
                    for c in cols:
                        v = e.get(c, '')
                        if v is None:
                            v = ''
                        # Always quote wx and metar_raw to prevent Excel formula interpretation
                        if c in ('wx', 'metar_raw') or (isinstance(v, str) and (',' in v or v.startswith('-') or v.startswith('+'))):
                            v = '"' + str(v).replace('"', '""') + '"'
                        else:
                            v = str(v)
                        row.append(v)
                    lines.append(','.join(row))
                body = '\n'.join(lines).encode()
                self.send_response(200)
                self.send_header('Content-Type', 'text/csv')
                self.send_header('Content-Disposition', 'attachment; filename="ksea_config.csv"')
                self.send_header('Access-Control-Allow-Origin', '*')
                self.send_header('Content-Length', len(body))
                self.end_headers()
                self.wfile.write(body)
            except Exception as e:
                self.send_json({'error': str(e)}, 500)

        elif path == '/version':
            vf = '/home/pi/adsb-analyzer/version.json'
            try:
                with open(vf, 'r') as f:
                    self.send_json(json.load(f))
            except:
                self.send_json({'version': '?', 'released': '?'})

        elif path == '/changelog':
            cf = '/home/pi/adsb-analyzer/CHANGELOG.md'
            try:
                with open(cf, 'r') as f:
                    content = f.read()
                body = content.encode()
                self.send_response(200)
                self.send_header('Content-Type', 'text/plain; charset=utf-8')
                self.send_header('Access-Control-Allow-Origin', '*')
                self.send_header('Content-Length', len(body))
                self.end_headers()
                self.wfile.write(body)
            except:
                self.send_json({'error': 'changelog not found'}, 404)

        else:
            super().do_GET()

    def log_message(self, format, *args):
        pass

if __name__ == '__main__':
    os.chdir('/home/pi/adsb-analyzer')
    print('[server] ADSB Web Server v2 running on port 8080...')
    server = http.server.ThreadingHTTPServer(('', 8080), Handler)
    server.serve_forever()
