from collections.abc import Sequence

from sqlalchemy import literal, select
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy.sql.expression import any_, or_

from csirtmu.perun_sync.config import DatabaseConfig
from csirtmu.perun_sync.perun_sync.models import PerunUser


class PerunUserRepository:
    def __init__(self, config: DatabaseConfig) -> None:
        self.session_factory = self.build_session_factory(config)

    @staticmethod
    def build_session_factory(
        config: DatabaseConfig,
    ) -> async_sessionmaker[AsyncSession]:
        return async_sessionmaker(create_async_engine(config.engine_url))

    async def get_user_by_mail(self, mail: str) -> Sequence[PerunUser]:
        async with self.session_factory() as session:
            return (
                (
                    await session.execute(
                        select(PerunUser).where(
                            or_(
                                PerunUser.preferred_mail.ilike(mail),
                                literal(mail).ilike(any_(PerunUser.aliases)),
                            )
                        )
                    )
                )
                .scalars()
                .all()
            )

    async def get_user_by_uco(self, uco: str) -> Sequence[PerunUser]:
        async with self.session_factory() as session:
            return (await session.execute(select(PerunUser).where(PerunUser.login_mu == uco))).scalars().all()

    async def save_changes(self, users: Sequence[PerunUser]) -> None:
        async with self.session_factory() as session:
            session.add_all(users)
            await session.commit()
