import logging
from decimal import Decimal
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, desc
from app.models.asset import AssetCost, AssetTelemetry, ExchangeRate
from app.models.gamification import UserStats
from app.models.system_config import SystemParameter
from app.schemas.asset_cost import AssetCostCreate
from datetime import datetime

logger = logging.getLogger(__name__)

class CostService:
    @staticmethod
    async def get_param(db: AsyncSession, key: str, default: any) -> any:
        """Rendszerparaméter lekérése (pl. XP szorzó)."""
        stmt = select(SystemParameter).where(SystemParameter.key == key)
        res = await db.execute(stmt)
        param = res.scalar_one_or_none()
        return param.value if param else default

    async def record_cost(self, db: AsyncSession, cost_in: AssetCostCreate, user_id: int):
        """
        Költség rögzítése: EUR konverzió + Telemetria + XP.
        """
        try:
            # 1. Árfolyam lekérése (EUR alapú pivot)
            # Megkeressük a legfrissebb rögzített árfolyamot a megadott devizához
            rate_stmt = select(ExchangeRate).where(
                ExchangeRate.target_currency == cost_in.currency_local
            ).order_by(desc(ExchangeRate.updated_at)).limit(1)
            
            rate_res = await db.execute(rate_stmt)
            rate_obj = rate_res.scalar_one_or_none()
            
            # Ha nincs rögzített árfolyam, 1.0-val számolunk (vagy hibát dobhatunk a konfigurációtól függően)
            exchange_rate = rate_obj.rate if rate_obj else Decimal("1.0")
            
            # EUR kalkuláció: Helyi összeg / Árfolyam (Pl. 40000 HUF / 400 = 100 EUR)
            amt_eur = Decimal(str(cost_in.amount_local)) / exchange_rate if exchange_rate > 0 else Decimal("0")

            # 2. Költség rekord létrehozása
            new_cost = AssetCost(
                asset_id=cost_in.asset_id,
                organization_id=cost_in.organization_id,
                driver_id=user_id,
                cost_type=cost_in.cost_type,
                amount_local=cost_in.amount_local,
                currency_local=cost_in.currency_local,
                amount_eur=amt_eur,
                net_amount_local=cost_in.net_amount_local,
                vat_rate=cost_in.vat_rate,
                exchange_rate_used=exchange_rate,
                mileage_at_cost=cost_in.mileage_at_cost,
                date=cost_in.date or datetime.now(),
                data=cost_in.data or {}
            )
            db.add(new_cost)

            # 3. Telemetria frissítése (Ha érkezett kilométeróra állás)
            if cost_in.mileage_at_cost:
                tel_stmt = select(AssetTelemetry).where(AssetTelemetry.asset_id == cost_in.asset_id)
                res = await db.execute(tel_stmt)
                telemetry = res.scalar_one_or_none()
                
                if telemetry:
                    # Megakadályozzuk a "visszatekerést"
                    if cost_in.mileage_at_cost > (telemetry.current_mileage or 0):
                        telemetry.current_mileage = cost_in.mileage_at_cost
                else:
                    # Ha még nem volt telemetria adat, létrehozzuk
                    new_telemetry = AssetTelemetry(
                        asset_id=cost_in.asset_id,
                        current_mileage=cost_in.mileage_at_cost
                    )
                    db.add(new_telemetry)

            # 4. Gamification XP jóváírás
            xp_reward = await self.get_param(db, "XP_PER_COST_LOG", 50)
            stats_stmt = select(UserStats).where(UserStats.user_id == user_id)
            stats_res = await db.execute(stats_stmt)
            user_stats = stats_res.scalar_one_or_none()
            
            if user_stats:
                user_stats.total_xp += int(xp_reward)
                logger.info(f"User {user_id} earned {xp_reward} XP for cost logging.")

            await db.commit()
            await db.refresh(new_cost)
            return new_cost

        except Exception as e:
            await db.rollback()
            logger.error(f"Error in record_cost: {str(e)}")
            raise e

cost_service = CostService()