from typing import Optional, List
from sqlalchemy import select
from src.models.usuarios import Usuario
from sqlalchemy.ext.asyncio import AsyncSession
from src.schemas.usuarios import UsuarioCreate, UsuarioUpdate
from src.core.timezone import get_now_brasil


class UsuarioCRUD:
    async def get_by_id(
        self,
            db: AsyncSession,
            usuario_id: int) -> Optional[Usuario]:
        result = await db.execute(
            select(Usuario).where(Usuario.id == usuario_id)
        )
        return result.scalar_one_or_none()

    async def get_by_nome(
        self,
            db: AsyncSession,
            nome: str) -> Optional[Usuario]:
        result = await db.execute(select(Usuario).where(Usuario.nome == nome))
        return result.scalar_one_or_none()

    async def list(
        self,
        db: AsyncSession,
        *,
        ativo: Optional[bool] = None,
        nome: Optional[str] = None,
    ) -> List[Usuario]:
        stmt = select(Usuario)
        if ativo is not None:
            stmt = stmt.where(Usuario.ativo == ativo)
        if nome:
            stmt = stmt.where(Usuario.nome.like(f"%{nome}%"))
        result = await db.execute(stmt)
        return list(result.scalars().all())

    async def create(
        self,
            db: AsyncSession,
            payload: UsuarioCreate) -> Usuario:
        obj = Usuario(
            nome=payload.nome,
            ativo=payload.ativo,
            data_criacao=get_now_brasil(),
        )
        db.add(obj)
        await db.commit()
        await db.refresh(obj)
        return obj

    async def update(
        self,
        db: AsyncSession,
        usuario_id: int,
        payload: UsuarioUpdate,
    ) -> Optional[Usuario]:
        obj = await self.get_by_id(db, usuario_id)
        if not obj:
            return None

        if payload.nome is not None:
            obj.nome = payload.nome
        if payload.ativo is not None:
            obj.ativo = payload.ativo
        if payload.ultimo_login is not None:
            obj.ultimo_login = payload.ultimo_login

        await db.commit()
        await db.refresh(obj)
        return obj

    async def delete(self, db: AsyncSession, usuario_id: int) -> bool:
        obj = await self.get_by_id(db, usuario_id)
        if not obj:
            return False
        await db.delete(obj)
        await db.commit()
        return True


crud = UsuarioCRUD()
