"""PRIMCS MCP server entry-point.

Run with:
    python -m server.main

Starts an MCP stdio server exposing the `run_code` tool.
"""

import logging
import os
from pathlib import Path

from fastmcp import FastMCP
from starlette.requests import Request
from starlette.responses import FileResponse, Response

from server.config import TMP_DIR
from server.prompts import python_programmer as python_programmer_prompt
from server.tools import mount_file as mount_file_tool
from server.tools import persist_artifact as persist_artifact_tool
from server.tools import run_code as run_code_tool
from server.tools import workspace_inspect as workspace_inspect_tool

logger = logging.getLogger(__name__)

# Expose a globally named `mcp` so the FastMCP CLI can auto-discover it.
mcp = FastMCP(name="primcs", version="0.1.0")
run_code_tool.register(mcp)
persist_artifact_tool.register(mcp)
workspace_inspect_tool.register(mcp)
mount_file_tool.register(mcp)
python_programmer_prompt.register(mcp)


@mcp.custom_route("/artifacts/{relative_path:path}", methods=["GET"])
async def get_artifact(request: Request) -> Response:
    """
    Serve an artifact file for the current session. The client must include
    the session ID in the "mcp-session-id" header. The URL path is the
    relative path returned by the tool (e.g. "plots/plot.png"), which is
    resolved under session_<id>/output/.
    """
    relative_path = request.path_params["relative_path"]
    relative_path = os.path.normpath(relative_path)
    path_obj = Path(relative_path)
    if relative_path.startswith("..") or path_obj.is_absolute():
        return Response("Invalid artifact path", status_code=400)

    session_id = request.headers.get("mcp-session-id")
    if not session_id:
        return Response("Missing mcp-session-id header", status_code=400)

    base_dir = TMP_DIR / f"session_{session_id}" / "output"
    file_path = base_dir / relative_path

    try:
        file_path = file_path.resolve(strict=True)
    except FileNotFoundError:
        return Response("File not found", status_code=404)

    # Ensure file is within the output directory
    if not str(file_path).startswith(str(base_dir.resolve())):
        return Response("Forbidden", status_code=403)
    if not file_path.is_file():
        return Response("Not a file", status_code=404)

    return FileResponse(str(file_path), filename=file_path.name)


if __name__ == "__main__":  # pragma: no cover
    port = int(os.getenv("PORT", "9000"))
    # Start the server with stdio transport by default
    transport = os.getenv("TRANSPORT", "stdio")
    if transport == "http":
        mcp.run(transport="streamable-http", host="0.0.0.0", port=port)
    else:
        mcp.run(transport="stdio")