"""
MCP server wrapping the CV-matching REST API.
Provides 3 tools: match_cvs, get_match_results, get_match_progress.
"""

from __future__ import annotations

import mimetypes
import os
import sys
from pathlib import Path

import httpx
from mcp.server.fastmcp import FastMCP

# ---------------------------------------------------------------------------
# Config
# ---------------------------------------------------------------------------


class _Config:
    """Holds base_url and api_key read from environment variables."""

    def __init__(self) -> None:
        self.base_url: str = os.environ.get("CV_MATCH_API_URL", "http://localhost:8000")
        api_key: str | None = os.environ.get("CV_MATCH_API_KEY")
        if not api_key:
            raise ValueError("CV_MATCH_API_KEY environment variable is required")
        self.api_key: str = api_key


config = _Config()

# ---------------------------------------------------------------------------
# FastMCP instance
# ---------------------------------------------------------------------------

mcp = FastMCP("cv-matching")

# ---------------------------------------------------------------------------
# Tools
# ---------------------------------------------------------------------------


@mcp.tool()
async def match_cvs(cv_paths: list[str], jd_text: str) -> dict:
    """
    Upload CV files and a job description to the matching API.

    Args:
        cv_paths: List of absolute file paths to CV files (PDF/DOCX).
        jd_text: Job description text.

    Returns:
        API response dict with job_id, status, cv_count, message, skipped_cvs.

    Raises:
        FileNotFoundError: One or more CV files do not exist.
        ValueError: cv_paths is empty or contains more than 10 files.
    """
    if not cv_paths:
        raise ValueError("cv_paths must not be empty")

    if len(cv_paths) > 10:
        raise ValueError("cv_paths must not contain more than 10 files")

    for path in cv_paths:
        if not Path(path).is_file():
            raise FileNotFoundError(f"CV file not found: {path}")

    files = []
    for path in cv_paths:
        filename = Path(path).name
        content = Path(path).read_bytes()
        mime = mimetypes.guess_type(filename)[0] or "application/octet-stream"
        files.append(("cvs", (filename, content, mime)))

    async with httpx.AsyncClient(timeout=60.0) as client:
        response = await client.post(
            f"{config.base_url}/api/match",
            headers={"X-API-Key": config.api_key},
            files=files,
            data={"jd_text": jd_text},
        )
        response.raise_for_status()
        return response.json()


@mcp.tool()
async def get_match_results(job_id: str) -> dict:
    """
    Retrieve match results for a job.

    Args:
        job_id: The job ID returned by match_cvs.

    Returns:
        API response dict with job_id, status, progress, results.
    """
    async with httpx.AsyncClient(timeout=60.0) as client:
        response = await client.get(
            f"{config.base_url}/api/match/{job_id}",
            headers={"X-API-Key": config.api_key},
        )
        response.raise_for_status()
        return response.json()


@mcp.tool()
async def get_match_progress(job_id: str) -> dict:
    """
    Retrieve processing progress for a match job.

    Args:
        job_id: The job ID returned by match_cvs.

    Returns:
        API response dict with status, total, completed, pending, processing.
    """
    async with httpx.AsyncClient(timeout=60.0) as client:
        response = await client.get(
            f"{config.base_url}/api/match/{job_id}/progress",
            headers={"X-API-Key": config.api_key},
        )
        response.raise_for_status()
        return response.json()


# ---------------------------------------------------------------------------
# Entry point
# ---------------------------------------------------------------------------

if __name__ == "__main__":
    transport: str = "stdio"
    if "--transport" in sys.argv:
        idx = sys.argv.index("--transport")
        if idx + 1 < len(sys.argv):
            transport = sys.argv[idx + 1]
    mcp.run(transport=transport)  # type: ignore[arg-type]
