#!/usr/bin/env python3
"""Mini-servidor local de KISUM para integrarlo en Strudel.

Expone un endpoint HTTP que recibe un archivo de audio/video, lo analiza con
kisum.analyze() y devuelve el codigo Strudel en JSON. Pensado para correr en
local (127.0.0.1) junto a Strudel; lo arranca strudel-launcher.sh.

    python3 kisum_server.py            # escucha en 127.0.0.1:3010
    KISUM_PORT=7331 python3 kisum_server.py

Endpoints:
    GET  /health              -> {"ok": true}
    POST /analyze?bars=4&bass=1   (cuerpo = bytes del archivo,
                                   cabecera X-Filename: nombre.mp4)
                              -> {"code": "<codigo strudel>", "filename": ...}
"""

import json
import os
import sys
import tempfile
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from urllib.parse import urlparse, parse_qs

HERE = os.path.dirname(os.path.abspath(__file__))
if HERE not in sys.path:
    sys.path.insert(0, HERE)

# Import pesado (librosa) al arrancar: asi la primera peticion ya es rapida.
import kisum  # noqa: E402

PORT = int(os.environ.get("KISUM_PORT", "3010"))


def _cors(handler):
    handler.send_header("Access-Control-Allow-Origin", "*")
    handler.send_header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
    handler.send_header("Access-Control-Allow-Headers", "Content-Type, X-Filename")


class Handler(BaseHTTPRequestHandler):
    def log_message(self, *a):
        pass  # silencio: el log lo lleva el launcher

    def _json(self, code, obj):
        body = json.dumps(obj, ensure_ascii=False).encode("utf-8")
        self.send_response(code)
        self.send_header("Content-Type", "application/json; charset=utf-8")
        self.send_header("Content-Length", str(len(body)))
        _cors(self)
        self.end_headers()
        self.wfile.write(body)

    def do_OPTIONS(self):
        self.send_response(204)
        _cors(self)
        self.end_headers()

    def do_GET(self):
        path = urlparse(self.path).path
        if path in ("/health", "/"):
            self._json(200, {"ok": True, "service": "kisum"})
        else:
            self._json(404, {"error": "not found"})

    def do_POST(self):
        parsed = urlparse(self.path)
        if parsed.path != "/analyze":
            self._json(404, {"error": "not found"})
            return

        qs = parse_qs(parsed.query)
        try:
            bars = max(1, int(qs.get("bars", ["4"])[0]))
        except ValueError:
            bars = 4
        want_bass = qs.get("bass", ["0"])[0] in ("1", "true", "yes", "on")

        filename = self.headers.get("X-Filename", "audio")
        ext = os.path.splitext(filename)[1] or ".bin"

        length = int(self.headers.get("Content-Length", "0") or 0)
        if length <= 0:
            self._json(400, {"error": "archivo vacio"})
            return
        data = self.rfile.read(length)

        tmp = tempfile.NamedTemporaryFile(suffix=ext, delete=False)
        tmp.write(data)
        tmp.close()
        try:
            code = kisum.analyze(tmp.name, bars, want_bass)
            # el comentario de cabecera lleva la ruta temporal: la cambiamos
            # por el nombre real del archivo que subio el usuario
            code = code.replace(tmp.name, filename)
            self._json(200, {"code": code, "filename": filename})
        except SystemExit as e:
            # kisum.analyze() hace sys.exit(msg) cuando no encuentra pulso, etc.
            msg = str(e.code) if e.code else "no se pudo analizar el audio"
            self._json(422, {"error": msg})
        except Exception as e:  # noqa: BLE001
            self._json(500, {"error": f"{type(e).__name__}: {e}"})
        finally:
            try:
                os.remove(tmp.name)
            except OSError:
                pass


def main():
    srv = ThreadingHTTPServer(("127.0.0.1", PORT), Handler)
    print(f"KISUM server escuchando en http://127.0.0.1:{PORT}", flush=True)
    try:
        srv.serve_forever()
    except KeyboardInterrupt:
        pass


if __name__ == "__main__":
    main()
