from collections.abc import AsyncIterable from dishka import Provider, Scope, provide from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker from dutylog.infrastructure.database.config import create_engine, create_session_maker from dutylog.infrastructure.database.dao.users_dao import UsersDAO from dutylog.infrastructure.database.dao.hours_transactions_dao import ( HoursTransactionsDAO, ) from dutylog.infrastructure.database.dao.rooms_dao import RoomsDAO from dutylog.infrastructure.database.dao.residents_dao import ResidentsDAO from dutylog.infrastructure.database.dao.floors_dao import FloorsDAO from dutylog.infrastructure.database.dao.reporting_periods_dao import ( ReportingPeriodsDAO, ) from dutylog.infrastructure.database.repositories.users_repository import ( UsersRepository, ) from dutylog.infrastructure.database.repositories.hours_transactions_repository import ( HoursTransactionsRepository, ) from dutylog.infrastructure.database.repositories.rooms_repository import ( RoomsRepository, ) from dutylog.infrastructure.database.repositories.residents_repository import ( ResidentsRepository, ) from dutylog.infrastructure.database.repositories.floors_repository import ( FloorsRepository, ) from dutylog.infrastructure.database.repositories.reporting_periods_repository import ( ReportingPeriodsRepository, ) from dutylog.infrastructure.utils.config import Config, load_config from dutylog.services.report_service import ReportService class ConfigProvider(Provider): @provide(scope=Scope.APP) def get_config(self) -> Config: return load_config() class DatabaseProvider(Provider): @provide(scope=Scope.APP) def get_engine(self, config: Config) -> AsyncEngine: return create_engine(config.database.url) @provide(scope=Scope.APP) def get_session_maker( self, engine: AsyncEngine ) -> async_sessionmaker[AsyncSession]: return create_session_maker(engine) @provide(scope=Scope.REQUEST) async def get_session( self, session_maker: async_sessionmaker[AsyncSession] ) -> AsyncIterable[AsyncSession]: async with session_maker() as session: yield session class DAOProvider(Provider): @provide(scope=Scope.REQUEST) def get_users_dao(self, session: AsyncSession) -> UsersDAO: return UsersDAO(session) @provide(scope=Scope.REQUEST) def get_hours_transactions_dao(self, session: AsyncSession) -> HoursTransactionsDAO: return HoursTransactionsDAO(session) @provide(scope=Scope.REQUEST) def get_rooms_dao(self, session: AsyncSession) -> RoomsDAO: return RoomsDAO(session) @provide(scope=Scope.REQUEST) def get_residents_dao(self, session: AsyncSession) -> ResidentsDAO: return ResidentsDAO(session) @provide(scope=Scope.REQUEST) def get_floors_dao(self, session: AsyncSession) -> FloorsDAO: return FloorsDAO(session) @provide(scope=Scope.REQUEST) def get_reporting_periods_dao(self, session: AsyncSession) -> ReportingPeriodsDAO: return ReportingPeriodsDAO(session) class RepositoryProvider(Provider): @provide(scope=Scope.REQUEST) def get_users_repository(self, users_dao: UsersDAO) -> UsersRepository: return UsersRepository(users_dao) @provide(scope=Scope.REQUEST) def get_hours_transactions_repository( self, transactions_dao: HoursTransactionsDAO, residents_dao: ResidentsDAO, ) -> HoursTransactionsRepository: return HoursTransactionsRepository(transactions_dao, residents_dao) @provide(scope=Scope.REQUEST) def get_rooms_repository(self, rooms_dao: RoomsDAO) -> RoomsRepository: return RoomsRepository(rooms_dao) @provide(scope=Scope.REQUEST) def get_residents_repository( self, residents_dao: ResidentsDAO ) -> ResidentsRepository: return ResidentsRepository(residents_dao) @provide(scope=Scope.REQUEST) def get_floors_repository(self, floors_dao: FloorsDAO) -> FloorsRepository: return FloorsRepository(floors_dao) @provide(scope=Scope.REQUEST) def get_reporting_periods_repository( self, reporting_periods_dao: ReportingPeriodsDAO ) -> ReportingPeriodsRepository: return ReportingPeriodsRepository(reporting_periods_dao) class ServiceProvider(Provider): @provide(scope=Scope.REQUEST) def get_report_service( self, hours_transactions_repository: HoursTransactionsRepository, residents_repository: ResidentsRepository, rooms_repository: RoomsRepository, floors_repository: FloorsRepository, users_repository: UsersRepository, ) -> ReportService: return ReportService( hours_transactions_repository, residents_repository, rooms_repository, floors_repository, users_repository, )