"""
Payment Routes
Wallet management, transactions, and withdrawals
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.ext.asyncio import AsyncSession

from app.database import get_db
from app.models.user import User, UserRole
from app.models.payment import PaymentMethod, TransactionType
from app.schemas.payment import (
    WalletResponse,
    WalletTopupRequest,
    TransactionResponse,
    WithdrawalRequest,
    WithdrawalResponse,
)
from app.schemas.common import MessageResponse, PaginatedResponse
from app.services.payment_service import PaymentService
from app.utils.helpers import build_order_by
from app.utils.dependencies import get_current_user, require_role, get_current_driver

router = APIRouter()


@router.get("/wallet", response_model=WalletResponse)
async def get_wallet(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get current user's wallet balance"""
    wallet = await PaymentService.get_wallet(db, current_user.id)
    
    if not wallet:
        wallet = await PaymentService.create_wallet(db, current_user.id)
    
    return WalletResponse(
        id=wallet.id,
        user_id=wallet.user_id,
        balance=wallet.balance,
        pending_balance=wallet.pending_balance,
        available_balance=wallet.available_balance,
        lifetime_credits=wallet.lifetime_credits,
        lifetime_debits=wallet.lifetime_debits,
        currency=wallet.currency,
        is_active=wallet.is_active
    )


@router.post("/wallet/topup", response_model=TransactionResponse)
async def topup_wallet(
    data: WalletTopupRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Add funds to wallet"""
    # TODO: Integrate with payment gateway (Stripe)
    # For now, just credit the wallet
    try:
        transaction = await PaymentService.topup_wallet(
            db,
            current_user.id,
            data.amount,
            data.payment_method,
            gateway_transaction_id=None  # Would come from payment gateway
        )
        return TransactionResponse.model_validate(transaction)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))


@router.get("/transactions", response_model=PaginatedResponse[TransactionResponse])
async def get_transactions(
    transaction_type: Optional[TransactionType] = None,
    page: int = Query(1, ge=1),
    limit: int = Query(20, ge=1, le=100),
    sort_by: str = Query("created_at", description="Field to sort by"),
    order: str = Query("desc", description="Sort order: asc or desc"),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get transaction history"""
    transactions, total = await PaymentService.get_transaction_history(
        db,
        current_user.id,
        page=page,
        limit=limit,
        transaction_type=transaction_type,
        sort_by=sort_by,
        order=order
    )
    items = [TransactionResponse.model_validate(t) for t in transactions]
    return PaginatedResponse.create(items, total, page, limit)


@router.post("/withdraw", response_model=WithdrawalResponse)
async def request_withdrawal(
    data: WithdrawalRequest,
    current_user: User = Depends(require_role(UserRole.DRIVER)),
    db: AsyncSession = Depends(get_db)
):
    """Request withdrawal of earnings (drivers only)"""
    from app.models.driver import Driver
    from sqlalchemy import select
    
    # Get driver
    query = select(Driver).where(Driver.user_id == current_user.id)
    result = await db.execute(query)
    driver = result.scalar_one_or_none()
    
    if not driver:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Driver profile not found")
    
    try:
        withdrawal = await PaymentService.create_withdrawal_request(db, driver.id, data.amount)
        
        return WithdrawalResponse(
            id=withdrawal.id,
            amount=withdrawal.amount,
            fee=withdrawal.fee,
            net_amount=withdrawal.net_amount,
            status=withdrawal.status,
            bank_name=withdrawal.bank_name,
            bank_account_number=withdrawal.bank_account_number,
            processed_at=withdrawal.processed_at,
            rejection_reason=withdrawal.rejection_reason,
            created_at=withdrawal.created_at
        )
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))


@router.get("/withdrawals", response_model=PaginatedResponse[WithdrawalResponse])
async def get_withdrawal_history(
    page: int = Query(1, ge=1),
    limit: int = Query(20, ge=1, le=100),
    sort_by: str = Query("created_at", description="Field to sort by"),
    order: str = Query("desc", description="Sort order: asc or desc"),
    current_user: User = Depends(require_role(UserRole.DRIVER)),
    db: AsyncSession = Depends(get_db)
):
    """Get withdrawal request history (drivers only)"""
    from app.models.driver import Driver
    from app.models.payment import WithdrawalRequest as WithdrawalModel
    from sqlalchemy import select, func
    
    query = select(Driver).where(Driver.user_id == current_user.id)
    result = await db.execute(query)
    driver = result.scalar_one_or_none()
    
    if not driver:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Driver profile not found")
    
    driver_filter = WithdrawalModel.driver_id == driver.id
    count_result = await db.execute(select(func.count(WithdrawalModel.id)).where(driver_filter))
    total = count_result.scalar() or 0

    offset = (page - 1) * limit
    order_clause = build_order_by(WithdrawalModel, sort_by, order, {"created_at", "updated_at", "amount", "id"})
    w_query = select(WithdrawalModel).where(driver_filter).order_by(order_clause).offset(offset).limit(limit)
    w_result = await db.execute(w_query)
    withdrawals = w_result.scalars().all()
    items = [WithdrawalResponse.model_validate(w) for w in withdrawals]
    
    return PaginatedResponse.create(items, total, page, limit)
