"""
iq config commands - Manage configuration files.
"""

from __future__ import annotations

import os
from pathlib import Path

import click

from iq_sdk.cli import (
    console,
    get_template_path,
    render_template,
    save_config_file,
)
from iq_sdk.config import (
    find_config_file,
    load_settings,
)


def get_project_root() -> Path:
    """
    Get project root directory.

    Uses active project from registry, or current directory as fallback.
    """
    from iq_sdk.cli.project import get_active_project

    active = get_active_project()
    if active:
        return active
    return Path.cwd()


def get_config_dir() -> Path:
    """Get config directory relative to project root."""
    return get_project_root() / "config"


@click.group(name="config", context_settings={"help_option_names": ["-h", "--help"]})
def config() -> None:
    """Manage configuration files."""
    pass


@config.command("add")
@click.argument("name", default="settings")
@click.option("--force", "-f", is_flag=True, help="Overwrite existing file")
def config_add(name: str, force: bool) -> None:
    """
    Create a new configuration file.

    NAME is the config name (without path/extension).
    Creates config/{NAME}.yml
    """
    output_path = get_config_dir() / f"{name}.yml"

    if output_path.exists() and not force:
        console.print(f"[yellow]Config '{name}' already exists: {output_path}[/yellow]")
        if not click.confirm("Overwrite?"):
            raise click.Abort()

    # Ensure config directory exists
    get_config_dir().mkdir(parents=True, exist_ok=True)

    template_file = get_template_path("project") / "config" / "settings.yml.j2"
    context = {"name": Path.cwd().name}

    if template_file.exists():
        render_template(template_file, output_path, context)
    else:
        # Fallback: create default config
        default_config = {
            "project_name": context["name"],
            "version": "0.1.0",
            "site": {
                "id": "default",
                "host": "http://localhost:3000",
                "user": "",
            },
            "sites": [],
            "worker": {
                "threads": 1,
                "min_threads": 1,
                "max_threads": 16,
                "autoscale": False,
            },
            "logging": {
                "level": "INFO",
            },
        }
        save_config_file(output_path, default_config)

    console.print(f"[bold green]✓ Created {output_path}[/bold green]")


@config.command("ls")
def config_ls() -> None:
    """List all configuration files in config/ directory."""
    if not get_config_dir().exists():
        console.print("[yellow]No config/ directory found[/yellow]")
        console.print("Run 'iq config create' to create a configuration file.")
        return

    configs = sorted(get_config_dir().glob("*.yml")) + sorted(get_config_dir().glob("*.yaml"))

    if not configs:
        console.print("[yellow]No configuration files found in config/[/yellow]")
        console.print("Run 'iq config create' to create a configuration file.")
        return

    # Find active config
    active_config = find_config_file(os.environ.get("IQ_CONFIG"))
    active_name = active_config.stem if active_config else "settings"

    console.print("[bold]Configuration Files[/bold]\n")
    for cfg in configs:
        name = cfg.stem
        is_active = name == active_name
        marker = " [green](active)[/green]" if is_active else ""
        console.print(f"  {name}{marker}")
        console.print(f"    [dim]{cfg}[/dim]")


@config.command("rm")
@click.argument("name")
@click.option("--force", "-f", is_flag=True, help="Skip confirmation")
def config_rm(name: str, force: bool) -> None:
    """
    Delete a configuration file.

    NAME is the config name (without path/extension).
    Deletes config/{NAME}.yml
    """
    config_path = get_config_dir() / f"{name}.yml"

    if not config_path.exists():
        # Try .yaml extension
        config_path = get_config_dir() / f"{name}.yaml"

    if not config_path.exists():
        console.print(f"[red]Config '{name}' not found[/red]")
        return

    if name == "settings" and not force:
        console.print("[yellow]Warning: You are deleting the default config![/yellow]")

    if not force:
        if not click.confirm(f"Delete {config_path}?"):
            raise click.Abort()

    config_path.unlink()
    console.print(f"[bold green]✓ Deleted {config_path}[/bold green]")


def _truncate(value: str, max_len: int = 25) -> str:
    """Truncate a string if too long."""
    if len(value) > max_len:
        return f"{value[: max_len - 2]}.."
    return value


def _add_config_row(
    table,
    option: str,
    config_value: str,
    env_name: str,
    indent: int = 0,
    is_secret: bool = False,
) -> None:
    """
    Add a row to the config table.

    Shows config value and ENV override. When ENV is set, the ENV value
    takes precedence and is highlighted.

    Args:
        is_secret: If True, mask the ENV value (show ✓ instead of value)
    """
    from rich.text import Text

    from iq_sdk.cli.project import was_loaded_from_dotenv

    env_value = os.environ.get(env_name) if env_name else None
    is_from_dotenv = was_loaded_from_dotenv(env_name) if env_name else False

    prefix = "  " * indent
    option_text = Text(f"{prefix}{option}")

    if env_value is not None:
        # ENV overrides config - show config as dim, ENV as highlighted
        config_text = Text(_truncate(str(config_value), 20), style="dim")
        env_name_text = Text(env_name, style="cyan")

        # Format ENV value - mask secrets
        if is_secret:
            # Show checkmark instead of value for secrets
            if is_from_dotenv:
                env_value_text = Text("✓ ", style="green bold")
                env_value_text.append("(.env)", style="cyan dim")
            else:
                env_value_text = Text("✓", style="green bold")
        elif env_value == "":
            display_val = "(empty)"
            if is_from_dotenv:
                env_value_text = Text(f"{display_val} ", style="cyan bold")
                env_value_text.append("(.env)", style="cyan dim")
            else:
                env_value_text = Text(display_val, style="cyan bold")
        else:
            display_val = _truncate(env_value, 15)
            if is_from_dotenv:
                env_value_text = Text(f"{display_val} ", style="cyan bold")
                env_value_text.append("(.env)", style="cyan dim")
            else:
                env_value_text = Text(display_val, style="cyan bold")
    else:
        # No ENV override - config value is active
        config_text = Text(_truncate(str(config_value), 20))
        env_name_text = Text(env_name, style="dim") if env_name else Text("")
        env_value_text = Text("-", style="dim")

    table.add_row(option_text, config_text, env_name_text, env_value_text)


