"""Auto-generate SKILL.md from workflow YAML definitions.

Bridges workflow definitions to Claude Code's skill discovery system by
generating SKILL.md files in ``.claude/skills/`` and ``.agents/skills/``.
Auto-generated skills are marked with ``<!-- synapse-workflow-autogen -->``
to distinguish them from hand-written skills.
"""

from __future__ import annotations

import logging
import shutil
from pathlib import Path

import yaml

from synapse.workflow import Workflow, WorkflowStore

logger = logging.getLogger(__name__)

_AUTOGEN_MARKER = "<!-- synapse-workflow-autogen -->"
_SKILL_BASE_DIRS = (".claude/skills", ".agents/skills")


def generate_skill_md(workflow: Workflow) -> str:
    """Generate SKILL.md content from a Workflow definition."""
    trigger_keywords = ""
    if workflow.trigger:
        trigger_keywords = f" Use this skill when: {workflow.trigger}."

    auto_spawn_flag = " --auto-spawn" if workflow.auto_spawn else ""

    description = (
        f"Workflow: {workflow.description or workflow.name}.{trigger_keywords} "
        f"Triggered by /{workflow.name} command."
    )

    frontmatter = yaml.safe_dump(
        {"name": workflow.name, "description": description},
        default_flow_style=False,
        allow_unicode=True,
    ).rstrip("\n")

    return (
        f"---\n"
        f"{frontmatter}\n"
        f"---\n"
        f"{_AUTOGEN_MARKER}\n"
        f"\n"
        f"# {workflow.name}\n"
        f"\n"
        f"Auto-generated from workflow YAML. "
        f"Do not edit — changes will be overwritten by `synapse workflow sync`.\n"
        f"\n"
        f"## Instructions\n"
        f"Run: `synapse workflow run {workflow.name}{auto_spawn_flag}`\n"
    )


def is_autogenerated_skill(skill_dir: Path) -> bool:
    """Check whether a skill directory contains an auto-generated SKILL.md."""
    skill_md = skill_dir / "SKILL.md"
    if not skill_md.is_file():
        return False
    try:
        content = skill_md.read_text(encoding="utf-8")
        return _AUTOGEN_MARKER in content
    except OSError:
        return False


def sync_workflow_skill(workflow: Workflow, project_dir: Path) -> list[Path]:
    """Generate/update SKILL.md for a single workflow.

    Writes to both ``.claude/skills/<name>/`` and ``.agents/skills/<name>/``
    under *project_dir*.  Skips a target directory if it contains a
    hand-written (non-autogenerated) skill.

    Returns list of paths that were written.
    """
    content = generate_skill_md(workflow)
    written: list[Path] = []

    for base in _SKILL_BASE_DIRS:
        skill_dir = project_dir / base / workflow.name
        # Protect hand-written skills (is_autogenerated_skill returns False
        # for nonexistent dirs, so new dirs pass through)
        if skill_dir.is_dir() and not is_autogenerated_skill(skill_dir):
            logger.info(
                "Skipping %s: hand-written skill detected",
                skill_dir,
            )
            continue

        skill_dir.mkdir(parents=True, exist_ok=True)
        skill_md = skill_dir / "SKILL.md"
        skill_md.write_text(content, encoding="utf-8")
        written.append(skill_md)
        logger.debug("Wrote %s", skill_md)

    return written


def remove_workflow_skill(name: str, project_dir: Path) -> list[Path]:
    """Remove auto-generated skill directories for a workflow.

    Only removes directories that contain the autogen marker.
    Returns list of directories that were removed.
    """
    removed: list[Path] = []

    for base in _SKILL_BASE_DIRS:
        skill_dir = project_dir / base / name
        if not skill_dir.exists():
            continue
        if not is_autogenerated_skill(skill_dir):
            logger.info(
                "Skipping removal of %s: hand-written skill",
                skill_dir,
            )
            continue

        shutil.rmtree(skill_dir)
        removed.append(skill_dir)
        logger.debug("Removed %s", skill_dir)

    return removed


def sync_all_workflows(
    project_dir: Path,
    user_dir: Path | None = None,
) -> tuple[list[Path], list[Path]]:
    """Sync all workflow YAMLs to skills and clean up orphans.

    Returns (written_paths, removed_paths).
    """
    store = WorkflowStore(
        project_dir=project_dir / ".synapse" / "workflows",
        user_dir=user_dir or (Path.home() / ".synapse" / "workflows"),
    )
    # Deduplicate by name (project-first, matching WorkflowStore.load precedence)
    all_workflows = store.list_workflows()
    seen: dict[str, Workflow] = {}
    for wf in all_workflows:
        if wf.name not in seen:
            seen[wf.name] = wf
    workflows = list(seen.values())
    workflow_names = set(seen)

    written: list[Path] = []
    removed: list[Path] = []

    # Sync each workflow
    for wf in workflows:
        written.extend(sync_workflow_skill(wf, project_dir))

    # Remove orphaned auto-generated skills
    orphan_names: set[str] = set()
    for base in _SKILL_BASE_DIRS:
        skills_dir = project_dir / base
        if not skills_dir.is_dir():
            continue
        for skill_dir in skills_dir.iterdir():
            if skill_dir.is_dir() and skill_dir.name not in workflow_names:
                orphan_names.add(skill_dir.name)

    for name in sorted(orphan_names):
        removed.extend(remove_workflow_skill(name, project_dir))

    return written, removed
