<?php
/**
 * BookiFlex Core
 *
 * @package    BookiFlex
 * @subpackage Core
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */


declare(strict_types=1);
namespace BookiFlex\Core\Trait;

use BookiFlex\Core\Contract\ExtensionInterface;
use Psr\Log\LoggerInterface;

defined( 'ABSPATH' ) || exit;

trait ExtensionsTrait
{
    protected array $loadedExtensions = [];

    /**
     * Load all extensions
     */
    protected function loadExtensions(): void
    {
        $this->loadConfiguredExtensions();

        // Give other developers to register extensions
        do_action('bookiflex_load_extensions', $this);
    }

    /**
     * Load extensions from configuration array in specific order
     */
    protected function loadConfiguredExtensions(): void
    {
        $config = $this->getExtensionsConfig();

        foreach ($config as $extensionName) {
            $this->loadExtension($extensionName);
        }
    }

    /**
     * Get extensions configuration
     * Must be implemented by child classes
     *
     * @return array List of extension names to load in order
     */
    abstract protected function getExtensionsConfig(): array;

    /**
     * Get logger instance
     * Must be implemented by class using this trait
     */
    abstract public function getLogger(): ?LoggerInterface;

    /**
     * Load single extension by name
     */
    protected function loadExtension(string $extensionName): void
    {
        if ($this->isExtensionLoaded($extensionName)) {
            return;
        }

//        $extensionPath = $this->pluginDir . 'src/Extensions/' . $extensionName;
//        $extensionMainFile = $extensionPath . '/' . $extensionName . '.php';
//
//        if (!file_exists($extensionMainFile)) {
//            error_log("BookiFlex: Extension not found: $extensionName at $extensionMainFile");
//            return;
//        }
//
//        require_once $extensionMainFile;
        $this->initializeExtension($extensionName);
    }

    /**
     * Initialize a single extension
     */
    protected function initializeExtension(string $extensionName): void
    {
        // Unified namespace for all extensions
        $className = 'BookiFlex\\Extensions\\' . $extensionName . '\\' . $extensionName;

        if (!class_exists($className)) {
            // Try alternative class name
            $className = 'BookiFlex\\Extensions\\' . $extensionName . '\\' . $extensionName . 'Extension';
        }

        if (class_exists($className)) {
            try {
                $extension = new $className();

                if ($extension instanceof ExtensionInterface) {
                    if ($extension->isCompatible($this->version)) {
                        $extension->init($this);
                        $this->registerExtension($extensionName, $extension);

                        do_action('bookiflex_extension_loaded', $extensionName, $extension);
                    } else {
                        $this->getLogger()?->warning(
                            'BookiFlex: Extension is not compatible with plugin version',
                            ['extension' => $extensionName, 'version' => $this->version]
                        );
                    }
                }
            } catch (\Exception $e) {
                $this->getLogger()?->error(
                    'BookiFlex: Failed to load extension',
                    ['extension' => $extensionName, 'error' => $e->getMessage()]
                );
            }
        }
    }

    /**
     * Register loaded extension
     */
    protected function registerExtension(string $name, ExtensionInterface $extension): void
    {
        $this->loadedExtensions[$name] = $extension;
    }

    /**
     * Check if extension is already loaded
     */
    protected function isExtensionLoaded(string $name): bool
    {
        return isset($this->loadedExtensions[$name]);
    }

    /**
     * Get loaded extension
     */
    public function getExtension(string $name): ?ExtensionInterface
    {
        return $this->loadedExtensions[$name] ?? null;
    }

    /**
     * Get all loaded extensions
     */
    public function getLoadedExtensions(): array
    {
        return $this->loadedExtensions;
    }
}
