"""vault MD + atom 小意打分回填。"""

from __future__ import annotations

from typing import Any

from niannian.soul.reflection_scorer import ScoredRound, TriReviewScorer
from niannian.vault.frontmatter import parse_md, serialize_md
from niannian.vault.store import VaultStore


def _verdict_from_score(score: float, *, seat_a_pass: bool) -> str:
    if not seat_a_pass:
        return "reject"
    if score >= 75:
        return "adopt"
    if score >= 50:
        return "hold"
    return "reject"


class VaultScoringService:
    def __init__(
        self,
        store: VaultStore,
        *,
        scorer: TriReviewScorer | None = None,
        config: dict[str, Any] | None = None,
        memory_store=None,
    ) -> None:
        self._store = store
        self._scorer = scorer
        self._config = config or {}
        self._memory = memory_store
        vault_cfg = self._config.get("vault") or {}
        scoring = vault_cfg.get("scoring") if isinstance(vault_cfg, dict) else {}
        self._on_niannian = bool((scoring or {}).get("on_niannian_crawl", True))

    def niannian_scoring_enabled(self) -> bool:
        return self._on_niannian and self._scorer is not None

    def score_text(
        self,
        text: str,
        *,
        values: dict[str, Any] | None = None,
    ) -> ScoredRound:
        if self._scorer is None:
            raise ValueError("scorer_unavailable")
        return self._scorer.score(text, kind="narrative_line", values=values)

    def apply_score(
        self,
        *,
        vault_id: str,
        rel_path: str,
        atom_id: str | None,
        scored: ScoredRound,
    ) -> dict[str, Any]:
        score = min(scored.seat_b_score, scored.seat_c_score)
        verdict = _verdict_from_score(score, seat_a_pass=scored.seat_a_pass)
        doc = self._store.read_document(rel_path)
        fm = dict(doc.get("frontmatter") or {})
        fm["score"] = round(score, 1)
        fm["score_verdict"] = verdict
        if atom_id:
            fm["atom_id"] = atom_id
        path = self._store._root / rel_path
        path.write_text(serialize_md(fm, doc.get("body") or ""), encoding="utf-8")
        if self._store._manifest is not None:
            self._store._manifest.update_file_entry(f"vault/{rel_path}", path)
        if atom_id and self._memory is not None:
            self._memory.patch_atom_meta(
                atom_id,
                {
                    "vault": {
                        "namespace": fm.get("namespace") or "niannian",
                        "path": rel_path,
                        "vault_id": vault_id,
                    },
                    "score": fm["score"],
                    "score_verdict": verdict,
                },
            )
        return {"vault_id": vault_id, "score": fm["score"], "score_verdict": verdict}
