from fastapi import FastAPI, HTTPException, Depends, status, Request
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, EmailStr, validator
from typing import Optional, List, Dict, Any
from datetime import datetime, timedelta
import jwt
import bcrypt
import uvicorn
from enum import Enum
import logging
import requests
import json
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
from slowapi.middleware import SlowAPIMiddleware

# Initialize rate limiter
limiter = Limiter(key_func=get_remote_address)

# Initialize FastAPI app
app = FastAPI(
    title="TimCash API",
    description="Comprehensive Financial Platform API",
    version="1.0.0"
)

# Add rate limiting middleware
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
app.add_middleware(SlowAPIMiddleware)

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000", "http://localhost:5173"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Security
security = HTTPBearer()
SECRET_KEY = "your-secret-key-here"
ALGORITHM = "HS256"

# Enums
class UserRole(str, Enum):
    ADMIN = "admin"
    MANAGER = "manager"
    USER = "user"

class TransactionType(str, Enum):
    CREDIT = "credit"
    DEBIT = "debit"
    TRANSFER = "transfer"
    LOAN = "loan"
    REPAYMENT = "repayment"

class TransactionStatus(str, Enum):
    PENDING = "pending"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELLED = "cancelled"

class LoanStatus(str, Enum):
    PENDING = "pending"
    APPROVED = "approved"
    REJECTED = "rejected"
    ACTIVE = "active"
    COMPLETED = "completed"
    OVERDUE = "overdue"

class PaymentStatus(str, Enum):
    PENDING = "pending"
    PROCESSING = "processing"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELLED = "cancelled"

class AdminTransactionType(str, Enum):
    LOAN_DISBURSEMENT = "loan_disbursement"
    LOAN_REPAYMENT = "loan_repayment"
    COMMISSION = "commission"
    PAYOUT = "payout"
    ADJUSTMENT = "adjustment"

# Pydantic models
class UserBase(BaseModel):
    email: EmailStr
    first_name: str
    last_name: str
    phone: str
    role: UserRole = UserRole.USER

class UserCreate(UserBase):
    password: str

class UserResponse(UserBase):
    id: str
    is_verified: bool = False
    is_blocked: bool = False
    created_at: datetime
    updated_at: datetime

class LoginRequest(BaseModel):
    email: EmailStr
    password: str

class LoginResponse(BaseModel):
    user: UserResponse
    token: str
    refresh_token: str
    token_type: str = "bearer"
    expires_in: int = 86400  # 24 hours

class RefreshTokenRequest(BaseModel):
    refresh_token: str

class RefreshTokenResponse(BaseModel):
    token: str
    refresh_token: str
    token_type: str = "bearer"
    expires_in: int = 86400

class WalletResponse(BaseModel):
    id: str
    user_id: str
    balance: float
    currency: str = "USD"
    is_active: bool = True
    created_at: datetime
    updated_at: datetime

class TransactionCreate(BaseModel):
    type: TransactionType
    amount: float
    currency: str = "USD"
    description: str
    reference_id: Optional[str] = None

class TransactionResponse(BaseModel):
    id: str
    wallet_id: str
    type: TransactionType
    amount: float
    currency: str
    description: str
    status: TransactionStatus
    reference_id: Optional[str] = None
    created_at: datetime
    updated_at: datetime

class LoanCreate(BaseModel):
    amount: float
    duration: int  # in months
    purpose: str

class LoanResponse(BaseModel):
    id: str
    user_id: str
    amount: float
    interest_rate: float
    duration: int
    status: LoanStatus
    monthly_payment: float
    total_repayment: float
    remaining_balance: float
    next_payment_date: Optional[datetime]
    created_at: datetime
    updated_at: datetime

class DashboardStats(BaseModel):
    total_users: int
    total_wallets: int
    total_transactions: int
    total_loans: int
    total_revenue: float
    active_loans: int
    pending_transactions: int

class AdminStockAccount(BaseModel):
    id: str
    balance: float
    total_credits: float
    total_debits: float
    total_commissions: float
    last_updated: datetime

class WalletReloadRequest(BaseModel):
    amount: float
    payment_method: str = "cinetpay"
    
    @validator('amount')
    def validate_amount(cls, v):
        if v <= 0:
            raise ValueError('Amount must be positive')
        if v > 10000:
            raise ValueError('Amount cannot exceed 10,000')
        return v

class WalletWithdrawRequest(BaseModel):
    amount: float
    destination: str
    
    @validator('amount')
    def validate_amount(cls, v):
        if v <= 0:
            raise ValueError('Amount must be positive')
        return v

class WalletTransferRequest(BaseModel):
    recipient_email: str
    amount: float
    description: Optional[str] = None
    
    @validator('amount')
    def validate_amount(cls, v):
        if v <= 0:
            raise ValueError('Amount must be positive')
        return v

class LoanCreateRequest(BaseModel):
    amount: float
    duration: int  # in months
    purpose: str
    
    @validator('amount')
    def validate_amount(cls, v):
        if v <= 0:
            raise ValueError('Amount must be positive')
        if v > 50000:
            raise ValueError('Loan amount cannot exceed 50,000')
        return v
    
    @validator('duration')
    def validate_duration(cls, v):
        if v < 1 or v > 60:
            raise ValueError('Loan duration must be between 1 and 60 months')
        return v

class AdminTransactionResponse(BaseModel):
    id: str
    type: AdminTransactionType
    amount: float
    description: str
    reference_id: Optional[str] = None
    balance_before: float
    balance_after: float
    created_at: datetime

class CinetPayCallbackRequest(BaseModel):
    transaction_id: str
    status: str
    amount: float
    reference: str
    signature: str

# In-memory storage (replace with actual database)
users_db: Dict[str, dict] = {}
wallets_db: Dict[str, dict] = {}
transactions_db: Dict[str, dict] = {}
loans_db: Dict[str, dict] = {}
refresh_tokens_db: Dict[str, dict] = {}
admin_transactions_db: Dict[str, dict] = {}
cinetpay_transactions_db: Dict[str, dict] = {}

admin_stock = {
    "id": "admin-stock-001",
    "balance": 100000.0,
    "total_credits": 0.0,
    "total_debits": 0.0,
    "total_commissions": 0.0,
    "last_updated": datetime.utcnow()
}

# CinetPay configuration
CINETPAY_API_KEY = "your-cinetpay-api-key"
CINETPAY_SITE_ID = "your-site-id"
CINETPAY_SECRET_KEY = "your-secret-key"
CINETPAY_BASE_URL = "https://api-checkout.cinetpay.com/v2"

# Utility functions
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(hours=24)
    to_encode.update({"exp": expire, "type": "access"})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

def create_refresh_token(data: dict):
    to_encode = data.copy()
    expire = datetime.utcnow() + timedelta(days=30)  # 30 days for refresh token
    to_encode.update({"exp": expire, "type": "refresh"})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

def verify_refresh_token(token: str):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        if payload.get("type") != "refresh":
            return None
        user_id: str = payload.get("sub")
        return user_id
    except jwt.PyJWTError:
        return None

def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
    try:
        payload = jwt.decode(credentials.credentials, SECRET_KEY, algorithms=[ALGORITHM])
        user_id: str = payload.get("sub")
        if user_id is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid authentication credentials",
                headers={"WWW-Authenticate": "Bearer"},
            )
        return user_id
    except jwt.PyJWTError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid authentication credentials",
            headers={"WWW-Authenticate": "Bearer"},
        )

