"""Persistence for human-review queue and decisions within a job output dir."""

import json
import os
from typing import Dict, List

from backend.review.schemas import validate_decision


class ReviewStore:
    def __init__(self, job_out_dir: str, create: bool = True) -> None:
        self.review_dir = os.path.join(job_out_dir, "review")
        if create:
            os.makedirs(self.review_dir, exist_ok=True)

    def _path(self, name: str) -> str:
        return os.path.join(self.review_dir, name)

    def _write_json(self, name: str, value) -> None:
        path = self._path(name)
        tmp = f"{path}.tmp"
        with open(tmp, "w", encoding="utf-8") as f:
            json.dump(value, f, indent=2)
        os.replace(tmp, path)

    def write_queue(self, queue: List[dict]) -> None:
        self._write_json("review_queue.json", queue)

    def read_queue(self) -> List[dict]:
        try:
            with open(self._path("review_queue.json"), encoding="utf-8") as f:
                value = json.load(f)
            return value if isinstance(value, list) else []
        except (OSError, json.JSONDecodeError):
            return []

    def append_decision(self, decision: dict) -> None:
        valid = validate_decision(decision)
        if not valid or not valid["review_item_id"]:
            raise ValueError("invalid review decision")
        decisions = self.read_decisions()
        decisions[valid["review_item_id"]] = valid
        self._write_json("review_decisions.json", decisions)

    def read_decisions(self) -> Dict[str, dict]:
        try:
            with open(self._path("review_decisions.json"), encoding="utf-8") as f:
                value = json.load(f)
            return value if isinstance(value, dict) else {}
        except (OSError, json.JSONDecodeError):
            return {}

    def progress(self, queue: List[dict]) -> dict:
        decisions = self.read_decisions()
        required = [item for item in queue if item.get("blocking")]
        completed = [item for item in required if item.get("review_item_id") in decisions]
        return {
            "required": len(required),
            "completed": len(completed),
            "remaining": len(required) - len(completed),
            "total": len(queue),
        }
