#!/usr/bin/env python3
"""
Serveur HTTP pour l'interface de débogage 3 volets.

Port 8888 :
  GET /              → page HTML 3 volets
  GET /serial        → SSE (Server-Sent Events) du port série QEMU
  GET /api/*         → proxy transparent vers le webserver ESP32 (port 10080)
  POST /api/*        → idem
"""
import http.server
import socketserver
import time
import urllib.request
import urllib.error
from urllib.parse import urlparse

ESP_URL   = 'http://127.0.0.1:10080'
SERIAL_LOG = '/tmp/serial.log'
PORT       = 8888


class Handler(http.server.BaseHTTPRequestHandler):

    def do_GET(self):
        if self.path in ('/', '/index.html'):
            self._serve_file('/emulator/ui/index.html', 'text/html; charset=utf-8')

        elif self.path == '/serial':
            self._sse_serial()

        elif self.path.startswith('/api/'):
            self._proxy('GET')

        else:
            self.send_error(404)

    def do_POST(self):
        if self.path.startswith('/api/'):
            self._proxy('POST')
        else:
            self.send_error(404)

    # ------------------------------------------------------------------
    def _serve_file(self, path, content_type):
        try:
            with open(path, 'rb') as f:
                data = f.read()
            self.send_response(200)
            self.send_header('Content-Type', content_type)
            self.send_header('Content-Length', str(len(data)))
            self.end_headers()
            self.wfile.write(data)
        except FileNotFoundError:
            self.send_error(404)

    def _sse_serial(self):
        self.send_response(200)
        self.send_header('Content-Type',  'text/event-stream')
        self.send_header('Cache-Control', 'no-cache')
        self.send_header('Access-Control-Allow-Origin', '*')
        self.end_headers()
        try:
            # Ouvrir le fichier log et se positionner à la fin
            with open(SERIAL_LOG, 'r', errors='replace') as f:
                f.seek(0, 2)
                while True:
                    line = f.readline()
                    if line:
                        msg = line.rstrip().replace('\n', ' ')
                        self.wfile.write(f'data: {msg}\n\n'.encode())
                        self.wfile.flush()
                    else:
                        time.sleep(0.1)
        except (BrokenPipeError, ConnectionResetError):
            pass
        except FileNotFoundError:
            # Log pas encore créé — attendre
            time.sleep(1)

    def _proxy(self, method):
        target = ESP_URL + self.path
        try:
            length = int(self.headers.get('Content-Length', 0))
            body   = self.rfile.read(length) if length else None
            req = urllib.request.Request(target, data=body, method=method)
            if body:
                req.add_header('Content-Type', self.headers.get('Content-Type', 'application/json'))
            with urllib.request.urlopen(req, timeout=3) as resp:
                data = resp.read()
                self.send_response(resp.status)
                self.send_header('Content-Type',  resp.headers.get('Content-Type', 'application/json'))
                self.send_header('Content-Length', str(len(data)))
                self.send_header('Access-Control-Allow-Origin', '*')
                self.end_headers()
                self.wfile.write(data)
        except urllib.error.URLError:
            self.send_response(503)
            self.send_header('Content-Type', 'application/json')
            self.end_headers()
            self.wfile.write(b'{"error":"ESP32 hors ligne"}')

    def log_message(self, *_):
        pass  # supprimer les logs d'accès


if __name__ == '__main__':
    with socketserver.ThreadingTCPServer(('', PORT), Handler) as httpd:
        httpd.allow_reuse_address = True
        print(f'[UI] Interface de débogage sur http://0.0.0.0:{PORT}', flush=True)
        httpd.serve_forever()