def get_current_user(user_id: str = Depends(verify_token)):
    user = users_db.get(user_id)
    if user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return user

def hash_password(password: str) -> str:
    return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

def verify_password(plain_password: str, hashed_password: str) -> bool:
    return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password.encode('utf-8'))

def generate_id(prefix: str) -> str:
    import uuid
    return f"{prefix}-{str(uuid.uuid4())[:8]}"

def update_admin_stock(amount: float, transaction_type: AdminTransactionType, description: str = "", reference_id: str = None):
    """Update admin stock account and create transaction record"""
    global admin_stock
    
    balance_before = admin_stock["balance"]
    
    if transaction_type == AdminTransactionType.LOAN_DISBURSEMENT:
        admin_stock["balance"] -= amount
        admin_stock["total_debits"] += amount
    elif transaction_type == AdminTransactionType.LOAN_REPAYMENT:
        admin_stock["balance"] += amount
        admin_stock["total_credits"] += amount
    elif transaction_type == AdminTransactionType.COMMISSION:
        admin_stock["balance"] += amount
        admin_stock["total_commissions"] += amount
    elif transaction_type == AdminTransactionType.PAYOUT:
        admin_stock["balance"] -= amount
        admin_stock["total_debits"] += amount
    elif transaction_type == AdminTransactionType.ADJUSTMENT:
        if amount > 0:
            admin_stock["balance"] += amount
            admin_stock["total_credits"] += amount
        else:
            admin_stock["balance"] += amount  # amount is already negative
            admin_stock["total_debits"] += abs(amount)
    
    admin_stock["last_updated"] = datetime.utcnow()
    
    # Create admin transaction record
    admin_txn_id = generate_id("admin_txn")
    admin_transaction = {
        "id": admin_txn_id,
        "type": transaction_type,
        "amount": amount,
        "description": description,
        "reference_id": reference_id,
        "balance_before": balance_before,
        "balance_after": admin_stock["balance"],
        "created_at": datetime.utcnow()
    }
    
    admin_transactions_db[admin_txn_id] = admin_transaction
    logger.info(f"Admin stock updated: {transaction_type} - {amount} - Balance: {admin_stock['balance']}")
    
    return admin_transaction

def initiate_cinetpay_payment(amount: float, transaction_id: str, customer_info: dict):
    """Initiate payment with CinetPay"""
    payload = {
        "apikey": CINETPAY_API_KEY,
        "site_id": CINETPAY_SITE_ID,
        "transaction_id": transaction_id,
        "amount": int(amount),
        "currency": "XOF",  # West African CFA franc
        "description": f"TimCash wallet reload - {amount}",
        "return_url": "https://your-domain.com/payment/success",
        "notify_url": "https://your-domain.com/wallet-paiements/callback",
        "customer_name": f"{customer_info.get('first_name', '')} {customer_info.get('last_name', '')}",
        "customer_email": customer_info.get('email', ''),
        "customer_phone_number": customer_info.get('phone', ''),
        "customer_address": customer_info.get('address', ''),
        "customer_city": customer_info.get('city', ''),
        "customer_country": "CI",  # Côte d'Ivoire
        "customer_state": customer_info.get('state', ''),
        "customer_zip_code": customer_info.get('zip_code', '')
    }
    
    try:
        response = requests.post(f"{CINETPAY_BASE_URL}/payment", json=payload, timeout=30)
        return response.json()
    except requests.RequestException as e:
        logger.error(f"CinetPay payment initiation failed: {e}")
        return None

def verify_cinetpay_signature(data: dict, signature: str) -> bool:
    """Verify CinetPay callback signature"""
    # Implementation depends on CinetPay's signature algorithm
    # This is a placeholder - implement according to CinetPay documentation
    return True  # For demo purposes

def find_user_by_email(email: str) -> Optional[dict]:
    """Find user by email address"""
    for user in users_db.values():
        if user["email"] == email:
            return user
    return None

def find_wallet_by_user_id(user_id: str) -> Optional[dict]:
    """Find wallet by user ID"""
    for wallet in wallets_db.values():
        if wallet["user_id"] == user_id:
            return wallet
    return None

# API Routes

@app.get("/")
async def root():
    return {"message": "TimCash API v1.0.0", "status": "operational"}

@app.post("/auth/register", response_model=UserResponse)
async def register(user: UserCreate):
    # Check if user exists
    for existing_user in users_db.values():
        if existing_user["email"] == user.email:
            raise HTTPException(status_code=400, detail="Email already registered")
    
    user_id = generate_id("user")
    hashed_password = hash_password(user.password)
    
    new_user = {
        "id": user_id,
        "email": user.email,
        "first_name": user.first_name,
        "last_name": user.last_name,
        "phone": user.phone,
        "role": user.role,
        "password": hashed_password,
        "is_verified": False,
        "is_blocked": False,
        "created_at": datetime.utcnow(),
        "updated_at": datetime.utcnow()
    }
    
    users_db[user_id] = new_user
    
    # Create wallet for user
    wallet_id = generate_id("wallet")
    wallet = {
        "id": wallet_id,
        "user_id": user_id,
        "balance": 0.0,
        "currency": "USD",
        "is_active": True,
        "created_at": datetime.utcnow(),
        "updated_at": datetime.utcnow()
    }
    wallets_db[wallet_id] = wallet
    
    return UserResponse(**{k: v for k, v in new_user.items() if k != "password"})

@app.post("/auth/login", response_model=LoginResponse)
@limiter.limit("5/minute")
async def login(request: Request, login_data: LoginRequest):
    # Find user by email
    user = None
    for u in users_db.values():
        if u["email"] == login_data.email:
            user = u
            break
    
    # For demo purposes, allow any password for existing users
    if not user:
        # Create demo users if they don't exist
        if login_data.email in ["admin@timcash.com", "user@timcash.com"]:
            role = UserRole.ADMIN if "admin" in login_data.email else UserRole.USER
            user_id = generate_id("user")
            user = {
                "id": user_id,
                "email": login_data.email,
                "first_name": "Demo",
                "last_name": "Admin" if role == UserRole.ADMIN else "User",
                "phone": "+1234567890",
                "role": role,
                "password": hash_password("password"),
                "is_verified": True,
                "is_blocked": False,
                "created_at": datetime.utcnow(),
                "updated_at": datetime.utcnow()
            }
            users_db[user_id] = user
            
            # Create wallet
            wallet_id = generate_id("wallet")
            wallet = {
                "id": wallet_id,
                "user_id": user_id,
                "balance": 5000.0 if role == UserRole.USER else 50000.0,
                "currency": "USD",
                "is_active": True,
                "created_at": datetime.utcnow(),
                "updated_at": datetime.utcnow()
            }
            wallets_db[wallet_id] = wallet
        else:
            raise HTTPException(status_code=400, detail="Invalid credentials")
    
    if user["is_blocked"]:
        raise HTTPException(status_code=400, detail="Account is blocked")
    
    # Create access token and refresh token
    access_token = create_access_token(data={"sub": user["id"]})
    refresh_token = create_refresh_token(data={"sub": user["id"]})
    
    # Store refresh token
    refresh_tokens_db[refresh_token] = {
        "user_id": user["id"],
        "created_at": datetime.utcnow(),
        "expires_at": datetime.utcnow() + timedelta(days=30)
    }
    
    user_response = UserResponse(**{k: v for k, v in user.items() if k != "password"})
    
    return LoginResponse(user=user_response, token=access_token, refresh_token=refresh_token)

