from typing import List
"""
CLI commands for anomaly profile discovery and management.

Provides commands to list, inspect, and validate anomaly profiles
that are used for generating realistic cloud cost incidents and events.
"""

import typer
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

from ..profiles.anomaly import (
    get_anomaly_profile,
    get_anomaly_profile_categories,
    get_anomaly_profile_info,
    get_anomaly_profiles_by_category,
    list_anomaly_profiles,
)
from .common.base import BaseCommand


class AnomalyCommand(BaseCommand):
    """Anomaly profile management with service integration."""

    def __init__(self):
        super().__init__()


anomaly_cmd = AnomalyCommand()

app = typer.Typer(
    help="Manage and explore anomaly profiles for realistic cloud cost incidents."
)


@app.command("list")
def list_profiles_cmd(
    category: str = typer.Option(None, "--category", "-c", help="Filter by category"),
):
    """List all available anomaly profiles, optionally filtered by category."""

    if category:
        profiles_dict = get_anomaly_profiles_by_category(category)
        if not profiles_dict:
            anomaly_cmd.console.print(
                f"[bold red]No profiles found in category '{category}'[/bold red]"
            )
            anomaly_cmd.console.print(
                f"Available categories: {', '.join(get_anomaly_profile_categories())}"
            )
            return
        profiles = list(profiles_dict.keys())
        title = f"Anomaly Profiles - {category.replace('_', ' ').title()} Category"
    else:
        profiles = list_anomaly_profiles()
        title = "Available Anomaly Profiles"

    table = Table(title=title, show_header=True, header_style="bold blue")
    table.add_column("Profile Name", style="cyan", no_wrap=True)
    table.add_column("Category", style="green")
    table.add_column("Pattern Type", style="yellow")
    table.add_column("Description", style="dim")

    for profile_name in sorted(profiles):
        info = get_anomaly_profile_info(profile_name)
        # Truncate description for table display
        desc = info["description"]
        if len(desc) > 60:
            desc = desc[:57] + "..."

        table.add_row(
            profile_name,
            info["category"].replace("_", " ").title(),
            info["pattern_type"],
            desc,
        )

    anomaly_cmd.console.print(table)
    anomaly_cmd.console.print(
        "\n💡 Use [bold cyan]czbillgen anomaly show <profile>[/bold cyan] to see details"
    )
    anomaly_cmd.console.print(
        "💡 Use [bold cyan]czbillgen anomaly list --category <category>[/bold cyan] to filter"
    )


@app.command()
def categories():
    """List all anomaly profile categories."""
    categories_list = get_anomaly_profile_categories()

    anomaly_cmd.console.print("[bold blue]Anomaly Profile Categories:[/bold blue]\n")

    for category in categories_list:
        profiles_in_category = get_anomaly_profiles_by_category(category)
        profile_count = len(profiles_in_category)

        anomaly_cmd.console.print(
            f"[bold green]{category.replace('_', ' ').title()}[/bold green] ({profile_count} profiles)"
        )

        # Show first few profile names as examples
        example_profiles = list(profiles_in_category.keys())[:3]
        for profile in example_profiles:
            anomaly_cmd.console.print(f"  • {profile}")
        if len(profiles_in_category) > 3:
            anomaly_cmd.console.print(f"  ... and {len(profiles_in_category) - 3} more")
        anomaly_cmd.console.print("")


