# /opt/docker/dev/service_finder/backend/app/services/cost_service.py
import uuid
import logging
from decimal import Decimal
from typing import Any, Dict
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, desc, func
from app.models import AssetCost, AssetTelemetry, ExchangeRate
from app.services.gamification_service import GamificationService
from app.services.config_service import config
from app.schemas.asset_cost import AssetCostCreate
from datetime import datetime


logger = logging.getLogger(__name__)

class CostService:
    """
    Industrial Cost & Telemetry Service.
    Összeköti a pénzügyi kiadásokat, az OCR bizonylatokat és a jármű állapotát.
    """

    async def record_cost(self, db: AsyncSession, cost_in: AssetCostCreate, user_id: int):
        """ Teljes körű költségrögzítés: Konverzió + Telemetria + OCR + XP. """
        try:
            # 1. Dinamikus konfiguráció lekérése
            base_currency = await config.get_setting(db, "finance_base_currency", default="EUR")
            base_xp = await config.get_setting(db, "xp_per_cost_log", default=50)
            ocr_multiplier = await config.get_setting(db, "xp_multiplier_ocr_cost", default=1.5)

            # 2. Intelligens Árfolyamkezelés
            exchange_rate = Decimal("1.0")
            if cost_in.currency_local != base_currency:
                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()
                exchange_rate = rate_obj.rate if rate_obj else Decimal("1.0")

            amt_base = Decimal(str(cost_in.amount_local)) / exchange_rate if exchange_rate > 0 else Decimal("0")

            # 3. Költség rekord rögzítése (Kapcsolva a Robot 1 OCR dokumentumához)
            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_base, 
                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(),
                # OCR Kapcsolat
                document_id=cost_in.document_id, 
                is_ai_generated=cost_in.document_id is not None,
                data=cost_in.data or {}
            )
            db.add(new_cost)

            # 4. Automatikus Telemetria (Kilométeróra frissítés)
            if cost_in.mileage_at_cost:
                await self._sync_telemetry(db, cost_in.asset_id, cost_in.mileage_at_cost)

            # 5. Gamification (Értékesebb az adat, ha van róla fotó/OCR)
            final_xp = base_xp
            if new_cost.is_ai_generated:
                final_xp = int(base_xp * float(ocr_multiplier))

            await GamificationService.award_points(
                db, user_id=user_id, amount=final_xp, reason=f"EXPENSE_LOG_{cost_in.cost_type}"
            )

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

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

    async def _sync_telemetry(self, db: AsyncSession, asset_id: int, mileage: int):
        """ Segédfüggvény: Biztonságos óraállás frissítés. """
        stmt = select(AssetTelemetry).where(AssetTelemetry.asset_id == asset_id)
        res = await db.execute(stmt)
        telemetry = res.scalar_one_or_none()
        
        if telemetry:
            # Csak akkor frissítünk, ha az új érték nagyobb (nincs visszatekerés)
            if mileage > (telemetry.current_mileage or 0):
                telemetry.current_mileage = mileage
                telemetry.last_updated = datetime.now()
        else:
            db.add(AssetTelemetry(asset_id=asset_id, current_mileage=mileage))

    async def get_asset_financial_summary(self, db: AsyncSession, asset_id: uuid.UUID) -> Dict[str, Any]:
        """
        Dinamikus pénzügyi összesítő SQL szintű aggregációval.
        MB 2.0: Nem loopolunk Pythonban, a DB számol!
        """
        # 1. Lekérjük az összesített adatokat kategóriánként (Local és EUR)
        stmt = (
            select(
                AssetCost.cost_type,
                func.sum(AssetCost.amount_local).label("total_local"),
                func.sum(AssetCost.amount_eur).label("total_eur"),
                func.count(AssetCost.id).label("transaction_count")
            )
            .where(AssetCost.asset_id == asset_id)
            .group_by(AssetCost.cost_type)
        )
        
        res = await db.execute(stmt)
        rows = res.all()

        summary = {
            "by_category": {},
            "grand_total_local": Decimal("0.0"),
            "grand_total_eur": Decimal("0.0"),
            "total_transactions": 0
        }

        for row in rows:
            cat = row.cost_type or "OTHER"
            summary["by_category"][cat] = {
                "local": float(row.total_local),
                "eur": float(row.total_eur),
                "count": row.transaction_count
            }
            summary["grand_total_local"] += row.total_local
            summary["grand_total_eur"] += row.total_eur
            summary["total_transactions"] += row.transaction_count

        # Decimal konverzió a JSON-höz
        summary["grand_total_local"] = float(summary["grand_total_local"])
        summary["grand_total_eur"] = float(summary["grand_total_eur"])

        return summary

cost_service = CostService()