"""Files router — directory listing, ffprobe, stat, path resolution.""" from __future__ import annotations import json import logging from typing import Any from fastapi import APIRouter, Depends, HTTPException, Query from media_library_viewer_api.clients.ssh import RemoteSSHClient from media_library_viewer_api.config import get_settings from media_library_viewer_api.dependencies import get_ssh_client from media_library_viewer_api.path_utils import resolve_remote_media_path logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/files", tags=["files"]) @router.get("/list") def list_directory( path: str = Query(..., description="Remote directory path to list"), ssh: RemoteSSHClient = Depends(get_ssh_client), ) -> dict[str, Any]: """List a remote directory.""" result = ssh.list_dir(path) if result.exit_status != 0: logger.warning("Files list failed path=%s exit_status=%s", path, result.exit_status) raise HTTPException(status_code=400, detail=result.stderr or result.stdout or "Failed to list directory") entries = json.loads(result.stdout) logger.info("Files list path=%s entries=%s", path, len(entries)) return { "path": path, "entries": entries, "count": len(entries), } @router.get("/ffprobe") def get_ffprobe( path: str = Query(..., description="Remote file path to probe"), ssh: RemoteSSHClient = Depends(get_ssh_client), ) -> dict[str, Any]: """Run ffprobe on a remote file and return parsed JSON.""" try: data = ssh.ffprobe_json(path) except RuntimeError as exc: logger.warning("Files ffprobe failed path=%s error=%s", path, exc) raise HTTPException(status_code=400, detail=str(exc)) logger.info("Files ffprobe path=%s", path) return data @router.get("/stat") def get_stat( path: str = Query(..., description="Remote path to stat"), ssh: RemoteSSHClient = Depends(get_ssh_client), ) -> dict[str, str]: """Run stat on a remote path.""" result = ssh.stat_path(path) if result.exit_status != 0: logger.warning("Files stat failed path=%s exit_status=%s", path, result.exit_status) raise HTTPException(status_code=400, detail=result.stderr or result.stdout or "stat failed") logger.info("Files stat path=%s", path) return {"path": path, "output": result.stdout} @router.get("/resolve-path") def resolve_path( path: str = Query(..., description="Jellyfin path to resolve to SSH path"), ) -> dict[str, str]: """Resolve a Jellyfin path to its SSH-visible equivalent.""" settings = get_settings() resolved = resolve_remote_media_path(path, settings.media_root, settings.path_prefix) logger.info("Files resolve path original=%s resolved=%s", path, resolved) return {"original": path, "resolved": resolved}