<?php
declare(strict_types=1);

namespace ROITheme\Shared\Infrastructure\Di;

use ROITheme\Shared\Domain\Contracts\ComponentRepositoryInterface;
use ROITheme\Shared\Domain\Contracts\ComponentDefaultsRepositoryInterface;
use ROITheme\Shared\Domain\Contracts\ValidationServiceInterface;
use ROITheme\Shared\Domain\Contracts\CacheServiceInterface;
use ROITheme\Shared\Domain\Contracts\CSSGeneratorInterface;
use ROITheme\Shared\Domain\Contracts\ComponentSettingsRepositoryInterface;
use ROITheme\Shared\Infrastructure\Persistence\WordPress\WordPressComponentRepository;
use ROITheme\Shared\Infrastructure\Persistence\WordPress\WordPressDefaultsRepository;
use ROITheme\Shared\Infrastructure\Persistence\WordPress\WordPressComponentSettingsRepository;
use ROITheme\Shared\Infrastructure\Services\WordPressValidationService;
use ROITheme\Shared\Infrastructure\Services\WordPressCacheService;
use ROITheme\Shared\Infrastructure\Services\SchemaSyncService;
use ROITheme\Shared\Infrastructure\Services\CleanupService;
use ROITheme\Shared\Infrastructure\Services\CSSGeneratorService;
use ROITheme\Shared\Application\UseCases\GetComponentSettings\GetComponentSettingsUseCase;
use ROITheme\Shared\Application\UseCases\SaveComponentSettings\SaveComponentSettingsUseCase;

/**
 * DIContainer - Contenedor de Inyección de Dependencias
 *
 * RESPONSABILIDAD: Crear y gestionar instancias de servicios
 *
 * PATRÓN: Service Locator + Lazy Initialization
 * - Lazy Initialization: Crear instancias solo cuando se necesitan
 * - Singleton Pattern: Una sola instancia por servicio
 * - Dependency Resolution: Resolver dependencias automáticamente
 *
 * USO:
 * ```php
 * $container = new DIContainer($wpdb, '/path/to/schemas');
 * $repository = $container->getComponentRepository();
 * $service = $container->getValidationService();
 * ```
 *
 * @package ROITheme\Shared\Infrastructure\DI
 */
final class DIContainer
{
    private array $instances = [];

    public function __construct(
        private \wpdb $wpdb,
        private string $schemasPath
    ) {}

    /**
     * Obtener repositorio de componentes
     *
     * Lazy initialization: Crea la instancia solo en la primera llamada
     *
     * @return ComponentRepositoryInterface
     */
    public function getComponentRepository(): ComponentRepositoryInterface
    {
        if (!isset($this->instances['componentRepository'])) {
            $this->instances['componentRepository'] = new WordPressComponentRepository(
                $this->wpdb
            );
        }

        return $this->instances['componentRepository'];
    }

    /**
     * Obtener repositorio de defaults
     *
     * Lazy initialization: Crea la instancia solo en la primera llamada
     *
     * @return ComponentDefaultsRepositoryInterface
     */
    public function getDefaultsRepository(): ComponentDefaultsRepositoryInterface
    {
        if (!isset($this->instances['defaultsRepository'])) {
            $this->instances['defaultsRepository'] = new WordPressDefaultsRepository(
                $this->wpdb
            );
        }

        return $this->instances['defaultsRepository'];
    }

    /**
     * Obtener servicio de validación
     *
     * Lazy initialization: Crea la instancia solo en la primera llamada
     * Resuelve dependencia: getDefaultsRepository()
     *
     * @return ValidationServiceInterface
     */
    public function getValidationService(): ValidationServiceInterface
    {
        if (!isset($this->instances['validationService'])) {
            $this->instances['validationService'] = new WordPressValidationService(
                $this->getDefaultsRepository()
            );
        }

        return $this->instances['validationService'];
    }

