"""
Routes API pour la gestion des transferts
"""
import uuid
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from sqlalchemy import or_, and_
from typing import List, Optional
from datetime import datetime, timedelta
import logging

from database import get_db
from models.models import Notification, NotificationPriority, PrelevementRequest, User, Transaction, TransactionType, TransactionStatus
from schemas.prelevement import PrelevementRequestSchema, UserSchema
from schemas.transaction import WalletTransactionRequest
from services.tim_business_service import prelevement_compte_client
from services.users import get_user_wallet
from utility.auth_token import get_current_user

router = APIRouter()
logger = logging.getLogger(__name__)

@router.get("/transfers")
async def get_user_transfers(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
    limit: int = Query(50, ge=1, le=100),
    offset: int = Query(0, ge=0),
    status: Optional[str] = Query(None),
    transfer_type: Optional[str] = Query(None),
    start_date: Optional[str] = Query(None),
    end_date: Optional[str] = Query(None)
):
    """
    Récupérer l'historique des transferts de l'utilisateur
    
    Filtres disponibles:
    - status: pending, completed, failed, cancelled
    - transfer_type: mobile_money_transfer, transfer_out, transfer_in, etc.
    - start_date: Date de début (format: YYYY-MM-DD)
    - end_date: Date de fin (format: YYYY-MM-DD)
    """
    try:
        logger.info(f"📊 Récupération des transferts pour {current_user.email}")
        
        # Query de base
        query = db.query(Transaction).filter(Transaction.user_id == current_user.id)
        
        # Filtrer par type de transfert
        if transfer_type:
            try:
                transaction_type = TransactionType[transfer_type.upper()]
                query = query.filter(Transaction.transaction_type == transaction_type)
            except KeyError:
                pass
        else:
            # Par défaut, afficher uniquement les transferts
            transfer_types = [
                TransactionType.MOBILE_MONEY_TRANSFER,
                TransactionType.TRANSFER_OUT,
                TransactionType.TRANSFER_IN,
                TransactionType.MOBILE_TRANSFER,
                TransactionType.VIREMENT_BANCAIRE
            ]
            query = query.filter(Transaction.transaction_type.in_(transfer_types))
        
        # Filtrer par statut
        if status:
            try:
                transaction_status = TransactionStatus[status.upper()]
                query = query.filter(Transaction.status == transaction_status)
            except KeyError:
                pass
        
        # Filtrer par date
        if start_date:
            try:
                start = datetime.fromisoformat(start_date)
                query = query.filter(Transaction.created_at >= start)
            except ValueError:
                pass
        
        if end_date:
            try:
                end = datetime.fromisoformat(end_date)
                # Ajouter 1 jour pour inclure toute la journée
                end = end + timedelta(days=1)
                query = query.filter(Transaction.created_at < end)
            except ValueError:
                pass
        
        # Compter le total
        total = query.count()
        
        # Pagination et tri
        transfers = query.order_by(Transaction.created_at.desc()).offset(offset).limit(limit).all()
        
        # Formater les résultats
        result = []
        for transfer in transfers:
            result.append({
                "id": transfer.id,
                "reference": transfer.reference,
                "type": transfer.transaction_type.value,
                "amount": transfer.amount,
                "commission_amount": transfer.commission_amount,
                "commission_rate": transfer.commission_rate,
                "status": transfer.status.value,
                "description": transfer.description,
                "merchant_name": transfer.merchant_name,
                "payment_method": transfer.payment_method.value if transfer.payment_method else None,
                "external_reference": transfer.external_reference,
                "created_at": transfer.created_at.isoformat() if transfer.created_at else None,
                "completed_at": transfer.completed_at.isoformat() if transfer.completed_at else None,
            })
        
        logger.info(f"✅ {len(result)} transferts récupérés")
        
        return {
            "success": True,
            "total": total,
            "limit": limit,
            "offset": offset,
            "transfers": result
        }
        
    except Exception as e:
        logger.error(f"❌ Erreur récupération transferts: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Erreur lors de la récupération des transferts: {str(e)}"
        )

