"""complyform MCP server — 8 read-only tools for AI assistants via stdio.

Hidden command. AI assistant spawns `complyform mcp-server` as subprocess.
Uses Anthropic's Python MCP SDK over stdio transport.
"""

from __future__ import annotations

import asyncio
import json
from typing import Any

from complyform.cli.main import app


def _error_json(
    *,
    code: int = 0,
    title: str,
    message: str,
    fix: str = "",
) -> str:
    """Build JSON error response for MCP tools."""
    return json.dumps(
        {
            "error": True,
            "code": code,
            "title": title,
            "message": message,
            "fix": fix,
        }
    )


def _success_json(data: Any) -> str:
    """Build JSON success response for MCP tools."""
    return json.dumps(data, default=str)


async def _handle_scan(arguments: dict[str, Any]) -> str:
    """Handle complyform_scan tool call."""
    from complyform.core.scanner.state_parser import StateParser

    state_path = arguments["state_path"]
    cloud = arguments.get("cloud", "gcp")

    parser = StateParser()
    resources, _metadata = parser.parse(state_path, cloud)
    return _success_json(
        {
            "cloud": cloud,
            "resource_count": len(resources),
            "resources": [r.model_dump(mode="json") for r in resources],
        }
    )


async def _handle_assess(arguments: dict[str, Any]) -> str:
    """Handle complyform_assess tool call."""
    from complyform.core.assessor.control_matcher import ControlMatcher, Finding
    from complyform.core.profiles.cross_mappings import get_all as get_all_cross
    from complyform.core.profiles.mapping_loader import load_mappings
    from complyform.core.profiles.models import CrossMappingIndex
    from complyform.core.scanner.state_parser import StateParser

    state_path = arguments["state_path"]
    cloud = arguments.get("cloud", "gcp")
    frameworks: list[str] = arguments.get("frameworks", ["soc2"])

    parser = StateParser()
    resources, _metadata = parser.parse(state_path, cloud)

    matcher = ControlMatcher()
    all_cross = get_all_cross()
    cross_index = CrossMappingIndex(schema_version=1, mappings=all_cross)
    findings: list[Finding] = []
    for fw_id in frameworks:
        try:
            mapping_file = load_mappings(fw_id, cloud)
        except Exception:
            continue
        findings.extend(matcher.match(resources, mapping_file, cross_index))
    return _success_json(
        {
            "cloud": cloud,
            "frameworks": frameworks,
            "finding_count": len(findings),
            "findings": [f.model_dump(mode="json") for f in findings],
        }
    )


async def _handle_frameworks_list(arguments: dict[str, Any]) -> str:
    """Handle complyform_frameworks_list tool call."""
    from complyform.core.profiles.registry import list_frameworks

    tier = arguments.get("tier")
    region = arguments.get("region")

    frameworks = list_frameworks(tier=tier, cloud=region)
    return _success_json(
        {
            "framework_count": len(frameworks),
            "frameworks": frameworks,
        }
    )


async def _handle_frameworks_info(arguments: dict[str, Any]) -> str:
    """Handle complyform_frameworks_info tool call."""
    from complyform.core.profiles.registry import get_framework

    framework = arguments["framework"]
    info = get_framework(framework)
    return _success_json(info)


async def _handle_frameworks_diff(arguments: dict[str, Any]) -> str:
    """Handle complyform_frameworks_diff tool call."""
    from complyform.core.profiles.cross_mappings import lookup

    framework_a = arguments["framework_a"]
    framework_b = arguments["framework_b"]

    mappings_a = lookup(framework_a, framework_b)
    mappings_b = lookup(framework_b, framework_a)
    return _success_json(
        {
            "framework_a": framework_a,
            "framework_b": framework_b,
            "a_to_b": mappings_a,
            "b_to_a": mappings_b,
        }
    )


async def _handle_explain(arguments: dict[str, Any]) -> str:
    """Handle complyform_explain tool call."""
    from complyform.core.explainer.deterministic import explain_finding

    target = arguments["target"]
    framework = arguments.get("framework")

    # Build a minimal finding-like object for the explainer
    explanation = {"target": target, "framework": framework}
    try:
        from complyform.core.assessor.control_matcher import Finding

        finding = Finding(
            control_id=target,
            framework=framework or "unknown",
            resource_address="",
            resource_type="",
            status="MANUAL_REVIEW",
            severity="MEDIUM",
            finding=f"Explain {target}",
            remediation="",
            checkov_id=None,
            cross_mappings=None,
            native_ids=None,
            confidence="inferred",
        )
        result = explain_finding(finding)
        explanation = result.model_dump(mode="json")
    except Exception:
        explanation = {
            "target": target,
            "framework": framework,
            "explanation": f"Control {target}",
        }

    return _success_json(explanation)


async def _handle_doctor(arguments: dict[str, Any]) -> str:
    """Handle complyform_doctor tool call."""
    from complyform.cli.doctor_cmd import build_diagnostic_string, run_doctor_checks

    results = run_doctor_checks()
    diag = build_diagnostic_string()
    return _success_json(
        {
            "checks": [
                {
                    "number": c.number,
                    "label": c.label,
                    "status": c.status,
                    "message": c.message,
                    "fix": c.fix,
                }
                for c in results.checks
            ],
            "summary": {
                "passed": results.passed,
                "errors": results.errors,
                "warnings": results.warnings,
                "info": results.info,
            },
            "diagnostic_string": diag,
        }
    )


