"""市場情報 MCP 整合就緒度 preview。

只檢查 MCP 設計、feature flag、tool registry、server health 與 telemetry 表狀態；
預設不連線、不寫 DB、不呼叫外部工具。
"""

from sqlalchemy import create_engine, inspect, text

from services.market_intel.mcp_contract import (
    EXPECTED_MARKET_INTEL_TOOLS,
    build_mcp_tool_contract_preview,
)


EXPECTED_EXTERNAL_SERVERS = ("postgres", "omnisearch", "firecrawl", "filesystem")


def _planned_server_statuses(base_hosts):
    return [
        {
            "server": server,
            "base_url": base_hosts.get(server),
            "configured": bool(base_hosts.get(server)),
            "health_checked": False,
            "healthy": False,
            "status": "planned_no_health_check",
            "error_message": None,
        }
        for server in EXPECTED_EXTERNAL_SERVERS
    ]


def _health_check_servers(base_hosts, timeout_sec):
    import requests

    statuses = []
    for server in EXPECTED_EXTERNAL_SERVERS:
        base_url = base_hosts.get(server)
        status = {
            "server": server,
            "base_url": base_url,
            "configured": bool(base_url),
            "health_checked": False,
            "healthy": False,
            "status": "not_configured" if not base_url else "error",
            "error_message": None,
        }
        if not base_url:
            statuses.append(status)
            continue
        try:
            response = requests.get(
                f"{base_url.rstrip('/')}/health",
                timeout=timeout_sec,
            )
            status["health_checked"] = True
            status["healthy"] = response.status_code == 200
            status["status"] = "healthy" if status["healthy"] else f"http_{response.status_code}"
        except Exception as exc:
            status["health_checked"] = True
            status["status"] = "error"
            status["error_message"] = str(exc)[:240]
        statuses.append(status)
    return statuses


def _build_telemetry_status(*, execute_requested, engine=None, database_url=None, database_type=None):
    if not execute_requested:
        return {
            "mode": "mcp_telemetry_planned",
            "table": "mcp_calls",
            "read_only_query_executed": False,
            "database_connection_opened": False,
            "database_session_created": False,
            "database_write_executed": False,
            "database_commit_executed": False,
            "table_exists": False,
            "total_calls": None,
            "recent_24h_calls": None,
            "server_counts": [],
        }

    from config import DATABASE_PATH, DATABASE_TYPE

    effective_database_url = database_url or DATABASE_PATH
    effective_database_type = (database_type or DATABASE_TYPE or "").lower()
    created_engine = False
    connection_opened = False
    try:
        if engine is None:
            connect_args = {}
            if effective_database_type == "postgresql":
                connect_args = {
                    "connect_timeout": 8,
                    "options": "-c statement_timeout=15000",
                }
            engine = create_engine(
                effective_database_url,
                isolation_level="AUTOCOMMIT",
                pool_pre_ping=True,
                connect_args=connect_args,
            )
            created_engine = True

        table_exists = inspect(engine).has_table("mcp_calls")
        total_calls = None
        recent_24h_calls = None
        server_counts = []
        with engine.connect() as conn:
            connection_opened = True
            if table_exists:
                total_calls = conn.execute(text("SELECT COUNT(*) FROM mcp_calls")).scalar()
                if effective_database_type == "postgresql":
                    recent_24h_calls = conn.execute(
                        text("SELECT COUNT(*) FROM mcp_calls WHERE called_at >= NOW() - INTERVAL '24 hours'")
                    ).scalar()
                else:
                    recent_24h_calls = total_calls
                server_counts = [
                    {"server": row[0], "calls": int(row[1])}
                    for row in conn.execute(
                        text(
                            """
                            SELECT server, COUNT(*) AS calls
                            FROM mcp_calls
                            GROUP BY server
                            ORDER BY calls DESC
                            LIMIT 10
                            """
                        )
                    ).fetchall()
                ]

        return {
            "mode": "mcp_telemetry_read_only",
            "table": "mcp_calls",
            "read_only_query_executed": True,
            "database_connection_opened": connection_opened,
            "database_session_created": False,
            "database_write_executed": False,
            "database_commit_executed": False,
            "table_exists": bool(table_exists),
            "total_calls": int(total_calls or 0) if table_exists else None,
            "recent_24h_calls": int(recent_24h_calls or 0) if table_exists else None,
            "server_counts": server_counts,
        }
    except Exception as exc:
        return {
            "mode": "mcp_telemetry_error",
            "table": "mcp_calls",
            "read_only_query_executed": False,
            "database_connection_opened": connection_opened,
            "database_session_created": False,
            "database_write_executed": False,
            "database_commit_executed": False,
            "table_exists": False,
            "total_calls": None,
            "recent_24h_calls": None,
            "server_counts": [],
            "error_message": str(exc)[:400],
        }
    finally:
        if created_engine:
            engine.dispose()


