"""Interactive prompts for Hikaflow CLI.

Uses questionary for beautiful selection menus, confirmations,
and other interactive terminal prompts.
"""

from __future__ import annotations

from typing import Optional

import questionary
from questionary import Choice, Style
from rich.console import Console
from rich.panel import Panel
from rich.syntax import Syntax

console = Console()

# Custom styling for questionary prompts
HIKAFLOW_STYLE = Style([
    ("qmark", "fg:green bold"),
    ("question", "bold"),
    ("answer", "fg:green"),
    ("pointer", "fg:green bold"),
    ("highlighted", "fg:green bold"),
    ("selected", "fg:green"),
    ("separator", "fg:gray"),
    ("instruction", "fg:gray"),
    ("text", ""),
])


def select_error_to_debug(errors: list[dict]) -> Optional[str]:
    """Interactive error selection.

    Args:
        errors: List of error dictionaries with id, exception_type, message fields.

    Returns:
        Selected error ID or None if cancelled/empty.
    """
    if not errors:
        console.print("[yellow]No errors found in your project.[/]")
        return None

    choices = []
    for e in errors:
        # Truncate message for display
        message = e.get("message", "")[:60]
        if len(e.get("message", "")) > 60:
            message += "..."

        exception_type = e.get("exception_type", "Error")
        error_id = e.get("id", "unknown")
        count = e.get("count", 1)

        # Format: [count] exception_type: message
        title = f"[{count}x] {exception_type}: {message}"

        choices.append(Choice(title=title, value=error_id))

    # Add cancel option
    choices.append(Choice(title="Cancel", value=None))

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


def select_multiple_errors(errors: list[dict]) -> list[str]:
    """Select multiple errors to debug in batch.

    Args:
        errors: List of error dictionaries.

    Returns:
        List of selected error IDs (empty if cancelled).
    """
    if not errors:
        console.print("[yellow]No errors found.[/]")
        return []

    choices = []
    for e in errors:
        message = e.get("message", "")[:50]
        if len(e.get("message", "")) > 50:
            message += "..."

        exception_type = e.get("exception_type", "Error")
        error_id = e.get("id", "unknown")

        title = f"{exception_type}: {message}"
        choices.append(Choice(title=title, value=error_id))

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

    return selected or []


def confirm_fix_application(diff: str, filename: Optional[str] = None) -> bool:
    """Confirm before applying a fix.

    Args:
        diff: The unified diff to display.
        filename: Optional filename being modified.

    Returns:
        True if user confirms, False otherwise.
    """
    console.print()

    if filename:
        console.print(f"[bold]Proposed changes to {filename}:[/]")
    else:
        console.print("[bold]Proposed fix:[/]")

    console.print()
    syntax = Syntax(diff, "diff", theme="monokai", line_numbers=False)
    console.print(Panel(syntax, border_style="green"))
    console.print()

    return questionary.confirm(
        "Apply this fix?",
        default=False,
        style=HIKAFLOW_STYLE,
    ).ask() or False


def select_fix_strategy() -> str:
    """Select fix generation strategy.

    Returns:
        Strategy identifier string.
    """
    return questionary.select(
        "How should I approach this fix?",
        choices=[
            Choice("Fix the code (recommended)", value="fix_code"),
            Choice("Fix the test", value="fix_test"),
            Choice("Add null/None check", value="add_null_check"),
            Choice("Add error handling (try/except)", value="add_error_handling"),
            Choice("Add input validation", value="add_validation"),
            Choice("Let AI decide automatically", value="auto"),
        ],
        style=HIKAFLOW_STYLE,
    ).ask() or "auto"


def confirm_pr_creation(title: str, branch: str) -> bool:
    """Confirm PR creation.

    Args:
        title: PR title.
        branch: Branch name.

    Returns:
        True if user confirms.
    """
    console.print()
    console.print(Panel(
        f"[bold]PR Title:[/] {title}\n"
        f"[bold]Branch:[/] {branch}",
        title="Create Pull Request",
        border_style="green",
    ))
    console.print()

    return questionary.confirm(
        "Create this pull request?",
        default=True,
        style=HIKAFLOW_STYLE,
    ).ask() or False


def select_environment() -> Optional[str]:
    """Select environment to filter errors.

    Returns:
        Environment name or None for all.
    """
    return questionary.select(
        "Which environment?",
        choices=[
            Choice("All environments", value=None),
            Choice("Production", value="production"),
            Choice("Staging", value="staging"),
            Choice("Development", value="development"),
        ],
        style=HIKAFLOW_STYLE,
    ).ask()


def select_time_range() -> str:
    """Select time range for error queries.

    Returns:
        Time range identifier.
    """
    return questionary.select(
        "Time range:",
        choices=[
            Choice("Last 24 hours (recommended)", value="24h"),
            Choice("Last 7 days", value="7d"),
            Choice("Last 30 days", value="30d"),
            Choice("All time", value="all"),
        ],
        style=HIKAFLOW_STYLE,
    ).ask() or "24h"


