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

"""Markdown emission helpers for agent/skill listing and generator content blocks.

Provides functions to emit agents and skills as markdown headings or
bullet lists, plus shared content blocks (guidelines, quality standards)
used by the various ``generate_*.py`` scripts.

Stdlib-only.

Usage::

    from emission import emit_agents_headings, emit_skills_bullets
    from emission import generate_general_guidelines
"""
from __future__ import annotations

from pathlib import Path

from frontmatter import frontmatter_field
from instruction_core import render_constitution_policy


def _resolve_toolkit_dir() -> Path:
    """Resolve the toolkit root directory (parent of scripts/)."""
    return Path(__file__).resolve().parent.parent


toolkit_dir: Path = _resolve_toolkit_dir()
app_dir: Path = toolkit_dir / "app"
agents_dir: Path = app_dir / "agents"
skills_dir: Path = app_dir / "skills"


# ---------------------------------------------------------------------------
# Counting
# ---------------------------------------------------------------------------

def agent_count() -> int:
    """Count agent .md files in app/agents/."""
    if not agents_dir.is_dir():
        return 0
    return sum(1 for f in agents_dir.iterdir() if f.suffix == ".md" and f.is_file())


def skill_count() -> int:
    """Count skill directories containing SKILL.md in app/skills/.

    Directories starting with ``_`` (like ``_lib``) are excluded.
    """
    if not skills_dir.is_dir():
        return 0
    return sum(1 for d in skills_dir.iterdir()
               if d.is_dir() and not d.name.startswith("_") and (d / "SKILL.md").is_file())


def count_agents_and_skills() -> tuple[int, int]:
    """Return (agent_count, skill_count) as a convenience tuple."""
    return agent_count(), skill_count()


# ---------------------------------------------------------------------------
# Markdown emission
# ---------------------------------------------------------------------------

def emit_agents_headings(level: str = "##") -> str:
    """Emit agents as markdown headings with descriptions."""
    lines: list[str] = []
    for agent_file in sorted(agents_dir.glob("*.md")):
        name = frontmatter_field(agent_file, "name")
        description = frontmatter_field(agent_file, "description")
        if not name or not description:
            continue
        lines.append(f"{level} {name}")
        lines.append(description)
        lines.append("")
    return "\n".join(lines)


def emit_agents_bullets() -> str:
    """Emit agents as bullet list: - **name**: description."""
    lines: list[str] = []
    for agent_file in sorted(agents_dir.glob("*.md")):
        name = frontmatter_field(agent_file, "name")
        description = frontmatter_field(agent_file, "description")
        if not name or not description:
            continue
        lines.append(f"- **{name}**: {description}")
    return "\n".join(lines)


def emit_skills_headings(level: str = "##") -> str:
    """Emit skills as markdown headings with descriptions."""
    lines: list[str] = []
    for skill_dir in sorted(skills_dir.iterdir()):
        if skill_dir.name.startswith("_"):
            continue
        skill_file = skill_dir / "SKILL.md"
        if not skill_file.is_file():
            continue
        name = frontmatter_field(skill_file, "name")
        description = frontmatter_field(skill_file, "description")
        if not name or not description:
            continue
        lines.append(f"{level} {name}")
        lines.append(description)
        lines.append("")
    return "\n".join(lines)


def emit_skills_bullets() -> str:
    """Emit skills as bullet list: - **name**: description."""
    lines: list[str] = []
    for skill_dir in sorted(skills_dir.iterdir()):
        if skill_dir.name.startswith("_"):
            continue
        skill_file = skill_dir / "SKILL.md"
        if not skill_file.is_file():
            continue
        name = frontmatter_field(skill_file, "name")
        description = frontmatter_field(skill_file, "description")
        if not name or not description:
            continue
        lines.append(f"- **{name}**: {description}")
    return "\n".join(lines)


# ---------------------------------------------------------------------------
# Toolkit markers (print helpers)
# ---------------------------------------------------------------------------

def print_toolkit_start() -> None:
    """Print the standard toolkit start marker and auto-generated comment."""
    print("<!-- TOOLKIT:ai-toolkit START -->")
    print("<!-- Auto-generated by ai-toolkit. Re-run to update. -->")
    print()


def print_toolkit_end() -> None:
    """Print the standard toolkit end marker."""
    print("<!-- TOOLKIT:ai-toolkit END -->")


# ---------------------------------------------------------------------------
# Shared content blocks for generators
# ---------------------------------------------------------------------------

def generate_general_guidelines() -> str:
    """Return the general guidelines block used by cursor/cline/windsurf generators."""
    lines = [
        "## General Guidelines",
        "",
        '- Apply "Safety First": no data loss, no blind execution, max 5 loop iterations',
        "- Research before acting: check existing code and context before proposing changes",
        "- Use structured commits: feat/fix/docs/refactor/test/chore prefixes",
        "- Quality gates: lint must pass, types must check, tests must be green before done",
        "- Prefer editing existing files over creating new ones",
        "- Never commit secrets or credentials",
    ]
    return "\n".join(lines)


def generate_quality_standards() -> str:
    """Return policy rendered from the canonical constitution file."""
    return render_constitution_policy(heading_level=2)


def generate_workflow_guidelines() -> str:
    """Return the workflow guidelines block used by the Gemini generator."""
    lines = [
        "## Workflow Guidelines",
        "",
        "- **Plan First**: Tasks longer than 1 hour require a plan,"
        " success criteria, and pre-mortem",
        "- **Multi-Agent**: Use minimum 3 agents for complex tasks;"
        " single-agent for simple tasks",
        "- **2-Phase Execution**: Plan \u2192 User Approval \u2192 Implement"
        " (never skip the approval checkpoint)",
        "- **KB-First Research**: Search the knowledge base before writing"
        " code or answering questions",
        "- **Structured Commits**: Use `feat/fix/docs/refactor/test/chore`"
        " prefixes (Conventional Commits)",
        "- **Quality Gates**: Run `ruff check .` (Python), `tsc` (TypeScript),"
        " `go vet` (Go) before marking done",
        "- **Cite Sources**: Always reference `[PATH: ...]` when making"
        " decisions based on existing knowledge",
        "- **Read-Only Exploration**: Discovery agents never write;"
        " writing agents never explore blindly",
        "- **No Secrets in Code**: Never commit credentials, API keys,"
        " or sensitive configuration values",
    ]
    return "\n".join(lines)


def generate_quality_guidelines() -> str:
    """Return policy from the canonical constitution (legacy public name)."""
    return render_constitution_policy(heading_level=2)
