"""
Service pour les transactions NFC avec cartes physiques
"""
import uuid
import json
from datetime import datetime
from sqlalchemy.orm import Session
from models.models import NFCCard, NFCCardTransaction, User, Transaction, TransactionType, TransactionStatus, Wallet
from services.users import get_user_wallet
from services.nfc_card_service import NFCCardService
from typing import Optional, Dict, Any
import logging

logger = logging.getLogger(__name__)

class NFCTransactionService:
    """Service pour les transactions NFC avec cartes physiques"""
    
    @staticmethod
    def process_nfc_payment(
        db: Session,
        card_uid: str,
        amount: float,
        merchant_user_id: str,
        device_info: str = None,
        location: str = None
    ) -> Dict[str, Any]:
        """
        Traiter un paiement NFC avec carte physique
        - Le client présente sa carte NFC
        - Le vendeur utilise son téléphone compatible NFC
        - La transaction est effectuée entre les comptes
        """
        try:
            # 1. Vérifier la carte NFC
            card = NFCCardService.get_card_by_uid(db, card_uid)
            if not card:
                raise ValueError("Carte NFC introuvable")
            
            if card.status != "active":
                raise ValueError("Carte NFC inactive")
            
            # 2. Récupérer les utilisateurs
            client_user = db.query(User).filter(User.id == card.user_id).first()
            merchant_user = db.query(User).filter(User.id == merchant_user_id).first()
            
            if not client_user or not merchant_user:
                raise ValueError("Utilisateur introuvable")
            
            if client_user.id == merchant_user.id:
                raise ValueError("Le client et le vendeur ne peuvent pas être la même personne")
            
            # 3. Récupérer les wallets
            client_wallet = get_user_wallet(client_user.id, db)
            merchant_wallet = get_user_wallet(merchant_user.id, db)
            
            # 4. Vérifier les soldes et limites
            if client_wallet.balance < amount:
                raise ValueError("Solde client insuffisant")
            
            if merchant_wallet.max_balance and (merchant_wallet.balance + amount) > merchant_wallet.max_balance:
                raise ValueError("Le compte vendeur atteindrait sa limite")
            
            # 5. Effectuer la transaction
            client_wallet.balance -= amount
            merchant_wallet.balance += amount
            
            # 6. Créer les transactions
            transfer_id = str(uuid.uuid4())
            
            # Transaction client (débit)
            client_transaction = Transaction(
                id=str(uuid.uuid4()),
                user_id=client_user.id,
                transaction_type=TransactionType.NFC_DEPOSIT,
                amount=-amount,  # Négatif car débit
                status=TransactionStatus.COMPLETED,
                description=f"Paiement NFC à {merchant_user.full_name}",
                reference=f"NFC-PAY-{transfer_id[:8]}",
                external_reference=transfer_id,
                merchant_name=merchant_user.full_name,
                location=location,
                device_info=device_info
            )
            
            # Transaction vendeur (crédit)
            merchant_transaction = Transaction(
                id=str(uuid.uuid4()),
                user_id=merchant_user.id,
                transaction_type=TransactionType.NFC_WITHDRAWAL,
                amount=amount,  # Positif car crédit
                status=TransactionStatus.COMPLETED,
                description=f"Encaissement NFC de {client_user.full_name}",
                reference=f"NFC-REC-{transfer_id[:8]}",
                external_reference=transfer_id,
                merchant_name=client_user.full_name,
                location=location,
                device_info=device_info
            )
            
            db.add_all([client_transaction, merchant_transaction])
            
            # 7. Créer l'enregistrement de transaction carte
            card_transaction = NFCCardTransaction(
                id=str(uuid.uuid4()),
                card_id=card.id,
                transaction_id=client_transaction.id,
                operation_type="payment",
                device_info=device_info,
                location=location
            )
            
            db.add(card_transaction)
            
            # 8. Mettre à jour la carte
            card.last_used_at = datetime.utcnow()
            
            # 9. Commit de toutes les modifications
            db.commit()
            
            logger.info(f"Paiement NFC traité: {amount} FCFA de {client_user.phone} vers {merchant_user.phone}")
            
            return {
                "success": True,
                "transaction_id": client_transaction.id,
                "amount": amount,
                "client_name": client_user.full_name,
                "merchant_name": merchant_user.full_name,
                "card_uid": card_uid,
                "reference": client_transaction.reference,
                "timestamp": datetime.utcnow().isoformat()
            }
            
        except Exception as e:
            db.rollback()
            logger.error(f"Erreur paiement NFC: {str(e)}")
            raise e
    
    @staticmethod
    def process_nfc_recharge(
        db: Session,
        card_uid: str,
        amount: float,
        recharger_user_id: str,
        device_info: str = None,
        location: str = None
    ) -> Dict[str, Any]:
        """
        Traiter une recharge NFC avec carte physique
        - Le client présente sa carte NFC
        - Le recharger utilise son téléphone compatible NFC
        - Le montant est crédité sur le compte du client
        """
        try:
            # 1. Vérifier la carte NFC
            card = NFCCardService.get_card_by_uid(db, card_uid)
            if not card:
                raise ValueError("Carte NFC introuvable")
            
            if card.status != "active":
                raise ValueError("Carte NFC inactive")
            
            # 2. Récupérer les utilisateurs
            client_user = db.query(User).filter(User.id == card.user_id).first()
            recharger_user = db.query(User).filter(User.id == recharger_user_id).first()
            
            if not client_user or not recharger_user:
                raise ValueError("Utilisateur introuvable")
            
            if client_user.id == recharger_user.id:
                raise ValueError("Le client et le recharger ne peuvent pas être la même personne")
            
            # 3. Récupérer les wallets
            client_wallet = get_user_wallet(client_user.id, db)
            recharger_wallet = get_user_wallet(recharger_user.id, db)
            
            # 4. Vérifier les soldes et limites
            if recharger_wallet.balance < amount:
                raise ValueError("Solde recharger insuffisant")
            
            if client_wallet.max_balance and (client_wallet.balance + amount) > client_wallet.max_balance:
                raise ValueError("Le compte client atteindrait sa limite")
            
            # 5. Effectuer la recharge
            recharger_wallet.balance -= amount
            client_wallet.balance += amount
            
            # 6. Créer les transactions
            transfer_id = str(uuid.uuid4())
            
            # Transaction client (crédit)
            client_transaction = Transaction(
                id=str(uuid.uuid4()),
                user_id=client_user.id,
                transaction_type=TransactionType.RECHARGE_BY_BUSINESS,
                amount=amount,  # Positif car crédit
                status=TransactionStatus.COMPLETED,
                description=f"Recharge NFC par {recharger_user.full_name}",
                reference=f"NFC-RCH-{transfer_id[:8]}",
                external_reference=transfer_id,
                merchant_name=recharger_user.full_name,
                location=location,
                device_info=device_info
            )
            
            # Transaction recharger (débit)
            recharger_transaction = Transaction(
                id=str(uuid.uuid4()),
                user_id=recharger_user.id,
                transaction_type=TransactionType.RECHARGE_BY_BUSINESS,
                amount=-amount,  # Négatif car débit
                status=TransactionStatus.COMPLETED,
                description=f"Recharge NFC pour {client_user.full_name}",
                reference=f"NFC-RCH-{transfer_id[:8]}",
                external_reference=transfer_id,
                merchant_name=client_user.full_name,
                location=location,
                device_info=device_info
            )
            
            db.add_all([client_transaction, recharger_transaction])
            
            # 7. Créer l'enregistrement de transaction carte
            card_transaction = NFCCardTransaction(
                id=str(uuid.uuid4()),
                card_id=card.id,
                transaction_id=client_transaction.id,
                operation_type="recharge",
                device_info=device_info,
                location=location
            )
            
            db.add(card_transaction)
            
            # 8. Mettre à jour la carte
            card.last_used_at = datetime.utcnow()
            
            # 9. Commit de toutes les modifications
            db.commit()
            
            logger.info(f"Recharge NFC traitée: {amount} FCFA pour {client_user.phone} par {recharger_user.phone}")
            
            return {
                "success": True,
                "transaction_id": client_transaction.id,
                "amount": amount,
                "client_name": client_user.full_name,
                "recharger_name": recharger_user.full_name,
                "card_uid": card_uid,
                "reference": client_transaction.reference,
                "timestamp": datetime.utcnow().isoformat()
            }
            
        except Exception as e:
            db.rollback()
            logger.error(f"Erreur recharge NFC: {str(e)}")
            raise e
    
    @staticmethod
    def get_nfc_transaction_history(
        db: Session,
        user_id: str,
        limit: int = 50,
        offset: int = 0
    ) -> list[Dict[str, Any]]:
        """Récupérer l'historique des transactions NFC d'un utilisateur"""
        try:
            # Récupérer les transactions NFC de l'utilisateur
            transactions = db.query(Transaction).filter(
                Transaction.user_id == user_id,
                Transaction.transaction_type.in_([
                    TransactionType.NFC_DEPOSIT,
                    TransactionType.NFC_WITHDRAWAL,
                    TransactionType.RECHARGE_BY_BUSINESS
                ])
            ).order_by(Transaction.created_at.desc()).offset(offset).limit(limit).all()
            
            # Formater les résultats
            history = []
            for transaction in transactions:
                history.append({
                    "id": transaction.id,
                    "type": transaction.transaction_type.value,
                    "amount": transaction.amount,
                    "description": transaction.description,
                    "reference": transaction.reference,
                    "merchant_name": transaction.merchant_name,
                    "location": transaction.location,
                    "status": transaction.status.value,
                    "created_at": transaction.created_at.isoformat()
                })
            
            return history
            
        except Exception as e:
            logger.error(f"Erreur récupération historique NFC: {str(e)}")
            raise e