@config.command("show")
@click.pass_context
def config_show(ctx: click.Context) -> None:
    """
    Show current configuration with ENV overrides.

    Displays the active configuration in a hierarchical table,
    showing ENV variable names and their values if set.
    """
    from rich.table import Table

    config_file = ctx.obj.get("config_file") if ctx.obj else None

    found_file = find_config_file(config_file)
    if found_file:
        console.print(f"[dim]Config: {found_file}[/dim]\n")
    else:
        console.print("[dim]Config: (defaults, no file found)[/dim]\n")

    settings = load_settings(config_file)

    # Create table
    table = Table(
        show_header=True,
        header_style="bold",
        border_style="dim",
        expand=False,
        padding=(0, 1),
    )
    table.add_column("Option", style="white", no_wrap=True)
    table.add_column("Config", style="white")
    table.add_column("ENV Variable", style="dim")
    table.add_column("ENV Override", style="dim")

    from rich.text import Text

    def section_header(text: str) -> Text:
        return Text(text, style="bold cyan")

    # === Project ===
    table.add_row(section_header("Project"), "", "", "")
    _add_config_row(table, "Name", settings.project_name, "IQ_PROJECT_NAME", indent=1)
    _add_config_row(table, "Version", settings.version, "IQ_VERSION", indent=1)

    # Worker ID
    worker_id = settings.get_worker_id()
    env_worker_id = os.environ.get("IQ_WORKER_ID")
    if not env_worker_id and not settings.worker_id:
        worker_display = f"{worker_id} (auto)"
    else:
        worker_display = worker_id
    _add_config_row(table, "Worker ID", worker_display, "IQ_WORKER_ID", indent=1)

    # === Sites ===
    all_sites = settings.get_sites()
    active_sites = [s for s in all_sites if s.is_active()]

    table.add_row("", "", "", "")  # Spacer
    table.add_row(
        section_header(f"Sites ({len(active_sites)}/{len(all_sites)} active)"), "", "", ""
    )

    for site in all_sites:
        site_id_upper = site.id.upper().replace("-", "_")
        is_default = site.id == settings.site.id
        is_active = site.is_active()

        # Site header
        site_header = Text(f"  {site.id}", style="bold")
        if is_default:
            site_header.append(" (default)", style="dim")
        if not is_active:
            site_header.append(" (inactive)", style="red")
        table.add_row(site_header, "", "", "")

        # Active (raw config value)
        active_env = f"IQ_SITE_{site_id_upper}_ACTIVE"
        config_active = "true" if site.active else "false"
        _add_config_row(table, "Active", config_active, active_env, indent=2)

        # Host (raw config value)
        host_env = f"IQ_SITE_{site_id_upper}_HOST"
        config_host = site.host
        _add_config_row(table, "Host", config_host, host_env, indent=2)

        # API Key (show checkmark if set, not the actual value)
        api_key_env = f"IQ_SITE_{site_id_upper}_API_KEY"
        config_has_key = bool(site.api_key)
        config_api_key = "✓" if config_has_key else "-"
        _add_config_row(table, "API Key", config_api_key, api_key_env, indent=2, is_secret=True)

        # API Secret (show checkmark if set, not the actual value)
        secret_env = f"IQ_SITE_{site_id_upper}_API_SECRET"
        secret_file_env = f"IQ_SITE_{site_id_upper}_API_SECRET_FILE"
        env_secret = os.environ.get(secret_env)
        env_secret_file = os.environ.get(secret_file_env)

        # Config value: check if secret is set in config (not from ENV)
        config_has_secret = bool(site.api_secret)
        secret_display = "✓" if config_has_secret else "✗"

        # Determine which ENV var is active
        if env_secret is not None:
            active_secret_env = secret_env
        elif env_secret_file is not None:
            active_secret_env = secret_file_env
        else:
            active_secret_env = secret_env

        _add_config_row(
            table, "API Secret", secret_display, active_secret_env, indent=2, is_secret=True
        )

        # Tools
        tools = site.get_tools()
        tools_display = ", ".join(t.name for t in tools) if tools else "-"
        _add_config_row(table, "Tools", tools_display, "", indent=2)

    # === Worker ===
    table.add_row("", "", "", "")  # Spacer
    table.add_row(section_header("Worker"), "", "", "")

    _add_config_row(table, "Threads", str(settings.worker.threads), "IQ_WORKER_THREADS", indent=1)
    _add_config_row(
        table, "Autoscale", str(settings.worker.autoscale), "IQ_WORKER_AUTOSCALE", indent=1
    )

    if settings.worker.autoscale:
        range_str = f"{settings.worker.min_threads}-{settings.worker.max_threads}"
        _add_config_row(table, "Thread Range", range_str, "", indent=1)

    # === Logging ===
    table.add_row("", "", "", "")  # Spacer
    table.add_row(section_header("Logging"), "", "", "")

    _add_config_row(table, "Level", settings.logging.level, "IQ_LOGGING_LEVEL", indent=1)

    console.print(table)