@app.post("/auth/refresh", response_model=RefreshTokenResponse)
async def refresh_token(refresh_request: RefreshTokenRequest):
    user_id = verify_refresh_token(refresh_request.refresh_token)
    if not user_id or refresh_request.refresh_token not in refresh_tokens_db:
        raise HTTPException(status_code=401, detail="Invalid refresh token")
    
    # Check if refresh token is expired
    token_data = refresh_tokens_db[refresh_request.refresh_token]
    if datetime.utcnow() > token_data["expires_at"]:
        del refresh_tokens_db[refresh_request.refresh_token]
        raise HTTPException(status_code=401, detail="Refresh token expired")
    
    # Generate new tokens
    new_access_token = create_access_token(data={"sub": user_id})
    new_refresh_token = create_refresh_token(data={"sub": user_id})
    
    # Remove old refresh token and store new one
    del refresh_tokens_db[refresh_request.refresh_token]
    refresh_tokens_db[new_refresh_token] = {
        "user_id": user_id,
        "created_at": datetime.utcnow(),
        "expires_at": datetime.utcnow() + timedelta(days=30)
    }
    
    return RefreshTokenResponse(token=new_access_token, refresh_token=new_refresh_token)

@app.post("/auth/logout")
async def logout(refresh_request: RefreshTokenRequest, current_user: dict = Depends(get_current_user)):
    # Remove refresh token from storage
    if refresh_request.refresh_token in refresh_tokens_db:
        del refresh_tokens_db[refresh_request.refresh_token]
    
    return {"message": "Successfully logged out"}

@app.get("/auth/me", response_model=UserResponse)
async def get_current_user_info(current_user: dict = Depends(get_current_user)):
    return UserResponse(**{k: v for k, v in current_user.items() if k != "password"})

@app.get("/wallet", response_model=WalletResponse)
async def get_wallet(current_user: dict = Depends(get_current_user)):
    # Find user's wallet
    wallet = None
    for w in wallets_db.values():
        if w["user_id"] == current_user["id"]:
            wallet = w
            break
    
    if not wallet:
        raise HTTPException(status_code=404, detail="Wallet not found")
    
    return WalletResponse(**wallet)

@app.post("/wallet/transaction", response_model=TransactionResponse)
async def create_transaction(
    transaction: TransactionCreate,
    current_user: dict = Depends(get_current_user)
):
    # Find user's wallet
    wallet = None
    for w in wallets_db.values():
        if w["user_id"] == current_user["id"]:
            wallet = w
            break
    
    if not wallet:
        raise HTTPException(status_code=404, detail="Wallet not found")
    
    # Validate transaction
    if transaction.type == TransactionType.DEBIT and wallet["balance"] < transaction.amount:
        raise HTTPException(status_code=400, detail="Insufficient balance")
    
    transaction_id = generate_id("txn")
    new_transaction = {
        "id": transaction_id,
        "wallet_id": wallet["id"],
        "type": transaction.type,
        "amount": transaction.amount,
        "currency": transaction.currency,
        "description": transaction.description,
        "status": TransactionStatus.COMPLETED,
        "reference_id": transaction.reference_id,
        "created_at": datetime.utcnow(),
        "updated_at": datetime.utcnow()
    }
    
    transactions_db[transaction_id] = new_transaction
    
    # Update wallet balance
    if transaction.type in [TransactionType.CREDIT, TransactionType.LOAN]:
        wallet["balance"] += transaction.amount
    elif transaction.type in [TransactionType.DEBIT, TransactionType.REPAYMENT]:
        wallet["balance"] -= transaction.amount
    
    wallet["updated_at"] = datetime.utcnow()
    wallets_db[wallet["id"]] = wallet
    
    return TransactionResponse(**new_transaction)

@app.get("/transactions", response_model=List[TransactionResponse])
async def get_transactions(current_user: dict = Depends(get_current_user)):
    # Find user's wallet
    wallet = None
    for w in wallets_db.values():
        if w["user_id"] == current_user["id"]:
            wallet = w
            break
    
    if not wallet:
        return []
    
    # Get transactions for this wallet
    user_transactions = []
    for t in transactions_db.values():
        if t["wallet_id"] == wallet["id"]:
            user_transactions.append(TransactionResponse(**t))
    
    # Sort by creation date (newest first)
    user_transactions.sort(key=lambda x: x.created_at, reverse=True)
    
    return user_transactions

# Wallet endpoints
@app.post("/wallet/reload")
@limiter.limit("10/minute")
async def reload_wallet(request: Request, reload_request: WalletReloadRequest, current_user: dict = Depends(get_current_user)):
    wallet = find_wallet_by_user_id(current_user["id"])
    if not wallet:
        raise HTTPException(status_code=404, detail="Wallet not found")
    
    # Generate transaction ID
    transaction_id = generate_id("reload")
    
    # Initiate CinetPay payment
    payment_response = initiate_cinetpay_payment(
        amount=reload_request.amount,
        transaction_id=transaction_id,
        customer_info=current_user
    )
    
    if not payment_response or payment_response.get("code") != "201":
        raise HTTPException(status_code=400, detail="Payment initiation failed")
    
    # Store transaction for tracking
    cinetpay_transactions_db[transaction_id] = {
        "id": transaction_id,
        "user_id": current_user["id"],
        "wallet_id": wallet["id"],
        "amount": reload_request.amount,
        "status": PaymentStatus.PENDING,
        "payment_url": payment_response.get("data", {}).get("payment_url"),
        "created_at": datetime.utcnow()
    }
    
    return {
        "transaction_id": transaction_id,
        "payment_url": payment_response.get("data", {}).get("payment_url"),
        "status": "pending"
    }

@app.post("/wallet/withdraw")
@limiter.limit("5/minute")
async def withdraw_from_wallet(request: Request, withdraw_request: WalletWithdrawRequest, current_user: dict = Depends(get_current_user)):
    wallet = find_wallet_by_user_id(current_user["id"])
    if not wallet:
        raise HTTPException(status_code=404, detail="Wallet not found")
    
    if wallet["balance"] < withdraw_request.amount:
        raise HTTPException(status_code=400, detail="Insufficient balance")
    
    # Create withdrawal transaction
    transaction_id = generate_id("txn")
    withdrawal_transaction = {
        "id": transaction_id,
        "wallet_id": wallet["id"],
        "type": TransactionType.DEBIT,
        "amount": withdraw_request.amount,
        "currency": "USD",
        "description": f"Withdrawal to {withdraw_request.destination}",
        "status": TransactionStatus.PENDING,
        "reference_id": None,
        "created_at": datetime.utcnow(),
        "updated_at": datetime.utcnow()
    }
    
    transactions_db[transaction_id] = withdrawal_transaction
    
    # Update wallet balance
    wallet["balance"] -= withdraw_request.amount
    wallet["updated_at"] = datetime.utcnow()
    wallets_db[wallet["id"]] = wallet
    
    # Update admin stock (withdrawal fee)
    commission = withdraw_request.amount * 0.02  # 2% commission
    update_admin_stock(
        amount=commission,
        transaction_type=AdminTransactionType.COMMISSION,
        description=f"Withdrawal commission - {withdraw_request.amount}",
        reference_id=transaction_id
    )
    
    return {
        "transaction_id": transaction_id,
        "amount": withdraw_request.amount,
        "status": "pending",
        "message": "Withdrawal request submitted successfully"
    }

