import logging
import math
from decimal import Decimal
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.models.gamification import UserStats, PointsLedger
from app.models.identity import User, Wallet
from app.models.core_logic import CreditTransaction
from app.models.system_config import SystemParameter

logger = logging.getLogger(__name__)

class GamificationService:
    @staticmethod
    async def get_config(db: AsyncSession):
        """Kiolvassa a GAMIFICATION_MASTER_CONFIG-ot a rendszerparaméterekből."""
        stmt = select(SystemParameter).where(SystemParameter.key == "GAMIFICATION_MASTER_CONFIG")
        res = await db.execute(stmt)
        param = res.scalar_one_or_none()
        return param.value if param else {
            "xp_logic": {"base_xp": 500, "exponent": 1.5},
            "penalty_logic": {
                "thresholds": {"level_1": 100, "level_2": 500, "level_3": 1000},
                "multipliers": {"level_0": 1.0, "level_1": 0.5, "level_2": 0.1, "level_3": 0.0},
                "recovery_rate": 0.5
            },
            "conversion_logic": {"social_to_credit_rate": 100},
            "level_rewards": {"credits_per_10_levels": 50},
            "blocked_roles": ["superadmin", "service_bot"]
        }

    async def process_activity(self, db: AsyncSession, user_id: int, xp_amount: int, social_amount: int, reason: str, is_penalty: bool = False):
        """A 'Bíró' logika: Ellenőriz, büntet, jutalmaz és szintez."""
        config = await self.get_config(db)
        
        # 1. Jogosultság ellenőrzése
        user_stmt = select(User).where(User.id == user_id)
        user = (await db.execute(user_stmt)).scalar_one_or_none()
        if not user or user.is_deleted or user.role.value in config.get("blocked_roles", []):
            return None

        # 2. Stats lekérése
        stats_stmt = select(UserStats).where(UserStats.user_id == user_id)
        stats = (await db.execute(stats_stmt)).scalar_one_or_none()
        if not stats:
            stats = UserStats(user_id=user_id)
            db.add(stats)

        # 3. Büntető logika (Penalty)
        if is_penalty:
            stats.penalty_points += xp_amount
            th = config["penalty_logic"]["thresholds"]
            if stats.penalty_points >= th["level_3"]: stats.restriction_level = 3
            elif stats.penalty_points >= th["level_2"]: stats.restriction_level = 2
            elif stats.penalty_points >= th["level_1"]: stats.restriction_level = 1
            
            db.add(PointsLedger(user_id=user_id, points=0, penalty_change=xp_amount, reason=f"PENALTY: {reason}"))
            await db.commit()
            return stats

        # 4. Dinamikus szorzó alkalmazása
        multipliers = config["penalty_logic"]["multipliers"]
        multiplier = multipliers.get(f"level_{stats.restriction_level}", 1.0)
        
        if multiplier <= 0:
            logger.warning(f"User {user_id} activity blocked (Level {stats.restriction_level})")
            return stats

        # 5. XP, Ledolgozás és Szintlépés
        final_xp = int(xp_amount * multiplier)
        if final_xp > 0:
            stats.total_xp += final_xp
            if stats.penalty_points > 0:
                rec_rate = config["penalty_logic"]["recovery_rate"]
                stats.penalty_points = max(0, stats.penalty_points - int(final_xp * rec_rate))

            xp_cfg = config["xp_logic"]
            new_level = int((stats.total_xp / xp_cfg["base_xp"]) ** (1/xp_cfg["exponent"])) + 1
            if new_level > stats.current_level:
                if new_level % 10 == 0:
                    reward = config["level_rewards"]["credits_per_10_levels"]
                    await self._add_credits(db, user_id, reward, f"Level {new_level} Achievement Bonus")
                stats.current_level = new_level

        # 6. Social pont és váltás
        final_social = int(social_amount * multiplier)
        if final_social > 0:
            stats.social_points += final_social
            rate = config["conversion_logic"]["social_to_credit_rate"]
            if stats.social_points >= rate:
                new_credits = stats.social_points // rate
                stats.social_points %= rate
                await self._add_credits(db, user_id, new_credits, "Social conversion")

        db.add(PointsLedger(user_id=user_id, points=final_xp, reason=reason))
        await db.commit()
        return stats

    async def _add_credits(self, db: AsyncSession, user_id: int, amount: int, reason: str):
        wallet_stmt = select(Wallet).where(Wallet.user_id == user_id)
        wallet = (await db.execute(wallet_stmt)).scalar_one_or_none()
        if wallet:
            wallet.credit_balance += Decimal(amount)
            db.add(CreditTransaction(org_id=None, amount=Decimal(amount), description=reason))

gamification_service = GamificationService()