"""Vault MD frontmatter 解析与序列化。"""

from __future__ import annotations

import re
from typing import Any

import yaml

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

PAGE_TYPES = frozenset({"sources", "concepts", "entities", "synthesis"})
DEFAULT_PAGE_TYPE = "sources"


class InvalidPageTypeError(ValueError):
    pass


def normalize_page_type(value: Any, *, strict: bool = True) -> str | None:
    """校验 page_type enum；缺省返回 None（flat 路径）。"""
    if value is None or str(value).strip() == "":
        return None
    pt = str(value).strip().lower()
    if pt not in PAGE_TYPES:
        if strict:
            raise InvalidPageTypeError(f"invalid page_type: {value!r}")
        return None
    return pt


def validate_frontmatter(fm: dict[str, Any]) -> dict[str, Any]:
    out = dict(fm)
    if "page_type" in out and str(out.get("page_type") or "").strip():
        out["page_type"] = normalize_page_type(out.get("page_type"))
    else:
        out.setdefault("page_type", DEFAULT_PAGE_TYPE)
    return out


def parse_md(raw: str) -> tuple[dict[str, Any], str]:
    text = raw.replace("\r\n", "\n")
    m = _FM_RE.match(text)
    if not m:
        return {}, text.strip()
    fm = yaml.safe_load(m.group(1)) or {}
    body = m.group(2).strip()
    if not isinstance(fm, dict):
        fm = {}
    return fm, body


def serialize_md(fm: dict[str, Any], body: str) -> str:
    header = yaml.safe_dump(fm, allow_unicode=True, sort_keys=False).strip()
    return f"---\n{header}\n---\n\n{body.strip()}\n"
