"""On-disk CRUD for keyframe group metadata."""

__author__ = "Lene Preuss <lene.preuss@gmail.com>"

import json
import re
from pathlib import Path

from stable_delusion.exceptions.project_error import ProjectError
from stable_delusion.project.models import KeyframeGroupMetadata


def _group_slug(index: int, name: str) -> str:
    clean = re.sub(r"[^a-z0-9]+", "-", name.lower().strip()).strip("-")
    return f"{index:02d}-{clean}"


class KeyframeGroupRepository:
    """On-disk CRUD for keyframe group metadata within a scene."""

    def create(self, scene_dir: Path, name: str, metadata: KeyframeGroupMetadata) -> Path:
        slug = _group_slug(metadata.index, name)
        group_dir = scene_dir / "keyframes" / slug
        if group_dir.exists():
            raise ProjectError(f"Keyframe group directory already exists: {group_dir}")
        group_dir.mkdir(parents=True)
        self._write(group_dir, metadata)
        return group_dir

    def get(self, group_dir: Path) -> KeyframeGroupMetadata:
        json_path = group_dir / "group.json"
        if not json_path.exists():
            raise ProjectError(f"group.json not found in {group_dir}")
        try:
            return KeyframeGroupMetadata.from_dict(
                json.loads(json_path.read_text(encoding="utf-8"))
            )
        except json.JSONDecodeError as e:
            raise ProjectError(f"group.json is malformed in {group_dir}") from e

    def update(self, group_dir: Path, metadata: KeyframeGroupMetadata) -> None:
        self._write(group_dir, metadata)

    def list_groups(self, scene_dir: Path) -> list[tuple[Path, KeyframeGroupMetadata]]:
        keyframes_dir = scene_dir / "keyframes"
        if not keyframes_dir.exists():
            return []
        results = []
        for entry in keyframes_dir.iterdir():
            if entry.is_dir() and (entry / "group.json").exists():
                results.append((entry, self.get(entry)))
        return sorted(results, key=lambda x: x[1].index)

    def next_index(self, scene_dir: Path) -> int:
        return len(self.list_groups(scene_dir)) + 1

    def _write(self, group_dir: Path, metadata: KeyframeGroupMetadata) -> None:
        json_path = group_dir / "group.json"
        json_path.write_text(json.dumps(metadata.to_dict(), indent=2), encoding="utf-8")
