"""
Booking and payment endpoints
"""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List
from uuid import UUID

from app.db.session import get_db
from app.models.booking import Booking, Review, UserWallet, WalletTransaction
from app.models.user import User, Currency
from app.models.beach import BeachPlace, BeachPlaceTerrain
from app.schemas.booking import (
    BookingCreate, BookingUpdate, Booking,
    ReviewCreate, ReviewUpdate, Review,
    UserWalletCreate, UserWalletUpdate, UserWallet,
    WalletTransactionCreate, WalletTransactionUpdate, WalletTransaction
)

router = APIRouter()


# Booking endpoints
@router.post("/", response_model=Booking)
def create_booking(
    booking: BookingCreate,
    db: Session = Depends(get_db)
):
    # Verify user exists
    db_user = db.query(User).filter(User.user_id == booking.user_id).first()
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    
    # Verify beach place exists
    db_beach_place = db.query(BeachPlace).filter(BeachPlace.beach_place_id == booking.beach_place_id).first()
    if db_beach_place is None:
        raise HTTPException(status_code=404, detail="Beach place not found")
    
    # Verify terrain exists
    db_terrain = db.query(BeachPlaceTerrain).filter(BeachPlaceTerrain.terrain_id == booking.terrain_id).first()
    if db_terrain is None:
        raise HTTPException(status_code=404, detail="Beach place terrain not found")
    
    # Verify currency exists
    db_currency = db.query(Currency).filter(Currency.currency_id == booking.currency_id).first()
    if db_currency is None:
        raise HTTPException(status_code=404, detail="Currency not found")
    
    db_booking = Booking(**booking.dict())
    db.add(db_booking)
    db.commit()
    db.refresh(db_booking)
    return db_booking


@router.get("/", response_model=List[Booking])
def read_bookings(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    bookings = db.query(Booking).offset(skip).limit(limit).all()
    return bookings


@router.get("/{booking_id}", response_model=Booking)
def read_booking(
    booking_id: UUID,
    db: Session = Depends(get_db)
):
    db_booking = db.query(Booking).filter(Booking.booking_id == booking_id).first()
    if db_booking is None:
        raise HTTPException(status_code=404, detail="Booking not found")
    return db_booking


@router.put("/{booking_id}", response_model=Booking)
def update_booking(
    booking_id: UUID,
    booking: BookingUpdate,
    db: Session = Depends(get_db)
):
    db_booking = db.query(Booking).filter(Booking.booking_id == booking_id).first()
    if db_booking is None:
        raise HTTPException(status_code=404, detail="Booking not found")
    
    update_data = booking.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_booking, key, value)
    
    db.commit()
    db.refresh(db_booking)
    return db_booking


@router.delete("/{booking_id}")
def delete_booking(
    booking_id: UUID,
    db: Session = Depends(get_db)
):
    db_booking = db.query(Booking).filter(Booking.booking_id == booking_id).first()
    if db_booking is None:
        raise HTTPException(status_code=404, detail="Booking not found")
    
    db.delete(db_booking)
    db.commit()
    return {"message": "Booking deleted successfully"}


# Review endpoints
@router.post("/reviews/", response_model=Review)
def create_review(
    review: ReviewCreate,
    db: Session = Depends(get_db)
):
    # Verify user exists
    db_user = db.query(User).filter(User.user_id == review.user_id).first()
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    
    # Verify beach place exists
    db_beach_place = db.query(BeachPlace).filter(BeachPlace.beach_place_id == review.beach_place_id).first()
    if db_beach_place is None:
        raise HTTPException(status_code=404, detail="Beach place not found")
    
    # Verify booking exists
    db_booking = db.query(Booking).filter(Booking.booking_id == review.booking_id).first()
    if db_booking is None:
        raise HTTPException(status_code=404, detail="Booking not found")
    
    db_review = Review(**review.dict())
    db.add(db_review)
    db.commit()
    db.refresh(db_review)
    return db_review


@router.get("/reviews/", response_model=List[Review])
def read_reviews(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    reviews = db.query(Review).offset(skip).limit(limit).all()
    return reviews


@router.get("/reviews/{review_id}", response_model=Review)
def read_review(
    review_id: UUID,
    db: Session = Depends(get_db)
):
    db_review = db.query(Review).filter(Review.review_id == review_id).first()
    if db_review is None:
        raise HTTPException(status_code=404, detail="Review not found")
    return db_review


@router.put("/reviews/{review_id}", response_model=Review)
def update_review(
    review_id: UUID,
    review: ReviewUpdate,
    db: Session = Depends(get_db)
):
    db_review = db.query(Review).filter(Review.review_id == review_id).first()
    if db_review is None:
        raise HTTPException(status_code=404, detail="Review not found")
    
    update_data = review.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_review, key, value)
    
    db.commit()
    db.refresh(db_review)
    return db_review


@router.delete("/reviews/{review_id}")
def delete_review(
    review_id: UUID,
    db: Session = Depends(get_db)
):
    db_review = db.query(Review).filter(Review.review_id == review_id).first()
    if db_review is None:
        raise HTTPException(status_code=404, detail="Review not found")
    
    db.delete(db_review)
    db.commit()
    return {"message": "Review deleted successfully"}