@app.command()
def show(profile_name: str):
    """Show detailed information about a specific anomaly profile.

    PROFILE_NAME: Name of the anomaly profile to inspect
    """
    try:
        profile_data = get_anomaly_profile(profile_name)
        info = get_anomaly_profile_info(profile_name)

        # Profile summary
        summary_text = Text()
        summary_text.append("Profile: ", style="bold")
        summary_text.append(f"{profile_name}\n", style="bold cyan")
        summary_text.append("Category: ", style="bold")
        summary_text.append(
            f"{info['category'].replace('_', ' ').title()}\n", style="green"
        )
        summary_text.append("Pattern Type: ", style="bold")
        summary_text.append(f"{info['pattern_type']}\n", style="yellow")
        summary_text.append("Description: ", style="bold")
        summary_text.append(f"{info['description']}", style="dim")

        anomaly_cmd.console.print(
            Panel(summary_text, title="Profile Summary", border_style="blue")
        )

        # Parameters table
        if info["parameters"]:
            table = Table(
                title=f"{profile_name} Parameters",
                show_header=True,
                header_style="bold blue",
            )
            table.add_column("Parameter", style="bold green", no_wrap=True)
            table.add_column("Value", style="yellow")
            table.add_column("Description", style="dim")

            # Parameter descriptions for better UX
            param_descriptions = {
                "magnitude_range": "Min/max cost multiplier range",
                "duration_range": "Min/max duration in hours",
                "recovery_pattern": "How the anomaly recovers",
                "trigger_probability": "Daily probability (0.0-1.0)",
                "timing_preferences": "Preferred timing patterns",
                "cascade_probability": "Chance of triggering other events",
                "recovery_duration": "Time to recover in hours",
                "spike_intervals": "Time between spikes",
                "buildup_duration": "Time to reach peak",
                "decay_half_life": "Half-life for exponential decay",
                "oscillation_amplitude": "Size of oscillations",
                "affected_services": "Number of services impacted",
                "drop_magnitude": "Percentage drop from baseline",
            }

            for param, value in info["parameters"].items():
                description = param_descriptions.get(param, "")
                if isinstance(value, list):
                    value_str = f"[{', '.join(map(str, value))}]"
                else:
                    value_str = str(value)

                table.add_row(param, value_str, description)

            anomaly_cmd.console.print("\n")
            anomaly_cmd.console.print(table)

        # Realistic use cases
        if info["realistic_for"]:
            use_cases_text = "Realistic for:\n"
            for use_case in info["realistic_for"]:
                use_cases_text += f"• {use_case.replace('_', ' ').title()}\n"

            anomaly_cmd.console.print(
                Panel(use_cases_text.strip(), title="Use Cases", border_style="green")
            )

        # Usage example
        usage_text = f"""[bold]Usage in generate config:[/bold]

[dim]# Apply {profile_name} anomaly pattern[/dim]
[cyan]anomaly_profile: "{profile_name}"[/cyan]

[dim]# This will create {info["description"].lower()}[/dim]
[dim]# Pattern type: {info["pattern_type"]}[/dim]"""

        anomaly_cmd.console.print(
            Panel(usage_text, title="Usage Example", border_style="magenta")
        )

    except KeyError as e:
        anomaly_cmd.console.print(f"[bold red]Error:[/bold red] {e}")
        anomaly_cmd.console.print(
            "\n💡 Use [bold cyan]czbillgen anomaly List[/bold cyan] to see available profiles"
        )


