"""
Action-Card 매핑 레이어
Q_Table의 action_id와 Card_Management의 card_id를 연결
"""

import json
from pathlib import Path
from typing import Dict, Optional


class ActionCardMapper:
    """
    action_id (0, 1, 2, ...) ↔ card_id ("no_0", "no_1", ...)

    Q_Table은 추상적인 action_id만 다루고,
    Card_Management는 구체적인 card_id만 다룬다.
    이 클래스가 둘을 연결하는 단일 책임을 가진다.

    매핑은 JSON 파일에서 로드되며, 카드 추가/삭제 시 수동으로 업데이트된다.
    """

    def __init__(self, mapping_file: Optional[str] = None):
        """
        Args:
            mapping_file: JSON 매핑 파일 경로
                         (기본: integration/data/action_card_mapping.json)
        """
        if mapping_file is None:
            current_dir = Path(__file__).parent
            mapping_file = current_dir / "data" / "action_card_mapping.json"

        self.mapping_file = Path(mapping_file)
        self.action_to_card: Dict[int, str] = {}
        self.card_to_action: Dict[str, int] = {}

        self._load_mapping()

    def _load_mapping(self):
        """JSON 파일에서 매핑 로드"""
        if not self.mapping_file.exists():
            raise FileNotFoundError(
                f"Mapping file not found: {self.mapping_file}\n"
                f"Please create action_card_mapping.json first."
            )

        with open(self.mapping_file, "r", encoding="utf-8") as f:
            data = json.load(f)

        # action_to_card: {"0": "no_0", "1": "no_1", ...}
        # JSON keys are strings, convert to int
        self.action_to_card = {int(k): v for k, v in data["action_to_card"].items()}

        # card_to_action: reverse mapping for quick lookup
        self.card_to_action = {v: int(k) for k, v in data["action_to_card"].items()}

    def get_card_id(self, action_id: int) -> Optional[str]:
        """
        action_id → card_id 변환

        Args:
            action_id: Q_Table에서 사용하는 액션 ID (0, 1, 2, ...)

        Returns:
            card_id: Card_Management에서 사용하는 카드 ID ("no_0", "no_1", ...)
                    매핑이 없으면 None

        Example:
            >>> mapper.get_card_id(5)
            'no_5'
        """
        return self.action_to_card.get(action_id)

    def get_action_id(self, card_id: str) -> Optional[int]:
        """
        card_id → action_id 변환

        Args:
            card_id: Card_Management에서 사용하는 카드 ID ("no_0", "no_1", ...)

        Returns:
            action_id: Q_Table에서 사용하는 액션 ID (0, 1, 2, ...)
                      매핑이 없으면 None

        Example:
            >>> mapper.get_action_id('no_5')
            5
        """
        return self.card_to_action.get(card_id)

    def get_action_space_size(self) -> int:
        """
        현재 매핑된 액션 개수 (= 카드 개수)

        Returns:
            액션 공간 크기

        Example:
            >>> mapper.get_action_space_size()
            21  # 21개의 카드
        """
        return len(self.action_to_card)

    def get_all_mappings(self) -> Dict[int, str]:
        """
        전체 매핑 반환

        Returns:
            {action_id: card_id} 딕셔너리

        Example:
            >>> mapper.get_all_mappings()
            {0: 'no_0', 1: 'no_1', ..., 20: 'no_20'}
        """
        return self.action_to_card.copy()

    def get_all_action_ids(self) -> list:
        """
        모든 action_id 리스트 반환 (정렬됨)

        Returns:
            [0, 1, 2, ..., 20]
        """
        return sorted(self.action_to_card.keys())

    def get_all_card_ids(self) -> list:
        """
        모든 card_id 리스트 반환 (action_id 순서)

        Returns:
            ['no_0', 'no_1', ..., 'no_20']
        """
        return [self.action_to_card[i] for i in sorted(self.action_to_card.keys())]

    def is_valid_action_id(self, action_id: int) -> bool:
        """action_id가 매핑에 존재하는지 확인"""
        return action_id in self.action_to_card

    def is_valid_card_id(self, card_id: str) -> bool:
        """card_id가 매핑에 존재하는지 확인"""
        return card_id in self.card_to_action

    def reload(self):
        """매핑 파일 다시 로드 (런타임 중 파일이 변경된 경우)"""
        self._load_mapping()

    def __repr__(self) -> str:
        return (
            f"ActionCardMapper("
            f"action_space_size={self.get_action_space_size()}, "
            f"mapping_file={self.mapping_file}"
            f")"
        )
