from __future__ import annotations

import json
import re
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any

import yaml

_FRONTMATTER = re.compile(r"^---\s*\n(.*?)\n---\s*\n(.*)$", re.DOTALL)


_VALID_KINDS = frozenset({"persona", "workflow", "ingest"})
_VALID_SCOPES = frozenset({"global", "vp", "mode"})


@dataclass
class SkillRecord:
    name: str
    description: str = ""
    enabled: bool = True
    triggers: list[str] = field(default_factory=list)
    priority: int = 0
    kind: str = "workflow"
    scope: str = "global"
    body: str = ""
    path: str = ""
    readonly: bool = False

    def to_dict(self) -> dict[str, Any]:
        return {
            "name": self.name,
            "description": self.description,
            "enabled": self.enabled,
            "triggers": self.triggers,
            "priority": self.priority,
            "kind": self.kind,
            "scope": self.scope,
            "readonly": self.readonly,
        }

    def full_dict(self) -> dict[str, Any]:
        d = self.to_dict()
        d["body"] = self.body
        d["path"] = self.path
        return d


def parse_skill_file(path: Path, *, readonly: bool = False) -> SkillRecord | None:
    text = path.read_text(encoding="utf-8")
    m = _FRONTMATTER.match(text)
    if not m:
        return None
    meta = yaml.safe_load(m.group(1)) or {}
    body = m.group(2).strip()
    name = str(meta.get("name") or path.parent.name)
    kind = str(meta.get("kind") or "workflow").strip().lower()
    if kind not in _VALID_KINDS:
        kind = "workflow"
    scope = str(meta.get("scope") or "global").strip().lower()
    if scope not in _VALID_SCOPES:
        scope = "global"
    return SkillRecord(
        name=name,
        description=str(meta.get("description") or ""),
        enabled=bool(meta.get("enabled", True)),
        triggers=list(meta.get("triggers") or []),
        priority=int(meta.get("priority") or 0),
        kind=kind,
        scope=scope,
        body=body,
        path=str(path),
        readonly=readonly,
    )


def load_state(state_path: Path) -> dict[str, Any]:
    if not state_path.is_file():
        return {}
    return json.loads(state_path.read_text(encoding="utf-8"))


def save_state(state_path: Path, state: dict[str, Any]) -> None:
    state_path.parent.mkdir(parents=True, exist_ok=True)
    state_path.write_text(json.dumps(state, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