    /**
     * Obtener servicio de cache
     *
     * Lazy initialization: Crea la instancia solo en la primera llamada
     *
     * @return CacheServiceInterface
     */
    public function getCacheService(): CacheServiceInterface
    {
        if (!isset($this->instances['cacheService'])) {
            $this->instances['cacheService'] = new WordPressCacheService(
                $this->wpdb
            );
        }

        return $this->instances['cacheService'];
    }

    /**
     * Obtener servicio de sincronización de schemas
     *
     * Lazy initialization: Crea la instancia solo en la primera llamada
     * Resuelve dependencia: getDefaultsRepository()
     *
     * @return SchemaSyncService
     */
    public function getSchemaSyncService(): SchemaSyncService
    {
        if (!isset($this->instances['schemaSyncService'])) {
            $this->instances['schemaSyncService'] = new SchemaSyncService(
                $this->getDefaultsRepository(),
                $this->schemasPath
            );
        }

        return $this->instances['schemaSyncService'];
    }

    /**
     * Obtener servicio de limpieza
     *
     * Lazy initialization: Crea la instancia solo en la primera llamada
     * Resuelve dependencias: getComponentRepository(), getDefaultsRepository()
     *
     * @return CleanupService
     */
    public function getCleanupService(): CleanupService
    {
        if (!isset($this->instances['cleanupService'])) {
            $this->instances['cleanupService'] = new CleanupService(
                $this->getComponentRepository(),
                $this->getDefaultsRepository()
            );
        }

        return $this->instances['cleanupService'];
    }

    /**
     * Obtener servicio de generación de CSS
     *
     * Lazy initialization: Crea la instancia solo en la primera llamada
     * Sin dependencias
     *
     * @return CSSGeneratorInterface
     */
    public function getCSSGeneratorService(): CSSGeneratorInterface
    {
        if (!isset($this->instances['cssGeneratorService'])) {
            $this->instances['cssGeneratorService'] = new CSSGeneratorService();
        }

        return $this->instances['cssGeneratorService'];
    }

    /**
     * Obtener repositorio de configuraciones de componentes
     *
     * Lazy initialization: Crea la instancia solo en la primera llamada
     *
     * @return ComponentSettingsRepositoryInterface
     */
    public function getComponentSettingsRepository(): ComponentSettingsRepositoryInterface
    {
        if (!isset($this->instances['componentSettingsRepository'])) {
            $this->instances['componentSettingsRepository'] = new WordPressComponentSettingsRepository(
                $this->wpdb
            );
        }

        return $this->instances['componentSettingsRepository'];
    }

    /**
     * Obtener caso de uso para obtener configuraciones de componentes
     *
     * Lazy initialization: Crea la instancia solo en la primera llamada
     * Resuelve dependencia: getComponentSettingsRepository()
     *
     * @return GetComponentSettingsUseCase
     */
    public function getGetComponentSettingsUseCase(): GetComponentSettingsUseCase
    {
        if (!isset($this->instances['getComponentSettingsUseCase'])) {
            $this->instances['getComponentSettingsUseCase'] = new GetComponentSettingsUseCase(
                $this->getComponentSettingsRepository()
            );
        }

        return $this->instances['getComponentSettingsUseCase'];
    }

    /**
     * Obtener caso de uso para guardar configuraciones de componentes
     *
     * Lazy initialization: Crea la instancia solo en la primera llamada
     * Resuelve dependencia: getComponentSettingsRepository()
     *
     * @return SaveComponentSettingsUseCase
     */
    public function getSaveComponentSettingsUseCase(): SaveComponentSettingsUseCase
    {
        if (!isset($this->instances['saveComponentSettingsUseCase'])) {
            $this->instances['saveComponentSettingsUseCase'] = new SaveComponentSettingsUseCase(
                $this->getComponentSettingsRepository()
            );
        }

        return $this->instances['saveComponentSettingsUseCase'];
    }
}
