"""
Experience Repository
Experience 데이터를 JSONL 형식으로 저장/로드
"""

import json
from pathlib import Path
from typing import List, Optional
from datetime import datetime
from ..model.experience import Experience


class ExperienceRepository:
    """
    Experience 데이터를 파일 시스템에 저장/로드하는 Repository

    JSONL (JSON Lines) 형식 사용:
    - 각 줄이 하나의 JSON 객체 (Experience)
    - 스트리밍 방식으로 읽기/쓰기 가능
    - 대용량 데이터 처리에 유리
    """

    def __init__(self, data_dir: Optional[str] = None):
        """
        Args:
            data_dir: Experience 데이터를 저장할 디렉토리
                     (기본: Q_Table/data/experiences/)
        """
        if data_dir is None:
            current_dir = Path(__file__).parent.parent.parent
            data_dir = current_dir / "data" / "experiences"

        self.data_dir = Path(data_dir)
        self.data_dir.mkdir(parents=True, exist_ok=True)

    def save(self, experience: Experience, filename: str = "experiences.jsonl"):
        """
        단일 Experience를 파일에 추가 저장

        Args:
            experience: 저장할 Experience
            filename: 파일명 (기본: experiences.jsonl)
        """
        file_path = self.data_dir / filename

        with open(file_path, "a", encoding="utf-8") as f:
            json.dump(experience.to_dict(), f, ensure_ascii=False)
            f.write("\n")

    def save_batch(
        self, experiences: List[Experience], filename: str = "experiences.jsonl"
    ):
        """
        여러 Experience를 배치로 저장

        Args:
            experiences: Experience 리스트
            filename: 파일명
        """
        file_path = self.data_dir / filename

        with open(file_path, "a", encoding="utf-8") as f:
            for exp in experiences:
                json.dump(exp.to_dict(), f, ensure_ascii=False)
                f.write("\n")

    def load_all(self, filename: str = "experiences.jsonl") -> List[Experience]:
        """
        파일에서 모든 Experience 로드

        Args:
            filename: 파일명

        Returns:
            Experience 리스트
        """
        file_path = self.data_dir / filename

        if not file_path.exists():
            return []

        experiences = []
        with open(file_path, "r", encoding="utf-8") as f:
            for line in f:
                if line.strip():
                    data = json.loads(line)
                    experiences.append(Experience.from_dict(data))

        return experiences

    def load_by_episode(
        self, episode_id: str, filename: str = "experiences.jsonl"
    ) -> List[Experience]:
        """
        특정 에피소드의 Experience들만 로드

        Args:
            episode_id: 에피소드 ID
            filename: 파일명

        Returns:
            해당 에피소드의 Experience 리스트
        """
        all_experiences = self.load_all(filename)
        return [exp for exp in all_experiences if exp.episode_id == episode_id]

    def count(self, filename: str = "experiences.jsonl") -> int:
        """
        저장된 Experience 개수

        Args:
            filename: 파일명

        Returns:
            Experience 개수
        """
        file_path = self.data_dir / filename

        if not file_path.exists():
            return 0

        with open(file_path, "r", encoding="utf-8") as f:
            return sum(1 for line in f if line.strip())

    def clear(self, filename: str = "experiences.jsonl"):
        """
        파일 내용 삭제

        Args:
            filename: 파일명
        """
        file_path = self.data_dir / filename

        if file_path.exists():
            file_path.unlink()

    def create_new_file(self, prefix: str = "exp") -> str:
        """
        타임스탬프가 포함된 새 파일 생성

        Args:
            prefix: 파일명 접두사

        Returns:
            생성된 파일명

        Example:
            >>> repo.create_new_file("train")
            'train_20251029_163000.jsonl'
        """
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"{prefix}_{timestamp}.jsonl"
        file_path = self.data_dir / filename
        file_path.touch()
        return filename

    def list_files(self) -> List[str]:
        """
        데이터 디렉토리의 모든 JSONL 파일 목록

        Returns:
            파일명 리스트
        """
        return [f.name for f in self.data_dir.glob("*.jsonl")]

    def get_file_info(self, filename: str) -> dict:
        """
        파일 정보 조회

        Args:
            filename: 파일명

        Returns:
            {
                'filename': 'experiences.jsonl',
                'path': '/path/to/file',
                'size': 1024,  # bytes
                'count': 100,   # experience 개수
                'created': '2025-10-29 16:30:00'
            }
        """
        file_path = self.data_dir / filename

        if not file_path.exists():
            return None

        stat = file_path.stat()

        return {
            "filename": filename,
            "path": str(file_path),
            "size": stat.st_size,
            "count": self.count(filename),
            "created": datetime.fromtimestamp(stat.st_ctime).strftime(
                "%Y-%m-%d %H:%M:%S"
            ),
            "modified": datetime.fromtimestamp(stat.st_mtime).strftime(
                "%Y-%m-%d %H:%M:%S"
            ),
        }
