"""obol disable / obol enable / obol uninstall - control Obol monitoring.

    obol disable        Pause monitoring (removes hooks from settings.json)
    obol enable         Resume monitoring (restores hooks to settings.json)
    obol uninstall      Remove everything (config, hooks, all traces)

Disable/enable work by manipulating Claude Code hooks in ~/.claude/settings.json.
This is the proper mechanism because:
  - It requires the USER to run the command (not the monitored agent)
  - Changes to settings.json are visible in the audit log
  - Claude Code won't call hooks that aren't in settings.json
"""
import json
import os
import sys

DISABLED_HOOKS_PATH = os.path.expanduser("~/.obol/disabled_hooks.json")


def setup_parser(subparsers):
    # Disable
    p = subparsers.add_parser("disable", help="Pause Obol monitoring")
    p.set_defaults(func=cmd_disable)

    # Enable
    p2 = subparsers.add_parser("enable", help="Resume Obol monitoring")
    p2.set_defaults(func=cmd_enable)

    # Uninstall
    p3 = subparsers.add_parser("uninstall", help="Remove Obol completely")
    p3.set_defaults(func=cmd_uninstall)


def cmd_disable(args):
    """Remove hooks from settings.json. Monitoring stops instantly."""
    removed_hooks = _remove_claude_hooks()

    if removed_hooks:
        # Save removed hooks so enable can restore them
        os.makedirs(os.path.dirname(DISABLED_HOOKS_PATH), exist_ok=True)
        with open(DISABLED_HOOKS_PATH, "w") as f:
            json.dump(removed_hooks, f, indent=2)

    print()
    if removed_hooks:
        print("  Obol monitoring paused.")
        print("  Claude Code hooks removed from ~/.claude/settings.json")
        print("  Saved hook config to ~/.obol/disabled_hooks.json")
    else:
        print("  No Obol hooks found in ~/.claude/settings.json")
        print("  Monitoring may already be disabled.")
    print()
    print("  Your config and API key are still saved.")
    print()
    print("  To resume: obol enable")
    print("  To remove everything: obol uninstall")
    print()


def cmd_enable(args):
    """Restore hooks to settings.json from saved config."""
    # First check if hooks are already present
    settings_path = os.path.expanduser("~/.claude/settings.json")
    if os.path.exists(settings_path):
        try:
            with open(settings_path) as f:
                settings = json.load(f)
            hooks = settings.get("hooks", {})
            if any("obol" in json.dumps(v).lower() for v in hooks.values()):
                print()
                print("  Obol hooks are already active in ~/.claude/settings.json")
                print("  Monitoring is already enabled.")
                print()
                return
        except Exception:
            pass

    # Try to restore from saved disabled hooks
    if os.path.exists(DISABLED_HOOKS_PATH):
        try:
            with open(DISABLED_HOOKS_PATH) as f:
                saved_hooks = json.load(f)
        except Exception:
            saved_hooks = None

        if saved_hooks:
            _restore_claude_hooks(saved_hooks)
            # Clean up the disabled hooks file
            try:
                os.remove(DISABLED_HOOKS_PATH)
            except Exception:
                pass
            print()
            print("  Obol monitoring resumed.")
            print("  Claude Code hooks restored to ~/.claude/settings.json")
            print()
            return

    # No saved hooks - rebuild from config
    config_path = os.path.expanduser("~/.obol/config.json")
    if not os.path.exists(config_path):
        print()
        print("  Obol is not set up. Run: obol setup")
        sys.exit(1)

    try:
        with open(config_path) as f:
            config = json.load(f)
    except Exception:
        print()
        print("  Could not read config. Run: obol setup")
        sys.exit(1)

    claude_dir = os.path.expanduser("~/.claude")
    if not os.path.isdir(claude_dir):
        print()
        print("  ~/.claude directory not found. Is Claude Code installed?")
        sys.exit(1)

    _install_claude_hooks(config)
    print()
    print("  Obol monitoring resumed.")
    print("  Claude Code hooks installed in ~/.claude/settings.json")
    print()


