"""
User 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.user import User, UserRole, Language, Currency, Country, EmailVerificationToken
from app.schemas.user import (
    UserCreate, UserUpdate, User,
    UserRoleCreate, UserRoleUpdate, UserRole,
    LanguageCreate, LanguageUpdate, Language,
    CurrencyCreate, CurrencyUpdate, Currency,
    CountryCreate, CountryUpdate, Country,
    EmailVerificationTokenCreate, EmailVerificationTokenUpdate, EmailVerificationToken
)

router = APIRouter()


# User endpoints
@router.post("/", response_model=User)
def create_user(
    user: UserCreate,
    db: Session = Depends(get_db)
):
    # Verify role exists
    db_role = db.query(UserRole).filter(UserRole.role_id == user.role_id).first()
    if db_role is None:
        raise HTTPException(status_code=404, detail="User role not found")
    
    # Verify language exists
    db_language = db.query(Language).filter(Language.language_id == user.preferred_language_id).first()
    if db_language is None:
        raise HTTPException(status_code=404, detail="Language not found")
    
    # Verify currency exists
    db_currency = db.query(Currency).filter(Currency.currency_id == user.preferred_currency_id).first()
    if db_currency is None:
        raise HTTPException(status_code=404, detail="Currency not found")
    
    # Check if user already exists
    existing_user = db.query(User).filter(User.email == user.email).first()
    if existing_user:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Email already registered"
        )
    
    db_user = User(**user.dict())
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user


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


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


@router.put("/{user_id}", response_model=User)
def update_user(
    user_id: UUID,
    user: UserUpdate,
    db: Session = Depends(get_db)
):
    db_user = db.query(User).filter(User.user_id == user_id).first()
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    
    update_data = user.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_user, key, value)
    
    db.commit()
    db.refresh(db_user)
    return db_user


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


# User Role endpoints
@router.post("/roles/", response_model=UserRole)
def create_user_role(
    role: UserRoleCreate,
    db: Session = Depends(get_db)
):
    db_role = UserRole(**role.dict())
    db.add(db_role)
    db.commit()
    db.refresh(db_role)
    return db_role


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


@router.get("/roles/{role_id}", response_model=UserRole)
def read_user_role(
    role_id: int,
    db: Session = Depends(get_db)
):
    db_role = db.query(UserRole).filter(UserRole.role_id == role_id).first()
    if db_role is None:
        raise HTTPException(status_code=404, detail="User role not found")
    return db_role


@router.put("/roles/{role_id}", response_model=UserRole)
def update_user_role(
    role_id: int,
    role: UserRoleUpdate,
    db: Session = Depends(get_db)
):
    db_role = db.query(UserRole).filter(UserRole.role_id == role_id).first()
    if db_role is None:
        raise HTTPException(status_code=404, detail="User role not found")
    
    update_data = role.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_role, key, value)
    
    db.commit()
    db.refresh(db_role)
    return db_role


@router.delete("/roles/{role_id}")
def delete_user_role(
    role_id: int,
    db: Session = Depends(get_db)
):
    db_role = db.query(UserRole).filter(UserRole.role_id == role_id).first()
    if db_role is None:
        raise HTTPException(status_code=404, detail="User role not found")
    
    db.delete(db_role)
    db.commit()
    return {"message": "User role deleted successfully"}


# Language endpoints
@router.post("/languages/", response_model=Language)
def create_language(
    language: LanguageCreate,
    db: Session = Depends(get_db)
):
    db_language = Language(**language.dict())
    db.add(db_language)
    db.commit()
    db.refresh(db_language)
    return db_language


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


@router.get("/languages/{language_id}", response_model=Language)
def read_language(
    language_id: int,
    db: Session = Depends(get_db)
):
    db_language = db.query(Language).filter(Language.language_id == language_id).first()
    if db_language is None:
        raise HTTPException(status_code=404, detail="Language not found")
    return db_language


@router.put("/languages/{language_id}", response_model=Language)
def update_language(
    language_id: int,
    language: LanguageUpdate,
    db: Session = Depends(get_db)
):
    db_language = db.query(Language).filter(Language.language_id == language_id).first()
    if db_language is None:
        raise HTTPException(status_code=404, detail="Language not found")
    
    update_data = language.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_language, key, value)
    
    db.commit()
    db.refresh(db_language)
    return db_language


@router.delete("/languages/{language_id}")
def delete_language(
    language_id: int,
    db: Session = Depends(get_db)
):
    db_language = db.query(Language).filter(Language.language_id == language_id).first()
    if db_language is None:
        raise HTTPException(status_code=404, detail="Language not found")
    
    db.delete(db_language)
    db.commit()
    return {"message": "Language deleted successfully"}


# Currency endpoints
@router.post("/currencies/", response_model=Currency)
def create_currency(
    currency: CurrencyCreate,
    db: Session = Depends(get_db)
):
    db_currency = Currency(**currency.dict())
    db.add(db_currency)
    db.commit()
    db.refresh(db_currency)
    return db_currency


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


@router.get("/currencies/{currency_id}", response_model=Currency)
def read_currency(
    currency_id: int,
    db: Session = Depends(get_db)
):
    db_currency = db.query(Currency).filter(Currency.currency_id == currency_id).first()
    if db_currency is None:
        raise HTTPException(status_code=404, detail="Currency not found")
    return db_currency


@router.put("/currencies/{currency_id}", response_model=Currency)
def update_currency(
    currency_id: int,
    currency: CurrencyUpdate,
    db: Session = Depends(get_db)
):
    db_currency = db.query(Currency).filter(Currency.currency_id == currency_id).first()
    if db_currency is None:
        raise HTTPException(status_code=404, detail="Currency not found")
    
    update_data = currency.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_currency, key, value)
    
    db.commit()
    db.refresh(db_currency)
    return db_currency


@router.delete("/currencies/{currency_id}")
def delete_currency(
    currency_id: int,
    db: Session = Depends(get_db)
):
    db_currency = db.query(Currency).filter(Currency.currency_id == currency_id).first()
    if db_currency is None:
        raise HTTPException(status_code=404, detail="Currency not found")
    
    db.delete(db_currency)
    db.commit()
    return {"message": "Currency deleted successfully"}


# Country endpoints
@router.post("/countries/", response_model=Country)
def create_country(
    country: CountryCreate,
    db: Session = Depends(get_db)
):
    db_country = Country(**country.dict())
    db.add(db_country)
    db.commit()
    db.refresh(db_country)
    return db_country


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


@router.get("/countries/{country_id}", response_model=Country)
def read_country(
    country_id: int,
    db: Session = Depends(get_db)
):
    db_country = db.query(Country).filter(Country.country_id == country_id).first()
    if db_country is None:
        raise HTTPException(status_code=404, detail="Country not found")
    return db_country


@router.put("/countries/{country_id}", response_model=Country)
def update_country(
    country_id: int,
    country: CountryUpdate,
    db: Session = Depends(get_db)
):
    db_country = db.query(Country).filter(Country.country_id == country_id).first()
    if db_country is None:
        raise HTTPException(status_code=404, detail="Country not found")
    
    update_data = country.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_country, key, value)
    
    db.commit()
    db.refresh(db_country)
    return db_country


@router.delete("/countries/{country_id}")
def delete_country(
    country_id: int,
    db: Session = Depends(get_db)
):
    db_country = db.query(Country).filter(Country.country_id == country_id).first()
    if db_country is None:
        raise HTTPException(status_code=404, detail="Country not found")
    
    db.delete(db_country)
    db.commit()
    return {"message": "Country deleted successfully"}


# Email Verification Token endpoints
@router.post("/verification-tokens/", response_model=EmailVerificationToken)
def create_verification_token(
    token: EmailVerificationTokenCreate,
    db: Session = Depends(get_db)
):
    # Verify user exists
    db_user = db.query(User).filter(User.user_id == token.user_id).first()
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    
    db_token = EmailVerificationToken(**token.dict())
    db.add(db_token)
    db.commit()
    db.refresh(db_token)
    return db_token


@router.get("/verification-tokens/", response_model=List[EmailVerificationToken])
def read_verification_tokens(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    tokens = db.query(EmailVerificationToken).offset(skip).limit(limit).all()
    return tokens


@router.get("/verification-tokens/{token_id}", response_model=EmailVerificationToken)
def read_verification_token(
    token_id: int,
    db: Session = Depends(get_db)
):
    db_token = db.query(EmailVerificationToken).filter(EmailVerificationToken.token_id == token_id).first()
    if db_token is None:
        raise HTTPException(status_code=404, detail="Verification token not found")
    return db_token


@router.put("/verification-tokens/{token_id}", response_model=EmailVerificationToken)
def update_verification_token(
    token_id: int,
    token: EmailVerificationTokenUpdate,
    db: Session = Depends(get_db)
):
    db_token = db.query(EmailVerificationToken).filter(EmailVerificationToken.token_id == token_id).first()
    if db_token is None:
        raise HTTPException(status_code=404, detail="Verification token not found")
    
    update_data = token.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_token, key, value)
    
    db.commit()
    db.refresh(db_token)
    return db_token


@router.delete("/verification-tokens/{token_id}")
def delete_verification_token(
    token_id: int,
    db: Session = Depends(get_db)
):
    db_token = db.query(EmailVerificationToken).filter(EmailVerificationToken.token_id == token_id).first()
    if db_token is None:
        raise HTTPException(status_code=404, detail="Verification token not found")
    
    db.delete(db_token)
    db.commit()
    return {"message": "Verification token deleted successfully"}