"""ガチャシステムのロジック"""
import random
import uuid
from datetime import datetime
from typing import Optional, Tuple
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.config import settings
from app.models.card import Card, CardRarity
from app.repositories.user import UserRepository
from app.repositories.card import CardRepository, UniqueCardRepository
from app.db.models import DrawHistory
from app.services.card_master import card_master_service


class GachaService:
    """ガチャシステムのサービスクラス"""
    
    def __init__(self, session: AsyncSession):
        self.session = session
        self.user_repo = UserRepository(session)
        self.card_repo = CardRepository(session)
        self.unique_repo = UniqueCardRepository(session)
        # Load card info from external source
        self.CARD_INFO = card_master_service.get_card_info()
    
    async def draw_card(self, user_did: str, is_paid: bool = False) -> Tuple[Card, bool]:
        """
        カードを抽選する
        
        Args:
            user_did: ユーザーのDID
            is_paid: 課金ガチャかどうか
            
        Returns:
            (Card, is_unique): 抽選されたカードとuniqueかどうか
        """
        # Get or create user
        user = await self.user_repo.get_or_create(user_did)
        # レアリティ抽選
        rarity = self._determine_rarity(is_paid)
        
        # カード種類を選択
        card_id = self._select_card_id(rarity)
        
        # CPを決定
        cp = self._calculate_cp(card_id, rarity)
        
        # uniqueカードチェック
        is_unique = False
        
        if rarity == CardRarity.UNIQUE:
            # uniqueカードの場合、利用可能かチェック
            is_available = await self.unique_repo.is_card_available(card_id)
            if not is_available:
                # 利用不可の場合はキラカードに変更
                rarity = CardRarity.KIRA
            else:
                is_unique = True
        
        # データベースにカードを保存
        user_card = await self.card_repo.create_user_card(
            user_id=user.id,
            card_id=card_id,
            cp=cp,
            status=rarity,
            skill=self._get_skill_for_card(card_id, rarity),
            is_unique=is_unique
        )
        
        # 抽選履歴を保存
        draw_history = DrawHistory(
            user_id=user.id,
            card_id=card_id,
            status=rarity,
            cp=cp,
            is_paid=is_paid
        )
        self.session.add(draw_history)
        
        # API用のCardモデルに変換
        card = Card(
            id=card_id,
            cp=cp,
            status=rarity,
            skill=user_card.skill,
            owner_did=user_did,
            obtained_at=user_card.obtained_at,
            is_unique=is_unique,
            unique_id=str(user_card.unique_id) if user_card.unique_id else None
        )
        
        # atproto PDSに同期(非同期で実行)
        try:
            from app.services.card_sync import CardSyncService
            sync_service = CardSyncService(self.session)
            await sync_service.sync_card_to_pds(user_card, user_did)
        except Exception:
            # 同期失敗してもガチャは成功とする
            pass
        
        return card, is_unique
    
    def _determine_rarity(self, is_paid: bool) -> CardRarity:
        """レアリティを抽選する"""
        rand = random.random() * 100
        
        if is_paid:
            # 課金ガチャは確率アップ
            if rand < settings.prob_unique * 2:  # 0.0002%
                return CardRarity.UNIQUE
            elif rand < settings.prob_kira * 2:  # 0.2%
                return CardRarity.KIRA
            elif rand < 0.5:  # 0.5%
                return CardRarity.SUPER_RARE
            elif rand < 5:  # 5%
                return CardRarity.RARE
        else:
            # 通常ガチャ
            if rand < settings.prob_unique:
                return CardRarity.UNIQUE
            elif rand < settings.prob_kira:
                return CardRarity.KIRA
            elif rand < settings.prob_super_rare:
                return CardRarity.SUPER_RARE
            elif rand < settings.prob_rare:
                return CardRarity.RARE
        
        return CardRarity.NORMAL
    
    def _select_card_id(self, rarity: CardRarity) -> int:
        """レアリティに応じてカードIDを選択"""
        if rarity in [CardRarity.UNIQUE, CardRarity.KIRA]:
            # レアカードは特定のIDに偏らせる
            weights = [1, 1, 2, 2, 3, 1, 1, 3, 5, 4, 5, 2, 3, 4, 6, 5]
        else:
            # 通常は均等
            weights = [1] * 16
        
        return random.choices(range(16), weights=weights)[0]
    
    def _calculate_cp(self, card_id: int, rarity: CardRarity) -> int:
        """カードのCPを計算"""
        base_range = self.CARD_INFO[card_id]["base_cp_range"]
        base_cp = random.randint(*base_range)
        
        # レアリティボーナス
        multiplier = {
            CardRarity.NORMAL: 1.0,
            CardRarity.RARE: 1.5,
            CardRarity.SUPER_RARE: 2.0,
            CardRarity.KIRA: 3.0,
            CardRarity.UNIQUE: 5.0,
        }[rarity]
        
        return int(base_cp * multiplier)
    
    def _get_skill_for_card(self, card_id: int, rarity: CardRarity) -> Optional[str]:
        """カードのスキルを取得"""
        if rarity in [CardRarity.KIRA, CardRarity.UNIQUE]:
            # TODO: スキル情報を返す
            return f"skill_{card_id}_{rarity.value}"
        return None