from pathlib import Path
from typing import List, Optional

import yaml
from pydantic import BaseModel


class _BlockDumper(yaml.Dumper):
    pass

_BlockDumper.add_representer(
    str,
    lambda dumper, data: dumper.represent_scalar(
        "tag:yaml.org,2002:str", data, style="|" if "\n" in data else None
    ),
)


class PlaybookItem(BaseModel):
    id: str
    title: str
    goal: str
    instructions: str
    tags: List[str] = []
    tools: List[str] = []
    model: str = ""
    order: int = 0


class PlaybookFileStore:
    def __init__(self, directory: Path):
        self.directory = directory
        directory.mkdir(parents=True, exist_ok=True)

    def _path(self, id: str) -> Path:
        return self.directory / f"{id}.yaml"

    def _read(self, path: Path) -> Optional[PlaybookItem]:
        try:
            with open(path, encoding="utf-8") as f:
                data = yaml.safe_load(f)
            return PlaybookItem(
                id=data["id"],
                title=data["title"],
                goal=data.get("goal", ""),
                instructions=data.get("instructions", ""),
                tags=data.get("tags", []),
                tools=data.get("tools", []),
                model=data.get("model", ""),
                order=data.get("order", 0),
            )
        except Exception:
            return None

    @staticmethod
    def _clean(s: str) -> str:
        return "\n".join(line.rstrip() for line in s.split("\n")).strip()

    def _write(self, item: PlaybookItem):
        data = {
            "id": item.id,
            "title": item.title,
            "goal": item.goal,
            "tags": item.tags,
            "tools": item.tools,
            "model": item.model,
            "order": item.order,
            "instructions": self._clean(item.instructions),
        }
        with open(self._path(item.id), "w", encoding="utf-8") as f:
            yaml.dump(data, f, Dumper=_BlockDumper, allow_unicode=True,
                      default_flow_style=False, sort_keys=False, width=4096)

    def all_playbooks(self) -> List[PlaybookItem]:
        items = [self._read(p) for p in self.directory.glob("*.yaml")]
        return sorted((i for i in items if i), key=lambda x: x.order)

    def get_playbook(self, id: str) -> Optional[PlaybookItem]:
        return self._read(self._path(id))

    def add_playbook(self, item: PlaybookItem):
        self._write(item)

    def delete_playbook(self, id: str):
        p = self._path(id)
        if p.exists():
            p.unlink()

    def reorder_playbooks(self, ordered_ids: List[str]):
        all_ids = {p.stem for p in self.directory.glob("*.yaml")}
        valid = [pid for pid in ordered_ids if pid in all_ids]
        missing = sorted(all_ids - set(valid))
        for index, pid in enumerate(valid + missing):
            item = self.get_playbook(pid)
            if item:
                item.order = index
                self._write(item)


from ..nexus_config import PLAYBOOK_DIR
playbook_store = PlaybookFileStore(PLAYBOOK_DIR)
