from __future__ import annotations

import json
import os
from typing import Any

import httpx
from mcp.server.fastmcp import FastMCP

mcp = FastMCP(
    "Aura Financial Intelligence",
    instructions=(
        "Aura provides financial research intelligence based on curated earnings call transcripts "
        "and due diligence interviews. Use search_company first to find a company, then use the "
        "other tools to retrieve and analyze its transcripts."
    ),
)

_API_URL = os.environ.get("AURA_API_URL", "").rstrip("/")
_API_KEY = os.environ.get("AURA_API_KEY", "")
_TIMEOUT = 120.0


def _headers() -> dict[str, str]:
    return {"X-API-KEY": _API_KEY, "Content-Type": "application/json"}


def _check_config() -> str | None:
    if not _API_URL:
        return "AURA_API_URL is not set. Add it to the MCP server environment config."
    if not _API_KEY:
        return "AURA_API_KEY is not set. Add it to the MCP server environment config."
    return None


async def _post(path: str, body: dict) -> dict[str, Any]:
    async with httpx.AsyncClient(timeout=_TIMEOUT) as client:
        resp = await client.post(f"{_API_URL}{path}", json=body, headers=_headers())
        resp.raise_for_status()
        return resp.json()


async def _get(path: str) -> dict[str, Any]:
    async with httpx.AsyncClient(timeout=_TIMEOUT) as client:
        resp = await client.get(f"{_API_URL}{path}", headers=_headers())
        resp.raise_for_status()
        return resp.json()


@mcp.tool()
async def search_company(query: str) -> str:
    """
    Search for a company in the Aura catalog by name, ticker, or description.

    Use this FIRST before calling any other tool. Returns the company ID needed
    by other tools.

    Args:
        query: Free-text search — company name, ticker symbol, or description
               (e.g. "Nubank", "MELI", "Mexican fintech unicorn")

    Returns:
        JSON with matched company: id, name, ticker, exchange.
        Returns an error message if no match is found.
    """
    err = _check_config()
    if err:
        return json.dumps({"error": err})
    try:
        data = await _post("/api/v1/companies/search", {"query": query})
        return json.dumps(data, ensure_ascii=False)
    except httpx.HTTPStatusError as exc:
        return json.dumps({"error": f"API {exc.response.status_code}: {exc.response.text}"})
    except Exception as exc:
        return json.dumps({"error": str(exc)})


@mcp.tool()
async def get_recent_transcripts(company_id: str, quarters: int = 3) -> str:
    """
    List the most recent transcripts available for a company.

    Use this after search_company to see what research materials are available
    before running a full analysis.

    Args:
        company_id: The company ID returned by search_company
        quarters:   How many past quarters to look back (default: 3)

    Returns:
        JSON list of transcript metadata: title, date, due_diligence_type,
        source_tone, call_quality, and id.
    """
    err = _check_config()
    if err:
        return json.dumps({"error": err})
    try:
        data = await _post(
            "/api/v1/transcripts/search",
            {"company_id": company_id, "quarters": quarters},
        )
        return json.dumps(data, ensure_ascii=False)
    except httpx.HTTPStatusError as exc:
        return json.dumps({"error": f"API {exc.response.status_code}: {exc.response.text}"})
    except Exception as exc:
        return json.dumps({"error": str(exc)})


@mcp.tool()
async def analyze_red_flags(company: str, quarters: int = 3) -> str:
    """
    Deep analysis of risk signals and red flags for a company using Aura's
    ReAct agent powered by curated transcripts and due diligence interviews.

    This is the primary analytical tool. It automatically searches for the
    company, retrieves relevant transcripts, and produces a structured risk
    analysis with citations.

    Args:
        company: Company name or ticker (e.g. "Rappi", "MELI", "Nubank")
        quarters: How many past quarters to analyze (default: 3)

    Returns:
        Structured markdown analysis with red flags by category, severity,
        trend, and auditable source citations.
    """
    err = _check_config()
    if err:
        return err
    try:
        prompt = (
            f"Perform a comprehensive red flag analysis for **{company}** "
            f"covering the last {quarters} quarters.\n\n"
            "Structure your response as follows:\n"
            "1. **Executive Summary** — 2-3 sentence overview of the risk profile\n"
            "2. **Red Flags** — organized by category (Operational, Financial, Management, "
            "Competitive, Macro). For each flag: description, severity (high/medium/low), "
            "trend (improving/worsening/stable), and source citations\n"
            "3. **Positive Signals** — counter-evidence or strengths worth noting\n"
            "4. **Overall Risk Assessment** — high / medium / low with rationale\n\n"
            "Include [Document Type: conversation](ID) citations for every claim. "
            "If no transcripts are found for this company, clearly state that."
        )
        data = await _post("/api/v1/agents/aura/query", {"query": prompt})
        return data.get("response", json.dumps(data, ensure_ascii=False))
    except httpx.HTTPStatusError as exc:
        return f"API error {exc.response.status_code}: {exc.response.text}"
    except Exception as exc:
        return f"Error running analysis: {str(exc)}"


@mcp.tool()
async def get_transcript_content(transcript_id: str) -> str:
    """
    Retrieve the full content of a specific transcript including all Q&A pairs.

    Use this when you need verbatim quotes or want to read the full context of
    a document returned by get_recent_transcripts or cited in analyze_red_flags.

    Args:
        transcript_id: The UUID of the transcript

    Returns:
        JSON with the full transcript payload including Q&A pairs, speakers,
        call date, and metadata.
    """
    err = _check_config()
    if err:
        return json.dumps({"error": err})
    try:
        data = await _get(f"/api/v1/transcripts/{transcript_id}")
        return json.dumps(data, ensure_ascii=False)
    except httpx.HTTPStatusError as exc:
        if exc.response.status_code == 404:
            return json.dumps({"found": False, "message": f"No transcript found: '{transcript_id}'"})
        return json.dumps({"error": f"API {exc.response.status_code}: {exc.response.text}"})
    except Exception as exc:
        return json.dumps({"error": str(exc)})