@app.post("/wallet/transfer")
@limiter.limit("10/minute")
async def transfer_funds(request: Request, transfer_request: WalletTransferRequest, current_user: dict = Depends(get_current_user)):
    # Find sender's wallet
    sender_wallet = find_wallet_by_user_id(current_user["id"])
    if not sender_wallet:
        raise HTTPException(status_code=404, detail="Sender wallet not found")
    
    # Find recipient user
    recipient_user = find_user_by_email(transfer_request.recipient_email)
    if not recipient_user:
        raise HTTPException(status_code=404, detail="Recipient not found")
    
    if recipient_user["id"] == current_user["id"]:
        raise HTTPException(status_code=400, detail="Cannot transfer to yourself")
    
    # Find recipient's wallet
    recipient_wallet = find_wallet_by_user_id(recipient_user["id"])
    if not recipient_wallet:
        raise HTTPException(status_code=404, detail="Recipient wallet not found")
    
    # Check sender balance
    transfer_fee = transfer_request.amount * 0.01  # 1% transfer fee
    total_amount = transfer_request.amount + transfer_fee
    
    if sender_wallet["balance"] < total_amount:
        raise HTTPException(status_code=400, detail="Insufficient balance (including transfer fee)")
    
    # Create transfer transactions
    transfer_id = generate_id("transfer")
    
    # Debit sender
    sender_txn_id = generate_id("txn")
    sender_transaction = {
        "id": sender_txn_id,
        "wallet_id": sender_wallet["id"],
        "type": TransactionType.TRANSFER,
        "amount": -total_amount,
        "currency": "USD",
        "description": f"Transfer to {transfer_request.recipient_email} - {transfer_request.description or 'No description'}",
        "status": TransactionStatus.COMPLETED,
        "reference_id": transfer_id,
        "created_at": datetime.utcnow(),
        "updated_at": datetime.utcnow()
    }
    
    # Credit recipient
    recipient_txn_id = generate_id("txn")
    recipient_transaction = {
        "id": recipient_txn_id,
        "wallet_id": recipient_wallet["id"],
        "type": TransactionType.TRANSFER,
        "amount": transfer_request.amount,
        "currency": "USD",
        "description": f"Transfer from {current_user['email']} - {transfer_request.description or 'No description'}",
        "status": TransactionStatus.COMPLETED,
        "reference_id": transfer_id,
        "created_at": datetime.utcnow(),
        "updated_at": datetime.utcnow()
    }
    
    # Update balances
    sender_wallet["balance"] -= total_amount
    sender_wallet["updated_at"] = datetime.utcnow()
    
    recipient_wallet["balance"] += transfer_request.amount
    recipient_wallet["updated_at"] = datetime.utcnow()
    
    # Save transactions and wallets
    transactions_db[sender_txn_id] = sender_transaction
    transactions_db[recipient_txn_id] = recipient_transaction
    wallets_db[sender_wallet["id"]] = sender_wallet
    wallets_db[recipient_wallet["id"]] = recipient_wallet
    
    # Update admin stock (transfer fee)
    update_admin_stock(
        amount=transfer_fee,
        transaction_type=AdminTransactionType.COMMISSION,
        description=f"Transfer commission - {transfer_request.amount}",
        reference_id=transfer_id
    )
    
    return {
        "transfer_id": transfer_id,
        "amount": transfer_request.amount,
        "fee": transfer_fee,
        "recipient": transfer_request.recipient_email,
        "status": "completed"
    }

@app.get("/wallet/history")
async def get_wallet_history(current_user: dict = Depends(get_current_user), limit: int = 50, offset: int = 0):
    wallet = find_wallet_by_user_id(current_user["id"])
    if not wallet:
        raise HTTPException(status_code=404, detail="Wallet not found")
    
    # Get transactions for this wallet
    user_transactions = []
    for t in transactions_db.values():
        if t["wallet_id"] == wallet["id"]:
            user_transactions.append(t)
    
    # Sort by creation date (newest first)
    user_transactions.sort(key=lambda x: x["created_at"], reverse=True)
    
    # Apply pagination
    paginated_transactions = user_transactions[offset:offset + limit]
    
    return {
        "transactions": [TransactionResponse(**t) for t in paginated_transactions],
        "total": len(user_transactions),
        "limit": limit,
        "offset": offset
    }

# Updated loan endpoints
@app.post("/wallet-loans/create", response_model=LoanResponse)
async def create_loan_with_stock_update(
    loan: LoanCreateRequest,
    current_user: dict = Depends(get_current_user)
):
    # Calculate loan terms
    interest_rate = 8.5  # 8.5% annual interest rate
    monthly_interest = interest_rate / 100 / 12
    monthly_payment = (loan.amount * monthly_interest * (1 + monthly_interest) ** loan.duration) / \
                     ((1 + monthly_interest) ** loan.duration - 1)
    total_repayment = monthly_payment * loan.duration
    
    loan_id = generate_id("loan")
    new_loan = {
        "id": loan_id,
        "user_id": current_user["id"],
        "amount": loan.amount,
        "interest_rate": interest_rate,
        "duration": loan.duration,
        "status": LoanStatus.APPROVED,  # Auto-approve for demo
        "monthly_payment": round(monthly_payment, 2),
        "total_repayment": round(total_repayment, 2),
        "remaining_balance": round(total_repayment, 2),
        "next_payment_date": datetime.utcnow() + timedelta(days=30),
        "created_at": datetime.utcnow(),
        "updated_at": datetime.utcnow()
    }
    
    loans_db[loan_id] = new_loan
    
    # Update admin stock (loan disbursement)
    update_admin_stock(
        amount=loan.amount,
        transaction_type=AdminTransactionType.LOAN_DISBURSEMENT,
        description=f"Loan disbursement - {loan.purpose}",
        reference_id=loan_id
    )
    
    # Add money to user's wallet
    wallet = None
    for w in wallets_db.values():
        if w["user_id"] == current_user["id"]:
            wallet = w
            break
    
    if wallet:
        wallet["balance"] += loan.amount
        wallet["updated_at"] = datetime.utcnow()
        wallets_db[wallet["id"]] = wallet
        
        # Create transaction record
        transaction_id = generate_id("txn")
        loan_transaction = {
            "id": transaction_id,
            "wallet_id": wallet["id"],
            "type": TransactionType.LOAN,
            "amount": loan.amount,
            "currency": "USD",
            "description": f"Loan disbursement - {loan.purpose}",
            "status": TransactionStatus.COMPLETED,
            "reference_id": loan_id,
            "created_at": datetime.utcnow(),
            "updated_at": datetime.utcnow()
        }
        transactions_db[transaction_id] = loan_transaction
    
    return LoanResponse(**new_loan)

@app.get("/wallet-loans/user-loans", response_model=List[LoanResponse])
async def get_user_loans(current_user: dict = Depends(get_current_user)):
    user_loans = []
    for loan in loans_db.values():
        if loan["user_id"] == current_user["id"]:
            user_loans.append(LoanResponse(**loan))
    
    user_loans.sort(key=lambda x: x.created_at, reverse=True)
    return user_loans

@app.get("/wallet-loans/search")
async def search_loans(
    current_user: dict = Depends(get_current_user),
    status: Optional[str] = None,
    min_amount: Optional[float] = None,
    max_amount: Optional[float] = None,
    limit: int = 50,
    offset: int = 0
):
    user_loans = []
    for loan in loans_db.values():
        if loan["user_id"] == current_user["id"]:
            # Apply filters
            if status and loan["status"] != status:
                continue
            if min_amount and loan["amount"] < min_amount:
                continue
            if max_amount and loan["amount"] > max_amount:
                continue
            user_loans.append(loan)
    
    # Sort by creation date (newest first)
    user_loans.sort(key=lambda x: x["created_at"], reverse=True)
    
    # Apply pagination
    paginated_loans = user_loans[offset:offset + limit]
    
    return {
        "loans": [LoanResponse(**loan) for loan in paginated_loans],
        "total": len(user_loans),
        "limit": limit,
        "offset": offset
    }

