"""Skill bundler and MCP configuration generator for exokit.

Copies essential Claude Code skills into a generated project's ``.claude/skills/``
directory and generates the ``.mcp.json`` MCP server configuration.
"""

from __future__ import annotations

import json
import logging
import shutil
from pathlib import Path

logger = logging.getLogger(__name__)

# ---------------------------------------------------------------------------
# Essential skills — the canonical set bundled into every demo project
# ---------------------------------------------------------------------------

ESSENTIAL_SKILLS: list[str] = [
    "databricks-spark-declarative-pipelines",
    "databricks-jobs",
    "databricks-aibi-dashboards",
    "databricks-asset-bundles",
    "databricks-model-serving",
    "databricks-agent-bricks",
    "databricks-synthetic-data-generation",
    "databricks-vector-search",
    "demo-governance",
    "demo-memory",
]

# ---------------------------------------------------------------------------
# Common locations for ai-dev-kit installation
# ---------------------------------------------------------------------------


# ---------------------------------------------------------------------------
# Default skills source — relative to the exokit package
# ---------------------------------------------------------------------------


def _default_skills_source() -> Path:
    """Return the default skills source directory (``skills/`` next to the exokit package)."""
    return Path(__file__).resolve().parent.parent.parent.parent / "skills"


# ---------------------------------------------------------------------------
# Public API
# ---------------------------------------------------------------------------


def bundle_skills(
    target_dir: Path,
    skills_source: Path | None = None,
) -> list[str]:
    """Copy essential skills from *skills_source* into the target project.

    Skills are copied to ``{target_dir}/.claude/skills/{skill_name}/``.

    Args:
        target_dir: Root of the generated project.
        skills_source: Directory containing skill subdirectories.
            Falls back to the ``skills/`` directory relative to the exokit package.

    Returns:
        List of skill names that were successfully copied.
    """
    source = skills_source or _default_skills_source()

    if not source.exists():
        logger.warning(
            "Skills source directory not found: %s — skipping skill bundling",
            source,
        )
        return []

    skills_target = target_dir / ".claude" / "skills"
    skills_target.mkdir(parents=True, exist_ok=True)

    copied: list[str] = []
    for skill_name in ESSENTIAL_SKILLS:
        skill_src = source / skill_name
        if not skill_src.exists():
            logger.warning("Skill not found in source: %s", skill_name)
            continue
        if not skill_src.is_dir():
            logger.warning("Skill source is not a directory: %s", skill_src)
            continue

        skill_dst = skills_target / skill_name
        if skill_dst.exists():
            logger.debug("Skill already exists, skipping: %s", skill_name)
            continue

        shutil.copytree(skill_src, skill_dst)
        copied.append(skill_name)
        logger.info("Bundled skill: %s", skill_name)

    return copied


def update_skills(
    project_dir: Path,
    skills_source: Path | None = None,
) -> list[str]:
    """Update (overwrite) existing skills in the project from the source.

    Same as :func:`bundle_skills` but replaces existing skill directories.

    Args:
        project_dir: Root of the generated project.
        skills_source: Directory containing skill subdirectories.

    Returns:
        List of skill names that were updated.
    """
    source = skills_source or _default_skills_source()

    if not source.exists():
        logger.warning(
            "Skills source directory not found: %s — skipping skill update",
            source,
        )
        return []

    skills_target = project_dir / ".claude" / "skills"
    skills_target.mkdir(parents=True, exist_ok=True)

    updated: list[str] = []
    for skill_name in ESSENTIAL_SKILLS:
        skill_src = source / skill_name
        if not skill_src.exists():
            logger.warning("Skill not found in source: %s", skill_name)
            continue
        if not skill_src.is_dir():
            logger.warning("Skill source is not a directory: %s", skill_src)
            continue

        skill_dst = skills_target / skill_name
        if skill_dst.exists():
            shutil.rmtree(skill_dst)

        shutil.copytree(skill_src, skill_dst)
        updated.append(skill_name)
        logger.info("Updated skill: %s", skill_name)

    return updated


def generate_mcp_config(
    target_dir: Path,
    ai_dev_kit_path: Path | None = None,
    databricks_profile: str | None = None,
) -> Path:
    """Generate a ``.mcp.json`` MCP server configuration file.

    Always generates a config using the standard ``~/.ai-dev-kit/`` path
    from the official installer. This makes the config portable — it works
    on any machine that has run the installer, regardless of who scaffolded
    the project.

    Args:
        target_dir: Root of the generated project.
        ai_dev_kit_path: Override path (used in tests).
        databricks_profile: Databricks CLI profile to use.

    Returns:
        Path to the generated ``.mcp.json`` file.
    """
    config = _build_mcp_config(ai_dev_kit_path, databricks_profile)

    mcp_json_path = target_dir / ".mcp.json"
    mcp_json_path.write_text(
        json.dumps(config, indent=2) + "\n",
        encoding="utf-8",
    )
    logger.info("Generated .mcp.json at %s", mcp_json_path)

    return mcp_json_path


# ---------------------------------------------------------------------------
# Internal helpers
# ---------------------------------------------------------------------------

# Standard installation path from the official install.sh
_STANDARD_KIT_PATH = "~/.ai-dev-kit"


def _build_mcp_config(
    kit_path_override: Path | None = None,
    databricks_profile: str | None = None,
) -> dict[str, object]:
    """Build the MCP configuration for .mcp.json.

    Uses the standard ~/.ai-dev-kit/ path so the config is portable.
    The official installer (install.sh) always installs there.

    Install: bash <(curl -sL https://raw.githubusercontent.com/
    databricks-solutions/ai-dev-kit/main/install.sh)
    """
    base = str(kit_path_override) if kit_path_override else _STANDARD_KIT_PATH

    env: dict[str, str] = {}
    if databricks_profile:
        env["DATABRICKS_CONFIG_PROFILE"] = databricks_profile

    server_config: dict[str, object] = {
        "command": f"{base}/.venv/bin/python",
        "args": [f"{base}/repo/databricks-mcp-server/run_server.py"],
        "defer_loading": True,
    }
    if env:
        server_config["env"] = env

    return {
        "_install": (
            "If the MCP server is not working, install ai-dev-kit with: "
            "bash <(curl -sL https://raw.githubusercontent.com/"
            "databricks-solutions/ai-dev-kit/main/install.sh)"
        ),
        "mcpServers": {
            "databricks": server_config,
        },
    }
