"""
Unified Profile System for CloudZero Billing Generator

Consolidates all profiles into one clean system:
- 9 Metadata Profiles: For realistic cloud resource metadata
- 10 Variance Profiles: For cost variance patterns with enhanced algorithms
- 10 Anomaly Profiles: For cost anomaly patterns with type differentiation

All profiles use standard interfaces and are designed for pipeline configuration.
"""

from dataclasses import asdict, dataclass
from typing import (
    Any,
    Dict,
    List,
    Union,
)

# Import existing profile systems
from .core_profiles import (
    CORE_ANOMALY_PROFILES,
    CORE_VARIANCE_PROFILES,
    AnomalyProfile,
    VarianceProfile,
)
from .metadata.profiles import METADATA_PROFILES


@dataclass
class MetadataProfile:
    """Standard metadata profile for cloud resource metadata."""

    name: str
    description: str
    profile_type: str = "metadata"
    canonical_count: int = 0
    total_variants: int = 0
    canonical_values: List[str] = None

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary for JSON serialization."""
        return asdict(self)


# Create metadata profile wrappers
UNIFIED_METADATA_PROFILES = {}

for profile_name, profile_data in METADATA_PROFILES.items():
    # Skip pattern-based profiles (these are configurations, not profiles)
    if "pattern" in profile_name or "strategy" in profile_name:
        continue

    canonical_values = list(profile_data.keys())
    total_variants = 0

    for canonical_value in canonical_values:
        if (
            isinstance(profile_data[canonical_value], dict)
            and "variants" in profile_data[canonical_value]
        ):
            total_variants += len(profile_data[canonical_value]["variants"])

    # Create descriptions for each metadata profile
    descriptions = {
        "regions": "AWS regions with usage weights for realistic geographic distribution",
        "products": "Product names with common variants and misspellings for realistic metadata",
        "features": "Feature names with variants representing real-world inconsistencies",
        "teams": "Engineering team names with typical naming variations",
        "business_units": "Business unit names with common abbreviations and variants",
        "cost_centers": "Cost center codes with formatting variations",
        "environments": "Environment names (prod, staging, dev) with weights and variants",
    }

    UNIFIED_METADATA_PROFILES[profile_name] = MetadataProfile(
        name=profile_name,
        description=descriptions.get(
            profile_name, f"Metadata profile for {profile_name}"
        ),
        canonical_count=len(canonical_values),
        total_variants=total_variants,
        canonical_values=canonical_values,
    )


class UnifiedProfileSystem:
    """Unified system for managing all profile types."""

    @staticmethod
    def get_profile_types() -> List[str]:
        """Get all available profile types."""
        return ["metadata", "variance", "anomaly"]

    @staticmethod
    def list_profiles(profile_type: str) -> List[str]:
        """List all profiles of a given type."""
        if profile_type == "metadata":
            return list(UNIFIED_METADATA_PROFILES.keys())
        elif profile_type == "variance":
            return list(CORE_VARIANCE_PROFILES.keys())
        elif profile_type == "anomaly":
            return list(CORE_ANOMALY_PROFILES.keys())
        else:
            raise ValueError(f"Unknown profile type: {profile_type}")

    @staticmethod
    def get_profile(
        profile_type: str, profile_name: str
    ) -> Union[MetadataProfile, VarianceProfile, AnomalyProfile]:
        """Get a specific profile by type and name."""
        if profile_type == "metadata":
            if profile_name not in UNIFIED_METADATA_PROFILES:
                available = list(UNIFIED_METADATA_PROFILES.keys())
                raise ValueError(
                    f"Metadata profile '{profile_name}' not found. Available: {available}"
                )
            return UNIFIED_METADATA_PROFILES[profile_name]

        elif profile_type == "variance":
            if profile_name not in CORE_VARIANCE_PROFILES:
                available = list(CORE_VARIANCE_PROFILES.keys())
                raise ValueError(
                    f"Variance profile '{profile_name}' not found. Available: {available}"
                )
            return CORE_VARIANCE_PROFILES[profile_name]

        elif profile_type == "anomaly":
            if profile_name not in CORE_ANOMALY_PROFILES:
                available = list(CORE_ANOMALY_PROFILES.keys())
                raise ValueError(
                    f"Anomaly profile '{profile_name}' not found. Available: {available}"
                )
            return CORE_ANOMALY_PROFILES[profile_name]

        else:
            raise ValueError(f"Unknown profile type: {profile_type}")

    @staticmethod
    def find_profile(profile_name: str) -> Dict[str, Any]:
        """Find a profile by name across all types."""
        for profile_type in ["metadata", "variance", "anomaly"]:
            try:
                profile = UnifiedProfileSystem.get_profile(profile_type, profile_name)
                return {"profile": profile, "type": profile_type, "name": profile_name}
            except ValueError:
                continue

        # Get all available profiles for error message
        all_profiles = []
        for ptype in ["metadata", "variance", "anomaly"]:
            all_profiles.extend(UnifiedProfileSystem.list_profiles(ptype))

        raise ValueError(
            f"Profile '{profile_name}' not found. Available profiles: {sorted(all_profiles)}"
        )

    @staticmethod
    def get_all_profiles() -> Dict[str, Dict[str, Any]]:
        """Get all profiles organized by type."""
        return {
            "metadata": UNIFIED_METADATA_PROFILES,
            "variance": CORE_VARIANCE_PROFILES,
            "anomaly": CORE_ANOMALY_PROFILES,
        }

    @staticmethod
    def get_profile_summary() -> Dict[str, int]:
        """Get summary counts of all profile types."""
        return {
            "metadata": len(UNIFIED_METADATA_PROFILES),
            "variance": len(CORE_VARIANCE_PROFILES),
            "anomaly": len(CORE_ANOMALY_PROFILES),
            "total": len(UNIFIED_METADATA_PROFILES)
            + len(CORE_VARIANCE_PROFILES)
            + len(CORE_ANOMALY_PROFILES),
        }

    @staticmethod
    def validate_profile_exists(profile_name: str, profile_type: str) -> bool:
        """Validate that a profile exists (used by generate stage)."""
        try:
            UnifiedProfileSystem.get_profile(profile_type, profile_name)
            return True
        except ValueError:
            return False

    @staticmethod
    def to_json_serializable(
        profile: Union[MetadataProfile, VarianceProfile, AnomalyProfile],
    ) -> Dict[str, Any]:
        """Convert any profile to JSON-serializable dictionary."""
        if hasattr(profile, "to_dict"):
            return profile.to_dict()
        elif hasattr(profile, "__dict__"):
            # Convert dataclass to dict
            return asdict(profile)
        else:
            # Fallback for other types
            return {"profile": str(profile), "type": type(profile).__name__}


# Convenience functions for backward compatibility and easy access
def get_metadata_profile(profile_name: str) -> MetadataProfile:
    """Get a metadata profile by name."""
    return UnifiedProfileSystem.get_profile("metadata", profile_name)


def get_variance_profile(profile_name: str) -> VarianceProfile:
    """Get a variance profile by name."""
    return UnifiedProfileSystem.get_profile("variance", profile_name)


def get_anomaly_profile(profile_name: str) -> AnomalyProfile:
    """Get an anomaly profile by name."""
    return UnifiedProfileSystem.get_profile("anomaly", profile_name)


def list_metadata_profiles() -> List[str]:
    """List all metadata profiles."""
    return UnifiedProfileSystem.list_profiles("metadata")


def list_variance_profiles() -> List[str]:
    """List all variance profiles."""
    return UnifiedProfileSystem.list_profiles("variance")


def list_anomaly_profiles() -> List[str]:
    """List all anomaly profiles."""
    return UnifiedProfileSystem.list_profiles("anomaly")


def validate_profile_exists(profile_name: str, profile_type: str) -> bool:
    """Validate that a profile exists - used by generate stage validation."""
    return UnifiedProfileSystem.validate_profile_exists(profile_name, profile_type)


# Create global registry instance
registry = UnifiedProfileSystem()
