"""VP MD direct edit — etag read/write (bypass enrich)."""

from __future__ import annotations

from datetime import datetime, timezone
from pathlib import Path

import yaml

from niannian.virtual_persona.profile_schema import validate_profile_sections
from niannian.virtual_persona.store import VirtualPersonaStore

MD_FILE_ALIASES: dict[str, str] = {
    "profile": "profile",
    "profile-md": "profile",
    "assembly_master": "assembly_master",
    "assembly-master": "assembly_master",
}

ALLOWED_MD_FILES = frozenset({"profile", "assembly_master"})


class MdStaleError(Exception):
    """If-Match does not match current file etag."""

    def __init__(self, current_etag: str) -> None:
        self.current_etag = current_etag
        super().__init__("stale etag")


def normalize_md_file(file_key: str) -> str:
    key = str(file_key or "").strip()
    normalized = MD_FILE_ALIASES.get(key)
    if normalized is None or normalized not in ALLOWED_MD_FILES:
        raise ValueError(f"unknown md file: {file_key!r}")
    return normalized


def file_etag(path: Path) -> str:
    if not path.is_file():
        return '"0"'
    stat = path.stat()
    return f'W/"{stat.st_mtime_ns}-{stat.st_size}"'


def md_path(store: VirtualPersonaStore, vp_id: str, file: str) -> Path:
    normalized = normalize_md_file(file)
    if normalized == "profile":
        return store.vp_dir(vp_id) / "profile.md"
    return store.assembly_master_path(vp_id)


def read_vp_md(store: VirtualPersonaStore, vp_id: str, file: str) -> tuple[str, str]:
    path = md_path(store, vp_id, file)
    content = path.read_text(encoding="utf-8") if path.is_file() else ""
    return content, file_etag(path)


def write_vp_md(
    store: VirtualPersonaStore,
    vp_id: str,
    file: str,
    content: str,
    *,
    if_match: str | None,
) -> tuple[str, str]:
    normalized = normalize_md_file(file)
    path = md_path(store, vp_id, normalized)
    current = file_etag(path)
    expected = str(if_match or "").strip()
    if not expected:
        raise ValueError("If-Match required")
    if expected != current:
        raise MdStaleError(current)
    if normalized == "profile":
        validate_profile_sections(content)
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content, encoding="utf-8")
    if normalized == "profile":
        _touch_meta_updated_at(store, vp_id)
    return content, file_etag(path)


def _touch_meta_updated_at(store: VirtualPersonaStore, vp_id: str) -> None:
    dest = store.vp_dir(vp_id)
    meta_path = dest / "meta.yaml"
    if not meta_path.is_file():
        return
    with meta_path.open(encoding="utf-8") as f:
        meta = yaml.safe_load(f) or {}
    if not isinstance(meta, dict):
        return
    meta["updated_at"] = datetime.now(timezone.utc).isoformat()
    with meta_path.open("w", encoding="utf-8") as f:
        yaml.safe_dump(meta, f, allow_unicode=True, sort_keys=False)
