"""Shared helpers for OKF Studio scripts.

Pure Python 3 standard library only — no third-party dependencies — so the
skill runs anywhere `python3` is available. Provides a minimal, dependency-free
YAML-frontmatter parser sufficient for OKF v0.1 conformance work plus small
filesystem / text utilities shared across the scripts.
"""

from __future__ import annotations

import os
import re
import sys
from typing import Any

RESERVED_FILENAMES = {"index.md", "log.md"}
# Agent-convention / instruction files that may sit at a bundle root to make it
# self-describing. They are NOT OKF concepts: the tooling ignores them (they are
# not validated, indexed, linked, or visualized as concepts).
AGENT_DOC_FILENAMES = {
    "agents.md", "claude.md", "gemini.md", "readme.md", "copilot-instructions.md",
}
FRONTMATTER_DELIM = "---"


def eprint(*args: Any) -> None:
    """Print to stderr."""
    print(*args, file=sys.stderr)


def slugify(text: str, max_len: int = 60) -> str:
    """Turn arbitrary text into a filesystem/URL-safe lowercase slug."""
    text = text.strip().lower()
    text = re.sub(r"[^\w\s-]", "", text)
    text = re.sub(r"[\s_]+", "-", text)
    text = re.sub(r"-+", "-", text).strip("-")
    return (text or "untitled")[:max_len].strip("-")


def split_frontmatter(content: str) -> tuple[str | None, str]:
    """Split a markdown document into (frontmatter_text, body).

    Returns (None, content) when no leading frontmatter block is present.
    The frontmatter block must start on the very first line with '---' and end
    on a later line that is exactly '---'.
    """
    lines = content.splitlines()
    if not lines or lines[0].strip() != FRONTMATTER_DELIM:
        return None, content
    for i in range(1, len(lines)):
        if lines[i].strip() == FRONTMATTER_DELIM:
            fm = "\n".join(lines[1:i])
            body = "\n".join(lines[i + 1:])
            return fm, body
    # Opening delimiter but no close — treat as no valid frontmatter.
    return None, content


def parse_frontmatter(fm_text: str) -> dict[str, Any]:
    """Parse a *simple* subset of YAML used by OKF frontmatter.

    Supports:
      key: scalar
      key: [a, b, c]          (inline list)
      key:                    (block list follows)
        - item
        - item
    Quotes around scalars are stripped. This is intentionally minimal; it covers
    the OKF reserved/recommended fields without requiring PyYAML.
    """
    data: dict[str, Any] = {}
    lines = fm_text.splitlines()
    i = 0
    while i < len(lines):
        raw = lines[i]
        line = raw.rstrip()
        if not line.strip() or line.strip().startswith("#"):
            i += 1
            continue
        m = re.match(r"^([A-Za-z0-9_\-]+):\s*(.*)$", line)
        if not m:
            i += 1
            continue
        key, value = m.group(1), m.group(2).strip()
        if value == "":
            # Possibly a block list on following indented lines.
            items: list[str] = []
            j = i + 1
            while j < len(lines) and re.match(r"^\s*-\s+", lines[j]):
                items.append(_strip_scalar(re.sub(r"^\s*-\s+", "", lines[j]).strip()))
                j += 1
            if items:
                data[key] = items
                i = j
                continue
            data[key] = ""
            i += 1
            continue
        if value.startswith("[") and value.endswith("]"):
            inner = value[1:-1].strip()
            data[key] = [_strip_scalar(p.strip()) for p in inner.split(",") if p.strip()] if inner else []
        else:
            data[key] = _strip_scalar(value)
        i += 1
    return data


def _strip_scalar(value: str) -> str:
    if len(value) >= 2 and value[0] == value[-1] and value[0] in {'"', "'"}:
        return value[1:-1]
    return value


def read_document(path: str) -> tuple[dict[str, Any] | None, str, str]:
    """Read a markdown file. Returns (frontmatter_dict_or_None, body, raw)."""
    with open(path, "r", encoding="utf-8") as fh:
        raw = fh.read()
    fm_text, body = split_frontmatter(raw)
    fm = parse_frontmatter(fm_text) if fm_text is not None else None
    return fm, body, raw


def iter_markdown(bundle_root: str):
    """Yield (abs_path, rel_path) for every .md file under bundle_root."""
    for dirpath, _dirnames, filenames in os.walk(bundle_root):
        for name in sorted(filenames):
            if name.lower().endswith(".md"):
                abs_path = os.path.join(dirpath, name)
                rel_path = os.path.relpath(abs_path, bundle_root).replace(os.sep, "/")
                yield abs_path, rel_path


def is_reserved(rel_path: str) -> bool:
    return os.path.basename(rel_path).lower() in RESERVED_FILENAMES


def is_agent_doc(rel_path: str) -> bool:
    """True for agent-convention files (AGENTS.md, CLAUDE.md, README.md, …)."""
    return os.path.basename(rel_path).lower() in AGENT_DOC_FILENAMES


def is_concept(rel_path: str) -> bool:
    """True when a markdown file is an OKF concept (not reserved/agent-doc)."""
    return not is_reserved(rel_path) and not is_agent_doc(rel_path)


MARKDOWN_LINK_RE = re.compile(r"\[([^\]]*)\]\(([^)\s]+)(?:\s+\"[^\"]*\")?\)")


def extract_links(body: str) -> list[tuple[str, str]]:
    """Return [(text, target), ...] for markdown links in a body."""
    return [(m.group(1), m.group(2)) for m in MARKDOWN_LINK_RE.finditer(body)]


def is_internal_link(target: str) -> bool:
    """True when a link points inside the bundle (not an external URL/anchor/mail)."""
    if target.startswith(("http://", "https://", "mailto:", "tel:", "#")):
        return False
    return target.endswith(".md") or "/" in target or target.endswith("/")
