"""
File serving endpoint for desktop chat.

Allows the desktop frontend to access workspace files (images, documents, etc.)
generated by agent tools like deliver_artifacts, generate_image, etc.

Security: Only serves files under the current workspace directory.
"""

import logging
import mimetypes
from pathlib import Path

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

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/files", tags=["files"])


def _get_workspace_root(request: Request) -> Path:
    """Get the workspace root directory from the running agent."""
    agent = getattr(request.app.state, "agent", None)

    if agent is not None:
        # Try to get workspace_dir from agent
        ws_dir = getattr(agent, "workspace_dir", None) or getattr(agent, "_workspace_dir", None)
        if ws_dir:
            return Path(ws_dir)

    # Fallback: try settings
    try:
        from openakita.core.settings import settings
        if settings.workspace_dir:
            return Path(settings.workspace_dir)
    except Exception:
        pass

    # Last resort: current working directory
    return Path.cwd()


@router.get("")
async def serve_file(request: Request, path: str = ""):
    """
    Serve a file from the workspace directory.

    Query parameter `path` can be relative to workspace root or absolute.
    Example: /api/files?path=data/temp/image.png
    Example: /api/files?path=D:/coder/myagent/data/temp/image.png
    """
    if not path:
        raise HTTPException(status_code=400, detail="Missing 'path' parameter")

    workspace = _get_workspace_root(request)

    # Handle both relative and absolute paths
    requested = Path(path)
    full_path = requested if requested.is_absolute() else workspace / path

    # Resolve to prevent path traversal
    try:
        full_path = full_path.resolve()
    except (OSError, ValueError):
        raise HTTPException(status_code=400, detail="Invalid path")

    # Security: ensure the file is under workspace OR under known safe directories
    # (e.g. user home, temp dirs used by agent tools)
    # Use Path.is_relative_to() instead of string prefix matching to avoid
    # false positives (e.g. /home/user matching /home/user_docs) and
    # case-sensitivity issues on Windows.
    workspace_resolved = workspace.resolve()
    safe_roots = [
        workspace_resolved,
        Path.home().resolve(),  # Allow files from user home (Downloads, etc.)
    ]

    is_safe = any(
        full_path.is_relative_to(root) for root in safe_roots
    )
    if not is_safe:
        raise HTTPException(status_code=403, detail="Access denied: path outside allowed directories")

    if not full_path.exists() or not full_path.is_file():
        raise HTTPException(status_code=404, detail=f"File not found: {path}")

    # Determine content type
    content_type, _ = mimetypes.guess_type(str(full_path))
    if not content_type:
        content_type = "application/octet-stream"

    return FileResponse(
        path=str(full_path),
        media_type=content_type,
        filename=full_path.name,
    )
