from typing import List

from pygeai.cli.commands import Option
from pygeai.cli.commands.skills.utils import (
    display_skills_table,
    prompt_selection,
    prompt_yes_no,
)
from pygeai.core.utils.console import Console
from pygeai.skills import Agent, Skill, SkillsEngine


def setup_skills(option_list: list = None):
    """
    Interactive setup wizard for installing skills to coding agents.

    Modes:
    1. Interactive (default): Guided setup
    2. Non-interactive: Use CLI options
    """
    opts = {opt.name: arg for opt, arg in option_list} if option_list else {}

    interactive = "non_interactive" not in opts

    engine = SkillsEngine()

    if interactive:
        _run_interactive_setup(engine)
    else:
        _run_noninteractive_setup(engine, opts)


def _run_interactive_setup(engine: SkillsEngine):
    """Run interactive setup wizard."""
    Console.write_stdout("\n" + "=" * 50)
    Console.write_stdout("    GEAI Skills Setup Wizard")
    Console.write_stdout("=" * 50 + "\n")

    Console.write_stdout("Detecting installed coding agents...")
    agents = engine.detect_agents()

    if not agents:
        Console.write_warning(
            "No coding agents detected. You can still install skills "
            "but they may not be automatically discovered.\n"
        )
        agents = _prompt_manual_agent_selection(engine)
        if not agents:
            Console.write_stdout("Setup cancelled.")
            return
    else:
        Console.write_success(f"Found {len(agents)} agent(s):\n")
        for i, agent in enumerate(agents, 1):
            Console.write_stdout(f"  {i}. {agent.display_name}")
        Console.write_stdout("")

    selected_agents = agents
    if len(agents) > 1:
        if not prompt_yes_no("Configure all detected agents?", default=True):
            selected_agents = _prompt_agent_selection(agents)
            if not selected_agents:
                Console.write_stdout("Setup cancelled.")
                return

    global_install = _prompt_installation_scope()

    Console.write_stdout("\nAvailable GEAI skills:\n")
    builtin_skills = engine.list_builtin_skills()
    display_skills_table(builtin_skills)

    selected_skills = _prompt_skill_selection(builtin_skills)
    if not selected_skills:
        Console.write_stdout("Setup cancelled.")
        return

    Console.write_stdout("\n" + "=" * 50)
    Console.write_stdout("    Installation Summary")
    Console.write_stdout("=" * 50)
    Console.write_stdout(
        f"Agents: {', '.join(a.display_name for a in selected_agents)}"
    )
    Console.write_stdout(f"Scope: {'Global' if global_install else 'Project'}")
    Console.write_stdout(
        f"Skills: {', '.join(s.name for s in selected_skills)}\n"
    )

    if not prompt_yes_no("Proceed with installation?", default=True):
        Console.write_stdout("Installation cancelled.")
        return

    Console.write_stdout("\nInstalling skills...\n")
    for skill in selected_skills:
        Console.write_stdout(f"Installing {skill.name}...")
        results = engine.install_skill(skill, selected_agents, global_install)

        for agent_name, success in results.items():
            if success:
                Console.write_success(f"  ✓ {agent_name}")
            else:
                Console.write_error(f"  ✗ {agent_name} (failed)")

    Console.write_success("\n✓ Setup complete!\n")
    _display_next_steps(selected_agents, global_install)


