<?php

namespace MintyPHP\Service\Auth;

use MintyPHP\Repository\Auth\ApiTokenRepository;
use MintyPHP\Repository\Auth\EmailVerificationRepository;
use MintyPHP\Repository\Auth\PasswordResetRepository;
use MintyPHP\Repository\Auth\RememberTokenRepository;
use MintyPHP\Repository\Tenant\TenantMicrosoftAuthRepository;
use MintyPHP\Repository\User\UserExternalIdentityRepository;
use MintyPHP\Service\Access\AccessServicesFactory;
use MintyPHP\Service\Access\PermissionGateway;
use MintyPHP\Service\Mail\MailServicesFactory;
use MintyPHP\Service\Settings\SettingGateway;
use MintyPHP\Service\Settings\SettingServicesFactory;
use MintyPHP\Service\Tenant\TenantServicesFactory;
use MintyPHP\Service\User\UserServicesFactory;

class AuthServicesFactory
{
    private ?AccessServicesFactory $accessServicesFactory = null;
    private ?TenantServicesFactory $tenantServicesFactory = null;
    private ?UserServicesFactory $userServicesFactory = null;
    private ?MailServicesFactory $mailServicesFactory = null;
    private ?SettingServicesFactory $settingServicesFactory = null;
    private ?AuthSettingsGateway $authSettingsGateway = null;
    private ?SettingGateway $settingGateway = null;
    private ?AuthScopeGateway $authScopeGateway = null;
    private ?AuthPermissionGateway $authPermissionGateway = null;
    private ?PermissionGateway $permissionGateway = null;
    private ?AuthTenantGateway $authTenantGateway = null;
    private ?AuthCryptoGateway $authCryptoGateway = null;
    private ?AuthTenantSsoGateway $authTenantSsoGateway = null;
    private ?AuthSavedFilterGateway $authSavedFilterGateway = null;
    private ?AuthAvatarGateway $authAvatarGateway = null;
    private ?AuthExternalIdentityGateway $authExternalIdentityGateway = null;
    private ?ApiTokenRepository $apiTokenRepository = null;
    private ?RememberTokenRepository $rememberTokenRepository = null;
    private ?PasswordResetRepository $passwordResetRepository = null;
    private ?EmailVerificationRepository $emailVerificationRepository = null;
    private ?TenantMicrosoftAuthRepository $tenantMicrosoftAuthRepository = null;
    private ?UserExternalIdentityRepository $userExternalIdentityRepository = null;
    private ?TenantSsoService $tenantSsoService = null;
    private ?OidcHttpGateway $oidcHttpGateway = null;
    private ?MicrosoftOidcStateStoreService $microsoftOidcStateStoreService = null;
    private ?MicrosoftOidcService $microsoftOidcService = null;
    private ?ApiTokenService $apiTokenService = null;
    private ?PasswordResetService $passwordResetService = null;
    private ?EmailVerificationService $emailVerificationService = null;
    private ?RememberMeService $rememberMeService = null;
    private ?AuthService $authService = null;
    private ?SsoUserLinkService $ssoUserLinkService = null;

    public function createApiTokenService(): ApiTokenService
    {
        return $this->apiTokenService ??= new ApiTokenService(
            $this->userServicesFactory()->createUserReadRepository(),
            $this->createApiTokenRepository(),
            $this->createAuthSettingsGateway(),
            $this->createAuthScopeGateway()
        );
    }

    public function createPasswordResetService(): PasswordResetService
    {
        return $this->passwordResetService ??= new PasswordResetService(
            $this->userServicesFactory()->createUserReadRepository(),
            $this->createPasswordResetRepository(),
            $this->userServicesFactory()->createUserPasswordService(),
            $this->createRememberMeService(),
            $this->mailServicesFactory()->createMailService()
        );
    }

    public function createEmailVerificationService(): EmailVerificationService
    {
        return $this->emailVerificationService ??= new EmailVerificationService(
            $this->userServicesFactory()->createUserReadRepository(),
            $this->userServicesFactory()->createUserWriteRepository(),
            $this->createEmailVerificationRepository(),
            $this->mailServicesFactory()->createMailService()
        );
    }

    public function createRememberMeService(): RememberMeService
    {
        return $this->rememberMeService ??= new RememberMeService(
            $this->userServicesFactory()->createUserReadRepository(),
            $this->userServicesFactory()->createUserWriteRepository(),
            $this->createRememberTokenRepository(),
            $this->userServicesFactory()->createUserTenantContextService(),
            $this->createAuthPermissionGateway(),
            $this->createAuthSavedFilterGateway()
        );
    }

    public function createAuthService(): AuthService
    {
        return $this->authService ??= new AuthService(
            $this->userServicesFactory()->createUserReadRepository(),
            $this->userServicesFactory()->createUserWriteRepository(),
            $this->userServicesFactory()->createUserAccountService(),
            $this->userServicesFactory()->createUserTenantContextService(),
            $this->createRememberMeService(),
            $this->createEmailVerificationService(),
            $this->createAuthPermissionGateway(),
            $this->createAuthTenantSsoGateway(),
            $this->createAuthSavedFilterGateway()
        );
    }