@app.command()
def validate():
    """Validate all anomaly profiles for consistency and correctness."""
    profiles = list_anomaly_profiles()
    anomaly_cmd.console.print("[bold blue]Validating anomaly profiles...[/bold blue]\n")

    issues_found = 0

    for profile_name in profiles:
        try:
            profile_data = get_anomaly_profile(profile_name)
            profile_issues = []

            # Check required fields
            required_fields = [
                "description",
                "category",
                "pattern_type",
                "trigger_probability",
            ]
            for field in required_fields:
                if field not in profile_data:
                    profile_issues.append(f"Missing required field: '{field}'")

            # Check description
            if "description" in profile_data:
                desc = profile_data["description"]
                if not desc or len(desc) < 10:
                    profile_issues.append("Description too short or missing")

            # Check category
            if "category" in profile_data:
                valid_categories = get_anomaly_profile_categories()
                if profile_data["category"] not in valid_categories:
                    profile_issues.append(
                        f"Invalid category: '{profile_data['category']}'"
                    )

            # Check probability fields
            probability_fields = ["trigger_probability", "cascade_probability"]
            for field in probability_fields:
                if field in profile_data:
                    value = profile_data[field]
                    if not isinstance(value, (int, float)):
                        profile_issues.append(
                            f"'{field}' must be numeric, got {type(value).__name__}"
                        )
                    elif not (0 <= value <= 1):
                        profile_issues.append(
                            f"'{field}' must be between 0 and 1, got {value}"
                        )

            # Check magnitude ranges
            if "magnitude_range" in profile_data:
                mag_range = profile_data["magnitude_range"]
                if not isinstance(mag_range, list) or len(mag_range) != 2:
                    profile_issues.append(
                        "'magnitude_range' must be a list with exactly 2 elements"
                    )
                elif not all(isinstance(x, (int, float)) for x in mag_range):
                    profile_issues.append("'magnitude_range' elements must be numeric")
                elif mag_range[0] >= mag_range[1]:
                    profile_issues.append(
                        "'magnitude_range' first element must be less than second"
                    )

            # Check duration ranges
            if "duration_range" in profile_data:
                dur_range = profile_data["duration_range"]
                if not isinstance(dur_range, list) or len(dur_range) != 2:
                    profile_issues.append(
                        "'duration_range' must be a list with exactly 2 elements"
                    )
                elif not all(isinstance(x, (int, float)) for x in dur_range):
                    profile_issues.append("'duration_range' elements must be numeric")
                elif dur_range[0] >= dur_range[1]:
                    profile_issues.append(
                        "'duration_range' first element must be less than second"
                    )

            # Report results for this profile
            if profile_issues:
                anomaly_cmd.console.print(f"[bold red]❌ {profile_name}:[/bold red]")
                for issue in profile_issues:
                    anomaly_cmd.console.print(f"   • {issue}")
                issues_found += len(profile_issues)
            else:
                info = get_anomaly_profile_info(profile_name)
                anomaly_cmd.console.print(
                    f"[bold green]✅ {profile_name}:[/bold green] {info['category']} - {info['pattern_type']}"
                )

        except Exception as e:
            anomaly_cmd.console.print(
                f"[bold red]❌ {profile_name}:[/bold red] Validation error: {e}"
            )
            issues_found += 1

    # Summary
    anomaly_cmd.console.print("\n" + "=" * 50)
    if issues_found == 0:
        anomaly_cmd.console.print(
            "[bold green]✅ All anomaly profiles are valid![/bold green]"
        )
    else:
        anomaly_cmd.console.print(
            f"[bold red]❌ Found {issues_found} issues across {len(profiles)} profiles[/bold red]"
        )
        anomaly_cmd.console.print(
            "Please fix the issues above before using the profiles."
        )


@app.command()
def patterns():
    """Show available pattern types and their behaviors."""
    profiles = list_anomaly_profiles()
    pattern_types = {}

    # Group profiles by pattern type
    for profile_name in profiles:
        info = get_anomaly_profile_info(profile_name)
        pattern_type = info["pattern_type"]
        if pattern_type not in pattern_types:
            pattern_types[pattern_type] = []
        pattern_types[pattern_type].append(profile_name)

    anomaly_cmd.console.print("[bold blue]Anomaly Pattern Types:[/bold blue]\n")

    for pattern_type in sorted(pattern_types.keys()):
        profile_list = pattern_types[pattern_type]
        anomaly_cmd.console.print(
            f"[bold green]{pattern_type}[/bold green] ({len(profile_list)} profiles)"
        )

        # Show example profiles
        for profile in profile_list[:2]:  # Show first 2 as examples
            anomaly_cmd.console.print(f"  • {profile}")
        if len(profile_list) > 2:
            anomaly_cmd.console.print(f"  ... and {len(profile_list) - 2} more")
        anomaly_cmd.console.print("")


# App is exported as 'app' for use in main CLI
