from dataclasses import dataclass
from typing import Dict, List, Optional
import json
import os
from pathlib import Path


@dataclass
class ActionInfo:
    id: int
    name: str
    description: str
    category: str
    strength: str

    def __str__(self) -> str:
        return f"{self.description} (ID: {self.id}, Category: {self.category}, Strength: {self.strength})"


class ActionSpace:
    def __init__(self, config_path: Optional[str] = None):
        if config_path is None:
            config_path = os.path.join(
                Path(__file__).parent.parent, "configs", "actions.json"
            )
        self._actions: Dict[int, ActionInfo] = {}
        self._load_actions(config_path)

    def _load_actions(self, config_path: str) -> None:
        """JSON 파일에서 액션 정보를 로드합니다."""
        with open(config_path, "r", encoding="utf-8") as f:
            data = json.load(f)

        for action in data["actions"]:
            self.add_action(
                id=action["id"],
                name=action["name"],
                description=action["description"],
                category=action["category"],
                strength=action["strength"],
            )

    def add_action(
        self, id: int, name: str, description: str, category: str, strength: str
    ) -> None:
        """새로운 액션을 추가합니다."""
        if id in self._actions:
            raise ValueError(f"Action with id {id} already exists")

        self._actions[id] = ActionInfo(
            id=id,
            name=name,
            description=description,
            category=category,
            strength=strength,
        )

    def remove_action(self, action_id: int) -> None:
        """지정된 ID의 액션을 제거합니다."""
        if action_id not in self._actions:
            raise ValueError(f"Action with id {action_id} does not exist")
        del self._actions[action_id]

    def get_action(self, action_id: int) -> ActionInfo:
        """액션 ID로 액션 정보를 조회합니다."""
        if action_id not in self._actions:
            raise ValueError(f"Invalid action id: {action_id}")
        return self._actions[action_id]

    def get_actions_by_category(self, category: str) -> List[ActionInfo]:
        """특정 카테고리의 모든 액션을 반환합니다."""
        return [
            action for action in self._actions.values() if action.category == category
        ]

    def get_actions_by_strength(self, strength: str) -> List[ActionInfo]:
        """특정 강도의 모든 액션을 반환합니다."""
        return [
            action for action in self._actions.values() if action.strength == strength
        ]

    def save_actions(self, file_path: str) -> None:
        """현재 액션 설정을 JSON 파일로 저장합니다."""
        data = {
            "actions": [
                {
                    "id": action.id,
                    "name": action.name,
                    "description": action.description,
                    "category": action.category,
                    "strength": action.strength,
                }
                for action in self._actions.values()
            ]
        }

        with open(file_path, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=4)

    @property
    def action_space_size(self) -> int:
        """현재 액션 공간의 크기를 반환합니다."""
        return len(self._actions)

    def list_actions(self) -> List[ActionInfo]:
        """모든 액션 정보를 리스트로 반환합니다."""
        return list(self._actions.values())
