"""
Provider Synchronization Service.

Handles provider-specific tag synchronization requirements for GCP and Azure.
Ensures consistency between resource_id and special provider tags.
"""

import logging
from typing import Dict

import polars as pl


logger = logging.getLogger(__name__)


class ProviderSynchronizationService:
    """Service for maintaining provider-specific tag synchronization."""
    
    def __init__(self):
        """Initialize provider synchronization service."""
        logger.info("Initialized ProviderSynchronizationService for GCP and Azure consistency")
    
    def synchronize_all_providers(self, df: pl.DataFrame) -> pl.DataFrame:
        """
        Apply all provider-specific synchronization rules.
        
        Args:
            df: DataFrame with resources to synchronize
            
        Returns:
            DataFrame with synchronized provider tags
        """
        if df.height == 0:
            return df
        
        logger.info(f"Synchronizing provider-specific tags for {df.height:,} resources")
        
        result = df.clone()
        
        # Apply GCP synchronization
        result = self.synchronize_gcp_resources(result)
        
        # Apply Azure synchronization  
        result = self.synchronize_azure_resources(result)
        
        logger.info("Completed provider-specific tag synchronization")
        return result
    
    def synchronize_gcp_resources(self, df: pl.DataFrame) -> pl.DataFrame:
        """
        Ensure GCP resource_id and gcp_cz:resource_name tag stay synchronized.
        
        For GCP: resource_id == resource/tag:gcp_cz:resource_name (exact match)
        For non-GCP: resource/tag:gcp_cz:resource_name = ""
        
        Args:
            df: DataFrame with resources
            
        Returns:
            DataFrame with synchronized GCP tags
        """
        if df.height == 0:
            return df
        
        result = df.with_columns([
            pl.when(pl.col('cloud_provider') == 'GCP')
            .then(pl.col('resource_id'))  # Always match resource_id for GCP
            .otherwise(pl.lit(''))        # Empty string for non-GCP
            .alias('resource/tag:gcp_cz:resource_name')
        ])
        
        # Log synchronization stats
        if 'cloud_provider' in df.columns:
            gcp_count = df.select((pl.col('cloud_provider') == 'GCP').sum()).item()
            non_gcp_count = df.height - gcp_count
            logger.debug(f"GCP synchronization: {gcp_count:,} GCP resources, {non_gcp_count:,} non-GCP resources")
        
        return result
    
    def synchronize_azure_resources(self, df: pl.DataFrame) -> pl.DataFrame:
        """
        Ensure Azure resource_id and resourceGroupName tag stay synchronized.
        
        For Azure: Extract resource group from ARM resource ID
        For non-Azure: resource/tag:azure:resourceGroupName = ""
        
        Args:
            df: DataFrame with resources
            
        Returns:
            DataFrame with synchronized Azure tags
        """
        if df.height == 0:
            return df
        
        result = df.with_columns([
            pl.when(pl.col('cloud_provider') == 'Azure')
            .then(
                # Vectorized Azure resource group extraction
                pl.when(
                    pl.col('resource_id').str.starts_with('/subscriptions/') &
                    pl.col('resource_id').str.contains('/resourceGroups/')
                )
                .then(
                    # Split by '/' and extract resource group name (position 4)
                    pl.col('resource_id')
                    .str.split('/')
                    .list.get(4)  # /subscriptions/{sub}/resourceGroups/{rg}/providers/...
                    .fill_null('')  # Handle cases where split doesn't have enough parts
                )
                .otherwise(pl.lit(''))  # Non-ARM format resource IDs
            )
            .otherwise(pl.lit(''))  # Empty string for non-Azure
            .alias('resource/tag:azure:resourceGroupName')
        ])
        
        # Log synchronization stats
        if 'cloud_provider' in df.columns:
            azure_count = df.select((pl.col('cloud_provider') == 'Azure').sum()).item()
            non_azure_count = df.height - azure_count
            logger.debug(f"Azure synchronization: {azure_count:,} Azure resources, {non_azure_count:,} non-Azure resources")
        
        return result
    
    def _extract_azure_resource_group(self, resource_id: str) -> str:
        """
        Extract resource group from ARM resource ID.
        
        Args:
            resource_id: ARM resource ID (e.g., /subscriptions/123/resourceGroups/my-rg/providers/...)
            
        Returns:
            Resource group name or empty string if extraction fails
        """
        try:
            if not resource_id or not resource_id.startswith('/subscriptions/'):
                return ''
            
            parts = resource_id.split('/')
            # ARM format: /subscriptions/{sub}/resourceGroups/{rg}/providers/...
            if len(parts) >= 5 and parts[3] == 'resourceGroups':
                return parts[4]  # Resource group name
            
            return ''
            
        except Exception as e:
            logger.debug(f"Failed to extract Azure resource group from {resource_id}: {e}")
            return ''
    
    def validate_synchronization(self, df: pl.DataFrame) -> Dict[str, bool]:
        """
        Validate provider-specific synchronization results.
        
        Args:
            df: DataFrame with synchronized resources
            
        Returns:
            Dictionary with validation results
        """
        validation_results = {
            'gcp_tags_synchronized': True,
            'azure_tags_synchronized': True,
            'non_gcp_tags_empty': True,
            'non_azure_tags_empty': True
        }
        
        if df.height == 0:
            return validation_results
        
        # Check GCP synchronization
        if 'resource/tag:gcp_cz:resource_name' in df.columns:
            # For GCP resources, tag should match resource_id
            gcp_resources = df.filter(pl.col('cloud_provider') == 'GCP')
            if gcp_resources.height > 0:
                mismatched = gcp_resources.filter(
                    pl.col('resource_id') != pl.col('resource/tag:gcp_cz:resource_name')
                ).height
                validation_results['gcp_tags_synchronized'] = (mismatched == 0)
            
            # For non-GCP resources, tag should be empty
            non_gcp_resources = df.filter(pl.col('cloud_provider') != 'GCP')
            if non_gcp_resources.height > 0:
                non_empty = non_gcp_resources.filter(
                    pl.col('resource/tag:gcp_cz:resource_name') != ''
                ).height
                validation_results['non_gcp_tags_empty'] = (non_empty == 0)
        
        # Check Azure synchronization
        if 'resource/tag:azure:resourceGroupName' in df.columns:
            # For Azure resources, tag should be extracted from resource_id
            azure_resources = df.filter(pl.col('cloud_provider') == 'Azure')
            if azure_resources.height > 0:
                # This is harder to validate programmatically since we need to re-extract
                # For now, just check that Azure resources have non-empty values
                empty_azure_tags = azure_resources.filter(
                    pl.col('resource/tag:azure:resourceGroupName') == ''
                ).height
                validation_results['azure_tags_synchronized'] = (empty_azure_tags == 0)
            
            # For non-Azure resources, tag should be empty
            non_azure_resources = df.filter(pl.col('cloud_provider') != 'Azure')
            if non_azure_resources.height > 0:
                non_empty = non_azure_resources.filter(
                    pl.col('resource/tag:azure:resourceGroupName') != ''
                ).height
                validation_results['non_azure_tags_empty'] = (non_empty == 0)
        
        return validation_results
    
    def get_synchronization_stats(self, df: pl.DataFrame) -> Dict[str, int]:
        """
        Get provider synchronization statistics.
        
        Args:
            df: DataFrame to analyze
            
        Returns:
            Dictionary with synchronization statistics
        """
        if df.height == 0:
            return {
                'total_resources': 0,
                'gcp_resources': 0,
                'azure_resources': 0,
                'other_provider_resources': 0
            }
        
        stats = {'total_resources': df.height}
        
        if 'cloud_provider' in df.columns:
            stats['gcp_resources'] = df.select((pl.col('cloud_provider') == 'GCP').sum()).item()
            stats['azure_resources'] = df.select((pl.col('cloud_provider') == 'Azure').sum()).item()
            stats['other_provider_resources'] = df.height - stats['gcp_resources'] - stats['azure_resources']
        else:
            stats.update({
                'gcp_resources': 0,
                'azure_resources': 0,
                'other_provider_resources': df.height
            })
        
        return stats