"""Run command for executing scry-run apps."""

import json
import os
import subprocess

import click
from rich.console import Console

from scry_run.home import get_app_dir
from scry_run.config import load_config, get_env_vars
from scry_run.packages import ensure_scry_run_installed

console = Console()


def load_app_settings(app_dir) -> dict:
    """Load per-app settings from settings.json."""
    settings_file = app_dir / "settings.json"
    if settings_file.exists():
        try:
            return json.loads(settings_file.read_text())
        except (json.JSONDecodeError, OSError):
            return {}
    return {}


@click.command(context_settings={"ignore_unknown_options": True, "allow_extra_args": True})
@click.option("--quiet", "-q", is_flag=True, help="Suppress status messages (for TUI apps)")
@click.argument("app_name")
@click.argument("args", nargs=-1, type=click.UNPROCESSED)
@click.pass_context
def run(ctx, quiet: bool, app_name: str, args: tuple[str, ...]) -> None:
    """Run an scry-run app.

    Loads config from ~/.scry-run/config.toml, converts to env vars,
    and executes the app with the provided arguments.

    Examples:

        scry-run run todo-app
        scry-run run todo-app add "Buy milk"
        scry-run run todo-app --help
        scry-run run --quiet my-tui-app
    """
    # Find app
    app_dir = get_app_dir(app_name)
    app_py = app_dir / "app.py"

    if not app_py.exists():
        console.print(f"[red]Error:[/red] App '{app_name}' not found.")
        console.print(f"[dim]Expected at: {app_py}[/dim]")
        console.print()
        console.print("Create it with:")
        console.print(f"  [cyan]scry-run init --name {app_name} --description '...'[/cyan]")
        ctx.exit(1)

    # Load per-app settings
    app_settings = load_app_settings(app_dir)
    default_flags = app_settings.get("default_flags", {})

    # Load config and convert to env vars
    config = load_config()
    env_vars = get_env_vars(config)

    # Merge with current environment (env_vars already respects existing env vars)
    env = os.environ.copy()
    env.update(env_vars)

    # Set quiet mode if requested via flag OR app default
    # CLI flag takes precedence over app settings
    use_quiet = quiet or default_flags.get("quiet", False)
    if use_quiet:
        env["SCRY_QUIET"] = "1"

    # Clear venv-related environment variables to prevent interference
    # from an activated venv (uv run --directory will use the app's venv)
    env.pop("VIRTUAL_ENV", None)
    env.pop("PYTHONHOME", None)
    # Remove activated venv's bin dir from PATH if present
    if "VIRTUAL_ENV" in os.environ:
        venv_bin = os.path.join(os.environ["VIRTUAL_ENV"], "bin")
        path_parts = env.get("PATH", "").split(os.pathsep)
        path_parts = [p for p in path_parts if p != venv_bin]
        env["PATH"] = os.pathsep.join(path_parts)

    # Ensure app has scry-run installed
    ensure_scry_run_installed(app_dir)

    # Build command
    cmd = ["uv", "run", "--directory", str(app_dir), "python", str(app_py)] + list(args)

    # Run app
    result = subprocess.run(cmd, env=env)
    ctx.exit(result.returncode)
