<?php

namespace WPUltimateSecurity\UltimateSecurity\Infrastructure\Container;

use WPUltimateSecurity\UltimateSecurity\Contracts\ServiceProviderInterface;

/**
 * Abstract Service Provider
 *
 * Base class for service providers that need access to the container.
 * Extends the existing ServiceProviderInterface to maintain backward compatibility.
 *
 * Usage:
 * ```php
 * class MyServiceProvider extends ServiceProvider
 * {
 *     public function register(): void
 *     {
 *         $this->singleton(MyService::class, function ($container) {
 *             return new MyService($container->get(DependencyService::class));
 *         });
 *
 *         $this->alias('my-service', MyService::class);
 *     }
 * }
 * ```
 *
 * @package WPUltimateSecurity\UltimateSecurity\Infrastructure\Container
 * @since 2.0.0
 */
abstract class ServiceProvider implements ServiceProviderInterface
{
    /**
     * The container instance.
     *
     * @var Container
     */
    protected Container $container;

    /**
     * Create a new service provider instance.
     *
     * @param Container|null $container The container instance (optional).
     */
    public function __construct(?Container $container = null)
    {
        $this->container = $container ?? Container::getInstance();
    }

    /**
     * Register services in the container.
     *
     * @return void
     */
    abstract public function register(): void;

    /**
     * Register a singleton binding.
     *
     * @param string   $id       The service identifier.
     * @param callable $resolver The resolver callback.
     *
     * @return void
     */
    protected function singleton(string $id, callable $resolver): void
    {
        $this->container->singleton($id, $resolver);
    }

    /**
     * Register a factory binding.
     *
     * @param string   $id       The service identifier.
     * @param callable $resolver The resolver callback.
     *
     * @return void
     */
    protected function bind(string $id, callable $resolver): void
    {
        $this->container->bind($id, $resolver);
    }

    /**
     * Register an existing instance.
     *
     * @param string $id       The service identifier.
     * @param mixed  $instance The instance to register.
     *
     * @return void
     */
    protected function instance(string $id, mixed $instance): void
    {
        $this->container->instance($id, $instance);
    }

    /**
     * Create an alias.
     *
     * @param string $alias    The alias name.
     * @param string $abstract The target binding.
     *
     * @return void
     */
    protected function alias(string $alias, string $abstract): void
    {
        $this->container->alias($alias, $abstract);
    }

    /**
     * Resolve a service from the container.
     *
     * @param string $id The service identifier.
     *
     * @return mixed
     */
    protected function resolve(string $id): mixed
    {
        return $this->container->get($id);
    }

    /**
     * Check if a service is registered.
     *
     * @param string $id The service identifier.
     *
     * @return bool
     */
    protected function has(string $id): bool
    {
        return $this->container->has($id);
    }
}