@app.get("/wallet-loans/filter")
async def filter_loans_by_date(
    current_user: dict = Depends(get_current_user),
    start_date: Optional[str] = None,
    end_date: Optional[str] = None,
    limit: int = 50,
    offset: int = 0
):
    user_loans = []
    
    # Parse dates if provided
    start_dt = None
    end_dt = None
    if start_date:
        try:
            start_dt = datetime.fromisoformat(start_date.replace('Z', '+00:00'))
        except ValueError:
            raise HTTPException(status_code=400, detail="Invalid start_date format")
    
    if end_date:
        try:
            end_dt = datetime.fromisoformat(end_date.replace('Z', '+00:00'))
        except ValueError:
            raise HTTPException(status_code=400, detail="Invalid end_date format")
    
    for loan in loans_db.values():
        if loan["user_id"] == current_user["id"]:
            loan_date = loan["created_at"]
            
            # Apply date filters
            if start_dt and loan_date < start_dt:
                continue
            if end_dt and loan_date > end_dt:
                continue
                
            user_loans.append(loan)
    
    # Sort by creation date (newest first)
    user_loans.sort(key=lambda x: x["created_at"], reverse=True)
    
    # Apply pagination
    paginated_loans = user_loans[offset:offset + limit]
    
    return {
        "loans": [LoanResponse(**loan) for loan in paginated_loans],
        "total": len(user_loans),
        "limit": limit,
        "offset": offset
    }

# CinetPay callback endpoint
@app.post("/wallet-paiements/callback")
async def cinetpay_callback(callback_data: CinetPayCallbackRequest):
    # Verify signature (implement according to CinetPay documentation)
    if not verify_cinetpay_signature(callback_data.dict(), callback_data.signature):
        raise HTTPException(status_code=400, detail="Invalid signature")
    
    # Find the transaction
    transaction = cinetpay_transactions_db.get(callback_data.transaction_id)
    if not transaction:
        raise HTTPException(status_code=404, detail="Transaction not found")
    
    # Update transaction status
    if callback_data.status == "ACCEPTED":
        transaction["status"] = PaymentStatus.COMPLETED
        
        # Credit user's wallet
        wallet = find_wallet_by_user_id(transaction["user_id"])
        if wallet:
            wallet["balance"] += transaction["amount"]
            wallet["updated_at"] = datetime.utcnow()
            wallets_db[wallet["id"]] = wallet
            
            # Create transaction record
            txn_id = generate_id("txn")
            reload_transaction = {
                "id": txn_id,
                "wallet_id": wallet["id"],
                "type": TransactionType.CREDIT,
                "amount": transaction["amount"],
                "currency": "USD",
                "description": f"Wallet reload via CinetPay - {callback_data.transaction_id}",
                "status": TransactionStatus.COMPLETED,
                "reference_id": callback_data.transaction_id,
                "created_at": datetime.utcnow(),
                "updated_at": datetime.utcnow()
            }
            transactions_db[txn_id] = reload_transaction
            
            # Update admin stock (reload commission)
            commission = transaction["amount"] * 0.005  # 0.5% commission
            update_admin_stock(
                amount=commission,
                transaction_type=AdminTransactionType.COMMISSION,
                description=f"Reload commission - {transaction['amount']}",
                reference_id=callback_data.transaction_id
            )
            
            logger.info(f"Wallet reload completed: {callback_data.transaction_id} - {transaction['amount']}")
    
    elif callback_data.status in ["REFUSED", "CANCELLED"]:
        transaction["status"] = PaymentStatus.FAILED
        logger.warning(f"Wallet reload failed: {callback_data.transaction_id} - {callback_data.status}")
    
    # Update transaction in database
    cinetpay_transactions_db[callback_data.transaction_id] = transaction
    
    return {"status": "success", "message": "Callback processed successfully"}

@app.get("/admin/dashboard", response_model=DashboardStats)
async def get_admin_dashboard(current_user: dict = Depends(get_current_user)):
    if current_user["role"] not in [UserRole.ADMIN, UserRole.MANAGER]:
        raise HTTPException(status_code=403, detail="Insufficient permissions")
    
    stats = DashboardStats(
        total_users=len(users_db),
        total_wallets=len(wallets_db),
        total_transactions=len(transactions_db),
        total_loans=len(loans_db),
        total_revenue=sum(t["amount"] for t in transactions_db.values() if t["type"] == TransactionType.REPAYMENT),
        active_loans=len([l for l in loans_db.values() if l["status"] == LoanStatus.ACTIVE]),
        pending_transactions=len([t for t in transactions_db.values() if t["status"] == TransactionStatus.PENDING])
    )
    
    return stats

@app.get("/admin/stock", response_model=AdminStockAccount)
async def get_admin_stock(current_user: dict = Depends(get_current_user)):
    if current_user["role"] != UserRole.ADMIN:
        raise HTTPException(status_code=403, detail="Admin access required")
    
    return AdminStockAccount(**admin_stock)

@app.get("/admin/users", response_model=List[UserResponse])
async def get_all_users(current_user: dict = Depends(get_current_user)):
    if current_user["role"] not in [UserRole.ADMIN, UserRole.MANAGER]:
        raise HTTPException(status_code=403, detail="Insufficient permissions")
    
    all_users = []
    for user in users_db.values():
        all_users.append(UserResponse(**{k: v for k, v in user.items() if k != "password"}))
    
    all_users.sort(key=lambda x: x.created_at, reverse=True)
    return all_users

@app.get("/admin/loans", response_model=List[LoanResponse])
async def get_all_loans(current_user: dict = Depends(get_current_user)):
    if current_user["role"] not in [UserRole.ADMIN, UserRole.MANAGER]:
        raise HTTPException(status_code=403, detail="Insufficient permissions")
    
    all_loans = []
    for loan in loans_db.values():
        all_loans.append(LoanResponse(**loan))
    
    all_loans.sort(key=lambda x: x.created_at, reverse=True)
    return all_loans

@app.get("/admin/transactions", response_model=List[TransactionResponse])
async def get_all_transactions(current_user: dict = Depends(get_current_user)):
    if current_user["role"] not in [UserRole.ADMIN, UserRole.MANAGER]:
        raise HTTPException(status_code=403, detail="Insufficient permissions")
    
    all_transactions = []
    for transaction in transactions_db.values():
        all_transactions.append(TransactionResponse(**transaction))
    
    all_transactions.sort(key=lambda x: x.created_at, reverse=True)
    return all_transactions

# Admin stock management endpoints
@app.get("/wallet-admins", response_model=List[AdminTransactionResponse])
async def get_admin_transactions(current_user: dict = Depends(get_current_user), limit: int = 50, offset: int = 0):
    if current_user["role"] != UserRole.ADMIN:
        raise HTTPException(status_code=403, detail="Admin access required")
    
    admin_transactions = list(admin_transactions_db.values())
    admin_transactions.sort(key=lambda x: x["created_at"], reverse=True)
    
    # Apply pagination
    paginated_transactions = admin_transactions[offset:offset + limit]
    
    return [AdminTransactionResponse(**txn) for txn in paginated_transactions]

