""" User related CRUD methods """
import uuid
from typing import Any

from sqlmodel import Session, select

from app.core.security import get_password_hash, verify_password
from app.models import User, UserCreate, UserUpdate, RoleEnum


def create_user(*, session: Session, user_create: UserCreate) -> User:
    db_obj = User.model_validate(
        user_create, update={"hashed_password": get_password_hash(user_create.password)}
    )
    session.add(db_obj)
    session.commit()
    session.refresh(db_obj)
    return db_obj


def update_user(*, session: Session, db_user: User, user_in: UserUpdate) -> Any:
    user_data = user_in.model_dump(exclude_unset=True)
    extra_data = {}
    if "password" in user_data:
        password = user_data["password"]
        hashed_password = get_password_hash(password)
        extra_data["hashed_password"] = hashed_password
    db_user.sqlmodel_update(user_data, update=extra_data)
    session.add(db_user)
    session.commit()
    session.refresh(db_user)
    return db_user


def get_user_by_email(*, session: Session, email: str) -> User | None:
    statement = select(User).where(User.email == email)
    session_user = session.exec(statement).first()
    return session_user

def get_user_by_cif(*, session: Session, cif: str) -> User | None:
    statement = select(User).where(User.cif == cif)
    session_user = session.exec(statement).first()
    return session_user


def get_user_by_id(*, session: Session, user_id: uuid.UUID) -> User | None:
    statement = select(User).where(User.id == user_id)
    session_user = session.exec(statement).first()
    return session_user


def authenticate(*, session: Session, email: str, password: str) -> User | None:
    db_user = get_user_by_email(session=session, email=email)
    if not db_user:
        return None
    if not verify_password(password, db_user.hashed_password):
        return None
    return db_user


def get_user_role(*, session: Session, user_id: uuid.UUID) -> RoleEnum | None:
    user = get_user_by_id(session=session, user_id=user_id)
    if not user:
        return None
    return user.role


def is_vendor_role(role: RoleEnum) -> bool:
    return "vendor" in role.value

def is_user_vendor(*, session: Session, user_id: uuid.UUID) -> bool:
    role = get_user_role(session=session, user_id=user_id)
    if not role:
        return False
    return is_vendor_role(role)


def get_user_by_dni(*, session: Session, dni: str) -> User | None:
    statement = select(User).where(User.dni == dni)
    session_user = session.exec(statement).first()
    return session_user

