from __future__ import annotations

import json
from pathlib import Path
from typing import Any

from app.core.config import SERVER_DIR
from app.services.agent_asset_spreadsheet import RULE_LIBRARY_NAMES

JSON_RULE_MIME_TYPE = "application/json"


class AgentAssetRuleLibraryManager:
    def __init__(self, rule_root: Path | None = None) -> None:
        self.rule_root = Path(rule_root or (SERVER_DIR / "rules")).resolve()

    def ensure_rule_library_dirs(self) -> None:
        for library in sorted(RULE_LIBRARY_NAMES):
            (self.rule_root / library).mkdir(parents=True, exist_ok=True)

    def resolve_rule_library_path(self, *, library: str, file_name: str) -> Path:
        normalized_library = str(library or "").strip()
        if normalized_library not in RULE_LIBRARY_NAMES:
            raise ValueError("Invalid rule library.")

        normalized_name = Path(str(file_name or "").strip()).name.strip()
        if not normalized_name or not normalized_name.endswith(".json"):
            raise ValueError("Rule JSON file name must end with .json.")

        library_dir = (self.rule_root / normalized_library).resolve()
        target_path = (library_dir / normalized_name).resolve()
        try:
            target_path.relative_to(library_dir)
        except ValueError:
            raise ValueError("Invalid rule JSON path.") from None
        return target_path

    def read_rule_library_json(self, *, library: str, file_name: str) -> dict[str, Any]:
        target_path = self.resolve_rule_library_path(library=library, file_name=file_name)
        if not target_path.exists():
            raise FileNotFoundError("Rule JSON file not found.")

        try:
            payload = json.loads(target_path.read_text(encoding="utf-8"))
        except json.JSONDecodeError as exc:
            raise ValueError("Rule JSON file is invalid.") from exc

        if not isinstance(payload, dict):
            raise ValueError("Rule JSON payload must be an object.")
        return payload

    def write_rule_library_json(
        self,
        *,
        library: str,
        file_name: str,
        payload: dict[str, Any],
    ) -> dict[str, Any]:
        if not isinstance(payload, dict):
            raise ValueError("Rule JSON payload must be an object.")

        rule_code = str(payload.get("rule_code") or "").strip()
        if not rule_code:
            raise ValueError("Rule JSON must include rule_code.")

        evaluator = str(payload.get("evaluator") or "").strip()
        if not evaluator:
            raise ValueError("Rule JSON must include evaluator.")

        target_path = self.resolve_rule_library_path(library=library, file_name=file_name)
        target_path.parent.mkdir(parents=True, exist_ok=True)
        target_path.write_text(
            f"{json.dumps(payload, ensure_ascii=False, indent=2)}\n",
            encoding="utf-8",
        )
        return payload

    def list_rule_library_json_files(self, *, library: str) -> list[str]:
        library_dir = self.resolve_rule_library_path(
            library=library,
            file_name="placeholder.json",
        ).parent
        library_dir.mkdir(parents=True, exist_ok=True)
        return sorted(path.name for path in library_dir.glob("*.json") if path.is_file())
