<?php

namespace MintyPHP\Service\Directory;

use MintyPHP\Repository\Access\RoleRepositoryInterface;
use MintyPHP\Repository\Org\DepartmentRepositoryInterface;
use MintyPHP\Repository\Tenant\TenantRepositoryInterface;
use MintyPHP\Service\Access\RoleService;
use MintyPHP\Service\Audit\AuditRecorderInterface;
use MintyPHP\Service\Org\DepartmentService;
use MintyPHP\Service\Tenant\TenantScopeService;
use MintyPHP\Service\Tenant\TenantService;
use MintyPHP\Service\User\UserServicesFactory;

class DirectoryServicesFactory
{
    private ?TenantService $tenantService = null;
    private ?DepartmentService $departmentService = null;
    private ?RoleService $roleService = null;

    public function __construct(
        private readonly UserServicesFactory $userServicesFactory,
        private readonly AuditRecorderInterface $auditRecorder,
        private readonly DirectoryRepositoryFactory $directoryRepositoryFactory,
        private readonly DirectoryGatewayFactory $directoryGatewayFactory
    ) {
    }

    public function createTenantService(): TenantService
    {
        return $this->tenantService ??= new TenantService(
            $this->createTenantRepository(),
            $this->createDepartmentRepository(),
            $this->createDirectorySettingsGateway(),
            $this->auditRecorder
        );
    }

    public function createDepartmentService(): DepartmentService
    {
        return $this->departmentService ??= new DepartmentService(
            $this->userServicesFactory,
            $this->createDepartmentRepository(),
            $this->createDirectorySettingsGateway(),
            $this->directoryGatewayFactory->getTenantScopeService(),
            $this->auditRecorder
        );
    }

    public function createRoleService(): RoleService
    {
        return $this->roleService ??= new RoleService(
            $this->createRoleRepository(),
            $this->createDirectorySettingsGateway(),
            $this->auditRecorder
        );
    }

    // Passthrough accessors so callers only need a reference to this factory, not the sub-factories.
    public function createTenantRepository(): TenantRepositoryInterface
    {
        return $this->directoryRepositoryFactory->createTenantRepository();
    }

    public function createDepartmentRepository(): DepartmentRepositoryInterface
    {
        return $this->directoryRepositoryFactory->createDepartmentRepository();
    }

    public function createRoleRepository(): RoleRepositoryInterface
    {
        return $this->directoryRepositoryFactory->createRoleRepository();
    }

    public function createDirectorySettingsGateway(): DirectorySettingsGateway
    {
        return $this->directoryGatewayFactory->createDirectorySettingsGateway();
    }

    public function getTenantScopeService(): TenantScopeService
    {
        return $this->directoryGatewayFactory->getTenantScopeService();
    }
}
