from typing import Optional, List
from sqlalchemy import select, delete
from src.models.empresas import Empresa
from sqlalchemy.ext.asyncio import AsyncSession
from src.schemas.empresas import EnterpriseCreate, EnterpriseUpdate


class EmpresaCRUD:
    async def get_by_id(
        self,
            db: AsyncSession,
            empresa_id: str) -> Optional[Empresa]:
        result = await db.execute(
            select(Empresa).where(Empresa.id == str(empresa_id))
        )
        return result.scalar_one_or_none()

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

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

    async def list(
        self,
        db: AsyncSession,
        *,
        enterprise_id: Optional[str] = None,
        nomeFantasia: Optional[str] = None,
    ) -> List[Empresa]:
        stmt = select(Empresa)
        if enterprise_id:
            stmt = stmt.where(Empresa.id == str(enterprise_id))
        if nomeFantasia:
            stmt = stmt.where(Empresa.nomeFantasia.like(f"%{nomeFantasia}%"))
        result = await db.execute(stmt)
        return list(result.scalars().all())

    async def create(
        self,
            db: AsyncSession,
            payload: EnterpriseCreate) -> Empresa:
        obj = Empresa(
            cnpj=payload.cnpj,
            razaoSocial=payload.razaoSocial,
            nomeFantasia=payload.nomeFantasia
        )
        db.add(obj)
        await db.commit()
        await db.refresh(obj)
        return obj

    async def update(
        self,
        db: AsyncSession,
        empresa_id: str,
        payload: EnterpriseUpdate,
    ) -> Optional[Empresa]:
        obj = await self.get_by_id(db, empresa_id)
        if not obj:
            return None
        for field, value in payload.model_dump(exclude_unset=True).items():
            setattr(obj, field, value)
        await db.commit()
        await db.refresh(obj)
        return obj

    async def delete(self, db: AsyncSession, empresa_id: str) -> bool:
        exists = await db.execute(
            select(Empresa.id).where(Empresa.id == str(empresa_id))
        )
        if exists.scalar_one_or_none() is None:
            return False
        await db.execute(
            delete(Empresa).where(Empresa.id == str(empresa_id))
        )
        await db.commit()
        return True


crud = EmpresaCRUD()
