from dependency_injector import containers, providers
from app.repositories import (
    UserRepository,
    QuizRepository,
    UserAnswerRepository,
    SubjectRepository,
    SessionRepository,
    NERSRLRepository,
)

from app.services import (
    UserService,
    AuthService,
    QuizService,
    AnswerService,
    HistoryService,
    SubjectService,
    SessionService,
    QuestionGenerationService,
)

from app.controllers import (
    UserController,
    AuthController,
    QuizController,
    HistoryController,
    SubjectController,
    SocketController,
    SessionController,
)


class Container(containers.DeclarativeContainer):
    """Dependency Injection Container"""

    mongo = providers.Dependency()
    redis = providers.Dependency()
    socketio = providers.Dependency()

    # repository
    user_repository = providers.Factory(UserRepository, mongo.provided.db)
    quiz_repository = providers.Factory(QuizRepository, mongo.provided.db)
    answer_repository = providers.Factory(UserAnswerRepository, mongo.provided.db)
    subject_repository = providers.Factory(SubjectRepository, mongo.provided.db)
    session_repository = providers.Factory(SessionRepository, mongo.provided.db)
    ner_srl_repository = providers.Factory(NERSRLRepository)

    # services
    auth_service = providers.Factory(
        AuthService,
        user_repository,
    )

    user_service = providers.Factory(
        UserService,
        user_repository,
    )

    quiz_service = providers.Factory(
        QuizService,
        quiz_repository,
        user_repository,
        subject_repository,
    )
    answer_service = providers.Factory(
        AnswerService,
        answer_repository,
        quiz_repository,
        user_repository,
    )

    history_service = providers.Factory(
        HistoryService,
        quiz_repository,
        answer_repository,
    )

    subject_service = providers.Factory(
        SubjectService,
        subject_repository,
    )

    session_service = providers.Factory(
        SessionService,
        session_repository,
        user_repository,
    )

    question_generation_service = providers.Factory(
        QuestionGenerationService, ner_srl_repository
    )

    # controllers
    auth_controller = providers.Factory(AuthController, user_service, auth_service)
    user_controller = providers.Factory(UserController, user_service)
    quiz_controller = providers.Factory(
        QuizController,
        quiz_service,
        answer_service,
        question_generation_service,
    )
    history_controller = providers.Factory(HistoryController, history_service)
    subject_controller = providers.Factory(SubjectController, subject_service)
    socket_controller = providers.Factory(
        SocketController,
        socketio,
        redis,
        session_service,
    )
    session_controller = providers.Factory(SessionController, session_service)