@app.get("/wallet-admins/{transaction_id}", response_model=AdminTransactionResponse)
async def get_admin_transaction_details(transaction_id: str, current_user: dict = Depends(get_current_user)):
    if current_user["role"] != UserRole.ADMIN:
        raise HTTPException(status_code=403, detail="Admin access required")
    
    transaction = admin_transactions_db.get(transaction_id)
    if not transaction:
        raise HTTPException(status_code=404, detail="Admin transaction not found")
    
    return AdminTransactionResponse(**transaction)

@app.get("/wallet-admins/search")
async def search_admin_transactions(
    current_user: dict = Depends(get_current_user),
    transaction_type: Optional[str] = None,
    start_date: Optional[str] = None,
    end_date: Optional[str] = None,
    min_amount: Optional[float] = None,
    max_amount: Optional[float] = None,
    limit: int = 50,
    offset: int = 0
):
    if current_user["role"] != UserRole.ADMIN:
        raise HTTPException(status_code=403, detail="Admin access required")
    
    filtered_transactions = []
    
    # Parse dates if provided
    start_dt = None
    end_dt = None
    if start_date:
        try:
            start_dt = datetime.fromisoformat(start_date.replace('Z', '+00:00'))
        except ValueError:
            raise HTTPException(status_code=400, detail="Invalid start_date format")
    
    if end_date:
        try:
            end_dt = datetime.fromisoformat(end_date.replace('Z', '+00:00'))
        except ValueError:
            raise HTTPException(status_code=400, detail="Invalid end_date format")
    
    for transaction in admin_transactions_db.values():
        # Apply filters
        if transaction_type and transaction["type"] != transaction_type:
            continue
        
        if start_dt and transaction["created_at"] < start_dt:
            continue
            
        if end_dt and transaction["created_at"] > end_dt:
            continue
            
        if min_amount and abs(transaction["amount"]) < min_amount:
            continue
            
        if max_amount and abs(transaction["amount"]) > max_amount:
            continue
        
        filtered_transactions.append(transaction)
    
    # Sort by creation date (newest first)
    filtered_transactions.sort(key=lambda x: x["created_at"], reverse=True)
    
    # Apply pagination
    paginated_transactions = filtered_transactions[offset:offset + limit]
    
    return {
        "transactions": [AdminTransactionResponse(**txn) for txn in paginated_transactions],
        "total": len(filtered_transactions),
        "limit": limit,
        "offset": offset
    }

# Enhanced admin endpoints
@app.get("/admin/stats")
async def get_enhanced_admin_stats(current_user: dict = Depends(get_current_user)):
    if current_user["role"] not in [UserRole.ADMIN, UserRole.MANAGER]:
        raise HTTPException(status_code=403, detail="Insufficient permissions")
    
    # Calculate enhanced statistics
    total_loan_amount = sum(loan["amount"] for loan in loans_db.values())
    total_repayments = sum(t["amount"] for t in transactions_db.values() if t["type"] == TransactionType.REPAYMENT)
    active_loans_count = len([l for l in loans_db.values() if l["status"] == LoanStatus.ACTIVE])
    
    # Wallet statistics
    total_wallet_balance = sum(w["balance"] for w in wallets_db.values())
    
    # Admin stock statistics
    admin_balance = admin_stock["balance"]
    total_commissions = admin_stock["total_commissions"]
    
    return {
        "users": {
            "total": len(users_db),
            "active": len([u for u in users_db.values() if not u["is_blocked"]]),
            "blocked": len([u for u in users_db.values() if u["is_blocked"]])
        },
        "wallets": {
            "total": len(wallets_db),
            "total_balance": total_wallet_balance,
            "active": len([w for w in wallets_db.values() if w["is_active"]])
        },
        "loans": {
            "total": len(loans_db),
            "active": active_loans_count,
            "total_amount": total_loan_amount,
            "total_repayments": total_repayments
        },
        "transactions": {
            "total": len(transactions_db),
            "pending": len([t for t in transactions_db.values() if t["status"] == TransactionStatus.PENDING]),
            "completed": len([t for t in transactions_db.values() if t["status"] == TransactionStatus.COMPLETED])
        },
        "admin_stock": {
            "balance": admin_balance,
            "total_credits": admin_stock["total_credits"],
            "total_debits": admin_stock["total_debits"],
            "total_commissions": total_commissions
        }
    }

@app.post("/admin/commission")
async def configure_commission(current_user: dict = Depends(get_current_user), commission_data: dict = None):
    if current_user["role"] != UserRole.ADMIN:
        raise HTTPException(status_code=403, detail="Admin access required")
    
    # This is a placeholder for commission configuration
    # In a real implementation, you would store these settings in a database
    return {"message": "Commission configuration updated", "data": commission_data}

@app.get("/admin/reports")
async def get_financial_reports(current_user: dict = Depends(get_current_user)):
    if current_user["role"] != UserRole.ADMIN:
        raise HTTPException(status_code=403, detail="Admin access required")
    
    # Generate financial reports
    monthly_revenue = sum(
        txn["amount"] for txn in admin_transactions_db.values()
        if txn["type"] == AdminTransactionType.COMMISSION
        and txn["created_at"].month == datetime.utcnow().month
    )
    
    return {
        "monthly_revenue": monthly_revenue,
        "admin_balance": admin_stock["balance"],
        "total_loans_disbursed": sum(
            txn["amount"] for txn in admin_transactions_db.values()
            if txn["type"] == AdminTransactionType.LOAN_DISBURSEMENT
        ),
        "total_commissions_earned": admin_stock["total_commissions"],
        "report_date": datetime.utcnow().isoformat()
    }

@app.get("/wallet-payouts")
async def get_cinetpay_payouts(current_user: dict = Depends(get_current_user)):
    if current_user["role"] != UserRole.ADMIN:
        raise HTTPException(status_code=403, detail="Admin access required")
    
    # Return CinetPay transaction history
    payouts = list(cinetpay_transactions_db.values())
    payouts.sort(key=lambda x: x["created_at"], reverse=True)
    
    return {
        "payouts": payouts,
        "total": len(payouts)
    }

# ==================== PAYS ET VILLES ====================

# Base de données simulée pour les pays et villes
countries_db = {
    "1": {
        "id": "1",
        "name": "Côte d'Ivoire",
        "code": "CI",
        "currency": "FCFA",
        "currencySymbol": "FCFA",
        "flag": "🇨🇮",
        "isActive": True,
        "totalUsers": 2847,
        "totalVolume": 562000000,
        "createdAt": "2024-01-01T00:00:00Z",
        "cities": [
            {
                "id": "1",
                "name": "Abidjan",
                "countryId": "1",
                "isActive": True,
                "branchCode": "TIM-CI-ABJ",
                "users": 1850,
                "volume": 425000000,
                "createdAt": "2024-01-01T00:00:00Z"
            },
            {
                "id": "2",
                "name": "Yamoussoukro",
                "countryId": "1",
                "isActive": True,
                "branchCode": "TIM-CI-YAM",
                "users": 450,
                "volume": 85000000,
                "createdAt": "2024-01-15T00:00:00Z"
            }
        ]
    },
    "2": {
        "id": "2",
        "name": "Sénégal",
        "code": "SN",
        "currency": "FCFA",
        "currencySymbol": "FCFA",
        "flag": "🇸🇳",
        "isActive": True,
        "totalUsers": 1250,
        "totalVolume": 185000000,
        "createdAt": "2024-02-15T00:00:00Z",
        "cities": [
            {
                "id": "4",
                "name": "Dakar",
                "countryId": "2",
                "isActive": True,
                "branchCode": "TIM-SN-DKR",
                "users": 950,
                "volume": 145000000,
                "createdAt": "2024-02-15T00:00:00Z"
            }
        ]
    }
}

