"""Uninstall logic for Tribunal.

Extracted from ``launcher/cli.py`` to keep that module under the 300-line
target.  The public surface (``_run_uninstall``) is re-exported from cli.py
so existing imports continue to work.
"""

from __future__ import annotations

import json
import shutil
from pathlib import Path

_ALIAS_TOKENS = (
    "# Tribunal",
    "alias tribunal",
    "alias sfc",
    "function tribunal",
    "function sfc",
    ".tribunal/bin/tribunal",
)

_SF_ENV_KEYS = {"SF_WORKER_URL", "SF_WORKER_TOKEN", "CLAUDE_PLUGIN_ROOT", "SF_SESSION_ID"}

_SHELL_CONFIG_NAMES = (
    ".bashrc",
    ".bash_profile",
    ".zshrc",
    ".zprofile",
)


def _remove_alias_basic(cfg: Path) -> None:
    """Remove Tribunal alias lines from *cfg* without the installer package."""
    content = cfg.read_text(errors="replace")
    lines = content.split("\n")
    new_lines = [line for line in lines if not any(token in line for token in _ALIAS_TOKENS)]
    cfg.write_text("\n".join(new_lines))


def _collect_shell_configs_with_alias(home: Path) -> list[Path]:
    """Return shell config files that contain Tribunal alias entries."""
    candidates: list[Path] = [home / name for name in _SHELL_CONFIG_NAMES]
    candidates.append(home / ".config" / "fish" / "config.fish")
    result: list[Path] = []
    for cfg in candidates:
        if not cfg.exists():
            continue
        content = cfg.read_text(errors="replace")
        if any(token in content for token in _ALIAS_TOKENS):
            result.append(cfg)
    return result


def _build_removal_plan(
    plugin_dir: Path,
    settings_path: Path,
    shell_configs: list[Path],
    tribunal_home: Path,
    remove_all: bool,
) -> list[str]:
    """Return human-readable lines describing what will be removed."""
    plan: list[str] = []
    if plugin_dir.exists():
        plan.append(f"  • Remove plugin directory:  {plugin_dir}")
    if settings_path.exists():
        plan.append(f"  • Clean tribunal entries from:  {settings_path}")
    for cfg in shell_configs:
        plan.append(f"  • Remove shell aliases from:  {cfg}")
    if remove_all and tribunal_home.exists():
        plan.append(f"  • Remove user data directory:  {tribunal_home}  [--all]")
    return plan


def _clean_claude_settings(settings_path: Path) -> str | None:
    """Remove Tribunal entries from Claude settings.json.

    Returns an error message string on failure, or None on success.
    """
    try:
        with open(settings_path) as f:
            settings: dict = json.load(f)

        changed = False

        if "hooks" in settings:
            del settings["hooks"]
            changed = True

        env = settings.get("env", {})
        removed_env = [k for k in list(env) if k in _SF_ENV_KEYS]
        for k in removed_env:
            del env[k]
        if removed_env:
            changed = True

        status_cmd = settings.get("statusCommand", "")
        if "tribunal" in str(status_cmd):
            del settings["statusCommand"]
            changed = True

        perms = settings.get("permissions", {})
        allow = perms.get("allow", [])
        new_allow = [p for p in allow if "tribunal" not in str(p).lower()]
        if len(new_allow) != len(allow):
            perms["allow"] = new_allow
            changed = True

        if changed:
            shutil.copy2(settings_path, str(settings_path) + ".bak")
            with open(settings_path, "w") as f:
                json.dump(settings, f, indent=2)
            print(f"[OK] Cleaned {settings_path}")
        else:
            print(f"[--] No tribunal settings found in {settings_path}")

    except (OSError, json.JSONDecodeError) as exc:
        return f"Could not update {settings_path}: {exc}"

    return None


def _remove_shell_aliases(shell_configs: list[Path], errors: list[str]) -> None:
    """Remove Tribunal alias lines from each config in *shell_configs*."""
    for cfg in shell_configs:
        try:
            try:
                from installer.steps.shell_config import remove_old_alias

                if remove_old_alias(cfg):
                    print(f"[OK] Removed aliases from {cfg}")
                else:
                    print(f"[--] No alias found in {cfg}")
            except ImportError:
                _remove_alias_basic(cfg)
                print(f"[OK] Removed aliases from {cfg} (basic)")
        except OSError as exc:
            errors.append(f"Could not modify {cfg}: {exc}")


def _run_uninstall(remove_all: bool = False, yes: bool = False) -> None:
    """Remove Tribunal hooks, plugin directory, and shell aliases.

    What is always removed (with confirmation):
      • ~/.claude/tribunal/           — plugin files
      • hooks/env/permissions entries in ~/.claude/settings.json

    Also removed (requires --all flag):
      • ~/.tribunal/                  — sessions, audit logs, observations

    Shell aliases are removed from .bashrc, .zshrc, and fish config.

    User data (~/.tribunal/) is NEVER removed unless ``--all`` is given.
    """
    home = Path.home()
    plugin_dir = home / ".claude" / "tribunal"
    settings_path = home / ".claude" / "settings.json"
    tribunal_home = home / ".tribunal"
    shell_configs = _collect_shell_configs_with_alias(home)
    plan = _build_removal_plan(plugin_dir, settings_path, shell_configs, tribunal_home, remove_all)

    if not plan:
        print("Nothing to remove — Tribunal does not appear to be installed.")
        return

    print("The following will be removed:\n")
    for line in plan:
        print(line)
    print()

    if not yes:
        try:
            answer = input("Proceed? [y/N] ").strip().lower()
        except (EOFError, KeyboardInterrupt):
            answer = ""
        if answer not in ("y", "yes"):
            print("Aborted.")
            return

    errors: list[str] = []

    if plugin_dir.exists():
        try:
            shutil.rmtree(plugin_dir)
            print(f"[OK] Removed {plugin_dir}")
        except OSError as exc:
            errors.append(f"Could not remove {plugin_dir}: {exc}")

    if settings_path.exists():
        err = _clean_claude_settings(settings_path)
        if err:
            errors.append(err)

    _remove_shell_aliases(shell_configs, errors)

    if remove_all and tribunal_home.exists():
        try:
            shutil.rmtree(tribunal_home)
            print(f"[OK] Removed user data directory {tribunal_home}")
        except OSError as exc:
            errors.append(f"Could not remove {tribunal_home}: {exc}")

    if errors:
        print("\nCompleted with errors:")
        for err in errors:
            print(f"  [!!] {err}")
    else:
        print("\nUninstall complete. Restart your terminal and Claude Code.")
        if not remove_all and tribunal_home.exists():
            print(f"\nUser data preserved at {tribunal_home}")
            print("Run 'tribunal uninstall --all' to also remove it.")