def build_mcp_readiness_plan(
    *,
    execute_requested=False,
    timeout_sec=3,
    engine=None,
    database_url=None,
    database_type=None,
):
    """建立市場情報 MCP readiness；預設不做 health check / DB query。"""
    from services.mcp_router import MCP_BASE_HOSTS, TOOL_REGISTRY, is_mcp_router_enabled

    execute_requested = bool(execute_requested)
    timeout_sec = max(1, min(int(timeout_sec or 3), 10))
    router_enabled = bool(is_mcp_router_enabled())
    server_statuses = (
        _health_check_servers(MCP_BASE_HOSTS, timeout_sec)
        if execute_requested
        else _planned_server_statuses(MCP_BASE_HOSTS)
    )
    telemetry = _build_telemetry_status(
        execute_requested=execute_requested,
        engine=engine,
        database_url=database_url,
        database_type=database_type,
    )

    registered_callers = sorted(TOOL_REGISTRY.keys())
    market_intel_tools = TOOL_REGISTRY.get("market_intel", {})
    tool_contract = build_mcp_tool_contract_preview(TOOL_REGISTRY)
    market_intel_tool_count = int(tool_contract["tool_count"])
    external_mcp_complete = bool(
        router_enabled
        and execute_requested
        and server_statuses
        and all(item["healthy"] for item in server_statuses)
    )
    internal_mcp_complete = bool(
        tool_contract["contract_ready"]
        and telemetry.get("table_exists")
    )
    market_intel_mcp_integrated = bool(tool_contract["contract_ready"])

    readiness_checks = {
        "mcp_router_module_present": True,
        "mcp_router_enabled": router_enabled,
        "external_server_health_checked": execute_requested,
        "external_servers_all_healthy": all(item["healthy"] for item in server_statuses),
        "mcp_calls_table_exists": bool(telemetry.get("table_exists")),
        "base_callers_registered": {"mcp_collector", "hermes_analyst", "openclaw_strategist"} <= set(registered_callers),
        "market_intel_caller_registered": bool(
            tool_contract["checks"]["market_intel_caller_registered"]
        ),
        "market_intel_tools_registered": bool(
            tool_contract["checks"]["all_router_tools_whitelisted"]
        ),
        "market_intel_tool_contract_ready": bool(tool_contract["contract_ready"]),
    }
    blocked_reasons = [
        key for key, passed in readiness_checks.items()
        if not passed
    ]
    if not execute_requested:
        blocked_reasons.insert(0, "execute_false_planned_only")

    return {
        "mode": "mcp_readiness_read_only" if execute_requested else "mcp_readiness_planned",
        "execute_requested": execute_requested,
        "router_enabled": router_enabled,
        "external_mcp_complete": external_mcp_complete,
        "internal_mcp_complete": internal_mcp_complete,
        "market_intel_mcp_integrated": market_intel_mcp_integrated,
        "server_statuses": server_statuses,
        "registered_callers": registered_callers,
        "market_intel_tools": market_intel_tools,
        "market_intel_tool_count": market_intel_tool_count,
        "expected_market_intel_tools": list(EXPECTED_MARKET_INTEL_TOOLS),
        "mcp_tool_contract": tool_contract,
        "telemetry": telemetry,
        "readiness_checks": readiness_checks,
        "database_session_created": False,
        "database_write_executed": False,
        "database_commit_executed": False,
        "external_network_executed": False,
        "scheduler_attached": False,
        "writes_executed": False,
        "would_write_database": False,
        "blocked_reasons": blocked_reasons,
        "next_required_steps": [
            "先通過 /api/market_intel/mcp_deploy_preflight 的 env、compose、port 與 fallback 檢查",
            "部署並健康檢查 docker-compose.mcp.yml 的 postgres / omnisearch / firecrawl / filesystem",
            "四個 MCP health endpoint 全部 200 後，才在正式環境設定 MCP_ROUTER_ENABLED=true",
            "人工 fetch 必須先通過 /api/market_intel/mcp_fetch_gate，再允許公開頁面限速探測",
        ],
    }