    public function createSsoUserLinkService(): SsoUserLinkService
    {
        return $this->ssoUserLinkService ??= new SsoUserLinkService(
            $this->userServicesFactory()->createUserReadRepository(),
            $this->userServicesFactory()->createUserWriteRepository(),
            $this->userServicesFactory()->createUserAssignmentService(),
            $this->userServicesFactory()->createUserTenantRepository(),
            $this->createAuthSettingsGateway(),
            $this->createAuthTenantSsoGateway(),
            $this->createAuthAvatarGateway(),
            $this->createAuthExternalIdentityGateway()
        );
    }

    public function createTenantSsoService(): TenantSsoService
    {
        return $this->tenantSsoService ??= new TenantSsoService(
            $this->createAuthTenantGateway(),
            $this->createTenantMicrosoftAuthRepository(),
            $this->createAuthSettingsGateway(),
            $this->createAuthCryptoGateway()
        );
    }

    public function createMicrosoftOidcStateStore(): MicrosoftOidcStateStoreService
    {
        return $this->microsoftOidcStateStoreService ??= new MicrosoftOidcStateStoreService();
    }

    public function createMicrosoftOidcService(): MicrosoftOidcService
    {
        return $this->microsoftOidcService ??= new MicrosoftOidcService(
            $this->createTenantSsoService(),
            $this->createAuthTenantGateway(),
            $this->createOidcHttpGateway(),
            $this->createMicrosoftOidcStateStore()
        );
    }

    private function userServicesFactory(): UserServicesFactory
    {
        return $this->userServicesFactory ??= new UserServicesFactory();
    }

    private function createAuthSettingsGateway(): AuthSettingsGateway
    {
        return $this->authSettingsGateway ??= new AuthSettingsGateway($this->createSettingGateway());
    }

    public function createAuthScopeGateway(): AuthScopeGateway
    {
        return $this->authScopeGateway ??= new AuthScopeGateway($this->tenantServicesFactory()->createTenantScopeService());
    }

    private function createAuthPermissionGateway(): AuthPermissionGateway
    {
        return $this->authPermissionGateway ??= new AuthPermissionGateway($this->createPermissionGateway());
    }

    private function createPermissionGateway(): PermissionGateway
    {
        return $this->permissionGateway ??= $this->accessServicesFactory()->createPermissionGateway();
    }

    private function accessServicesFactory(): AccessServicesFactory
    {
        return $this->accessServicesFactory ??= new AccessServicesFactory();
    }

    private function createSettingGateway(): SettingGateway
    {
        return $this->settingGateway ??= $this->settingServicesFactory()->createSettingGateway();
    }

    private function settingServicesFactory(): SettingServicesFactory
    {
        return $this->settingServicesFactory ??= new SettingServicesFactory();
    }

    private function mailServicesFactory(): MailServicesFactory
    {
        return $this->mailServicesFactory ??= new MailServicesFactory();
    }

    private function tenantServicesFactory(): TenantServicesFactory
    {
        return $this->tenantServicesFactory ??= new TenantServicesFactory();
    }

    private function createAuthTenantGateway(): AuthTenantGateway
    {
        return $this->authTenantGateway ??= new AuthTenantGateway();
    }

    private function createAuthCryptoGateway(): AuthCryptoGateway
    {
        return $this->authCryptoGateway ??= new AuthCryptoGateway();
    }

    private function createAuthTenantSsoGateway(): AuthTenantSsoGateway
    {
        return $this->authTenantSsoGateway ??= new AuthTenantSsoGateway($this->createTenantSsoService());
    }

    private function createAuthSavedFilterGateway(): AuthSavedFilterGateway
    {
        return $this->authSavedFilterGateway ??= new AuthSavedFilterGateway(
            $this->userServicesFactory()->createUserSavedFilterService()
        );
    }

    private function createAuthAvatarGateway(): AuthAvatarGateway
    {
        return $this->authAvatarGateway ??= new AuthAvatarGateway(
            $this->userServicesFactory()->createUserAvatarService()
        );
    }

    private function createAuthExternalIdentityGateway(): AuthExternalIdentityGateway
    {
        return $this->authExternalIdentityGateway ??= new AuthExternalIdentityGateway(
            $this->createUserExternalIdentityRepository()
        );
    }

    private function createTenantMicrosoftAuthRepository(): TenantMicrosoftAuthRepository
    {
        return $this->tenantMicrosoftAuthRepository ??= new TenantMicrosoftAuthRepository();
    }

    private function createApiTokenRepository(): ApiTokenRepository
    {
        return $this->apiTokenRepository ??= new ApiTokenRepository();
    }

    private function createRememberTokenRepository(): RememberTokenRepository
    {
        return $this->rememberTokenRepository ??= new RememberTokenRepository();
    }

    private function createPasswordResetRepository(): PasswordResetRepository
    {
        return $this->passwordResetRepository ??= new PasswordResetRepository();
    }

    private function createEmailVerificationRepository(): EmailVerificationRepository
    {
        return $this->emailVerificationRepository ??= new EmailVerificationRepository();
    }

    private function createUserExternalIdentityRepository(): UserExternalIdentityRepository
    {
        return $this->userExternalIdentityRepository ??= new UserExternalIdentityRepository();
    }

    private function createOidcHttpGateway(): OidcHttpGateway
    {
        return $this->oidcHttpGateway ??= new OidcHttpGateway();
    }
}
