"""
Cluster isolation validation for K8s allocation.

Validates that K8s clusters are properly isolated by cloud provider
to prevent cross-provider cluster assignments.
"""

from typing import Dict, Any, List
import polars as pl
from rich.console import Console

from src.log_context import get_logger


class ClusterIsolationValidator:
    """
    Validates that K8s clusters are properly isolated by cloud provider.
    
    Uses Polars-native operations for optimal performance without nested loops.
    """
    
    def __init__(self, console: Console = None):
        self.console = console or Console()
        self.logger = get_logger(__name__)
    
    def validate_provider_isolation(self, k8s_data: pl.DataFrame) -> Dict[str, Any]:
        """
        Validate that cluster names are unique per provider using Polars aggregation.
        
        Args:
            k8s_data: DataFrame with K8s allocation data including k8s_cluster and cloud_provider columns
            
        Returns:
            Validation report with isolation results
        """
        if k8s_data.is_empty():
            return {
                "isolation_violations": [],
                "total_clusters": 0,
                "shared_clusters": 0,
                "validation_passed": True,
                "provider_clusters": {}
            }
        
        # Validate required columns exist
        required_columns = ["k8s_cluster", "cloud_provider"]
        missing_columns = [col for col in required_columns if col not in k8s_data.columns]
        if missing_columns:
            raise ValueError(f"Missing required columns for cluster isolation validation: {missing_columns}")
        
        self.logger.debug(
            "Starting cluster isolation validation",
            total_rows=len(k8s_data),
            unique_clusters=k8s_data["k8s_cluster"].n_unique(),
            unique_providers=k8s_data["cloud_provider"].n_unique()
        )
        
        # Single Polars aggregation: find clusters shared across providers
        cluster_analysis = (
            k8s_data
            .group_by("k8s_cluster")
            .agg([
                pl.col("cloud_provider").n_unique().alias("provider_count"),
                pl.col("cloud_provider").unique().sort().alias("providers")
            ])
            .with_columns([
                pl.col("provider_count").gt(1).alias("is_violation")
            ])
        )
        
        # Extract violations using Polars filtering
        violations_df = cluster_analysis.filter(pl.col("is_violation"))
        violations = []
        
        if not violations_df.is_empty():
            for row in violations_df.iter_rows(named=True):
                violations.append({
                    "cluster": row["k8s_cluster"],
                    "providers": row["providers"],
                    "provider_count": row["provider_count"]
                })
        
        # Generate provider-specific cluster mapping for additional insights
        provider_clusters = self._generate_provider_cluster_mapping(k8s_data)
        
        validation_results = {
            "isolation_violations": violations,
            "total_clusters": len(cluster_analysis),
            "shared_clusters": len(violations),
            "validation_passed": len(violations) == 0,
            "provider_clusters": provider_clusters
        }
        
        self.logger.info(
            "Cluster isolation validation completed",
            total_clusters=validation_results["total_clusters"],
            shared_clusters=validation_results["shared_clusters"],
            validation_passed=validation_results["validation_passed"]
        )
        
        return validation_results
    
    def _generate_provider_cluster_mapping(self, k8s_data: pl.DataFrame) -> Dict[str, List[str]]:
        """
        Generate mapping of provider -> unique cluster names using Polars operations.
        
        Args:
            k8s_data: DataFrame with K8s allocation data
            
        Returns:
            Dictionary mapping provider names to lists of cluster names
        """
        provider_clusters = {}
        
        # Use Polars groupby to efficiently get clusters per provider
        provider_cluster_mapping = (
            k8s_data
            .group_by("cloud_provider")
            .agg(pl.col("k8s_cluster").unique().sort().alias("clusters"))
        )
        
        for row in provider_cluster_mapping.iter_rows(named=True):
            provider_clusters[row["cloud_provider"]] = row["clusters"]
        
        return provider_clusters
    
    def display_validation_results(self, results: Dict[str, Any]) -> None:
        """
        Display cluster isolation validation results in a user-friendly format.
        
        Args:
            results: Validation results from validate_provider_isolation()
        """
        if results["validation_passed"]:
            self.console.print("✅ [green]All clusters are properly isolated by provider[/green]")
            
            # Show provider cluster distribution
            if results["provider_clusters"]:
                self.console.print("\n📊 [cyan]Provider Cluster Distribution:[/cyan]")
                for provider, clusters in results["provider_clusters"].items():
                    self.console.print(f"  • {provider}: {len(clusters)} clusters")
                    if clusters:  # Show first few cluster names as examples
                        examples = clusters[:3]
                        if len(clusters) > 3:
                            examples_str = ", ".join(examples) + f", ... (+{len(clusters)-3} more)"
                        else:
                            examples_str = ", ".join(examples)
                        self.console.print(f"    Examples: {examples_str}")
        else:
            self.console.print("❌ [red]Cluster isolation violations found![/red]")
            self.console.print(f"Found {results['shared_clusters']} shared clusters out of {results['total_clusters']} total clusters")
            
            # Display violation details
            for violation in results["isolation_violations"]:
                providers_str = " & ".join(violation["providers"])
                self.console.print(f"  • Cluster '{violation['cluster']}' shared by: {providers_str}")
            
            # Show guidance
            self.console.print("\n💡 [yellow]This indicates the provider parameter is not being passed correctly[/yellow]")
            self.console.print("   [yellow]Each provider should generate unique cluster names[/yellow]")