"""Asset routes: CRUD, file upload/download, prebuilt restore."""

from pathlib import Path

from fastapi import APIRouter, Depends, File, HTTPException, Query, UploadFile
from fastapi.responses import FileResponse

from wled_controller.api.auth import AuthRequired
from wled_controller.api.dependencies import fire_entity_event, get_asset_store
from wled_controller.api.schemas.assets import (
    AssetListResponse,
    AssetResponse,
    AssetUpdate,
)
from wled_controller.config import get_config
from wled_controller.storage.asset_store import AssetStore
from wled_controller.storage.base_store import EntityNotFoundError
from wled_controller.utils import get_logger

logger = get_logger(__name__)

router = APIRouter()

# Prebuilt sounds directory (shipped with the app)
_PREBUILT_SOUNDS_DIR = Path(__file__).resolve().parents[2] / "data" / "prebuilt_sounds"


def _asset_to_response(asset) -> AssetResponse:
    d = asset.to_dict()
    return AssetResponse(**d)


# ---------------------------------------------------------------------------
# CRUD
# ---------------------------------------------------------------------------


@router.get(
    "/api/v1/assets",
    response_model=AssetListResponse,
    tags=["Assets"],
)
async def list_assets(
    _: AuthRequired,
    asset_type: str | None = Query(None, description="Filter by type: sound, image, video, other"),
    store: AssetStore = Depends(get_asset_store),
):
    """List all assets, optionally filtered by type."""
    if asset_type:
        assets = store.get_assets_by_type(asset_type)
    else:
        assets = store.get_visible_assets()
    return AssetListResponse(
        assets=[_asset_to_response(a) for a in assets],
        count=len(assets),
    )


@router.get(
    "/api/v1/assets/{asset_id}",
    response_model=AssetResponse,
    tags=["Assets"],
)
async def get_asset(
    asset_id: str,
    _: AuthRequired,
    store: AssetStore = Depends(get_asset_store),
):
    """Get asset metadata by ID."""
    try:
        asset = store.get_asset(asset_id)
    except EntityNotFoundError:
        raise HTTPException(status_code=404, detail=f"Asset not found: {asset_id}")
    if asset.deleted:
        raise HTTPException(status_code=404, detail=f"Asset not found: {asset_id}")
    return _asset_to_response(asset)


@router.post(
    "/api/v1/assets",
    response_model=AssetResponse,
    status_code=201,
    tags=["Assets"],
)
async def upload_asset(
    _: AuthRequired,
    file: UploadFile = File(...),
    name: str | None = Query(None, description="Display name (defaults to filename)"),
    description: str | None = Query(None, description="Optional description"),
    store: AssetStore = Depends(get_asset_store),
):
    """Upload a new asset file."""
    config = get_config()
    max_size = getattr(getattr(config, "assets", None), "max_file_size_mb", 50) * 1024 * 1024

    data = await file.read()
    if len(data) > max_size:
        raise HTTPException(
            status_code=400,
            detail=f"File too large (max {max_size // (1024 * 1024)} MB)",
        )

    if not data:
        raise HTTPException(status_code=400, detail="Empty file")

    display_name = name or Path(file.filename or "unnamed").stem.replace("_", " ").replace("-", " ").title()

    try:
        asset = store.create_asset(
            name=display_name,
            filename=file.filename or "unnamed",
            file_data=data,
            mime_type=file.content_type,
            description=description,
        )
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))

    fire_entity_event("asset", "created", asset.id)
    return _asset_to_response(asset)


@router.put(
    "/api/v1/assets/{asset_id}",
    response_model=AssetResponse,
    tags=["Assets"],
)
async def update_asset(
    asset_id: str,
    body: AssetUpdate,
    _: AuthRequired,
    store: AssetStore = Depends(get_asset_store),
):
    """Update asset metadata."""
    try:
        asset = store.update_asset(
            asset_id,
            name=body.name,
            description=body.description,
            tags=body.tags,
        )
    except EntityNotFoundError:
        raise HTTPException(status_code=404, detail=f"Asset not found: {asset_id}")
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))

    fire_entity_event("asset", "updated", asset.id)
    return _asset_to_response(asset)


@router.delete(
    "/api/v1/assets/{asset_id}",
    tags=["Assets"],
)
async def delete_asset(
    asset_id: str,
    _: AuthRequired,
    store: AssetStore = Depends(get_asset_store),
):
    """Delete an asset. Prebuilt assets are soft-deleted and can be restored."""
    try:
        asset = store.get_asset(asset_id)
    except EntityNotFoundError:
        raise HTTPException(status_code=404, detail=f"Asset not found: {asset_id}")

    store.delete_asset(asset_id)
    fire_entity_event("asset", "deleted", asset_id)

    return {
        "status": "deleted",
        "id": asset_id,
        "restorable": asset.prebuilt,
    }


# ---------------------------------------------------------------------------
# File serving
# ---------------------------------------------------------------------------


@router.get(
    "/api/v1/assets/{asset_id}/file",
    tags=["Assets"],
)
async def serve_asset_file(
    asset_id: str,
    _: AuthRequired,
    store: AssetStore = Depends(get_asset_store),
):
    """Serve the actual asset file for playback/display."""
    file_path = store.get_file_path(asset_id)
    if file_path is None:
        raise HTTPException(status_code=404, detail=f"Asset file not found: {asset_id}")

    try:
        asset = store.get_asset(asset_id)
    except EntityNotFoundError:
        raise HTTPException(status_code=404, detail=f"Asset not found: {asset_id}")

    return FileResponse(
        path=str(file_path),
        media_type=asset.mime_type,
        filename=asset.filename,
    )


# ---------------------------------------------------------------------------
# Prebuilt restore
# ---------------------------------------------------------------------------


@router.post(
    "/api/v1/assets/restore-prebuilt",
    tags=["Assets"],
)
async def restore_prebuilt_assets(
    _: AuthRequired,
    store: AssetStore = Depends(get_asset_store),
):
    """Re-import any deleted prebuilt assets."""
    restored = store.restore_prebuilt(_PREBUILT_SOUNDS_DIR)
    return {
        "status": "ok",
        "restored_count": len(restored),
        "restored": [_asset_to_response(a) for a in restored],
    }