def prompt_command() -> str:
    """Get free-form command input.

    Returns:
        User input string.
    """
    return questionary.text(
        "What would you like to do?",
        style=HIKAFLOW_STYLE,
    ).ask() or ""


def select_model() -> str:
    """Select AI model to use.

    Returns:
        Model identifier string.
    """
    return questionary.select(
        "Which AI model?",
        choices=[
            Choice("Claude Sonnet 4.5 (recommended)", value="claude-sonnet-4-5-20250929"),
            Choice("Claude Haiku 4.5 (faster)", value="claude-haiku-4-5-20251001"),
            Choice("GPT-5", value="openai:gpt-5"),
            Choice("GPT-5 Mini", value="openai:gpt-5-mini"),
            Choice("Local (Ollama)", value="ollama:llama3.2"),
        ],
        style=HIKAFLOW_STYLE,
    ).ask() or "openai:gpt-5"


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

    Args:
        message: Confirmation message.
        default: Default value if user just presses enter.

    Returns:
        True if confirmed.
    """
    return questionary.confirm(
        message,
        default=default,
        style=HIKAFLOW_STYLE,
    ).ask() or False


def select_from_list(prompt: str, choices: list[str]) -> Optional[str]:
    """Generic selection from a list of strings.

    Args:
        prompt: Question to ask.
        choices: List of string options.

    Returns:
        Selected string or None if cancelled.
    """
    return questionary.select(
        prompt,
        choices=choices,
        style=HIKAFLOW_STYLE,
    ).ask()


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

    Args:
        prompt: Question to ask.
        default: Default value.

    Returns:
        User input string.
    """
    return questionary.text(
        prompt,
        default=default,
        style=HIKAFLOW_STYLE,
    ).ask() or default


def input_password(prompt: str = "Enter token:") -> str:
    """Get password/token input (hidden).

    Args:
        prompt: Question to ask.

    Returns:
        User input string.
    """
    return questionary.password(
        prompt,
        style=HIKAFLOW_STYLE,
    ).ask() or ""


def select_debug_action() -> str:
    """Select next action during debug session.

    Returns:
        Action identifier.
    """
    return questionary.select(
        "What would you like to do next?",
        choices=[
            Choice("Generate a fix", value="fix"),
            Choice("Replay the error", value="replay"),
            Choice("View full transcript", value="transcript"),
            Choice("Search similar errors", value="similar"),
            Choice("Ask a question", value="ask"),
            Choice("Exit debug session", value="exit"),
        ],
        style=HIKAFLOW_STYLE,
    ).ask() or "exit"


def confirm_replay_execution() -> bool:
    """Confirm before running replay.

    Returns:
        True if user confirms.
    """
    console.print()
    console.print(Panel(
        "[bold yellow]Warning:[/] Replay will execute the recorded request against your local environment.\n\n"
        "Make sure:\n"
        "  - Your local server is running\n"
        "  - Database is in a safe state (or use a test database)\n"
        "  - You're not replaying against production",
        title="Replay Confirmation",
        border_style="yellow",
    ))
    console.print()

    return questionary.confirm(
        "Proceed with replay?",
        default=False,
        style=HIKAFLOW_STYLE,
    ).ask() or False


def select_file_to_edit(files: list[str]) -> Optional[str]:
    """Select a file to edit from a list.

    Args:
        files: List of file paths.

    Returns:
        Selected file path or None.
    """
    if not files:
        console.print("[yellow]No files to select.[/]")
        return None

    choices = [Choice(title=f, value=f) for f in files]
    choices.append(Choice(title="Cancel", value=None))

    return questionary.select(
        "Which file would you like to edit?",
        choices=choices,
        style=HIKAFLOW_STYLE,
    ).ask()


def confirm_branch_switch(branch: str) -> bool:
    """Confirm before switching git branches.

    Args:
        branch: Target branch name.

    Returns:
        True if user confirms.
    """
    return questionary.confirm(
        f"Switch to branch '{branch}'?",
        default=True,
        style=HIKAFLOW_STYLE,
    ).ask() or False


def select_commit_files(files: list[str]) -> list[str]:
    """Select files to include in commit.

    Args:
        files: List of modified files.

    Returns:
        List of selected files.
    """
    if not files:
        return []

    choices = [Choice(title=f, value=f, checked=True) for f in files]

    selected = questionary.checkbox(
        "Select files to commit:",
        choices=choices,
        style=HIKAFLOW_STYLE,
    ).ask()

    return selected or []


def input_commit_message() -> str:
    """Get commit message from user.

    Returns:
        Commit message string.
    """
    return questionary.text(
        "Commit message:",
        style=HIKAFLOW_STYLE,
    ).ask() or ""
