from sqlalchemy.orm import Session
from sqlalchemy import or_
from src.utils.helpers.pagination import QueryPaginator
from typing import Optional, Tuple, Union, List, Dict
from src.database.models.users import User
from src.modules.users.schemas.requests import UserCreateSchema, UserUpdateSchema
from src.modules.users.schemas.responses import UserResponseSchema
from src.modules._lib.repositories.base import BaseRepository


class UserRepository(
    BaseRepository[User, UserCreateSchema, UserUpdateSchema, UserResponseSchema]
):

    async def create_user(self, db: Session, payload: UserCreateSchema):
        db_user = User(
            name=payload.name,
            email=payload.email,
            password=payload.password,
        )
        print(f"===============db_user=============={db_user}")
        db.add(db_user)
        db.commit()
        db.refresh(db_user)
        return db_user

    def get_user_by_id(self, db: Session, user_id: int):
        return db.query(User).filter(User.id == user_id).first()

    def get_user_by_email(self, db: Session, email: str):
        return db.query(User).filter(User.email == email).first()

    def update_user(self, db: Session, user_id: int, paylaod: UserUpdateSchema):
        db_user = db.query(User).filter(User.id == user_id).first()
        if db_user:
            for key, value in paylaod.model_dump(exclude_unset=True).items():
                setattr(db_user, key, value)
            db.commit()
            db.refresh(db_user)
        return db_user

    def delete_user(self, db: Session, user_id: int):
        db_user = db.query(User).filter(User.id == user_id).first()
        if db_user:
            db.delete(db_user)
            db.commit()
        return db_user

    async def get_list(
        self,
        db: Session,
        skip: Optional[int] = None,
        limit: Optional[int] = None,
        sort_by: List[str] = ["-created_at"],
        search: Optional[str] = None,
        paginate: bool = False,
        pagination_url: str = "",
        use_orm: bool = True,
    ) -> Union[List[UserResponseSchema], Dict]:
        query = db.query(User)

        if search:
            query = query.filter(
                or_(User.name.ilike(f"%{search}%"), User.email.ilike(f"%{search}%"))
            )

        sort_order = [getattr(User, col.lstrip("-")) for col in sort_by]

        if any(col is None for col in sort_order):
            raise ValueError(f"Cannot sort with unidentified column")

        query = query.order_by(
            *(col.desc() if col.name.startswith("-") else col for col in sort_order)
        )

        if paginate:
            paginator = QueryPaginator(
                query=query,
                schema=UserResponseSchema,
                url=pagination_url,
                offset=skip,
                limit=limit,
                use_orm=use_orm,
            )
            return {**paginator.paginate()}

        return [UserResponseSchema.model_validate(user) for user in query.all()]


user_repository = UserRepository(User, UserResponseSchema)
