"""Config commands: manage persistent CLI settings and shell completions."""

import os
import re
import sys
from pathlib import Path

import click

from ._core import config_group


# ---------------------------------------------------------------------------
# Shared: ~/.maeris/.env helpers
# ---------------------------------------------------------------------------


def _config_file() -> Path:
    return Path.home() / ".maeris" / ".env"


def _read_config() -> dict[str, str]:
    """Return all KEY=VALUE pairs from ~/.maeris/.env as a dict."""
    cfg = _config_file()
    if not cfg.exists():
        return {}
    _KEY_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
    result: dict[str, str] = {}
    for line in cfg.read_text(encoding="utf-8").splitlines():
        line = line.strip()
        if not line or line.startswith("#"):
            continue
        if "=" in line:
            k, _, v = line.partition("=")
            k = k.strip()
            if not _KEY_RE.match(k):
                import structlog as _sl
                _sl.get_logger(__name__).warning("invalid_config_key_skipped", key=k)
                continue
            result[k] = v.strip()
    return result


def _write_config(data: dict[str, str]) -> None:
    """Rewrite ~/.maeris/.env from a dict, preserving comments."""
    cfg = _config_file()
    cfg.parent.mkdir(parents=True, exist_ok=True)

    existing_lines: list[str] = cfg.read_text(encoding="utf-8").splitlines() if cfg.exists() else []
    updated_keys: set[str] = set()
    new_lines: list[str] = []

    for line in existing_lines:
        stripped = line.strip()
        if stripped.startswith("#") or not stripped:
            new_lines.append(line)
            continue
        if "=" in stripped:
            k = stripped.split("=", 1)[0].strip()
            if k in data:
                new_lines.append(f"{k}={data[k]}")
                updated_keys.add(k)
            else:
                new_lines.append(line)
        else:
            new_lines.append(line)

    for k, v in data.items():
        if k not in updated_keys:
            new_lines.append(f"{k}={v}")

    cfg.write_text("\n".join(new_lines) + "\n", encoding="utf-8")


# ---------------------------------------------------------------------------
# config set
# ---------------------------------------------------------------------------


@config_group.command("set")
@click.argument("key")
@click.argument("value")
def config_set_cmd(key: str, value: str) -> None:
    """Set a persistent CLI configuration value.

    Values are stored in ~/.maeris/.env and loaded on every maeris invocation.

    \b
    Common keys:
      MAERIS_APP_URL      Override the portal URL
      default_model       Default Claude model for scan/generate commands

    \b
    Examples:
      maeris config set MAERIS_APP_URL https://light-dev.up.railway.app
      maeris config set default_model claude-opus-4-6
    """
    current = _read_config()
    current[key] = value
    _write_config(current)
    click.secho(f"✓ {key}={value}", fg="green")
    click.echo(f"  Saved to {_config_file()}")


# ---------------------------------------------------------------------------
# config get
# ---------------------------------------------------------------------------


@config_group.command("get")
@click.argument("key")
def config_get_cmd(key: str) -> None:
    """Get the current value of a CLI configuration key.

    \b
    Examples:
      maeris config get MAERIS_APP_URL
      maeris config get default_model
    """
    current = _read_config()
    # Also check live environment (may be set by shell)
    value = current.get(key) or os.environ.get(key)
    if value is None:
        click.secho(f"✗ Key '{key}' not found in config.", fg="yellow")
        sys.exit(1)
    click.echo(value)


# ---------------------------------------------------------------------------
# config list
# ---------------------------------------------------------------------------


@config_group.command("list")
def config_list_cmd() -> None:
    """List all persistent CLI configuration values.

    \b
    Examples:
      maeris config list
    """
    cfg = _config_file()
    if not cfg.exists():
        click.echo(f"No config file found at {cfg}")
        click.echo("Use 'maeris config set KEY VALUE' to create one.")
        return

    data = _read_config()
    if not data:
        click.echo("Config file is empty.")
        return

    click.echo(f"Config: {cfg}\n")
    max_key = max(len(k) for k in data)
    for k, v in sorted(data.items()):
        click.echo(f"  {k:<{max_key}}  =  {v}")


# ---------------------------------------------------------------------------
# config completions  (moved from auth_cmds.py)
# ---------------------------------------------------------------------------


@config_group.command("completions")
@click.option(
    "--install", "-i",
    is_flag=True,
    default=False,
    help="Append the completion line to your shell config file automatically.",
)
def completions_cmd(install: bool) -> None:
    """Set up shell auto-completion for maeris.

    \b
    Supports bash, zsh, and fish. After running, restart your shell
    (or source your config) and pressing <TAB> after 'maeris' will
    show available commands and options.

    \b
    Examples:
      maeris config completions           # show setup instructions
      maeris config completions --install # append to shell config automatically
    """
    shell_name = Path(os.environ.get("SHELL", "")).name

    completions: dict[str, tuple[str, str]] = {
        "zsh":  ("~/.zshrc",  'eval "$(_MAERIS_COMPLETE=zsh_source maeris)"'),
        "bash": ("~/.bashrc", 'eval "$(_MAERIS_COMPLETE=bash_source maeris)"'),
        "fish": (
            "~/.config/fish/completions/maeris.fish",
            "_MAERIS_COMPLETE=fish_source maeris | source",
        ),
    }

    if shell_name not in completions:
        click.secho(
            f"Shell '{shell_name}' not directly supported.\n"
            "Add one of the following lines manually:",
            fg="yellow",
        )
        for sh, (cfg, line) in completions.items():
            click.echo(f"\n  {click.style(sh, bold=True)} ({cfg}):")
            click.echo(f"    {line}")
        return

    config_file, eval_line = completions[shell_name]

    click.echo(f"\nAdd the following line to {click.style(config_file, bold=True)}:\n")
    click.echo(f"  {click.style(eval_line, fg='cyan')}\n")

    should_install = install
    if not should_install:
        try:
            should_install = click.confirm(f"Append to {config_file} now?", default=True)
        except click.Abort:
            click.echo("\nAborted.")
            return

    if should_install:
        expanded = Path(config_file).expanduser()
        expanded.parent.mkdir(parents=True, exist_ok=True)
        with open(expanded, "a") as f:
            f.write(f"\n# maeris shell completion\n{eval_line}\n")
        click.secho(
            f"✓ Added to {config_file}.\n"
            f"  Activate now with:  source {config_file}",
            fg="green",
        )
    else:
        click.echo(f"Skipped. Run  source {config_file}  after adding the line manually.")
