"""FastAPI 中控许可中间件与 /license 页。"""

from __future__ import annotations

import os
from pathlib import Path

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse

from lib.license.license_lib import (
    get_device_id,
    get_license_status,
    is_license_valid,
    redeem_code,
    validate_license,
)

_TEMPLATE_PATH = Path(__file__).resolve().parent / "templates" / "license.html"


def _allowed_path(path: str) -> bool:
    if path in (
        "/license",
        "/api/license/status",
        "/api/license/redeem",
        "/api/license/validate",
        "/health",
    ):
        return True
    if path.startswith("/assets/") or path.startswith("/static/"):
        return True
    if path.startswith("/favicon"):
        return True
    return False


def install_license_middleware(app: FastAPI) -> None:
    @app.get("/health")
    async def _license_health():
        st = get_license_status(skip_remote=True)
        return {"ok": True, "license_valid": bool(st.get("valid")), "service": "manual_trading_hub"}

    @app.get("/api/license/status")
    async def _license_status_api():
        return get_license_status()

    @app.post("/api/license/redeem")
    async def _license_redeem_api(request: Request):
        try:
            data = await request.json()
        except Exception:
            data = {}
        if not isinstance(data, dict):
            data = {}
        code = str(data.get("code") or "").strip()
        ckey = str(data.get("client_api_key") or "").strip()
        return redeem_code(code, client_api_key=ckey or None)

    @app.post("/api/license/validate")
    async def _license_validate_api():
        return validate_license(force=True)

    @app.api_route("/license", methods=["GET", "POST"])
    async def _license_page(request: Request):
        msg = ""
        err = ""
        if request.method == "POST":
            form = await request.form()
            code = str(form.get("code") or "").strip()
            ckey = str(form.get("client_api_key") or "").strip()
            result = redeem_code(code, client_api_key=ckey or None)
            if result.get("ok"):
                msg = result.get("message") or "激活成功"
            else:
                err = result.get("message") or "激活失败"
        status = get_license_status()
        html = _TEMPLATE_PATH.read_text(encoding="utf-8")
        # 简单替换，避免 Jinja 依赖差异
        filled = (
            html.replace("{{ device_id }}", get_device_id())
            .replace("{{ api_url }}", str(status.get("api_url") or ""))
            .replace("{{ wechat }}", "dekun03")
            .replace("{{ message }}", msg)
            .replace("{{ error }}", err)
            .replace("{{ status_message }}", str(status.get("message") or ""))
            .replace("{{ expires_at }}", str(status.get("expires_at") or "—"))
            .replace("{{ plan }}", str(status.get("plan") or "—"))
            .replace("{{ valid_text }}", "已授权" if status.get("valid") else "未授权")
        )
        # Flask 模板用 Jinja；FastAPI 路径用占位符版本
        if "{%" in filled or "{{" in filled:
            from jinja2 import Template

            filled = Template(html).render(
                device_id=get_device_id(),
                status=status,
                message=msg,
                error=err,
                api_url=status.get("api_url") or "",
                wechat="dekun03",
            )
        return HTMLResponse(filled)

    @app.middleware("http")
    async def _license_http_middleware(request: Request, call_next):
        if os.getenv("LICENSE_DISABLED", "").strip().lower() in ("1", "true", "yes", "on"):
            return await call_next(request)
        path = request.url.path or "/"
        if _allowed_path(path):
            return await call_next(request)
        if is_license_valid():
            return await call_next(request)
        if path.startswith("/api/"):
            return JSONResponse(
                {"ok": False, "error": "license_required", "message": "请先激活许可"},
                status_code=403,
            )
        return RedirectResponse(url="/license", status_code=302)
