<?php

declare(strict_types=1);

namespace CloudXM\NFe\Bootstrap;

use CloudXM\NFe\Config\Configuration;
use CloudXM\NFe\Services\UpdateService;
use CloudXM\SDK\Bootstrap\AbstractPlugin;
use CloudXM\SDK\Contracts\ContainerInterface;
use CloudXM\SDK\Providers\UpdateServiceProvider;
use CloudXM\SDK\Support\HasLogger;
use CloudXM\NFe\Providers\CoreServiceProvider;
use CloudXM\NFe\Providers\RestServiceProvider;
use CloudXM\NFe\Providers\AdminServiceProvider;

/**
 * Main Plugin Bootstrap
 *
 * Minimal bootstrap class that initializes container and service providers.
 * All business logic should be in services, all hooks in providers.
 */
final class Plugin extends AbstractPlugin
{
    use HasLogger;

    private static ?self $instance = null;
    private Container $container;
    private Configuration $config;
    private bool $booted = false;
    private bool $serviceProvidersRegistered = false;

    /**
     * Get plugin instance (singleton)
     *
     * @internal Only for WordPress/WooCommerce integration
     */
    public static function getInstance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Private constructor
     */
    private function __construct()
    {
        // Define plugin constants
        $this->defineConstants();

        $this->config = new Configuration();
        $this->container = new Container();
    }

    /**
     * Get service container
     */
    public function container(): ContainerInterface
    {
        return $this->container;
    }

    /**
     * Child plugin supplies list of provider class-names
     */
    public function getProviders(): array
    {
        return [
            UpdateServiceProvider::class,
            CoreServiceProvider::class,
            RestServiceProvider::class,
            AdminServiceProvider::class,
        ];
    }

    /**
     * Check plugin requirements before booting
     */
    public function checkRequirements(): bool
    {
        return $this->checkMyRequirements();
    }

    /**
     * Get minimum PHP version required
     */
    public function getMinPhpVersion(): string
    {
        return '8.1';
    }

    /**
     * Check if service exists
     */
    public function hasService(string $service): bool
    {
        return $this->container->has($service);
    }

    /**
     * Boot plugin
     */
    public function boot(): void
    {
        if ($this->booted) {
            return;
        }

        // Check requirements
        if (!$this->checkRequirements()) {
            return;
        }

        // Register service providers
        $this->registerServiceProviders();

        // Plugin upgrade - run migrations if version changed
        $this->checkPluginVersion();

        // Boot all providers
        $this->bootServiceProviders();

        $this->booted = true;
    }

    /**
     * Define plugin constants
     */
    private function defineConstants(): void
    {
        // Constants are already defined in main plugin file
        // This method is for future expansion
    }

    /**
     * Check plugin requirements
     */
    private function checkMyRequirements(): bool
    {
        $errors = [];

        // Check PHP version
        if (version_compare(PHP_VERSION, $this->getMinPhpVersion(), '<')) {
            $errors[] = sprintf(
                'CloudXM NFe requires PHP 8.1 or higher. You are running PHP %s.',
                PHP_VERSION
            );
        }

        // Check WordPress version (only if WordPress is loaded)
        if (function_exists('get_bloginfo')) {
            if (version_compare(get_bloginfo('version'), '6.4', '<')) {
                $errors[] = sprintf(
                    'CloudXM NFe requires WordPress 6.4 or higher. You are running WordPress %s.',
                    get_bloginfo('version')
                );
            }
        }

        // WooCommerce check removed — plugin relies on WordPress activation system

        // Display errors if any (only if WordPress is loaded)
        if (!empty($errors) && function_exists('add_action')) {
            foreach ($errors as $error) {
                add_action('admin_notices', function () use ($error) {
                    echo '<div class="notice notice-error"><p>' . esc_html($error) . '</p></div>';
                });
            }
            return false;
        }

        return true;
    }

    /**
     * Register service providers
     */
    private function registerServiceProviders(): void
    {
        if ($this->serviceProvidersRegistered) {
            return;
        }

        // Common SDK binding for container contract.
        $this->container->singleton(\CloudXM\SDK\Contracts\ContainerInterface::class, fn() => $this->container);

        // Bind ConfigurationInterface so providers can resolve it.
        $this->container->singleton(\CloudXM\SDK\Contracts\ConfigurationInterface::class, fn() => $this->config);

        $this->container->singleton(UpdateServiceProvider::class, function ($c) {
            return new UpdateServiceProvider(
                $c->get(\CloudXM\SDK\Contracts\ConfigurationInterface::class),
                UpdateService::class
            );
        });

        $providers = $this->getProviders();

        foreach ($providers as $providerClass) {
            if (!class_exists($providerClass)) {
                continue;
            }

            // Skip providers already explicitly registered above
            if ($this->container->has($providerClass)) {
                if (method_exists($providerClass, 'register')) {
                    $provider = $this->container->get($providerClass);
                    $provider->register();
                }
                continue;
            }

            // Register provider class in container first
            $this->container->singleton($providerClass, function () use ($providerClass) {
                return new $providerClass($this->container);
            });
            
            if (method_exists($providerClass, 'register')) {
                $provider = $this->container->get($providerClass);
                $provider->register();
            }
        }

        $this->serviceProvidersRegistered = true;
    }

    /**
     * Boot service providers
     */
    private function bootServiceProviders(): void
    {
        $providers = $this->getProviders();

        foreach ($providers as $providerClass) {
            if (!class_exists($providerClass)) {
                continue;
            }

            $provider = $this->container->get($providerClass);
            
            if (method_exists($provider, 'boot')) {
                $provider->boot();
            }
        }
    }

    /**
     * Run migrations when plugin version changes.
     * Also triggers on activation since version option doesn't exist yet.
     */
    private function checkPluginVersion(): void
    {
        $runner = new \CloudXM\SDK\Persistence\MigrationRunner($this->config);
        $runner->runMigrationsIfVersionChanged('nfe_last_version', $this->config->getVersion());
    }
}
