from datetime import date, datetime, timedelta, timezone
import shutil
import uuid

from schedule import every, repeat
from fastapi import File, HTTPException, UploadFile
from pydantic import BaseModel
from utility.payment_api import InitPaymentWeb
from utility.stock import get_admin_stock
from models.models import Loan, LoanStatus, Notification, NotificationPriority, TimAccountType, Transaction, TransactionStatus, TransactionType, User
from schemas.loans import CommissionRequest, LoanRequestWithInfo, RepayLoanRequest
from services.users import get_user_wallet
from sqlalchemy.orm import Session
from utility.transactions import cinetpay_service 
from core.config import settings

async def create_loan_with_info(
    current_user: str,  # ID de l'utilisateur
    db: Session,
    request_amount: CommissionRequest,
):
    """
    Créer un nouveau prêt R-online pour un utilisateur
    """
    # 1. Récupérer l'utilisateur complet
    user = db.query(User).filter(User.id == current_user).first()
    if not user:
        raise HTTPException(
            status_code=404, 
            detail="Utilisateur introuvable"
        )   

    # if user.kyc_verifications_status != "approved":
    #     raise HTTPException(
    #         status_code=400,
    #         detail="Votre KYC n'est pas approuvé. Veuillez compléter votre KYC pour demander un R-online."
    #     )
    
    # 2. Vérifier les limites selon le type de compte
    max_loan_amounts = {
        TimAccountType.TIM_MINI: 0,
        TimAccountType.TIM_MAXI: 10000,
        TimAccountType.TIM_BUSINESS: 10000
    }
    
    max_amount = max_loan_amounts.get(user.tim_account_type, 0)
    
    if request_amount.amount > max_amount:
        raise HTTPException(
            status_code=400,
            detail=f"Le montant du r-online dépasse la limite de {max_amount} FCFA pour votre type de compte"
        )
    
    # 3. Vérifier qu'il n'y a pas de prêt actif
    active_loan = db.query(Loan).filter(
        Loan.user_id == user.id,
        Loan.status == LoanStatus.APPROVED
    ).first()
    
    if active_loan:
        raise HTTPException(
            status_code=400,
            detail="Vous avez un R-online en cours. Veuillez rembourser avant de prendre un autre R-online."
        )
    
    # 4. Vérifier le stock admin
    admin_stock = get_admin_stock(db)
    if admin_stock.balance < request_amount.amount:
        raise HTTPException(
            status_code=400,
            detail="Fonds insuffisants dans le stock admin. Veuillez réessayer plus tard."
        )
    
    # 5. Calculer les montants
    interest_rate = 0.06
    total_amount = request_amount.amount * (1 + interest_rate)
    
    # 6. Créer le prêt
    loan = Loan(
        id=str(uuid.uuid4()),
        user_id=user.id,
        amount=request_amount.amount,
        interest_rate=interest_rate,
        penalty_rate=0.06,
        remaining_balance=total_amount,
        monthly_payment=total_amount,
        total_payments=1,
        payments_completed=0,
        status=LoanStatus.APPROVED,
        due_date=datetime.utcnow() + timedelta(days=3),
        days_overdue=0,
    )
    db.add(loan)
    
    # 7. Débiter le stock admin
    admin_stock.balance -= request_amount.amount
    admin_stock.total_debits += request_amount.amount
    
    # 8. Créditer le portefeuille utilisateur
    wallet = get_user_wallet(current_user, db)
    wallet.balance += request_amount.amount
    
    # 9. Créer la transaction
    transaction = Transaction(
        id=str(uuid.uuid4()),
        user_id=user.id,
        transaction_type=TransactionType.PRET_MOBILE,
        amount=request_amount.amount,
        commission_amount=request_amount.amount * interest_rate,
        commission_rate=interest_rate,
        status=TransactionStatus.COMPLETED,
        description=f"Prêt SOS - Prêt d'urgence",
        reference=f"LOAN-{loan.id[:8]}",
        external_reference=loan.id
    )
    db.add(transaction)
    
    # 10. Sauvegarder tout
    try:
        db.commit()
        db.refresh(loan)
        db.refresh(transaction)
    except Exception as e:
        db.rollback()
        raise HTTPException(
            status_code=500,
            detail=f"Erreur lors de l'enregistrement: {str(e)}"
        )
    
    # 11. Retourner la réponse
    return {
        "loan_id": loan.id,
        "amount": loan.amount,
        "interest_amount": loan.amount * interest_rate,
        "total_repayment": total_amount,
        "due_date": loan.due_date.isoformat() if loan.due_date else None,
        "status": "approved",
        "message": "Votre  R-online a ete approuve avec succes"
    }
