#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
# Copyright 2024-2026 Lukasz Krzemien (biuro@softspark.eu)
# Source: https://github.com/softspark/ai-toolkit

"""Generate Antigravity IDE ``.agents/rules/``, ``.agents/workflows/``, and
skill pointer files.

Antigravity 2.0 reads rules/workflows from the plural ``.agents/`` directory by
default; singular ``.agent/`` is still accepted as a backward-compatible
fallback (Antigravity checks plural first, then singular). We emit plural.
Antigravity reads rules from:
  * ``GEMINI.md`` (highest priority) — generated by ``generate_gemini.py``
  * ``AGENTS.md`` (cross-tool) — generated by ``generate_agents_md.py``
  * ``.agents/rules/*.md`` — per-category rule files (this generator)
  * ``.agents/workflows/*.md`` — workflow templates (this generator)

Antigravity also supports the Agent Skills standard. The IDE reads
``.agent/skills/<skill-name>/SKILL.md`` (singular), while the Antigravity CLI
(GA 2026-05-19) reads ``.agents/skills/`` (plural) — so the skill pointer is
dual-emitted to both. We do not duplicate our full skill catalogue; instead we
emit a single pointer skill that teaches Antigravity to look up the real
catalogue in ``~/.softspark/ai-toolkit/app/skills/`` (global install) or
``.claude/skills/`` (local install).

Usage:
  python3 scripts/generate_antigravity.py [target-dir]

Writes rules/workflows to target-dir/.agents/{rules,workflows}/ and the skill
pointer to target-dir/.agent/skills/ (IDE) + target-dir/.agents/skills/ (CLI).
"""
from __future__ import annotations

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
from dir_rules_shared import (
    STANDARD_RULES,
    STANDARD_WORKFLOWS,
    build_language_rules,
    build_registered_rules,
    write_rules,
)
from emission import emit_skills_bullets


# ---------------------------------------------------------------------------
# Skill pointer — a single SKILL.md that directs Antigravity to our catalogue
# ---------------------------------------------------------------------------

POINTER_SKILL_NAME = "ai-toolkit-skill-catalogue"


def _pointer_skill_md() -> str:
    """Build the SKILL.md body for the pointer skill."""
    body = (
        "# AI Toolkit Skill Catalogue\n\n"
        "This workspace uses the ai-toolkit. Real skills are installed "
        "alongside Claude Code at `.claude/skills/` (project install) or "
        "`~/.claude/skills/` (global install). If the ai-toolkit installer "
        "has run, every skill below already exists as an agent-invocable "
        "SKILL.md on disk.\n\n"
        "## When to use this skill\n\n"
        "- You are asked to run a task that maps to one of the catalogued "
        "skills below.\n"
        "- You want to discover which skills the user has installed before "
        "reinventing the wheel.\n\n"
        "## How to invoke a catalogue entry\n\n"
        "1. Match the user's task to a skill name in the catalogue.\n"
        "2. Read the skill's SKILL.md from `.claude/skills/<name>/SKILL.md` "
        "or `~/.claude/skills/<name>/SKILL.md` (whichever exists).\n"
        "3. Follow its Rules, Gotchas, and When NOT to Use sections.\n\n"
        "## Catalogue (installed skills)\n\n"
        f"{emit_skills_bullets()}\n"
    )
    return (
        "---\n"
        f"name: {POINTER_SKILL_NAME}\n"
        "description: Index of ai-toolkit skills installed at .claude/skills/"
        " or ~/.claude/skills/. Read this first when the user's request "
        "matches a named skill.\n"
        "---\n"
        f"{body}"
    )


def _write_skill_pointer(target_dir: Path) -> None:
    """Write the pointer SKILL.md for both the IDE and the CLI surface.

    The IDE reads ``.agent/skills/`` (singular); the Antigravity CLI reads
    ``.agents/skills/`` (plural).
    """
    content = _pointer_skill_md()
    for tree in (".agent", ".agents"):
        skill_dir = target_dir / tree / "skills" / POINTER_SKILL_NAME
        skill_dir.mkdir(parents=True, exist_ok=True)
        (skill_dir / "SKILL.md").write_text(content, encoding="utf-8")
        print(f"  Generated: {tree}/skills/{POINTER_SKILL_NAME}/SKILL.md")


# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------

def generate_global(target_dir: Path) -> None:
    """Write the skill pointer to Antigravity's documented HOME-scoped skill
    dirs. ``~/.gemini/config/skills/`` is shared across all Antigravity products
    (IDE, editor, CLI); ``~/.gemini/antigravity-cli/skills/`` is CLI-private.
    Antigravity RULES have no documented global file surface, so only the skill
    pointer is emitted globally (rules stay project-local).
    """
    content = _pointer_skill_md()
    for rel in (".gemini/config/skills", ".gemini/antigravity-cli/skills"):
        skill_dir = target_dir / rel / POINTER_SKILL_NAME
        skill_dir.mkdir(parents=True, exist_ok=True)
        (skill_dir / "SKILL.md").write_text(content, encoding="utf-8")
        print(f"  Generated: {rel}/{POINTER_SKILL_NAME}/SKILL.md")


def generate(target_dir: Path, *,
             language_modules: list[str] | None = None,
             rules_dir: Path | None = None,
             emit_skill_pointer: bool = True) -> None:
    """Write ``.agents/{rules,workflows}/`` and the dual skill pointers.

    ``emit_skill_pointer`` controls whether the pointer SKILL.md is written
    to ``.agent/skills/`` (IDE) and ``.agents/skills/`` (CLI). Set to
    ``False`` if you manage those directories yourself.
    """
    rules = dict(STANDARD_RULES)
    rules.update(build_language_rules(language_modules))
    rules.update(build_registered_rules(rules_dir))
    write_rules(target_dir, rules, ".agents/rules")
    write_rules(target_dir, STANDARD_WORKFLOWS, ".agents/workflows")
    if emit_skill_pointer:
        _write_skill_pointer(target_dir)


def main() -> None:
    target = Path(sys.argv[1]) if len(sys.argv) > 1 else Path.cwd()
    from paths import RULES_DIR
    generate(target, rules_dir=RULES_DIR)


if __name__ == "__main__":
    main()
