from pathlib import Path

from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import FileResponse, HTMLResponse, Response

from src.frontend_bundle import build_frontend
from src.compression import _quality

router = APIRouter()
DASHBOARD_FILE = Path(__file__).resolve().parent.parent / "frontend" / "index.html"
MANIFEST_FILE = DASHBOARD_FILE.parent / "manifest.webmanifest"
FRONTEND_BUILD = build_frontend(DASHBOARD_FILE.parent)

LOGIN_HTML = """<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Sign in · Stackchain Dashboard</title>
<style>body{margin:0;background:#07111f;color:#eef6ff;font:16px system-ui;display:grid;min-height:100vh;place-items:center}main{box-sizing:border-box;width:min(90vw,24rem);padding:2rem;border:1px solid #29415d;border-radius:1rem;background:#0d1b2b}label,input,button{display:block;width:100%;box-sizing:border-box}input,button{min-height:48px;margin-top:.6rem;border-radius:.6rem;border:1px solid #49647f;padding:.75rem}button{margin-top:1rem;background:#55d6be;color:#06121b;font-weight:700}p{color:#a9bed3}</style></head>
<body><main><h1>Operator sign in</h1><p>Use an enrolled passkey, or enter the dashboard access token for bootstrap and recovery. The token is exchanged for a private, short-lived session and is never stored on this device.</p>
<form id="sign-in"><label>Device name<input name="device_label" type="text" autocomplete="name" maxlength="64" value="This device" required></label><button id="passkey-sign-in" type="button">Sign in with a passkey</button><p>Recovery</p><label>Access token<input name="access_token" type="password" autocomplete="current-password" required></label><button id="submit-sign-in">Sign in with access token</button><p id="status" role="status" aria-live="polite"></p></form></main>
<script src="static/private-data-registry.js"></script><script src="static/private-device-data.js"></script><script src="static/login.js"></script></body></html>"""


class RevalidatingHTMLResponse(HTMLResponse):
    def __init__(self, content, status_code=200, headers=None, media_type=None, background=None):
        response_headers = dict(headers or {})
        response_headers["Cache-Control"] = "no-cache"
        super().__init__(content, status_code, response_headers, media_type, background)


@router.get("/", response_class=RevalidatingHTMLResponse)
async def dashboard() -> str:
    return FRONTEND_BUILD.dashboard_html


@router.get("/login", response_class=RevalidatingHTMLResponse)
async def login() -> str:
    return LOGIN_HTML


@router.get("/manifest.webmanifest", response_class=FileResponse)
async def web_app_manifest() -> FileResponse:
    return FileResponse(MANIFEST_FILE, media_type="application/manifest+json")


@router.get("/service-worker.js")
async def service_worker() -> Response:
    return Response(
        FRONTEND_BUILD.service_worker_source,
        media_type="application/javascript",
        headers={"Service-Worker-Allowed": "/", "Cache-Control": "no-cache"},
    )


@router.get("/runtime-{digest}.js")
async def runtime_bundle(digest: str, request: Request) -> Response:
    if digest != FRONTEND_BUILD.runtime_digest:
        raise HTTPException(status_code=404, detail="Runtime revision not found")
    accepts_gzip = _quality(request.headers.get("Accept-Encoding", ""), "gzip") > 0
    return Response(
        (
            FRONTEND_BUILD.runtime_gzip_bytes
            if accepts_gzip
            else FRONTEND_BUILD.runtime_bytes
        ),
        media_type="application/javascript",
        headers={
            "Cache-Control": "public, max-age=31536000, immutable",
            "Vary": "Accept-Encoding",
            **({"Content-Encoding": "gzip"} if accepts_gzip else {}),
        },
    )


@router.get("/feature-{name}-{digest}.js")
async def feature_bundle(name: str, digest: str, request: Request) -> Response:
    bundle = FRONTEND_BUILD.feature_bundles.get(name)
    if bundle is None or digest != bundle.runtime_digest:
        raise HTTPException(status_code=404, detail="Feature revision not found")
    accepts_gzip = _quality(request.headers.get("Accept-Encoding", ""), "gzip") > 0
    return Response(
        bundle.runtime_gzip_bytes if accepts_gzip else bundle.runtime_bytes,
        media_type="application/javascript",
        headers={
            "Cache-Control": "public, max-age=31536000, immutable",
            "Vary": "Accept-Encoding",
            **({"Content-Encoding": "gzip"} if accepts_gzip else {}),
        },
    )