@app.get("/countries")
async def get_countries():
    """Récupérer tous les pays TIM CASH"""
    countries = list(countries_db.values())
    return {
        "countries": countries,
        "total": len(countries)
    }

@app.post("/countries")
async def create_country(country_data: dict):
    """Créer un nouveau pays"""
    country_id = str(len(countries_db) + 1)
    new_country = {
        "id": country_id,
        "name": country_data.get("name"),
        "code": country_data.get("code"),
        "currency": country_data.get("currency", "FCFA"),
        "currencySymbol": country_data.get("currencySymbol", "FCFA"),
        "flag": country_data.get("flag", "🌍"),
        "isActive": True,
        "totalUsers": 0,
        "totalVolume": 0,
        "createdAt": datetime.utcnow().isoformat() + "Z",
        "cities": []
    }
    countries_db[country_id] = new_country
    return {"message": "Pays créé avec succès", "country": new_country}

@app.post("/countries/{country_id}/cities")
async def create_city(country_id: str, city_data: dict):
    """Ajouter une ville à un pays"""
    if country_id not in countries_db:
        raise HTTPException(status_code=404, detail="Pays non trouvé")
    
    city_id = str(len([c for country in countries_db.values() for c in country["cities"]]) + 1)
    new_city = {
        "id": city_id,
        "name": city_data.get("name"),
        "countryId": country_id,
        "isActive": True,
        "branchCode": city_data.get("branchCode"),
        "users": 0,
        "volume": 0,
        "createdAt": datetime.utcnow().isoformat() + "Z"
    }
    
    countries_db[country_id]["cities"].append(new_city)
    return {"message": "Ville créée avec succès", "city": new_city}

# ==================== PUBLICITÉS ====================

# Base de données simulée pour les publicités
advertisements_db = {
    "1": {
        "id": "1",
        "title": "Promo TIM MAXI - 0% Frais",
        "description": "Ouvrez votre compte TIM MAXI sans frais pendant 30 jours",
        "imageUrl": "/api/placeholder/400/200",
        "type": "banner",
        "status": "active",
        "targetCountries": ["Côte d'Ivoire", "Sénégal"],
        "targetCities": ["Abidjan", "Dakar"],
        "startDate": "2024-01-15T00:00:00Z",
        "endDate": "2024-02-15T00:00:00Z",
        "budget": 500000,
        "spent": 285000,
        "impressions": 125000,
        "clicks": 3750,
        "ctr": 3.0,
        "createdAt": "2024-01-10T00:00:00Z",
        "createdBy": "Admin TIM"
    },
    "2": {
        "id": "2",
        "title": "Paiement NFC Rapide",
        "description": "Payez en 2 secondes avec votre téléphone",
        "imageUrl": "/api/placeholder/400/200",
        "type": "popup",
        "status": "active",
        "targetCountries": ["Côte d'Ivoire"],
        "targetCities": ["Abidjan", "Yamoussoukro"],
        "startDate": "2024-01-20T00:00:00Z",
        "endDate": "2024-03-20T00:00:00Z",
        "budget": 750000,
        "spent": 425000,
        "impressions": 89000,
        "clicks": 2670,
        "ctr": 3.0,
        "createdAt": "2024-01-18T00:00:00Z",
        "createdBy": "Marketing Team"
    }
}

@app.get("/advertisements")
async def get_advertisements():
    """Récupérer toutes les publicités"""
    ads = list(advertisements_db.values())
    return {
        "advertisements": ads,
        "total": len(ads)
    }

@app.post("/advertisements")
async def create_advertisement(ad_data: dict):
    """Créer une nouvelle publicité"""
    ad_id = str(len(advertisements_db) + 1)
    new_ad = {
        "id": ad_id,
        "title": ad_data.get("title"),
        "description": ad_data.get("description"),
        "imageUrl": ad_data.get("imageUrl", "/api/placeholder/400/200"),
        "type": ad_data.get("type", "banner"),
        "status": "active",
        "targetCountries": ad_data.get("targetCountries", []),
        "targetCities": ad_data.get("targetCities", []),
        "startDate": datetime.utcnow().isoformat() + "Z",
        "endDate": ad_data.get("endDate"),
        "budget": ad_data.get("budget", 0),
        "spent": 0,
        "impressions": 0,
        "clicks": 0,
        "ctr": 0.0,
        "createdAt": datetime.utcnow().isoformat() + "Z",
        "createdBy": "Admin TIM"
    }
    advertisements_db[ad_id] = new_ad
    return {"message": "Publicité créée avec succès", "advertisement": new_ad}

@app.put("/advertisements/{ad_id}/status")
async def update_advertisement_status(ad_id: str, status_data: dict):
    """Mettre à jour le statut d'une publicité"""
    if ad_id not in advertisements_db:
        raise HTTPException(status_code=404, detail="Publicité non trouvée")
    
    new_status = status_data.get("status")
    if new_status not in ["active", "paused", "scheduled", "expired"]:
        raise HTTPException(status_code=400, detail="Statut invalide")
    
    advertisements_db[ad_id]["status"] = new_status
    return {"message": "Statut mis à jour avec succès", "advertisement": advertisements_db[ad_id]}

@app.delete("/advertisements/{ad_id}")
async def delete_advertisement(ad_id: str):
    """Supprimer une publicité"""
    if ad_id not in advertisements_db:
        raise HTTPException(status_code=404, detail="Publicité non trouvée")
    
    deleted_ad = advertisements_db.pop(ad_id)
    return {"message": "Publicité supprimée avec succès", "advertisement": deleted_ad}

# ==================== COMPTE STOCK ET PRÊTS ====================

# Base de données simulée pour le compte stock
stock_account = {
    "balance": 847000000,  # 847,000,000 FCFA
    "reserve_balance": 8500000,  # 8,500,000 FCFA (CinetPay)
    "total_loans_disbursed": 2850000,
    "total_repaid": 1950000,
    "total_commissions": 185000,
    "active_loans": 45,
    "overdue_loans": 8
}

# Historique des transactions du compte stock
stock_transactions_db = {
    "1": {
        "id": "1",
        "type": "credit",
        "amount": 5000000,
        "description": "Alimentation compte stock par Admin",
        "status": "completed",
        "createdAt": "2024-01-20T10:30:00Z",
        "reference": "STOCK-001"
    },
    "2": {
        "id": "2",
        "type": "loan_disbursement",
        "amount": 50000,
        "description": "Prêt automatique TIM MAXI",
        "userId": "user123",
        "userName": "Kouassi Jean",
        "userType": "tim_maxi",
        "status": "completed",
        "createdAt": "2024-01-20T14:15:00Z",
        "reference": "LOAN-001"
    },
    "3": {
        "id": "3",
        "type": "loan_repayment",
        "amount": 53000,
        "description": "Remboursement prêt + commission 6%",
        "userId": "user123",
        "userName": "Kouassi Jean",
        "userType": "tim_maxi",
        "status": "completed",
        "createdAt": "2024-01-22T09:45:00Z",
        "reference": "REPAY-001"
    }
}

