"""Serves the built Vue SPA from frontend/dist/ with history-mode fallback,
the on-disk image library + thumbnails from /images, and the signed
Firefox extension XPI from frontend/dist/extension/.
"""

import re
from pathlib import Path

from quart import Blueprint, abort, send_file, send_from_directory

FRONTEND_DIST = Path(__file__).resolve().parent.parent.parent / "frontend" / "dist"
IMAGES_ROOT = Path("/images")
XPI_DIR = FRONTEND_DIST / "extension"

_XPI_NAME_RE = re.compile(r"^fabledcurator-[\w.-]+\.xpi$")

frontend_bp = Blueprint("frontend", __name__)


@frontend_bp.route("/images/<path:subpath>")
async def serve_image(subpath: str):
    """Serve a file from the /images volume (originals + thumbnails).

    Without this route the SPA catch-all below would swallow image
    requests and return index.html, leaving the browser to render the
    aspect-ratio-shaped grey placeholder.
    """
    target = (IMAGES_ROOT / subpath).resolve()
    # Defend against path-traversal: refuse anything that escapes /images.
    try:
        target.relative_to(IMAGES_ROOT)
    except ValueError:
        abort(404)
    if not target.is_file():
        abort(404)
    return await send_from_directory(IMAGES_ROOT, subpath)


@frontend_bp.route("/extension/<filename>")
async def serve_extension(filename: str):
    """Serve the signed FC Firefox extension XPI.

    Path whitelist: filename must match fabledcurator-*.xpi. The special
    name fabledcurator-latest.xpi serves the most-recently-modified XPI
    in the directory.

    The application/x-xpinstall MIME tells Firefox to show its native
    install prompt instead of downloading the file as a blob.
    """
    if not _XPI_NAME_RE.fullmatch(filename):
        abort(404)
    if not XPI_DIR.is_dir():
        abort(404)
    if filename == "fabledcurator-latest.xpi":
        xpis = sorted(XPI_DIR.glob("fabledcurator-*.xpi"), key=lambda p: p.stat().st_mtime)
        if not xpis:
            abort(404)
        latest = xpis[-1]
        return await send_file(
            latest, mimetype="application/x-xpinstall",
            attachment_filename=latest.name,
        )
    target = (XPI_DIR / filename).resolve()
    try:
        target.relative_to(XPI_DIR)
    except ValueError:
        abort(404)
    if not target.is_file():
        abort(404)
    return await send_file(
        target, mimetype="application/x-xpinstall",
        attachment_filename=filename,
    )


@frontend_bp.route("/")
@frontend_bp.route("/<path:subpath>")
async def serve_spa(subpath: str = ""):
    if subpath and (FRONTEND_DIST / subpath).is_file():
        return await send_from_directory(FRONTEND_DIST, subpath)
    return await send_from_directory(FRONTEND_DIST, "index.html")
