"""
Module: config_cmd
Description: Configuration management commands

Implements:
    - docs/cli/reference.md#huitzo-config
"""

from typing import Any

import typer
from rich.console import Console
from rich.table import Table

from huitzo_cli.auth import AuthClient, TokenStore
from huitzo_cli.config import ConfigManager

console = Console()
config_app = typer.Typer(help="Manage configuration")

_SENSITIVE_PATTERNS = ("token", "secret", "key", "password", "credential")


def _is_sensitive(key: str) -> bool:
    k = key.lower()
    return any(p in k for p in _SENSITIVE_PATTERNS)


@config_app.callback(invoke_without_command=True)
def config_callback(ctx: typer.Context) -> None:
    """Manage configuration - get, set, list, and view config files."""
    if ctx.invoked_subcommand is None:
        console.print(ctx.get_help())
        raise typer.Exit(0)


@config_app.command()
def get(
    key: str,
    reveal: bool = typer.Option(False, "--reveal", help="Show sensitive values unmasked"),
) -> None:
    """Get configuration value.

    Args:
        key: Configuration key (e.g., 'api_url' or 'auth.token')
    """
    # auth.token lives in TokenStore, not config.yaml
    if key == "auth.token":
        config = ConfigManager()
        auth = AuthClient(config)
        value = auth.get_token()
        if value is None:
            console.print("[yellow]Not authenticated. Run: huitzo login[/yellow]")
            raise typer.Exit(1)
        display = "********" if not reveal else value
        console.print(f"{key} = {display}")
        return

    config = ConfigManager()
    value = config.get(key)

    if value is None:
        console.print(f"[yellow]{key} not set[/yellow]")
        raise typer.Exit(1)

    if _is_sensitive(key) and not reveal:
        display = "********"
    else:
        display = value
    console.print(f"{key} = {display}")


@config_app.command()
def set(
    key: str,
    value: str | None = typer.Argument(None, help="Value to set (prompted for sensitive keys)"),
    scope: str = typer.Option("user", "--scope", help="Config scope (user or project)"),
) -> None:
    """Set configuration value.

    For sensitive keys (containing 'token', 'secret', 'key', 'password',
    'credential'), the value is always prompted interactively with hidden
    input to prevent exposure in shell history.

    Args:
        key: Configuration key (e.g., 'auth.token')
        value: Value to set (ignored for sensitive keys)
    """
    # auth.token is stored in TokenStore, not config.yaml
    if key == "auth.token":
        console.print("[yellow]Prefer 'huitzo login' to set auth tokens.[/yellow]")
        # Always prompt interactively — ignore positional arg to avoid shell history leak
        token_value = typer.prompt(f"Value for {key}", hide_input=True)
        TokenStore().save(token_value)
        console.print(f"[green]{key} updated[/green]")
        return

    config = ConfigManager()

    if _is_sensitive(key):
        # Always prompt interactively for sensitive keys
        value = typer.prompt(f"Value for {key}", hide_input=True)
    elif value is None:
        value = typer.prompt(f"Value for {key}")

    try:
        config.set(key, value, scope=scope)
        if _is_sensitive(key):
            console.print(f"[green]{key} updated[/green]")
        else:
            console.print(f"[green]{key} set to {value}[/green]")
    except Exception as e:
        console.print(f"[red]Failed to set {key}: {e}[/red]")
        raise typer.Exit(1)


@config_app.command(name="list")
def list_config() -> None:
    """List all configuration."""
    config = ConfigManager()
    config_dict = config.to_dict()

    table = Table(title="Configuration")
    table.add_column("Key", style="cyan")
    table.add_column("Value", style="green")

    def flatten_dict(d: dict[str, Any], parent_key: str = "") -> list[tuple[str, str]]:
        items = []
        for k, v in d.items():
            new_key = f"{parent_key}.{k}" if parent_key else k
            if isinstance(v, dict):
                items.extend(flatten_dict(v, new_key))
            else:
                items.append((new_key, str(v)))
        return items

    for key, value in flatten_dict(config_dict):
        display = "********" if _is_sensitive(key) else value
        table.add_row(key, display)

    console.print(table)


@config_app.command()
def path(
    scope: str = typer.Option("user", "--scope", help="Config scope (user or project)"),
) -> None:
    """Show configuration file path.

    Args:
        scope: Config scope (user or project)
    """
    config = ConfigManager()
    config_path = config.get_config_path(scope=scope)
    console.print(f"[cyan]{scope.capitalize()} config:[/cyan] {config_path}")
    console.print(f"[yellow]Exists:[/yellow] {config_path.exists()}")