# Base de données des prêts
loans_db = {
    "1": {
        "id": "1",
        "userId": "user123",
        "userName": "Kouassi Jean",
        "userType": "tim_maxi",
        "amount": 50000,
        "commission": 3000,  # 6%
        "totalAmount": 53000,
        "status": "active",
        "dueDate": "2024-01-25T00:00:00Z",
        "createdAt": "2024-01-22T10:30:00Z"
    },
    "2": {
        "id": "2",
        "userId": "biz789",
        "userName": "SARL TECH SOLUTIONS",
        "userType": "tim_business",
        "amount": 150000,
        "commission": 9000,  # 6%
        "totalAmount": 159000,
        "status": "overdue",
        "dueDate": "2024-01-20T00:00:00Z",
        "createdAt": "2024-01-17T14:15:00Z",
        "daysOverdue": 3
    }
}

@app.get("/stock-account")
async def get_stock_account():
    """Récupérer l'état du compte stock"""
    return {
        "account": stock_account,
        "recent_transactions": list(stock_transactions_db.values())[-10:]  # 10 dernières
    }

@app.post("/stock-account/credit")
async def credit_stock_account(transaction_data: dict):
    """Alimenter le compte stock"""
    amount = transaction_data.get("amount")
    description = transaction_data.get("description", "Alimentation compte stock")
    
    # Mettre à jour le solde
    stock_account["balance"] += amount
    
    # Créer la transaction
    transaction_id = str(len(stock_transactions_db) + 1)
    new_transaction = {
        "id": transaction_id,
        "type": "credit",
        "amount": amount,
        "description": description,
        "status": "completed",
        "createdAt": datetime.utcnow().isoformat() + "Z",
        "reference": f"STOCK-{transaction_id}"
    }
    
    stock_transactions_db[transaction_id] = new_transaction
    
    return {
        "message": "Compte stock alimenté avec succès",
        "transaction": new_transaction,
        "new_balance": stock_account["balance"]
    }

@app.post("/stock-account/debit")
async def debit_stock_account(transaction_data: dict):
    """Retirer du compte stock"""
    amount = transaction_data.get("amount")
    description = transaction_data.get("description", "Retrait compte stock")
    
    if stock_account["balance"] < amount:
        raise HTTPException(status_code=400, detail="Solde insuffisant")
    
    # Mettre à jour le solde
    stock_account["balance"] -= amount
    
    # Créer la transaction
    transaction_id = str(len(stock_transactions_db) + 1)
    new_transaction = {
        "id": transaction_id,
        "type": "debit",
        "amount": amount,
        "description": description,
        "status": "completed",
        "createdAt": datetime.utcnow().isoformat() + "Z",
        "reference": f"WITHDRAW-{transaction_id}"
    }
    
    stock_transactions_db[transaction_id] = new_transaction
    
    return {
        "message": "Retrait effectué avec succès",
        "transaction": new_transaction,
        "new_balance": stock_account["balance"]
    }

@app.get("/loans")
async def get_loans():
    """Récupérer tous les prêts"""
    loans = list(loans_db.values())
    return {
        "loans": loans,
        "total": len(loans),
        "stats": {
            "active": len([l for l in loans if l["status"] == "active"]),
            "overdue": len([l for l in loans if l["status"] == "overdue"]),
            "repaid": len([l for l in loans if l["status"] == "repaid"]),
            "blocked": len([l for l in loans if l["status"] == "blocked"])
        }
    }

@app.post("/loans/automatic")
async def create_automatic_loan(loan_data: dict):
    """Créer un prêt automatique pour TIM MAXI/BUSINESS"""
    user_type = loan_data.get("userType")
    amount = loan_data.get("amount")
    user_id = loan_data.get("userId")
    user_name = loan_data.get("userName")
    
    # Vérifier le type d'utilisateur
    if user_type not in ["tim_maxi", "tim_business"]:
        raise HTTPException(status_code=400, detail="Type d'utilisateur non autorisé pour les prêts")
    
    # Vérifier les limites de prêt
    if user_type == "tim_maxi" and (amount < 500 or amount > 100000):
        raise HTTPException(status_code=400, detail="Montant invalide pour TIM MAXI (500-100000 FCFA)")
    
    # Vérifier le solde du compte stock
    if stock_account["balance"] < amount:
        raise HTTPException(status_code=400, detail="Fonds insuffisants dans le compte stock")
    
    # Calculer la commission (6%)
    commission = amount * 0.06
    total_amount = amount + commission
    
    # Créer le prêt
    loan_id = str(len(loans_db) + 1)
    due_date = datetime.utcnow() + timedelta(days=3)  # 3 jours pour rembourser
    
    new_loan = {
        "id": loan_id,
        "userId": user_id,
        "userName": user_name,
        "userType": user_type,
        "amount": amount,
        "commission": commission,
        "totalAmount": total_amount,
        "status": "active",
        "dueDate": due_date.isoformat() + "Z",
        "createdAt": datetime.utcnow().isoformat() + "Z"
    }
    
    loans_db[loan_id] = new_loan
    
    # Débiter le compte stock
    stock_account["balance"] -= amount
    stock_account["total_loans_disbursed"] += amount
    stock_account["active_loans"] += 1
    
    # Créer la transaction dans l'historique
    transaction_id = str(len(stock_transactions_db) + 1)
    transaction = {
        "id": transaction_id,
        "type": "loan_disbursement",
        "amount": amount,
        "description": f"Prêt automatique {user_type.upper()}",
        "userId": user_id,
        "userName": user_name,
        "userType": user_type,
        "status": "completed",
        "createdAt": datetime.utcnow().isoformat() + "Z",
        "reference": f"LOAN-{loan_id}"
    }
    
    stock_transactions_db[transaction_id] = transaction
    
    return {
        "message": "Prêt accordé avec succès",
        "loan": new_loan,
        "transaction": transaction
    }

@app.post("/loans/{loan_id}/repay")
async def repay_loan(loan_id: str, repayment_data: dict):
    """Rembourser un prêt"""
    if loan_id not in loans_db:
        raise HTTPException(status_code=404, detail="Prêt non trouvé")
    
    loan = loans_db[loan_id]
    if loan["status"] != "active" and loan["status"] != "overdue":
        raise HTTPException(status_code=400, detail="Ce prêt ne peut pas être remboursé")
    
    amount_paid = repayment_data.get("amount", loan["totalAmount"])
    
    # Mettre à jour le prêt
    loan["status"] = "repaid"
    loan["repaidAt"] = datetime.utcnow().isoformat() + "Z"
    
    # Créditer le compte stock
    stock_account["balance"] += amount_paid
    stock_account["total_repaid"] += amount_paid
    stock_account["total_commissions"] += loan["commission"]
    stock_account["active_loans"] -= 1
    
    # Créer la transaction de remboursement
    transaction_id = str(len(stock_transactions_db) + 1)
    transaction = {
        "id": transaction_id,
        "type": "loan_repayment",
        "amount": amount_paid,
        "description": f"Remboursement prêt + commission",
        "userId": loan["userId"],
        "userName": loan["userName"],
        "userType": loan["userType"],
        "status": "completed",
        "createdAt": datetime.utcnow().isoformat() + "Z",
        "reference": f"REPAY-{loan_id}"
    }
    
    stock_transactions_db[transaction_id] = transaction
    
    return {
        "message": "Prêt remboursé avec succès",
        "loan": loan,
        "transaction": transaction
    }

if __name__ == "__main__":
    uvicorn.run("main:app", host="127.0.0.1", port=8001, reload=True)