"""OpenCode agent integration for Vicoa CLI.

This module provides the CLI entry point for running OpenCode with Vicoa integration.
It installs the opencode-vicoa plugin if needed and launches OpenCode with the
appropriate environment variables.
"""

import json
import os
import shutil
import subprocess
import sys
import uuid
from pathlib import Path
from typing import List

PLUGIN_NAME = "@vicoa/opencode"
OPENCODE_CONFIG_PATH = Path.home() / ".config" / "opencode" / "config.json"
OPENCODE_CACHE_PLUGIN_PATH = (
    Path.home() / ".cache" / "opencode" / "node_modules" / PLUGIN_NAME
)


def run_opencode(args, unknown_args: List[str], api_key: str) -> int:
    """Run OpenCode with Vicoa plugin integration.

    This function:
    1. Checks if OpenCode is installed
    2. Ensures opencode-vicoa plugin is installed
    3. Sets up environment variables
    4. Launches OpenCode (plugin loads automatically)

    Args:
        args: Parsed command-line arguments
        unknown_args: Additional arguments to pass through
        api_key: Vicoa API key

    Returns:
        Exit code (0 for success, non-zero for error)
    """
    # Check if OpenCode is installed
    opencode_path = shutil.which("opencode")
    if not opencode_path:
        print("Error: OpenCode not installed", file=sys.stderr)
        print("Install OpenCode from: https://opencode.ai/", file=sys.stderr)
        return 1

    # Handle --upgrade-plugin: upgrade and exit immediately
    if getattr(args, "upgrade", False):
        upgrade_plugin()
        return 0

    # Extract args
    project_path = getattr(args, "project_path", None) or os.getcwd()
    model = getattr(args, "model", None)
    name = getattr(args, "name", None) or "OpenCode"
    agent_instance_id = getattr(args, "agent_instance_id", None)
    base_url = getattr(args, "base_url", None)
    resume = getattr(args, "resume", None)
    # headless = getattr(args, "headless", False)

    # Use resume as agent_instance_id if provided
    if resume:
        agent_instance_id = resume
    elif not agent_instance_id:
        agent_instance_id = str(uuid.uuid4())

    # # If headless mode, use ACP wrapper
    # if headless:
    #     return _run_opencode_headless(
    #         api_key=api_key,
    #         base_url=base_url,
    #         project_path=project_path,
    #         agent_instance_id=agent_instance_id,
    #         name=name,
    #         is_resuming=bool(resume),
    #         model=model,
    #     )

    # Register plugin in OpenCode config (OpenCode auto-installs on first run)
    if not _ensure_plugin_registered():
        print(
            "Warning: Failed to register Vicoa plugin, continuing anyway...",
            file=sys.stderr,
        )

    # Set up environment variables
    env = os.environ.copy()
    env["VICOA_API_KEY"] = api_key

    if base_url:
        env["VICOA_API_URL"] = base_url
        env["VICOA_BASE_URL"] = base_url

    env["VICOA_AGENT_INSTANCE_ID"] = agent_instance_id
    env["VICOA_AGENT_NAME"] = name

    if model:
        env["OPENCODE_MODEL"] = model

    # Build OpenCode command
    command = ["opencode"]

    # Add any additional args
    if unknown_args:
        command.extend(unknown_args)

    # Launch OpenCode (plugin loads automatically)
    try:
        result = subprocess.run(command, env=env, cwd=project_path)
        return result.returncode
    except KeyboardInterrupt:
        print("\nInterrupted by user")
        return 0
    except Exception as e:
        print(f"Error launching OpenCode: {e}", file=sys.stderr)
        return 1


def _load_opencode_config() -> dict:
    """Load ~/.opencode/config.json, returning an empty dict if it doesn't exist."""
    if not OPENCODE_CONFIG_PATH.exists():
        return {}
    try:
        with open(OPENCODE_CONFIG_PATH, "r") as f:
            data = json.load(f)
            return data if isinstance(data, dict) else {}
    except (json.JSONDecodeError, OSError):
        return {}


def _save_opencode_config(config: dict) -> None:
    """Write config back to ~/.opencode/config.json, creating the directory if needed."""
    OPENCODE_CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
    with open(OPENCODE_CONFIG_PATH, "w") as f:
        json.dump(config, f, indent=2)


def _ensure_plugin_registered() -> bool:
    """Ensure opencode-vicoa is listed in the OpenCode config plugin array.

    OpenCode automatically installs any plugin listed in config on next run,
    so we only need to write the config entry. Existing plugins are preserved.

    Returns:
        True if the plugin is (now) registered, False on write failure.
    """
    config = _load_opencode_config()

    # Add $schema if not present (for new configs)
    if "$schema" not in config:
        config["$schema"] = "https://opencode.ai/config.json"

    plugins: list = config.get("plugin", [])

    if PLUGIN_NAME in plugins:
        return True

    plugins.append(PLUGIN_NAME)
    config["plugin"] = plugins

    try:
        _save_opencode_config(config)
        print(f"✓ Vicoa plugin registered in {OPENCODE_CONFIG_PATH}")
        print("  OpenCode installs it automatically on first run")
        return True
    except OSError as e:
        print(f"Warning: Failed to write OpenCode config: {e}", file=sys.stderr)
        return False


def upgrade_plugin() -> None:
    """Upgrade the opencode-vicoa plugin.

    OpenCode does not auto-update cached plugins, so we clear the cached
    copy.  The plugin entry in config is left intact so that OpenCode
    re-fetches the latest version on the next run.
    """
    if OPENCODE_CACHE_PLUGIN_PATH.exists():
        shutil.rmtree(OPENCODE_CACHE_PLUGIN_PATH)
        print(f"✓ Removed cached plugin from {OPENCODE_CACHE_PLUGIN_PATH}")
    else:
        print("  No cached plugin found — nothing to clear")

    # Make sure the config entry is still present so OpenCode re-installs
    _ensure_plugin_registered()
    print("✓ Plugin will be upgraded on next OpenCode run")
