#!/usr/bin/env python3
"""
Autoscaler policy tools for CAST.AI External MCP Server.

Provides read-only tools for viewing and analyzing cluster autoscaling policies.
These tools allow you to understand how CAST.AI will autoscale your clusters
without risking accidental configuration changes.
"""

import json

from fastmcp import FastMCP

from ..cache import resolve_cluster_id
from ..client import make_paginated_request, make_request
from .evictor import register_evictor_tool


def register_policy_tools(mcp: FastMCP):
    """Register all policy-related MCP tools (read-only and write operations)."""

    # Register write operation tool
    register_evictor_tool(mcp)

    @mcp.tool()
    async def list_cluster_policies(
        cluster_id_or_name: str,
        page_limit: int | None = None,
        auto_paginate: bool = False,
        max_pages: int | None = None,
    ) -> str:
        """
        List all autoscaler policies for a cluster.

        Returns the cluster's autoscaling policies including node scaling rules,
        evictor configuration, cluster limits, and optimization settings.

        Autoscaler policies control:
        - How nodes are added/removed from the cluster
        - When pods can be evicted and rescheduled
        - CPU and memory constraints for the cluster
        - Spot instance usage and fallback behavior
        - Optimization aggressiveness

        Use this to understand how CAST.AI will autoscale your cluster and
        what constraints are in place.

        Args:
            cluster_id_or_name: The cluster ID (UUID) or cluster name
            page_limit: Number of items per page (optional)
            auto_paginate: If True, automatically fetch all pages (default: False)
            max_pages: Maximum number of pages to fetch when auto_paginate is True (optional)

        Returns:
            JSON string with autoscaler policy configurations including:
            - Policy ID, name, and description
            - Node scaling rules (min/max nodes, scaling speed)
            - Evictor settings (enabled, aggressive mode, cycle interval)
            - Cluster limits (min/max CPU cores, memory)
            - Spot instance configuration
            - Creation and modification timestamps
        """
        try:
            cluster_id = await resolve_cluster_id(cluster_id_or_name)

            result = await make_paginated_request(
                "GET",
                f"/v1/kubernetes/clusters/{cluster_id}/policies",
                page_limit=page_limit,
                auto_paginate=auto_paginate,
                max_pages=max_pages,
            )

            return json.dumps(result, indent=2)
        except Exception as e:
            return json.dumps({"error": str(e)})

    @mcp.tool()
    async def get_cluster_policy_details(
        cluster_id_or_name: str,
        policy_id: str,
    ) -> str:
        """
        Get detailed configuration for a specific autoscaler policy.

        Returns comprehensive policy details including all configuration
        settings that control how CAST.AI autoscales the cluster.

        Policy configuration includes:
        - **Node Scaling Rules**: Min/max nodes, scaling speed, node selection
        - **Evictor Settings**: Pod eviction behavior, grace periods, aggressive mode
        - **Cluster Limits**: CPU/memory min/max constraints, enabled features
        - **Spot Instance Config**: Spot usage, fallback behavior, interruption handling
        - **Workload Rules**: Which workloads this policy applies to (GVK patterns)
        - **Scoped Mode**: Whether policy is scoped to specific namespaces

        Use this to examine a policy's full configuration and understand
        how it will affect cluster autoscaling behavior. This is helpful for:
        - Troubleshooting autoscaling issues
        - Understanding cost optimization settings
        - Reviewing policy before proposing changes
        - Documenting cluster configuration

        Args:
            cluster_id_or_name: The cluster ID (UUID) or cluster name
            policy_id: The policy ID (UUID) - get this from list_cluster_policies

        Returns:
            JSON string with detailed policy configuration including all
            nested settings and rules
        """
        try:
            cluster_id = await resolve_cluster_id(cluster_id_or_name)

            result = await make_request(
                "GET",
                f"/v1/kubernetes/clusters/{cluster_id}/policies/{policy_id}",
            )

            return json.dumps(result, indent=2)
        except Exception as e:
            return json.dumps({"error": str(e)})

    @mcp.tool()
    async def analyze_policy_configuration(
        cluster_id_or_name: str,
    ) -> str:
        """
        Analyze cluster autoscaler policy configuration and provide insights.

        This tool fetches all policies for a cluster and provides analysis including:
        - Number of policies configured
        - Evictor settings summary (aggressive vs conservative)
        - Cluster scaling limits (CPU/memory constraints)
        - Spot instance usage configuration
        - Scoped mode status
        - Potential optimization opportunities or concerns

        Use this to get a high-level understanding of how autoscaling is
        configured without reading through detailed policy JSON.

        Args:
            cluster_id_or_name: The cluster ID (UUID) or cluster name

        Returns:
            JSON string with policy analysis and insights
        """
        try:
            cluster_id = await resolve_cluster_id(cluster_id_or_name)

            # Fetch all policies
            result = await make_paginated_request(
                "GET",
                f"/v1/kubernetes/clusters/{cluster_id}/policies",
                auto_paginate=True,
            )

            policies = result.get("items", [])

            if not policies:
                return json.dumps(
                    {
                        "message": "No policies configured for this cluster",
                        "recommendation": "Configure autoscaler policies in the CAST.AI console to enable autoscaling",
                    }
                )

            # Analyze policies
            analysis = {
                "cluster_id": cluster_id,
                "total_policies": len(policies),
                "policies_summary": [],
                "evictor_analysis": {
                    "enabled_count": 0,
                    "aggressive_mode_count": 0,
                    "dry_run_count": 0,
                },
                "cluster_limits": [],
                "scoped_mode_count": 0,
            }

            for policy in policies:
                policy_summary = {
                    "id": policy.get("id"),
                    "name": policy.get("name", "unnamed"),
                    "enabled": policy.get("enabled", False),
                }

                # Analyze evictor settings
                evictor = policy.get("evictor", {})
                if evictor.get("enabled"):
                    analysis["evictor_analysis"]["enabled_count"] += 1
                if evictor.get("aggressiveMode"):
                    analysis["evictor_analysis"]["aggressive_mode_count"] += 1
                if evictor.get("dryRun"):
                    analysis["evictor_analysis"]["dry_run_count"] += 1

                policy_summary["evictor_enabled"] = evictor.get("enabled", False)
                policy_summary["evictor_aggressive"] = evictor.get("aggressiveMode", False)

                # Analyze cluster limits
                cluster_limits = policy.get("clusterLimits", {})
                if cluster_limits.get("enabled"):
                    cpu_limits = cluster_limits.get("cpu", {})
                    limits_info = {
                        "policy_name": policy.get("name", "unnamed"),
                        "enabled": True,
                        "min_cores": cpu_limits.get("minCores"),
                        "max_cores": cpu_limits.get("maxCores"),
                    }
                    analysis["cluster_limits"].append(limits_info)
                    policy_summary["has_cpu_limits"] = True
                else:
                    policy_summary["has_cpu_limits"] = False

                # Check scoped mode
                if policy.get("isScopedMode"):
                    analysis["scoped_mode_count"] += 1
                    policy_summary["scoped_mode"] = True
                else:
                    policy_summary["scoped_mode"] = False

                analysis["policies_summary"].append(policy_summary)

            # Add insights
            insights = []

            if analysis["evictor_analysis"]["dry_run_count"] > 0:
                insights.append(
                    {
                        "type": "info",
                        "message": f"{analysis['evictor_analysis']['dry_run_count']} policy(ies) have evictor in dry-run mode (no actual evictions)",
                    }
                )

            if analysis["evictor_analysis"]["aggressive_mode_count"] > 0:
                insights.append(
                    {
                        "type": "warning",
                        "message": f"{analysis['evictor_analysis']['aggressive_mode_count']} policy(ies) have aggressive evictor mode enabled",
                    }
                )

            if not analysis["cluster_limits"]:
                insights.append(
                    {
                        "type": "info",
                        "message": "No cluster CPU limits configured - cluster can scale without constraints",
                    }
                )

            if analysis["scoped_mode_count"] > 0:
                insights.append(
                    {
                        "type": "info",
                        "message": f"{analysis['scoped_mode_count']} policy(ies) use scoped mode (namespace-specific)",
                    }
                )

            analysis["insights"] = insights

            return json.dumps(analysis, indent=2)

        except Exception as e:
            return json.dumps({"error": str(e)})