"""MCP server for JusCABA — Buenos Aires City judicial system."""

import json
import sys
from pathlib import Path

from mcp.server.fastmcp import FastMCP

from client import JusCABAClient
from config import DOWNLOAD_DIR

mcp = FastMCP(
    "juscaba",
    instructions=(
        "JusCABA MCP server provides access to Buenos Aires City (CABA) judicial "
        "system public data. Search cases by person name, get case details, "
        "proceedings, parties, and download PDFs. All data is publicly available — "
        "no authentication required."
    ),
)

_client = JusCABAClient()


def _json(data) -> str:
    return json.dumps(data, ensure_ascii=False, default=str)


# --- Tools ---


@mcp.tool()
async def juscaba_search(name: str, page: int = 0, size: int = 10) -> str:
    """Search JusCABA cases by person name (party, lawyer, or subject).

    Returns a paginated list of case IDs (expId) matching the name.
    Use juscaba_case_header with each expId to get case details.
    Check totalElements to see how many results exist.

    Example: juscaba_search("garcia juan") → 150 cases found
    """
    result = await _client.search(name, page, size)
    return _json(result)


@mcp.tool()
async def juscaba_case_header(exp_id: int) -> str:
    """Get case header: CUIJ, carátula (title), estado administrativo, fecha inicio.

    This is the quickest way to get basic case info. Use exp_id from juscaba_search results.
    """
    result = await _client.case_header(exp_id)
    return _json(result)


@mcp.tool()
async def juscaba_case_details(exp_id: int) -> str:
    """Get full case details: tribunal, objeto de juicio, ubicación actual, monto, etiquetas.

    More detailed than juscaba_case_header. Includes court assignment and case classification.
    """
    result = await _client.case_details(exp_id)
    return _json(result)


@mcp.tool()
async def juscaba_case_fuero(exp_id: int) -> str:
    """Get the fuero (jurisdiction type) for a case.

    Returns a string like "CAYT" (Contencioso Administrativo y Tributario),
    "PCyF" (Penal, Contravencional y de Faltas), etc.
    """
    result = await _client.case_fuero(exp_id)
    return _json({"fuero": result})


@mcp.tool()
async def juscaba_list_proceedings(
    exp_id: int,
    page: int = 0,
    size: int = 10,
    include_cedulas: bool = True,
    include_escritos: bool = True,
    include_despachos: bool = True,
    include_notas: bool = True,
) -> str:
    """List proceedings (actuaciones) for a case: escritos, despachos, cédulas, notas.

    Each proceeding has: titulo, numero, fechaFirma, firmantes, and whether it has attachments.
    Use juscaba_list_attachments with actId to see available PDFs.
    Paginated — check totalElements for total count.
    """
    result = await _client.proceedings(
        exp_id, page, size,
        cedulas=include_cedulas,
        escritos=include_escritos,
        despachos=include_despachos,
        notas=include_notas,
    )
    return _json(result)


@mcp.tool()
async def juscaba_list_parties(exp_id: int, page: int = 0, size: int = 10) -> str:
    """List parties (partes) in a case with their roles, addresses, and representatives.

    Returns: nombreApellido, vinculo (role: ACTOR, DEMANDADO, etc.), domicilios,
    and representantes (lawyers) with their own contact info.
    """
    result = await _client.parties(exp_id, page, size)
    return _json(result)


@mcp.tool()
async def juscaba_related_cases(exp_id: int, page: int = 0, size: int = 10) -> str:
    """List cases related to the given case (incidentes, apelaciones, etc.)."""
    result = await _client.related_cases(exp_id, page, size)
    return _json(result)


@mcp.tool()
async def juscaba_last_action(exp_id: int) -> str:
    """Get the last action on a case: description, date, and type.

    Useful for monitoring — compare dates to detect new activity.
    Types include: Actuacion, Cedula, Escrito.
    """
    result = await _client.last_action(exp_id)
    return _json(result)


@mcp.tool()
async def juscaba_has_sentence(exp_id: int) -> str:
    """Check if a case has a sentence (sentencia)."""
    result = await _client.has_sentence(exp_id)
    return _json({"hasSentence": result})


@mcp.tool()
async def juscaba_list_attachments(act_id: int, exp_id: int) -> str:
    """List PDF attachments for a specific proceeding (actuación).

    Returns adjuntos with adjId, titulo (filename), fecha, and nivelAccesoCod.
    Use adjId as aac_id in juscaba_download_pdf to download the file.
    """
    result = await _client.list_attachments(act_id, exp_id)
    return _json(result)


@mcp.tool()
async def juscaba_download_pdf(
    aac_id: int,
    exp_id: int,
    act_id: int,
    es_cedula: bool = False,
) -> str:
    """Download a PDF attachment from a proceeding.

    Get aac_id from juscaba_list_attachments (adjId field).
    File is saved to /tmp/juscaba-downloads/ and path is returned.
    """
    result = await _client.download_pdf(aac_id, exp_id, act_id, es_cedula)

    if isinstance(result, dict) and "error" in result:
        return _json(result)

    if not isinstance(result, bytes):
        return _json({"error": "Unexpected response type", "type": str(type(result))})

    download_dir = Path(DOWNLOAD_DIR)
    download_dir.mkdir(exist_ok=True)
    filename = f"exp_{exp_id}_act_{act_id}_aac_{aac_id}.pdf"
    filepath = download_dir / filename
    filepath.write_bytes(result)

    return _json({
        "path": str(filepath),
        "filename": filename,
        "size_bytes": len(result),
    })


def main():
    """Entry point with transport detection."""
    if "--http" in sys.argv:
        idx = sys.argv.index("--http")
        port = int(sys.argv[idx + 1]) if idx + 1 < len(sys.argv) else 8000
        mcp.run(transport="streamable-http", host="0.0.0.0", port=port)
    else:
        mcp.run()


if __name__ == "__main__":
    main()