def _run_noninteractive_setup(engine: SkillsEngine, opts: dict):
    """Run non-interactive setup using CLI options."""
    agent_names = opts.get("agent", "").split(",") if "agent" in opts else []
    skill_names = opts.get("skills", "").split(",") if "skills" in opts else []
    global_install = "global" in opts

    if not agent_names:
        agents = engine.detect_agents()
        if not agents:
            Console.write_error(
                "No agents detected. Use --agent to specify agents explicitly."
            )
            return
    else:
        agents = []
        for name in agent_names:
            agent = engine.detector.get_agent(name.strip())
            if agent:
                agents.append(agent)
            else:
                Console.write_warning(f"Unknown agent '{name}', skipping")

    if not agents:
        Console.write_error("No valid agents specified")
        return

    if not skill_names or skill_names == ["all"]:
        skills = engine.list_builtin_skills()
    else:
        skills = []
        for name in skill_names:
            skill = engine.get_skill(name.strip())
            if skill:
                skills.append(skill)
            else:
                Console.write_warning(f"Unknown skill '{name}', skipping")

    if not skills:
        Console.write_error("No valid skills specified")
        return

    Console.write_stdout(f"Installing {len(skills)} skill(s) to {len(agents)} agent(s)...")

    for skill in skills:
        results = engine.install_skill(skill, agents, global_install)
        for agent_name, success in results.items():
            if success:
                Console.write_success(f"✓ {skill.name} -> {agent_name}")
            else:
                Console.write_error(f"✗ {skill.name} -> {agent_name}")

    Console.write_success("\n✓ Installation complete")


def _prompt_manual_agent_selection(engine: SkillsEngine) -> List[Agent]:
    """Prompt user to manually select agents."""
    Console.write_stdout("\nSupported agents:")
    supported = engine.get_supported_agents()

    indices = prompt_selection(
        supported, "Select agents to configure", allow_all=True
    )

    if not indices:
        return []

    agents = []
    for i in indices:
        agent = engine.detector.get_agent(supported[i])
        if agent:
            agents.append(agent)

    return agents


def _prompt_agent_selection(agents: List[Agent]) -> List[Agent]:
    """Prompt user to select which detected agents to configure."""
    agent_names = [a.display_name for a in agents]

    indices = prompt_selection(
        agent_names, "Select agents to configure", allow_all=True
    )

    return [agents[i] for i in indices]


def _prompt_installation_scope() -> bool:
    """Prompt for global vs project installation."""
    Console.write_stdout("\nInstallation scope:")
    Console.write_stdout("  1. Project (current directory only)")
    Console.write_stdout("  2. Global (all projects)")

    choice = input("\nSelect scope [1]: ").strip() or "1"
    return choice == "2"


def _prompt_skill_selection(skills: List[Skill]) -> List[Skill]:
    """Prompt user to select skills to install."""
    skill_names = [f"{s.name} - {s.description}" for s in skills]

    indices = prompt_selection(
        skill_names, "Select skills to install", allow_all=True
    )

    return [skills[i] for i in indices]


def _display_next_steps(agents: List[Agent], global_install: bool):
    """Display next steps after installation."""
    Console.write_stdout("Next steps:\n")

    if global_install:
        Console.write_stdout(
            "  Skills are installed globally and will be available to all your projects."
        )
    else:
        Console.write_stdout(
            "  Skills are installed in the current project directory.\n"
            "  Other developers will need to run 'geai skills setup' or commit\n"
            "  the .*/skills directories to version control."
        )

    Console.write_stdout("\n  To use skills in your coding agent:")
    for agent in agents:
        if agent.name == "claude-code":
            Console.write_stdout("    - Claude Code: Skills auto-loaded on startup")
        elif agent.name == "codex":
            Console.write_stdout("    - Codex: Skills available via skill selector")
        elif agent.name == "coda-cli":
            Console.write_stdout("    - Coda: Skills loaded automatically")
        else:
            Console.write_stdout(
                f"    - {agent.display_name}: Check agent documentation"
            )

    Console.write_stdout("\n  View installed skills: geai skills list")
    Console.write_stdout("  Get skill info: geai skills info <skill-name>\n")


setup_options = [
    Option(
        "agent",
        ["--agent", "-a"],
        "Target agent(s) (comma-separated: opencode,claude-code,codex,cursor,coda-cli)",
        True,
    ),
    Option(
        "skills",
        ["--skills", "-s"],
        "Skills to install (comma-separated names or 'all')",
        True,
    ),
    Option(
        "global",
        ["--global", "-g"],
        "Install globally (default: project-level)",
        False,
    ),
    Option(
        "non_interactive",
        ["--no-interactive", "--quiet"],
        "Skip interactive prompts",
        False,
    ),
]
