<?php

namespace MintyPHP\Service\User;

use MintyPHP\Service\Access\AccessServicesFactory;
use MintyPHP\Service\Access\PermissionGateway;
use MintyPHP\Repository\Access\UserRoleRepository;
use MintyPHP\Repository\Org\UserDepartmentRepository;
use MintyPHP\Repository\Tenant\UserTenantRepository;
use MintyPHP\Repository\User\UserListQueryRepository;
use MintyPHP\Repository\User\UserReadRepository;
use MintyPHP\Repository\User\UserSavedFilterRepository;
use MintyPHP\Repository\User\UserWriteRepository;
use MintyPHP\Service\Audit\AuditServicesFactory;
use MintyPHP\Service\Audit\UserLifecycleAuditService;
use MintyPHP\Service\Settings\SettingGateway;
use MintyPHP\Service\Settings\SettingServicesFactory;
use MintyPHP\Service\Tenant\TenantServicesFactory;

class UserServicesFactory
{
    private ?AccessServicesFactory $accessServicesFactory = null;
    private ?TenantServicesFactory $tenantServicesFactory = null;
    private ?UserReadRepository $userReadRepository = null;
    private ?AuditServicesFactory $auditServicesFactory = null;
    private ?SettingServicesFactory $settingServicesFactory = null;
    private ?UserWriteRepository $userWriteRepository = null;
    private ?UserListQueryRepository $userListQueryRepository = null;
    private ?UserSavedFilterRepository $userSavedFilterRepository = null;
    private ?UserTenantRepository $userTenantRepository = null;
    private ?UserRoleRepository $userRoleRepository = null;
    private ?UserDepartmentRepository $userDepartmentRepository = null;
    private ?UserPasswordPolicyService $userPasswordPolicyService = null;
    private ?UserPasswordService $userPasswordService = null;
    private ?UserAvatarService $userAvatarService = null;
    private ?UserSavedFilterService $userSavedFilterService = null;
    private ?UserSettingsGateway $userSettingsGateway = null;
    private ?SettingGateway $settingGateway = null;
    private ?UserScopeGateway $userScopeGateway = null;
    private ?UserDirectoryGateway $userDirectoryGateway = null;
    private ?UserPermissionGateway $userPermissionGateway = null;
    private ?PermissionGateway $permissionGateway = null;
    private ?UserAssignmentService $userAssignmentService = null;
    private ?UserTenantContextService $userTenantContextService = null;
    private ?UserAccountService $userAccountService = null;
    private ?UserLifecycleService $userLifecycleService = null;
    private ?UserLifecycleRestoreService $userLifecycleRestoreService = null;
    private ?UserLifecycleAuditService $userLifecycleAuditService = null;

    public function createUserAccountService(): UserAccountService
    {
        return $this->userAccountService ??= new UserAccountService(
            $this->createUserReadRepository(),
            $this->createUserWriteRepository(),
            $this->createUserListQueryRepository(),
            $this->createUserAssignmentService(),
            $this->createUserPasswordService(),
            $this->createUserSettingsGateway(),
            $this->createUserScopeGateway()
        );
    }

    public function createUserAssignmentService(): UserAssignmentService
    {
        return $this->userAssignmentService ??= new UserAssignmentService(
            $this->createUserWriteRepository(),
            $this->createUserTenantRepository(),
            $this->createUserRoleRepository(),
            $this->createUserDepartmentRepository(),
            $this->createUserDirectoryGateway(),
            $this->createUserPermissionGateway()
        );
    }

    public function createUserTenantContextService(): UserTenantContextService
    {
        return $this->userTenantContextService ??= new UserTenantContextService(
            $this->createUserReadRepository(),
            $this->createUserWriteRepository(),
            $this->createUserTenantRepository(),
            $this->createUserScopeGateway(),
            $this->createUserDirectoryGateway()
        );
    }

    public function createUserPasswordService(): UserPasswordService
    {
        return $this->userPasswordService ??= new UserPasswordService(
            $this->createUserPasswordPolicyService(),
            $this->createUserWriteRepository()
        );
    }

    public function createUserAvatarService(): UserAvatarService
    {
        return $this->userAvatarService ??= new UserAvatarService();
    }

    public function createUserSavedFilterService(): UserSavedFilterService
    {
        return $this->userSavedFilterService ??= new UserSavedFilterService(
            $this->createUserSavedFilterRepository()
        );
    }

    public function createUserReadRepository(): UserReadRepository
    {
        return $this->userReadRepository ??= new UserReadRepository();
    }

    public function createUserWriteRepository(): UserWriteRepository
    {
        return $this->userWriteRepository ??= new UserWriteRepository();
    }

    public function createUserListQueryRepository(): UserListQueryRepository
    {
        return $this->userListQueryRepository ??= new UserListQueryRepository();
    }

    public function createUserSavedFilterRepository(): UserSavedFilterRepository
    {
        return $this->userSavedFilterRepository ??= new UserSavedFilterRepository();
    }

    public function createUserTenantRepository(): UserTenantRepository
    {
        return $this->userTenantRepository ??= new UserTenantRepository();
    }

    public function createUserRoleRepository(): UserRoleRepository
    {
        return $this->userRoleRepository ??= new UserRoleRepository();
    }

    public function createUserDepartmentRepository(): UserDepartmentRepository
    {
        return $this->userDepartmentRepository ??= new UserDepartmentRepository();
    }

    public function createUserPasswordPolicyService(): UserPasswordPolicyService
    {
        return $this->userPasswordPolicyService ??= new UserPasswordPolicyService();
    }

    public function createUserSettingsGateway(): UserSettingsGateway
    {
        return $this->userSettingsGateway ??= new UserSettingsGateway($this->createSettingGateway());
    }

    public function createUserScopeGateway(): UserScopeGateway
    {
        return $this->userScopeGateway ??= new UserScopeGateway($this->tenantServicesFactory()->createTenantScopeService());
    }

    public function createUserDirectoryGateway(): UserDirectoryGateway
    {
        return $this->userDirectoryGateway ??= new UserDirectoryGateway();
    }

    public function createUserPermissionGateway(): UserPermissionGateway
    {
        return $this->userPermissionGateway ??= new UserPermissionGateway($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 tenantServicesFactory(): TenantServicesFactory
    {
        return $this->tenantServicesFactory ??= new TenantServicesFactory();
    }

    public function createUserLifecycleService(): UserLifecycleService
    {
        return $this->userLifecycleService ??= new UserLifecycleService(
            $this->createUserReadRepository(),
            $this->createUserWriteRepository(),
            $this->createUserSettingsGateway(),
            $this->createUserLifecycleAuditService()
        );
    }

    public function createUserLifecycleRestoreService(): UserLifecycleRestoreService
    {
        return $this->userLifecycleRestoreService ??= new UserLifecycleRestoreService(
            $this->createUserReadRepository(),
            $this->createUserWriteRepository(),
            $this->createUserLifecycleAuditService()
        );
    }

    private function createUserLifecycleAuditService(): UserLifecycleAuditService
    {
        return $this->userLifecycleAuditService ??= $this->auditServicesFactory()->createUserLifecycleAuditService();
    }

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