"""Interactive CLI prompts for user interaction.

Provides questionary-based prompts for selecting errors, confirming actions,
and gathering user input in the CLI.
"""

from __future__ import annotations

from typing import Any, Dict, List, Optional

import questionary


def select_error_to_debug(errors: List[Dict[str, Any]]) -> Optional[str]:
    """Prompt user to select an error to debug.

    Args:
        errors: List of error dicts with id, exception_type, message, count

    Returns:
        Selected error ID or None if cancelled/empty
    """
    if not errors:
        return None

    choices = []
    for error in errors:
        count = error.get("count", 1)
        label = f"{error['exception_type']}: {error['message'][:50]} ({count}x)"
        choices.append(questionary.Choice(title=label, value=error["id"]))

    result = questionary.select(
        "Which error would you like to debug?",
        choices=choices,
    ).ask()

    return result


def select_multiple_errors(errors: List[Dict[str, Any]]) -> List[str]:
    """Prompt user to select multiple errors.

    Args:
        errors: List of error dicts with id, exception_type, message

    Returns:
        List of selected error IDs (empty if cancelled)
    """
    if not errors:
        return []

    choices = []
    for error in errors:
        label = f"{error['exception_type']}: {error['message'][:50]}"
        choices.append(questionary.Choice(title=label, value=error["id"]))

    result = questionary.checkbox(
        "Select errors to debug (space to select, enter to confirm):",
        choices=choices,
    ).ask()

    return result if result else []


def confirm_fix_application(diff: str) -> bool:
    """Prompt user to confirm applying a fix.

    Args:
        diff: The diff content to display

    Returns:
        True if user confirms, False otherwise
    """
    print("\nProposed fix:")
    print("-" * 40)
    print(diff)
    print("-" * 40)

    result = questionary.confirm(
        "Apply this fix?",
        default=False,
    ).ask()

    return result if result is not None else False


def select_fix_strategy() -> str:
    """Prompt user to select a fix strategy.

    Returns:
        Selected strategy name or 'auto' if cancelled
    """
    choices = [
        questionary.Choice(title="Auto (let AI decide)", value="auto"),
        questionary.Choice(title="Fix code", value="fix_code"),
        questionary.Choice(title="Add validation", value="add_validation"),
        questionary.Choice(title="Add error handling", value="add_error_handling"),
        questionary.Choice(title="Refactor", value="refactor"),
    ]

    result = questionary.select(
        "Select fix strategy:",
        choices=choices,
    ).ask()

    return result if result else "auto"


def confirm_pr_creation(title: str, branch: str) -> bool:
    """Prompt user to confirm PR creation.

    Args:
        title: PR title
        branch: Target branch name

    Returns:
        True if user confirms, False otherwise
    """
    print(f"\nPR Title: {title}")
    print(f"Branch: {branch}")

    result = questionary.confirm(
        "Create this pull request?",
        default=True,
    ).ask()

    return result if result is not None else False


def select_environment() -> Optional[str]:
    """Prompt user to select an environment.

    Returns:
        Selected environment or None for all environments
    """
    choices = [
        questionary.Choice(title="All environments", value=None),
        questionary.Choice(title="Production", value="production"),
        questionary.Choice(title="Staging", value="staging"),
        questionary.Choice(title="Development", value="development"),
        questionary.Choice(title="Test", value="test"),
    ]

    result = questionary.select(
        "Select environment:",
        choices=choices,
    ).ask()

    return result


def select_time_range() -> str:
    """Prompt user to select a time range.

    Returns:
        Selected time range (e.g., '24h', '7d') or '24h' if cancelled
    """
    choices = [
        questionary.Choice(title="Last hour", value="1h"),
        questionary.Choice(title="Last 24 hours", value="24h"),
        questionary.Choice(title="Last 7 days", value="7d"),
        questionary.Choice(title="Last 30 days", value="30d"),
        questionary.Choice(title="All time", value="all"),
    ]

    result = questionary.select(
        "Select time range:",
        choices=choices,
    ).ask()

    return result if result else "24h"


def select_model() -> str:
    """Prompt user to select an AI model.

    Returns:
        Selected model identifier or 'openai:gpt-5' if cancelled
    """
    choices = [
        questionary.Choice(title="Claude Sonnet 4.5 (recommended)", value="claude-sonnet-4-5-20250929"),
        questionary.Choice(title="Claude Haiku 4.5 (faster)", value="claude-haiku-4-5-20251001"),
        questionary.Choice(title="GPT-5", value="openai:gpt-5"),
        questionary.Choice(title="GPT-5 Mini", value="openai:gpt-5-mini"),
    ]

    result = questionary.select(
        "Select AI model:",
        choices=choices,
    ).ask()

    return result if result else "openai:gpt-5"


def confirm_action(message: str, default: bool = False) -> bool:
    """Generic confirmation prompt.

    Args:
        message: Confirmation message to display
        default: Default value if user presses enter

    Returns:
        True if user confirms, False otherwise
    """
    result = questionary.confirm(
        message,
        default=default,
    ).ask()

    return result if result is not None else default


def select_debug_action() -> str:
    """Prompt user to select a debug action.

    Returns:
        Selected action or 'exit' if cancelled
    """
    choices = [
        questionary.Choice(title="Replay request", value="replay"),
        questionary.Choice(title="View transcript", value="transcript"),
        questionary.Choice(title="Generate fix", value="fix"),
        questionary.Choice(title="Export data", value="export"),
        questionary.Choice(title="Exit", value="exit"),
    ]

    result = questionary.select(
        "Select debug action:",
        choices=choices,
    ).ask()

    return result if result else "exit"


def input_text(prompt: str, default: str = "") -> str:
    """Prompt user for text input.

    Args:
        prompt: Prompt message to display
        default: Default value if user cancels

    Returns:
        User input or default if cancelled
    """
    result = questionary.text(
        prompt,
        default=default,
    ).ask()

    return result if result is not None else default


def input_password(prompt: str = "Enter password:") -> str:
    """Prompt user for password input.

    Args:
        prompt: Prompt message to display

    Returns:
        Password or empty string if cancelled
    """
    result = questionary.password(
        prompt,
    ).ask()

    return result if result is not None else ""


__all__ = [
    "select_error_to_debug",
    "select_multiple_errors",
    "confirm_fix_application",
    "select_fix_strategy",
    "confirm_pr_creation",
    "select_environment",
    "select_time_range",
    "select_model",
    "confirm_action",
    "select_debug_action",
    "input_text",
    "input_password",
]