async def _handle_config_status(arguments: dict[str, Any]) -> str:
    """Handle complyform_config_status tool call."""
    from complyform import __version__
    from complyform.core.auth.license import LicenseManager

    verbose = arguments.get("verbose", False)

    mgr = LicenseManager()
    cache = mgr.load_cache()

    tier = "community"
    license_status = "Community (no license)"
    expires = None

    if cache is not None:
        tier = cache.tier
        expires = cache.expires_at
        if expires:
            license_status = f"Active (expires {expires})"
        else:
            license_status = f"Active ({tier} tier)"

    result: dict[str, Any] = {
        "version": __version__,
        "tier": tier,
        "license_status": license_status,
        "expires": expires,
    }

    if verbose:
        from complyform.core.auth.tier_config import TIER_CONFIG

        tier_cfg = TIER_CONFIG.get(tier, {})
        result["features"] = tier_cfg.get("features", [])
        result["scan_sources"] = tier_cfg.get("scan_sources", [])

    return _success_json(result)


_TOOL_HANDLERS: dict[str, Any] = {
    "complyform_scan": _handle_scan,
    "complyform_assess": _handle_assess,
    "complyform_frameworks_list": _handle_frameworks_list,
    "complyform_frameworks_info": _handle_frameworks_info,
    "complyform_frameworks_diff": _handle_frameworks_diff,
    "complyform_explain": _handle_explain,
    "complyform_doctor": _handle_doctor,
    "complyform_config_status": _handle_config_status,
}


def _create_server() -> Any:
    """Create MCP server with 8 read-only tools."""
    from mcp.server import Server
    from mcp.types import TextContent, Tool

    server = Server("complyform")

    @server.list_tools()  # type: ignore[no-untyped-call, untyped-decorator]
    async def list_tools() -> list[Tool]:
        return [
            Tool(
                name="complyform_scan",
                description="Scan Terraform state file for resource inventory",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "state_path": {
                            "type": "string",
                            "description": "Path to .tfstate file",
                        },
                        "cloud": {
                            "type": "string",
                            "enum": ["gcp", "aws", "azure"],
                            "default": "gcp",
                            "description": "Cloud provider",
                        },
                    },
                    "required": ["state_path"],
                },
            ),
            Tool(
                name="complyform_assess",
                description="Assess resources against compliance framework",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "state_path": {
                            "type": "string",
                            "description": "Path to .tfstate file",
                        },
                        "cloud": {
                            "type": "string",
                            "enum": ["gcp", "aws", "azure"],
                            "default": "gcp",
                            "description": "Cloud provider",
                        },
                        "frameworks": {
                            "type": "array",
                            "items": {"type": "string"},
                            "default": ["soc2"],
                            "description": "Compliance frameworks to assess against",
                        },
                    },
                    "required": ["state_path"],
                },
            ),
            Tool(
                name="complyform_frameworks_list",
                description="List all 53 supported compliance frameworks",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "tier": {
                            "type": "string",
                            "description": "Filter by tier",
                        },
                        "region": {
                            "type": "string",
                            "description": "Filter by region",
                        },
                    },
                },
            ),
            Tool(
                name="complyform_frameworks_info",
                description="Show framework details and cross-mappings",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "framework": {
                            "type": "string",
                            "description": "Framework identifier",
                        },
                    },
                    "required": ["framework"],
                },
            ),
            Tool(
                name="complyform_frameworks_diff",
                description="Compare two frameworks — shared and unique controls",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "framework_a": {
                            "type": "string",
                            "description": "First framework",
                        },
                        "framework_b": {
                            "type": "string",
                            "description": "Second framework",
                        },
                    },
                    "required": ["framework_a", "framework_b"],
                },
            ),
            Tool(
                name="complyform_explain",
                description="Explain a finding or control in plain English",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "target": {
                            "type": "string",
                            "description": "Control ID or finding to explain",
                        },
                        "framework": {
                            "type": "string",
                            "description": "Framework context (optional)",
                        },
                    },
                    "required": ["target"],
                },
            ),
            Tool(
                name="complyform_doctor",
                description="Run environment health checks",
                inputSchema={
                    "type": "object",
                    "properties": {},
                },
            ),
            Tool(
                name="complyform_config_status",
                description="Show current tier, license, and environment info",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "verbose": {
                            "type": "boolean",
                            "default": False,
                            "description": "Include detailed feature list",
                        },
                    },
                },
            ),
        ]

    @server.call_tool()  # type: ignore[untyped-decorator]
    async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
        from complyform.core.errors import ComplyFormError

        handler = _TOOL_HANDLERS.get(name)
        if handler is None:
            return [
                TextContent(
                    type="text",
                    text=_error_json(
                        title="Unknown tool",
                        message=f"No tool named '{name}'",
                    ),
                )
            ]

        try:
            result = await handler(arguments)
            return [TextContent(type="text", text=result)]
        except ComplyFormError as e:
            return [
                TextContent(
                    type="text",
                    text=_error_json(
                        code=e.error_code,
                        title=e.title,
                        message=e.message,
                        fix=e.fix,
                    ),
                )
            ]
        except Exception as e:
            return [
                TextContent(
                    type="text",
                    text=_error_json(
                        title="Unexpected error",
                        message=str(e),
                    ),
                )
            ]

    return server


async def _run_server(server: Any) -> None:
    """Run MCP server on stdio."""
    from mcp.server.stdio import stdio_server

    async with stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            server.create_initialization_options(),
        )


def run_mcp_server() -> None:
    """Entry point called by the Typer command."""
    server = _create_server()
    asyncio.run(_run_server(server))


@app.command(hidden=True)
def mcp_server() -> None:
    """Launch MCP server on stdio for AI assistants."""
    run_mcp_server()
