"""
API для управления балансом пользователя
"""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from sqlalchemy import and_
from typing import List
from datetime import datetime, timedelta
from decimal import Decimal

from app.db.session import get_db
from app.db.models import UserBalance, BalanceTransaction, Tenant
from app.api.deps import get_current_user
from pydantic import BaseModel

router = APIRouter()


# Pydantic схемы
class UserBalanceOut(BaseModel):
    id: int
    tenant_id: int
    balance: Decimal
    total_deposited: Decimal
    total_spent: Decimal
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


class BalanceTransactionOut(BaseModel):
    id: int
    tenant_id: int
    transaction_type: str
    amount: Decimal
    balance_before: Decimal
    balance_after: Decimal
    description: str
    reference_id: str
    created_at: datetime

    class Config:
        from_attributes = True


class DepositRequest(BaseModel):
    amount: Decimal
    payment_method: str = "card"  # card, bank_transfer, wallet


class WithdrawRequest(BaseModel):
    amount: Decimal
    description: str


# Эндпоинты
@router.get("/balance", response_model=UserBalanceOut)
def get_user_balance(
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """Получить баланс пользователя"""
    balance = db.query(UserBalance).filter(
        UserBalance.tenant_id == current_user.tenant_id
    ).first()
    
    if not balance:
        # Создаем баланс если его нет
        balance = UserBalance(
            tenant_id=current_user.tenant_id,
            balance=Decimal('0'),
            total_deposited=Decimal('0'),
            total_spent=Decimal('0')
        )
        db.add(balance)
        db.commit()
        db.refresh(balance)
    
    return balance


@router.get("/transactions", response_model=List[BalanceTransactionOut])
def get_balance_transactions(
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """Получить историю транзакций по балансу"""
    transactions = db.query(BalanceTransaction).filter(
        BalanceTransaction.tenant_id == current_user.tenant_id
    ).order_by(BalanceTransaction.created_at.desc()).limit(50).all()
    
    return transactions


@router.post("/deposit", response_model=UserBalanceOut)
def deposit_balance(
    request: DepositRequest,
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """Пополнить баланс"""
    if request.amount <= 0:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Сумма пополнения должна быть больше 0"
        )
    
    # Получаем или создаем баланс
    balance = db.query(UserBalance).filter(
        UserBalance.tenant_id == current_user.tenant_id
    ).first()
    
    if not balance:
        balance = UserBalance(
            tenant_id=current_user.tenant_id,
            balance=Decimal('0'),
            total_deposited=Decimal('0'),
            total_spent=Decimal('0')
        )
        db.add(balance)
        db.commit()
        db.refresh(balance)
    
    # Обновляем баланс
    balance_before = balance.balance
    balance.balance += request.amount
    balance.total_deposited += request.amount
    balance.updated_at = datetime.utcnow()
    
    # Создаем транзакцию
    transaction = BalanceTransaction(
        tenant_id=current_user.tenant_id,
        transaction_type="deposit",
        amount=request.amount,
        balance_before=balance_before,
        balance_after=balance.balance,
        description=f"Пополнение баланса через {request.payment_method}",
        reference_id=f"DEPOSIT-{int(datetime.utcnow().timestamp())}"
    )
    db.add(transaction)
    
    db.commit()
    db.refresh(balance)
    
    return balance


@router.post("/withdraw", response_model=UserBalanceOut)
def withdraw_balance(
    request: WithdrawRequest,
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """Списать с баланса"""
    if request.amount <= 0:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Сумма списания должна быть больше 0"
        )
    
    # Получаем баланс с блокировкой для предотвращения race condition
    balance = db.query(UserBalance).filter(
        UserBalance.tenant_id == current_user.tenant_id
    ).with_for_update().first()
    
    if not balance:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Баланс не найден"
        )
    
    if balance.balance < request.amount:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Недостаточно средств на балансе"
        )
    
    # Обновляем баланс
    balance_before = balance.balance
    balance.balance -= request.amount
    balance.total_spent += request.amount
    balance.updated_at = datetime.utcnow()
    
    # Создаем транзакцию
    transaction = BalanceTransaction(
        tenant_id=current_user.tenant_id,
        transaction_type="withdraw",
        amount=-request.amount,  # Отрицательная сумма для списания
        balance_before=balance_before,
        balance_after=balance.balance,
        description=request.description,
        reference_id=f"WITHDRAW-{int(datetime.utcnow().timestamp())}"
    )
    db.add(transaction)
    
    db.commit()
    db.refresh(balance)
    
    return balance


@router.post("/pay-subscription", response_model=UserBalanceOut)
def pay_subscription(
    subscription_id: int,
    db: Session = Depends(get_db),
    current_user = Depends(get_current_user)
):
    """Оплатить подписку с баланса"""
    from app.db.models import Subscription
    
    # Получаем подписку
    subscription = db.query(Subscription).filter(
        and_(
            Subscription.id == subscription_id,
            Subscription.tenant_id == current_user.tenant_id,
            Subscription.status == "pending_payment"
        )
    ).first()
    
    if not subscription:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Подписка не найдена или уже оплачена"
        )
    
    # Получаем баланс с блокировкой для предотвращения race condition
    balance = db.query(UserBalance).filter(
        UserBalance.tenant_id == current_user.tenant_id
    ).with_for_update().first()
    
    if not balance:
        balance = UserBalance(
            tenant_id=current_user.tenant_id,
            balance=Decimal('0'),
            total_deposited=Decimal('0'),
            total_spent=Decimal('0')
        )
        db.add(balance)
        db.commit()
        db.refresh(balance)
    
    payment_amount = subscription.plan.monthly_price
    
    if balance.balance < payment_amount:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Недостаточно средств на балансе. Требуется: {payment_amount} ₽, доступно: {balance.balance} ₽"
        )
    
    # Списываем с баланса
    balance_before = balance.balance
    balance.balance -= payment_amount
    balance.total_spent += payment_amount
    balance.updated_at = datetime.utcnow()
    
    # Создаем транзакцию
    transaction = BalanceTransaction(
        tenant_id=current_user.tenant_id,
        transaction_type="subscription_payment",
        amount=-payment_amount,
        balance_before=balance_before,
        balance_after=balance.balance,
        description=f"Оплата тарифа {subscription.plan.name}",
        reference_id=str(subscription_id)
    )
    db.add(transaction)
    
    # Активируем подписку
    subscription.status = "active"
    subscription.started_at = datetime.utcnow()
    subscription.expires_at = datetime.utcnow() + timedelta(days=30)
    
    # Создаем запись об использовании
    from app.db.models import UsageRecord
    now = datetime.utcnow()
    usage_record = UsageRecord(
        tenant_id=current_user.tenant_id,
        subscription_id=subscription.id,
        period_start=now,
        period_end=now + timedelta(days=30),
        notifications_sent=0,
        notifications_limit=subscription.plan.notifications_limit
    )
    db.add(usage_record)
    
    # Создаем запись о платеже
    from app.db.models import Payment
    payment = Payment(
        tenant_id=current_user.tenant_id,
        subscription_id=subscription.id,
        amount=payment_amount,
        currency="RUB",
        status="completed",
        payment_method="balance",
        transaction_id=f"BALANCE-{int(datetime.utcnow().timestamp())}",
        completed_at=datetime.utcnow()
    )
    db.add(payment)
    
    db.commit()
    db.refresh(balance)
    
    return balance
