import json
from pathlib import Path
from typing import Any

from agentmux.adapters.base import ConvertedFile, ToolAdapter
from agentmux.core.component import (
    Agent,
    Command,
    Component,
    ComponentType,
    Instructions,
    MCPConfig,
    Rule,
    Skill,
)
from agentmux.utils.frontmatter import dump as dump_frontmatter
from agentmux.utils.symlink import sanitize_component_name


class GeminiAdapter(ToolAdapter):
    @property
    def name(self) -> str:
        return "gemini"

    def detect(self) -> bool:
        return Path.home().joinpath(".gemini").exists()

    def get_global_base_dir(self) -> Path:
        return Path.home() / ".gemini"

    def get_project_subdir(self) -> Path:
        return Path(".gemini")

    def validate(self, component: Component) -> list[str]:
        if isinstance(component, Rule):
            return ["Gemini CLI does not support standalone rule files"]
        return []

    def convert_agent(self, agent: Agent) -> list[ConvertedFile]:
        meta: dict[str, Any] = {
            "name": agent.name,
            "description": agent.description,
            **agent.extra_meta,
            "kind": "local",  # always override — Gemini requires kind=local
        }
        content = dump_frontmatter(meta, agent.body) + "\n"
        safe_name = sanitize_component_name(agent.name)
        return [
            ConvertedFile(
                path=Path("agents") / f"{safe_name}.md",
                content=content,
                source=None,  # always transformed — source would bypass kind:local injection
                scope="global",
            )
        ]

    def convert_command(self, command: Command) -> list[ConvertedFile]:
        # Prefer TOML multiline literal strings ('''...''') which do NOT process escape sequences,
        # making them safe for bodies containing backslashes, \n, \t, etc.
        # However, a literal string cannot contain ''', so fall back to a basic multiline
        # string ("""...""") in that case, escaping backslashes and double-quotes.
        if "'''" not in command.body:
            prompt_toml = f"prompt = '''\n{command.body}\n'''"
        else:
            escaped_body = command.body.replace("\\", "\\\\").replace('"', '\\"')
            prompt_toml = f'prompt = """\n{escaped_body}\n"""'
        lines = [prompt_toml]
        if command.description:
            escaped_desc = command.description.replace('"', '\\"')
            lines.append(f'description = "{escaped_desc}"')
        content = "\n".join(lines) + "\n"
        stem = command.source_path.stem if command.source_path else command.name
        return [
            ConvertedFile(
                path=Path("commands") / f"{stem}.toml",
                content=content,
                scope="global",
            )
        ]

    def convert_skill(self, skill: Skill) -> list[ConvertedFile]:
        dir_name = skill.source_dir.name if skill.source_dir else skill.name
        return [
            ConvertedFile(
                path=Path("skills") / dir_name,
                content=None,
                source=skill.source_dir,
                is_directory=True,
                scope="global",
            )
        ]

    def convert_rule(self, rule: Rule) -> list[ConvertedFile]:
        # Gemini CLI does not support standalone rule files; use validate() to report this.
        return []

    def convert_instructions(self, instructions: Instructions) -> list[ConvertedFile]:
        return [
            ConvertedFile(
                path=Path("GEMINI.md"),
                content=instructions.body + "\n",
                scope="global",
            )
        ]

    def convert_mcp(self, mcp: MCPConfig) -> list[ConvertedFile]:
        return [
            ConvertedFile(
                path=Path("settings.json"),
                content=json.dumps({"mcpServers": mcp.servers}),
                merge=True,
                scope="global",
            )
        ]

    def post_sync(self, base_dir: Path, synced_types: set[ComponentType]) -> list[ConvertedFile]:
        if ComponentType.AGENT in synced_types:
            return [
                ConvertedFile(
                    path=Path("settings.json"),
                    content=json.dumps({"experimental": {"enableAgents": True}}),
                    merge=True,
                    scope="global",
                )
            ]
        return []
