#!/usr/bin/env python3
"""
Local review server for High Orbit translation review.
Run:  python server.py
Open: http://localhost:8765/review.html
"""
import http.server
import json
import os
import subprocess
import sys
import glob
from datetime import datetime
from pathlib import Path
from urllib.parse import urlparse, parse_qs

BASE_DIR       = Path(__file__).parent
APPROVALS_FILE = BASE_DIR / "approvals.json"
COMMENTS_FILE  = BASE_DIR / "comments.json"
CARDS_FILE     = BASE_DIR / "translations" / "cards.json"
CORPS_FILE     = BASE_DIR / "translations" / "corps.json"
PORT           = 8765


def load():
    if APPROVALS_FILE.exists():
        return json.loads(APPROVALS_FILE.read_text(encoding="utf-8"))
    return {}


def save(data):
    APPROVALS_FILE.write_text(
        json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8"
    )


def load_comments():
    if COMMENTS_FILE.exists():
        return json.loads(COMMENTS_FILE.read_text(encoding="utf-8"))
    return {}


def save_comments(data):
    COMMENTS_FILE.write_text(
        json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8"
    )


class Handler(http.server.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, directory=str(BASE_DIR), **kwargs)

    # ------------------------------------------------------------------ helpers
    def send_json(self, obj, status=200):
        body = json.dumps(obj, ensure_ascii=False).encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", "application/json; charset=utf-8")
        self.send_header("Content-Length", str(len(body)))
        self.send_header("Cache-Control", "no-cache")
        self.end_headers()
        self.wfile.write(body)

    def read_json(self):
        n = int(self.headers.get("Content-Length", 0))
        return json.loads(self.rfile.read(n).decode("utf-8"))

    def send_png(self, data):
        self.send_response(200)
        self.send_header("Content-Type", "image/png")
        self.send_header("Content-Length", str(len(data)))
        self.send_header("Cache-Control", "no-cache")
        self.end_headers()
        self.wfile.write(data)

    def send_404(self, msg="Not found"):
        body = msg.encode("utf-8")
        self.send_response(404)
        self.send_header("Content-Type", "text/plain; charset=utf-8")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    # ------------------------------------------------------------------ GET
    def do_GET(self):
        if self.path == "/api/approvals":
            self.send_json(load())
        elif self.path == "/api/comments":
            self.send_json(load_comments())
        elif self.path == "/api/cards":
            self.send_json(json.loads(CARDS_FILE.read_text(encoding="utf-8")))
        elif self.path == "/api/corps":
            self.send_json(json.loads(CORPS_FILE.read_text(encoding="utf-8")))
        elif self.path.startswith("/api/overlay"):
            self._handle_overlay()
        else:
            super().do_GET()

    def _handle_overlay(self):
        parsed = urlparse(self.path)
        qs = parse_qs(parsed.query)
        card_type = qs.get("type", ["card"])[0]
        name_parts = qs.get("name", [])
        if not name_parts:
            self.send_404("Missing 'name' parameter")
            return
        name = name_parts[0]

        if card_type == "corp":
            self._overlay_corp(name)
        else:
            self._overlay_card(name)

    def _overlay_card(self, name):
        """Run apply_translations.py --card NAME and serve the first output PNG."""
        script = BASE_DIR / "scripts" / "apply_translations.py"
        result = subprocess.run(
            [sys.executable, str(script), "--card", name],
            capture_output=True,
            cwd=str(BASE_DIR),
        )
        if result.returncode != 0:
            self.send_404(f"apply_translations failed: {result.stderr.decode('utf-8', errors='replace')[:400]}")
            return

        # Find the first output file matching this card name
        out_dir = BASE_DIR / "output" / "cards"
        pattern = str(out_dir / f"* {name} 1.png")
        matches = sorted(glob.glob(pattern))
        if not matches:
            self.send_404(f"Output file not found for card: {name}")
            return

        self.send_png(Path(matches[0]).read_bytes())

    def _overlay_corp(self, name):
        """Run apply_corp_translations.py --card NAME and serve the output PNG."""
        script = BASE_DIR / "scripts" / "apply_corp_translations.py"
        result = subprocess.run(
            [sys.executable, str(script), "--card", name],
            capture_output=True,
            cwd=str(BASE_DIR),
        )
        if result.returncode != 0:
            self.send_404(f"apply_corp_translations failed: {result.stderr.decode('utf-8', errors='replace')[:400]}")
            return

        # Determine output filename from corps.json
        try:
            corps_data = json.loads(CORPS_FILE.read_text(encoding="utf-8"))
        except Exception:
            self.send_404("Could not read corps.json")
            return

        # Find matching corp (case-insensitive)
        corp_entry = None
        for k, v in corps_data.items():
            if k.lower() == name.lower():
                corp_entry = v
                break
        if corp_entry is None or not corp_entry.get("file"):
            self.send_404(f"Corp not found in corps.json: {name}")
            return

        out_path = BASE_DIR / "output" / "corps" / corp_entry["file"]
        if not out_path.exists():
            self.send_404(f"Output file not found: {out_path.name}")
            return

        self.send_png(out_path.read_bytes())

    # ------------------------------------------------------------------ POST
    def do_POST(self):
        if self.path == "/api/approve":
            body = self.read_json()
            data = load()
            data[body["id"]] = {
                "label":       body.get("label", ""),
                "text":        body["text"],
                "edited":      body.get("edited", False),
                "status":      "approved",
                "approved_at": datetime.now().isoformat(timespec="seconds"),
            }
            save(data)
            self.send_json({"ok": True})

        elif self.path == "/api/unapprove":
            body = self.read_json()
            data = load()
            data.pop(body["id"], None)
            save(data)
            self.send_json({"ok": True})

        elif self.path == "/api/comment":
            body = self.read_json()
            data = load_comments()
            if body.get("text", "").strip():
                data[body["id"]] = body["text"]
            else:
                data.pop(body["id"], None)
            save_comments(data)
            self.send_json({"ok": True})

        elif self.path == "/api/cards":
            body = self.read_json()
            CARDS_FILE.write_text(
                json.dumps(body, ensure_ascii=False, indent=2), encoding="utf-8"
            )
            self.send_json({"ok": True})

        elif self.path == "/api/corps":
            body = self.read_json()
            CORPS_FILE.write_text(
                json.dumps(body, ensure_ascii=False, indent=2), encoding="utf-8"
            )
            self.send_json({"ok": True})

        elif self.path == "/api/save-translation":
            body  = self.read_json()
            kind  = body.get("type")        # "card" or "corp"
            name  = body.get("name", "")
            field = body.get("field", "")
            text  = body.get("text", "")
            if kind == "card":
                data = json.loads(CARDS_FILE.read_text(encoding="utf-8"))
                if name in data and field in data[name]:
                    data[name][field] = text
                    CARDS_FILE.write_text(
                        json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8"
                    )
                    self.send_json({"ok": True})
                else:
                    self.send_json({"ok": False, "error": f"Card '{name}' or field '{field}' not found"}, 404)
            elif kind == "corp":
                data = json.loads(CORPS_FILE.read_text(encoding="utf-8"))
                if name in data and field in data[name]:
                    data[name][field] = text
                    CORPS_FILE.write_text(
                        json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8"
                    )
                    self.send_json({"ok": True})
                else:
                    self.send_json({"ok": False, "error": f"Corp '{name}' or field '{field}' not found"}, 404)
            else:
                self.send_json({"ok": False, "error": "Invalid type"}, 400)

        else:
            self.send_response(404)
            self.end_headers()

    def log_message(self, fmt, *args):
        pass   # silence request log


if __name__ == "__main__":
    save(load())   # ensure file exists
    print(f"  Review server:  http://localhost:{PORT}/review.html")
    print(f"  Approvals file: {APPROVALS_FILE}")
    print(f"  Ctrl+C to stop.\n")
    with http.server.HTTPServer(("0.0.0.0", PORT), Handler) as srv:
        srv.serve_forever()
