"""µFrame compile, DSL metadata, and image upload endpoints."""

import os
from pathlib import Path

from fastapi import APIRouter, HTTPException, UploadFile, File
from pydantic import BaseModel

import uframe
import uframe.keywords  # noqa: F401 — triggers keyword registration
from uframe.errors import UFrameError
from uframe.registry import get_dsl_meta

router = APIRouter()

UPLOAD_DIR = Path(os.environ.get("SOURCES_DIR", "/data/sources")) / "images"


class CompileRequest(BaseModel):
    source: str
    width: int = 64


class CompileResponse(BaseModel):
    ascii: str
    micron: str
    script: str
    is_dynamic: bool
    warnings: list[str]


@router.post("/compile", response_model=CompileResponse)
async def compile_source(req: CompileRequest):
    """Compile µFrame .uf source into ASCII and Micron output."""
    try:
        result = uframe.compile(req.source, width=req.width)
        return CompileResponse(
            ascii=result.ascii,
            micron=result.micron,
            script=result.script,
            is_dynamic=result.is_dynamic,
            warnings=[w.message for w in result.warnings],
        )
    except UFrameError as e:
        raise HTTPException(status_code=422, detail=str(e))


@router.get("/dsl-meta")
async def dsl_meta():
    """Return DSL metadata for frontend syntax highlighting and autocomplete."""
    return get_dsl_meta()


@router.post("/upload-image")
async def upload_image(file: UploadFile = File(...)):
    """Upload an image for use in .uf pages."""
    UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
    # Sanitize filename
    name = file.filename or "upload.png"
    safe_name = "".join(c for c in name if c.isalnum() or c in "._-").rstrip(".")
    if not safe_name:
        safe_name = "upload.png"
    dest = UPLOAD_DIR / safe_name
    content = await file.read()
    dest.write_bytes(content)
    # Return the path relative to backend working directory
    rel_path = str(dest)
    return {"path": rel_path, "filename": safe_name, "size": len(content)}


@router.get("/images")
async def list_images():
    """List uploaded images available for embedding."""
    if not UPLOAD_DIR.is_dir():
        return []
    images = []
    for f in sorted(UPLOAD_DIR.iterdir()):
        if f.suffix.lower() in (".png", ".jpg", ".jpeg", ".bmp", ".webp", ".gif"):
            images.append({
                "filename": f.name,
                "path": str(f),
                "size": f.stat().st_size,
            })
    return images