@router.get("/transfers/{transfer_id}")
async def get_transfer_details(
    transfer_id: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    Récupérer les détails d'un transfert spécifique
    """
    try:
        transfer = db.query(Transaction).filter(
            Transaction.id == transfer_id,
            Transaction.user_id == current_user.id
        ).first()
        
        if not transfer:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Transfert non trouvé"
            )
        
        return {
            "success": True,
            "transfer": {
                "id": transfer.id,
                "reference": transfer.reference,
                "type": transfer.transaction_type.value,
                "amount": transfer.amount,
                "commission_amount": transfer.commission_amount,
                "commission_rate": transfer.commission_rate,
                "status": transfer.status.value,
                "description": transfer.description,
                "merchant_name": transfer.merchant_name,
                "payment_method": transfer.payment_method.value if transfer.payment_method else None,
                "external_reference": transfer.external_reference,
                "location": transfer.location,
                "device_info": transfer.device_info,
                "created_at": transfer.created_at.isoformat() if transfer.created_at else None,
                "completed_at": transfer.completed_at.isoformat() if transfer.completed_at else None,
            }
        }
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"❌ Erreur récupération détails transfert: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Erreur lors de la récupération: {str(e)}"
        )

@router.get("/transfers/stats/summary")
async def get_transfers_summary(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
    period: str = Query("month", regex="^(week|month|year)$")
):
    """
    Récupérer un résumé des transferts (statistiques)
    """
    try:
        # Calculer la date de début selon la période
        now = datetime.utcnow()
        if period == "week":
            start_date = now - timedelta(days=7)
        elif period == "month":
            start_date = now - timedelta(days=30)
        else:  # year
            start_date = now - timedelta(days=365)
        
        # Récupérer tous les transferts de la période
        transfers = db.query(Transaction).filter(
            Transaction.user_id == current_user.id,
            Transaction.created_at >= start_date,
            Transaction.transaction_type.in_([
                TransactionType.MOBILE_MONEY_TRANSFER,
                TransactionType.TRANSFER_OUT,
                TransactionType.TRANSFER_IN,
                TransactionType.MOBILE_TRANSFER,
                TransactionType.VIREMENT_BANCAIRE
            ])
        ).all()
        
        # Calculer les statistiques
        total_transfers = len(transfers)
        total_amount_sent = sum(abs(t.amount) for t in transfers if t.amount < 0)
        total_amount_received = sum(t.amount for t in transfers if t.amount > 0)
        total_fees = sum(t.commission_amount for t in transfers)
        
        completed = len([t for t in transfers if t.status == TransactionStatus.COMPLETED])
        pending = len([t for t in transfers if t.status == TransactionStatus.PENDING])
        failed = len([t for t in transfers if t.status == TransactionStatus.FAILED])
        
        return {
            "success": True,
            "period": period,
            "summary": {
                "total_transfers": total_transfers,
                "total_amount_sent": total_amount_sent,
                "total_amount_received": total_amount_received,
                "total_fees": total_fees,
                "completed": completed,
                "pending": pending,
                "failed": failed
            }
        }
        
    except Exception as e:
        logger.error(f"❌ Erreur récupération statistiques: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Erreur lors de la récupération des statistiques: {str(e)}"
        )

@router.post("/financials/prelevement/wallet")
async def get_daily_transfer_stats(request_data: WalletTransactionRequest , current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
   return await prelevement_compte_client(current_user,request_data, db,)


from sqlalchemy.orm import joinedload

@router.get("/prelevement/pending/{prelevement_id}", response_model=PrelevementRequestSchema)
def get_pending_prelevement(
    prelevement_id: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    # Charger la demande en incluant client et merchant
    pending_request = db.query(PrelevementRequest)\
        .options(
            joinedload(PrelevementRequest.client),
            joinedload(PrelevementRequest.merchant)
        )\
        .filter(
            PrelevementRequest.id == prelevement_id,
            PrelevementRequest.client_id == current_user.id,
            PrelevementRequest.status == "pending"
        ).first()

    if not pending_request:
        raise HTTPException(status_code=404, detail="Prélèvement introuvable ou déjà traité")

    # Convertir SQLAlchemy User en Pydantic UserSchema
    client_schema = UserSchema(
        id=pending_request.client.id,
        email=pending_request.client.email,
        phone=pending_request.client.phone,
        full_name=pending_request.client.full_name
    )

    merchant_schema = UserSchema(
        id=pending_request.merchant.id,
        email=pending_request.merchant.email,
        phone=pending_request.merchant.phone,
        full_name=pending_request.merchant.full_name
    )

    return PrelevementRequestSchema(
        id=pending_request.id,
        merchant_id=pending_request.merchant_id,
        client_id=pending_request.client_id,
        amount=pending_request.amount,
        description=pending_request.description,
        status=pending_request.status,
        created_at=pending_request.created_at,
        user=merchant_schema,
    )

@router.patch("/finance/prelevements/{prelevement_id}/validate")
async def update_prelevement_status(
    prelevement_id: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):

    # Récupérer la demande de prélèvement
    prelevement = db.query(PrelevementRequest).filter(
        PrelevementRequest.id == prelevement_id,
        PrelevementRequest.client_id == current_user.id,
        PrelevementRequest.status == "pending"
    ).first()


    if not prelevement:
            raise HTTPException(status_code=404, detail="Prélèvement introuvable")
    if prelevement.status != "pending":
            raise HTTPException(status_code=400, detail="Prélèvement déjà traité")
    
    client_wallet =  get_user_wallet(current_user.id, db)
    merchant_wallet =  get_user_wallet(prelevement.merchant_id, db)
    
    if client_wallet.balance < prelevement.amount:
            raise HTTPException(status_code=400, detail="Solde insuffisant pour effectuer le prélèvement")
    
    client_wallet.balance -= prelevement.amount
    merchant_wallet.balance += prelevement.amount
    
    transfer_id = str(uuid.uuid4())

    client_txn = Transaction(
            id=str(uuid.uuid4()),
            user_id=current_user.id,
            transaction_type=TransactionType.PRELEVEMENT,
            amount=-prelevement.amount,
            status=TransactionStatus.COMPLETED,
            description=f"Prélèvement vers {prelevement.merchant.full_name}",
            reference=f"PRELEV-OUT-{transfer_id[:8]}",
            external_reference=transfer_id
        )

    merchant_txn = Transaction(
            id=str(uuid.uuid4()),
            user_id=prelevement.merchant_id,
            transaction_type=TransactionType.PRELEVEMENT,
            amount=prelevement.amount,
            status=TransactionStatus.COMPLETED,
            description=f"Prélèvement reçu de {current_user.full_name}",
            reference=f"PRELEV-IN-{transfer_id[:8]}",
            external_reference=transfer_id
        )
    db.add_all([client_txn, merchant_txn])
    
    # Mettre à jour le statut de la demande de prélèvement
    new_status = "approved"  # ou "rejected" selon la logique métier
    prelevement.status = new_status
    db.commit()
    db.refresh(prelevement)
    
    # Notification pour le marchand
    notification_merchant = Notification(
        id=str(uuid.uuid4()),
        user_id=prelevement.merchant_id,
        title="Prélèvement confirmé",
        message=f"{current_user.full_name} a confirmé le paiement de {prelevement.amount} XOF.",
        type="prelevement_completed",
        priority=NotificationPriority.HIGH,
        amount=prelevement.amount,
        merchant=current_user.full_name,  # ici c'est l'utilisateur qui paie
        created_at=datetime.utcnow()
    )

    # Notification pour l'utilisateur courant
    notification_user = Notification(
        id=str(uuid.uuid4()),
        user_id=current_user.id,
        title="Paiement confirmé",
        message=f"Vous avez confirmé le paiement de {prelevement.amount} XOF à {prelevement.merchant.full_name}.",
        type="prelevement_completed",
        priority=NotificationPriority.HIGH,
        amount=prelevement.amount,
        merchant=prelevement.merchant.full_name,  # ici c'est le destinataire du paiement
        created_at=datetime.utcnow()
    )

    db.add_all([notification_merchant,notification_user])
    db.commit()

    return {"success": True, "message": f"Statut du prélèvement mis à jour à '{new_status}'"}