import json
import os
import platform
import shutil
import sys
from pathlib import Path

from jinja2 import Template

_HERE = Path(__file__).parent
CLAUDE_DESKTOP_CONFIG_TEMPLATE = _HERE / "claude_desktop_config.json"

system = platform.system()
if system == "Darwin":
    CLAUDE_DESKTOP_CONFIG_PATH = os.path.expanduser("~/Library/Application Support/Claude/claude_desktop_config.json")
elif system == "Windows":
    CLAUDE_DESKTOP_CONFIG_PATH = os.path.join(os.environ["APPDATA"], "Claude", "claude_desktop_config.json")
else:
    CLAUDE_DESKTOP_CONFIG_PATH = None


def get_endpoint_path() -> str:
    """
    Find the path to the mcp-email-server script.
    Similar to the 'which' command in Unix-like systems.

    Returns:
        str: The full path to the mcp-email-server script
    """
    # First try using shutil.which to find the script in PATH
    script_path = shutil.which("mcp-email-server")
    if script_path:
        return script_path

    # If not found in PATH, try to find it in the current Python environment
    # This handles cases where the script is installed but not in PATH
    bin_dir = Path(sys.executable).parent
    possible_paths = [
        bin_dir / "mcp-email-server",
        bin_dir / "mcp-email-server.exe",  # For Windows
    ]

    for path in possible_paths:
        if path.exists():
            return str(path)

    # If we can't find it, return the script name and hope it's in PATH when executed
    return "mcp-email-server"


def install_claude_desktop():
    # Read the template config
    template_content = CLAUDE_DESKTOP_CONFIG_TEMPLATE.read_text()
    rendered_content = Template(template_content).render(ENTRYPOINT=get_endpoint_path())
    template_config = json.loads(rendered_content)
    if not CLAUDE_DESKTOP_CONFIG_PATH:
        raise NotImplementedError

    # Read the existing config file or create an empty JSON object
    try:
        with open(CLAUDE_DESKTOP_CONFIG_PATH) as f:
            existing_config = json.load(f)
    except FileNotFoundError:
        existing_config = {}

    # Merge the template config into the existing config
    if "mcpServers" not in existing_config:
        existing_config["mcpServers"] = {}
    existing_config["mcpServers"].update(template_config["mcpServers"])

    # Write the merged config back to the Claude config file
    os.makedirs(os.path.dirname(CLAUDE_DESKTOP_CONFIG_PATH), exist_ok=True)
    with open(CLAUDE_DESKTOP_CONFIG_PATH, "w") as f:
        json.dump(existing_config, f, indent=4)


def uninstall_claude_desktop():
    if not CLAUDE_DESKTOP_CONFIG_PATH:
        raise NotImplementedError
    try:
        with open(CLAUDE_DESKTOP_CONFIG_PATH) as f:
            existing_config = json.load(f)
    except FileNotFoundError:
        return

    if "mcpServers" not in existing_config:
        return

    if "zerolib-email" in existing_config["mcpServers"]:
        del existing_config["mcpServers"]["zerolib-email"]

    with open(CLAUDE_DESKTOP_CONFIG_PATH, "w") as f:
        json.dump(existing_config, f, indent=4)


def is_installed() -> bool:
    """
    Check if the MCP email server is installed in the Claude desktop configuration.

    Returns:
        bool: True if installed, False otherwise
    """
    if not CLAUDE_DESKTOP_CONFIG_PATH:
        return False

    try:
        with open(CLAUDE_DESKTOP_CONFIG_PATH) as f:
            config = json.load(f)

        return "mcpServers" in config and "zerolib-email" in config["mcpServers"]
    except (FileNotFoundError, json.JSONDecodeError):
        return False


def need_update() -> bool:
    """
    Check if the installed configuration needs to be updated.

    Returns:
        bool: True if an update is needed, False otherwise
    """
    if not is_installed():
        return True

    try:
        # Get the template config
        template_content = CLAUDE_DESKTOP_CONFIG_TEMPLATE.read_text()
        rendered_content = Template(template_content).render(ENTRYPOINT=get_endpoint_path())
        template_config = json.loads(rendered_content)

        # Get the installed config
        with open(CLAUDE_DESKTOP_CONFIG_PATH) as f:
            installed_config = json.load(f)

        # Compare the relevant parts of the configs
        template_server = template_config["mcpServers"]["zerolib-email"]
        installed_server = installed_config["mcpServers"]["zerolib-email"]

        # Check if any key configuration elements differ
        return (
            template_server.get("command") != installed_server.get("command")
            or template_server.get("args") != installed_server.get("args")
            or template_server.get("env") != installed_server.get("env")
        )
    except (FileNotFoundError, json.JSONDecodeError, KeyError):
        # If any error occurs during comparison, suggest an update
        return True


def get_claude_desktop_config() -> str:
    if not CLAUDE_DESKTOP_CONFIG_PATH:
        raise NotImplementedError

    with open(CLAUDE_DESKTOP_CONFIG_PATH) as f:
        return f.read()
