"""
GitHub Webhook Service - Phase 13.1
====================================
封裝 GitHub Webhook 相關的 Redis 操作

遵循 leWOOOgo 積木化原則:
- Router 層不直接存取 Redis
- 透過 Service 層封裝資料存取邏輯
"""

import json
from typing import Protocol

import structlog

from src.core.redis_client import get_redis

logger = structlog.get_logger(__name__)


# Redis TTL: 7 天
GITHUB_REVIEW_TTL_SECONDS = 7 * 24 * 60 * 60


class IGitHubReviewRepository(Protocol):
    """GitHub Review Repository Interface"""

    async def save_review(self, review_id: str, review_data: dict) -> bool:
        """儲存審查結果"""
        ...

    async def get_review(self, review_id: str) -> dict | None:
        """取得審查結果"""
        ...


class GitHubReviewRedisRepository:
    """Redis 實作的 GitHub Review Repository"""

    KEY_PREFIX = "github_review:"

    async def save_review(self, review_id: str, review_data: dict) -> bool:
        """
        儲存審查結果到 Redis

        Args:
            review_id: 審查 ID
            review_data: 審查結果資料

        Returns:
            bool: 儲存是否成功
        """
        try:
            redis_client = get_redis()
            key = f"{self.KEY_PREFIX}{review_id}"
            await redis_client.set(
                key,
                json.dumps(review_data, ensure_ascii=False),
                ex=GITHUB_REVIEW_TTL_SECONDS,
            )
            logger.debug("github_review_saved", review_id=review_id)
            return True
        except Exception as e:
            logger.error("github_review_save_failed", review_id=review_id, error=str(e))
            return False

    async def get_review(self, review_id: str) -> dict | None:
        """
        取得審查結果

        Args:
            review_id: 審查 ID

        Returns:
            審查結果資料，或 None
        """
        try:
            redis_client = get_redis()
            key = f"{self.KEY_PREFIX}{review_id}"
            result = await redis_client.get(key)
            if result:
                return json.loads(result)
            return None
        except Exception as e:
            logger.error("github_review_get_failed", review_id=review_id, error=str(e))
            return None


class GitHubWebhookService:
    """
    GitHub Webhook 服務

    封裝審查結果的儲存與查詢
    """

    def __init__(self, repository: IGitHubReviewRepository | None = None):
        self._repository = repository or GitHubReviewRedisRepository()

    async def save_review_result(
        self,
        review_id: str,
        review_data: dict,
    ) -> bool:
        """儲存審查結果"""
        return await self._repository.save_review(review_id, review_data)

    async def get_review_result(self, review_id: str) -> dict | None:
        """取得審查結果"""
        return await self._repository.get_review(review_id)


# 單例
_service: GitHubWebhookService | None = None


def get_github_webhook_service() -> GitHubWebhookService:
    """取得 GitHubWebhookService 單例"""
    global _service
    if _service is None:
        _service = GitHubWebhookService()
    return _service