def cmd_uninstall(args):
    """Remove everything: hooks, config, all traces."""
    print()

    # Remove Claude Code hooks
    removed = _remove_claude_hooks()
    if removed:
        print("  Claude Code hooks removed.")

    # Remove config (includes disabled_hooks.json)
    config_dir = os.path.expanduser("~/.obol")
    if os.path.isdir(config_dir):
        import shutil
        shutil.rmtree(config_dir, ignore_errors=True)
        print("  Config removed (~/.obol)")

    print()
    print("  Obol is completely removed from this machine.")
    print("  Your account and data on the server are unchanged.")
    print("  To reinstall: pip install obol-sdk && obol setup")
    print()


def _remove_claude_hooks():
    """Remove Obol hooks from Claude Code settings.

    Returns a dict of {event_name: [removed_hook_entries]} if hooks were found,
    or None if no Obol hooks were present.
    """
    settings_path = os.path.expanduser("~/.claude/settings.json")
    if not os.path.exists(settings_path):
        return None

    try:
        with open(settings_path) as f:
            settings = json.load(f)
    except Exception:
        return None

    hooks = settings.get("hooks", {})
    if not hooks:
        return None

    removed = {}
    for event in list(hooks.keys()):
        obol_entries = [
            h for h in hooks[event]
            if "obol" in json.dumps(h).lower()
        ]
        non_obol = [
            h for h in hooks[event]
            if "obol" not in json.dumps(h).lower()
        ]
        if obol_entries:
            removed[event] = obol_entries
            hooks[event] = non_obol
        if not hooks[event]:
            del hooks[event]

    if not removed:
        return None

    if not hooks:
        settings.pop("hooks", None)

    with open(settings_path, "w") as f:
        json.dump(settings, f, indent=2)

    return removed


def _restore_claude_hooks(saved_hooks):
    """Restore previously saved Obol hooks into Claude Code settings."""
    settings_path = os.path.expanduser("~/.claude/settings.json")

    settings = {}
    if os.path.exists(settings_path):
        try:
            with open(settings_path) as f:
                settings = json.load(f)
        except Exception:
            pass

    if "hooks" not in settings:
        settings["hooks"] = {}

    hooks = settings["hooks"]
    for event, entries in saved_hooks.items():
        if event not in hooks:
            hooks[event] = entries
        else:
            # Only add back entries that aren't already present
            existing_json = json.dumps(hooks[event]).lower()
            for entry in entries:
                if "obol" not in existing_json:
                    hooks[event].append(entry)

    with open(settings_path, "w") as f:
        json.dump(settings, f, indent=2)


def _install_claude_hooks(config):
    """Reinstall Obol hooks into Claude Code settings (fresh install)."""
    settings_path = os.path.expanduser("~/.claude/settings.json")
    from obol.cli._base import quote_path

    hook_cmd = f"{quote_path(sys.executable)} -m obol.hooks.claude_code"
    gate_cmd = f"{quote_path(sys.executable)} -m obol.hooks.gate"

    settings = {}
    if os.path.exists(settings_path):
        try:
            with open(settings_path) as f:
                settings = json.load(f)
        except Exception:
            pass

    if "hooks" not in settings:
        settings["hooks"] = {}

    hooks = settings["hooks"]
    obol_hook = {"type": "command", "command": hook_cmd, "timeout": 10}
    obol_gate = {"type": "command", "command": gate_cmd, "timeout": 3}

    hook_events = {
        "PreToolUse": {"matcher": ".*", "hooks": [obol_gate]},
        "PostToolUse": {"matcher": ".*", "hooks": [{**obol_hook, "async": True}]},
        "PostToolUseFailure": {"matcher": ".*", "hooks": [{**obol_hook, "async": True}]},
        "SessionStart": {"hooks": [{**obol_hook, "async": True}]},
        "SessionEnd": {"hooks": [{**obol_hook, "async": True}]},
    }

    for event, handler in hook_events.items():
        if event not in hooks:
            hooks[event] = [handler]
        else:
            existing_json = json.dumps(hooks[event])
            if "obol" not in existing_json:
                hooks[event].append(handler)

    with open(settings_path, "w") as f:
        json.dump(settings, f, indent=2)