# User Wallet endpoints
@router.post("/wallets/", response_model=UserWallet)
def create_user_wallet(
    wallet: UserWalletCreate,
    db: Session = Depends(get_db)
):
    # Verify user exists
    db_user = db.query(User).filter(User.user_id == wallet.user_id).first()
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    
    # Verify currency exists
    db_currency = db.query(Currency).filter(Currency.currency_id == wallet.currency_id).first()
    if db_currency is None:
        raise HTTPException(status_code=404, detail="Currency not found")
    
    # Check if user already has a wallet
    existing_wallet = db.query(UserWallet).filter(UserWallet.user_id == wallet.user_id).first()
    if existing_wallet:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="User already has a wallet"
        )
    
    db_wallet = UserWallet(**wallet.dict())
    db.add(db_wallet)
    db.commit()
    db.refresh(db_wallet)
    return db_wallet


@router.get("/wallets/", response_model=List[UserWallet])
def read_user_wallets(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    wallets = db.query(UserWallet).offset(skip).limit(limit).all()
    return wallets


@router.get("/wallets/{wallet_id}", response_model=UserWallet)
def read_user_wallet(
    wallet_id: UUID,
    db: Session = Depends(get_db)
):
    db_wallet = db.query(UserWallet).filter(UserWallet.wallet_id == wallet_id).first()
    if db_wallet is None:
        raise HTTPException(status_code=404, detail="User wallet not found")
    return db_wallet


@router.put("/wallets/{wallet_id}", response_model=UserWallet)
def update_user_wallet(
    wallet_id: UUID,
    wallet: UserWalletUpdate,
    db: Session = Depends(get_db)
):
    db_wallet = db.query(UserWallet).filter(UserWallet.wallet_id == wallet_id).first()
    if db_wallet is None:
        raise HTTPException(status_code=404, detail="User wallet not found")
    
    update_data = wallet.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_wallet, key, value)
    
    db.commit()
    db.refresh(db_wallet)
    return db_wallet


@router.delete("/wallets/{wallet_id}")
def delete_user_wallet(
    wallet_id: UUID,
    db: Session = Depends(get_db)
):
    db_wallet = db.query(UserWallet).filter(UserWallet.wallet_id == wallet_id).first()
    if db_wallet is None:
        raise HTTPException(status_code=404, detail="User wallet not found")
    
    db.delete(db_wallet)
    db.commit()
    return {"message": "User wallet deleted successfully"}


# Wallet Transaction endpoints
@router.post("/transactions/", response_model=WalletTransaction)
def create_wallet_transaction(
    transaction: WalletTransactionCreate,
    db: Session = Depends(get_db)
):
    # Verify wallet exists
    db_wallet = db.query(UserWallet).filter(UserWallet.wallet_id == transaction.wallet_id).first()
    if db_wallet is None:
        raise HTTPException(status_code=404, detail="User wallet not found")
    
    # Verify currency exists
    db_currency = db.query(Currency).filter(Currency.currency_id == transaction.currency_id).first()
    if db_currency is None:
        raise HTTPException(status_code=404, detail="Currency not found")
    
    db_transaction = WalletTransaction(**transaction.dict())
    db.add(db_transaction)
    db.commit()
    db.refresh(db_transaction)
    return db_transaction


@router.get("/transactions/", response_model=List[WalletTransaction])
def read_wallet_transactions(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    transactions = db.query(WalletTransaction).offset(skip).limit(limit).all()
    return transactions


@router.get("/transactions/{transaction_id}", response_model=WalletTransaction)
def read_wallet_transaction(
    transaction_id: UUID,
    db: Session = Depends(get_db)
):
    db_transaction = db.query(WalletTransaction).filter(WalletTransaction.transaction_id == transaction_id).first()
    if db_transaction is None:
        raise HTTPException(status_code=404, detail="Wallet transaction not found")
    return db_transaction


@router.put("/transactions/{transaction_id}", response_model=WalletTransaction)
def update_wallet_transaction(
    transaction_id: UUID,
    transaction: WalletTransactionUpdate,
    db: Session = Depends(get_db)
):
    db_transaction = db.query(WalletTransaction).filter(WalletTransaction.transaction_id == transaction_id).first()
    if db_transaction is None:
        raise HTTPException(status_code=404, detail="Wallet transaction not found")
    
    update_data = transaction.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_transaction, key, value)
    
    db.commit()
    db.refresh(db_transaction)
    return db_transaction


@router.delete("/transactions/{transaction_id}")
def delete_wallet_transaction(
    transaction_id: UUID,
    db: Session = Depends(get_db)
):
    db_transaction = db.query(WalletTransaction).filter(WalletTransaction.transaction_id == transaction_id).first()
    if db_transaction is None:
        raise HTTPException(status_code=404, detail="Wallet transaction not found")
    
    db.delete(db_transaction)
    db.commit()
    return {"message": "Wallet transaction deleted successfully"}