#!/usr/bin/env python3
import argparse
import cgi
import json
import os
import re
import time
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from urllib.parse import urlparse

ROOT = Path(__file__).resolve().parent
MENU_FILE = ROOT / "menu-data.json"
UPLOAD_DIR = ROOT / "assets" / "uploads"
MAX_UPLOAD_BYTES = 12 * 1024 * 1024
ALLOWED_EXTENSIONS = {".png", ".jpg", ".jpeg", ".webp", ".gif", ".avif"}


class MenuHandler(SimpleHTTPRequestHandler):
    def translate_path(self, path):
        relative_path = super().translate_path(path)
        return relative_path

    def _send_json(self, status_code, payload):
        body = json.dumps(payload, ensure_ascii=False, indent=2).encode("utf-8")
        self.send_response(status_code)
        self.send_header("Content-Type", "application/json; charset=utf-8")
        self.send_header("Content-Length", str(len(body)))
        self.send_header("Cache-Control", "no-store")
        self.end_headers()
        self.wfile.write(body)

    def _read_menu_file(self):
        if not MENU_FILE.exists():
            return None
        with MENU_FILE.open("r", encoding="utf-8") as handle:
            return json.load(handle)

    def _safe_slug(self, value):
        normalized = re.sub(r"[^a-zA-Z0-9_-]+", "-", str(value or "item")).strip("-").lower()
        return normalized or "item"

    def _infer_extension(self, filename, content_type):
        extension = Path(filename or "").suffix.lower()
        if extension in ALLOWED_EXTENSIONS:
            return extension

        by_type = {
            "image/png": ".png",
            "image/jpeg": ".jpg",
            "image/webp": ".webp",
            "image/gif": ".gif",
            "image/avif": ".avif"
        }
        return by_type.get((content_type or "").lower(), ".webp")

    def _handle_upload(self):
        content_type = self.headers.get("Content-Type", "")
        if "multipart/form-data" not in content_type:
            self._send_json(400, {"error": "Se esperaba multipart/form-data"})
            return

        form = cgi.FieldStorage(
            fp=self.rfile,
            headers=self.headers,
            environ={
                "REQUEST_METHOD": "POST",
                "CONTENT_TYPE": content_type
            }
        )

        if "image" not in form:
            self._send_json(400, {"error": "No se recibió el campo image"})
            return

        image_field = form["image"]
        if isinstance(image_field, list):
            image_field = image_field[0]

        filename = image_field.filename or ""
        if not filename:
            self._send_json(400, {"error": "Archivo de imagen inválido"})
            return

        file_bytes = image_field.file.read()
        if len(file_bytes) <= 0:
            self._send_json(400, {"error": "Archivo vacío"})
            return

        if len(file_bytes) > MAX_UPLOAD_BYTES:
            self._send_json(413, {"error": "El archivo excede el límite de 12 MB"})
            return

        extension = self._infer_extension(filename, getattr(image_field, "type", None))
        item_slug = self._safe_slug(form.getfirst("itemId", "item"))
        stamp = int(time.time() * 1000)
        final_name = f"{item_slug}-{stamp}{extension}"

        UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
        target_path = UPLOAD_DIR / final_name

        with target_path.open("wb") as handle:
            handle.write(file_bytes)

        self._send_json(
            200,
            {
                "uploaded": True,
                "path": f"./assets/uploads/{final_name}",
                "bytes": len(file_bytes)
            }
        )

    def do_GET(self):
        parsed = urlparse(self.path)
        if parsed.path == "/api/health":
            self._send_json(200, {"ok": True, "mode": "file-persistence"})
            return

        if parsed.path == "/api/menu":
            data = self._read_menu_file()
            if data is None:
                self._send_json(404, {"error": "menu-data.json no encontrado"})
                return
            self._send_json(200, data)
            return

        super().do_GET()

    def do_POST(self):
        parsed = urlparse(self.path)
        if parsed.path == "/api/upload":
            self._handle_upload()
            return

        if parsed.path != "/api/menu":
            self._send_json(404, {"error": "Ruta no encontrada"})
            return

        content_length = int(self.headers.get("Content-Length", "0"))
        if content_length <= 0:
            self._send_json(400, {"error": "Body vacío"})
            return

        raw_body = self.rfile.read(content_length)
        try:
            payload = json.loads(raw_body.decode("utf-8"))
        except json.JSONDecodeError:
            self._send_json(400, {"error": "JSON inválido"})
            return

        if not isinstance(payload, dict):
            self._send_json(400, {"error": "El JSON raíz debe ser un objeto"})
            return

        with MENU_FILE.open("w", encoding="utf-8") as handle:
            json.dump(payload, handle, ensure_ascii=False, indent=2)
            handle.write("\n")

        self._send_json(200, {"saved": True, "file": str(MENU_FILE.name)})


def main():
    parser = argparse.ArgumentParser(description="Servidor local para Tita's Brunch & Burger")
    parser.add_argument("--port", type=int, default=int(os.environ.get("PORT", "4173")))
    args = parser.parse_args()

    os.chdir(ROOT)
    server = ThreadingHTTPServer(("0.0.0.0", args.port), MenuHandler)
    print(f"Servidor activo en http://127.0.0.1:{args.port}")
    print("Persistencia de carta en archivo: menu-data.json")
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        pass
    finally:
        server.server_close()


if __name__ == "__main__":
    main()