async def create_commission_users(
    current_user: User,
    db: Session ,
    request: CommissionRequest,
):
    user = db.query(User).filter(User.id == current_user).first()
    if not user:
        raise HTTPException(status_code=404, detail="Utilisateur introuvable")
    # Créer la transaction
    transaction = Transaction(
        id=str(uuid.uuid4()),
        user_id=user.id,
        transaction_type=TransactionType.COMMISSION,
        amount=request.amount,
        status=TransactionStatus.PENDING,
        description=f"Activations de commission Prêt d 'urgence",
        reference=f"COMM-{str(uuid.uuid4())[:8]}",

    )
    db.add(transaction)
    db.commit()
    
    payment_data = {
            "transaction_id": transaction.reference,
            'currency' : "XOF",
            "amount": request.amount,  # Montant avec commission TIM CASH
            "description": transaction.description,
            "recipient_phone": user.phone, # ⚠️ Numéro associé au wallet
            "notify_url": f"{settings.CINETPAY_CALLBACK_URL}",
            "return_url": f"{settings.APP_BASE_URL}/payment/success",
            'customer_name' :user.full_name,                              
            'customer_surname' : user.last_name, 
        }
        
    print(f"Transcation data {payment_data}")

    print(f"📤 Envoi à CinetPay: {request.amount} FCFA")

        # Appeler CinetPay
        # Appeler CinetPay
    cinetpay_response = await cinetpay_service.create_payment_url(payment_data)
    print(f"Réponse CinetPay: {cinetpay_response}")



    return {
        "transaction_id": transaction.id,
        "description": f"Paiment de commission ",
        "payment_url": cinetpay_response['payment_url'],
    }

async def repay_loan(current_user: User, db: Session):
    loan = db.query(Loan).filter(
        Loan.user_id == current_user.id,
        Loan.status.in_([LoanStatus.APPROVED, LoanStatus.ACTIVE, LoanStatus.OVERDUE])
    ).first()

    if not loan:
        raise HTTPException(status_code=404, detail="Aucun prêt actif trouvé")

    base_amount = loan.amount * (1 + loan.interest_rate)
    today = datetime.now(timezone.utc)

    # Pénalité si retard
    if today > loan.due_date:
        days_late = (today - loan.due_date).days
        loan.days_overdue = days_late
        penalty = loan.amount * loan.penalty_rate
    else:
        penalty = 0

    total_due = base_amount + penalty

    # ⚡ Paiement selon ce que l'utilisateur a dans son wallet
    wallet = get_user_wallet(current_user.id, db)
    amount_to_pay = min(wallet.balance, total_due)

    wallet.balance -= amount_to_pay
    remaining = total_due - amount_to_pay
    loan.remaining_balance = remaining

    # ✔ Mise à jour du statut du prêt
    if remaining <= 0:
        loan.status = LoanStatus.COMPLETED
    else:
        
        if today > loan.due_date:
            loan.status = LoanStatus.APPROVED
        else:
            loan.status = LoanStatus.APPROVED

    # Remboursement admin
    admin_stock = get_admin_stock(db)
    admin_stock.balance += amount_to_pay

    db.commit()

    # Transaction
    transaction = Transaction(
        id=str(uuid.uuid4()),
        user_id=current_user.id,
        transaction_type=TransactionType.REMBOURSEMENT_AUTO,
        amount=amount_to_pay,
        status=TransactionStatus.COMPLETED,
        description=f"Remboursement du prêt",
        reference=f"COMM-{str(uuid.uuid4())[:8]}",
    )
    db.add(transaction)
    db.commit()
    
    notification = Notification(
        id=str(uuid.uuid4()),
        user_id=current_user.id,
        title="Remboursement effectué",
        message=f"Votre remboursement de {amount_to_pay} XOF a été effectué avec succès. Solde  du prêt: {remaining} XOF.",
        type="loan_repayment",
        priority=NotificationPriority.HIGH,
        amount=amount_to_pay,
        merchant="TIM CASH",
        created_at=datetime.utcnow()
    )

    db.add(notification)
    db.commit()
    return {
        "status": "success",
        "paid_amount": amount_to_pay,
        "remaining_due": remaining,
        "penalty": penalty,
        "days_overdue": getattr(loan, "days_overdue", 0),
        "expected_total": total_due,
        "loan_status": loan.status.value
    }



async def loands_rembousement_users(
    current_user: User,
    db: Session ,
    request: CommissionRequest,
):
    user = db.query(User).filter(User.id == current_user).first()
    if not user:
        raise HTTPException(status_code=404, detail="Utilisateur introuvable")
    # Créer la transaction
    transaction = Transaction(
        id=str(uuid.uuid4()),
        user_id=user.id,
        transaction_type=TransactionType.REMBOURSEMENT_AUTO,
        amount=request.amount,
        status=TransactionStatus.PENDING,
        description=f"Remboursement automatique de prêt d ' urgence",
        reference=f"PRET{str(uuid.uuid4())[:8]}",

    )
    db.add(transaction)
    db.commit()
    
    payment_data = {
            "transaction_id": transaction.reference,
            'currency' : "XOF",
            "amount": request.amount,  # Montant avec commission TIM CASH
            "description": transaction.description,
            "recipient_phone": user.phone, # ⚠️ Numéro associé au wallet
            "notify_url": f"{settings.CINETPAY_CALLBACK_URL}",
            "return_url": f"{settings.APP_BASE_URL}/payment/success",
            'customer_name' :user.full_name,                              
            'customer_surname' : user.last_name, 
        }
        
    print(f"Transcation data {payment_data}")

    print(f"📤 Envoi à CinetPay: {request.amount} FCFA")

        # Appeler CinetPay
        # Appeler CinetPay
    cinetpay_response = await cinetpay_service.create_payment_url(payment_data)
    print(f"Réponse CinetPay: {cinetpay_response}")



    return {
        "transaction_id": transaction.id,
        "description": f"Paiment de commission ",
        "payment_url": cinetpay_response['payment_url'],
    }
