<?php
/**
 * AI Provider Manager
 *
 * Manages AI providers registration, activation, and retrieval.
 * Singleton pattern for global access.
 *
 * @package FleekDash\AI\Core
 * @since 2.3.0
 */

namespace FleekDash\AI\Core;

defined('ABSPATH') || exit;

/**
 * Class AIProviderManager
 *
 * Central manager for all AI providers.
 */
class AIProviderManager
{
    /**
     * Singleton instance
     *
     * @var AIProviderManager|null
     */
    private static ?AIProviderManager $instance = null;

    /**
     * Registered providers
     *
     * @var array<string, AIProviderInterface>
     */
    private array $providers = [];

    /**
     * Active provider ID
     *
     * @var string|null
     */
    private ?string $activeProviderId = null;

    /**
     * Initialization flag
     *
     * @var bool
     */
    private bool $initialized = false;

    /**
     * Private constructor (singleton)
     */
    private function __construct()
    {
    }

    /**
     * Get singleton instance
     *
     * @return AIProviderManager
     */
    public static function getInstance(): AIProviderManager
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * Initialize the manager
     * Registers all built-in providers
     *
     * @return void
     */
    public function init(): void
    {
        if ($this->initialized) {
            return;
        }

        // Auto-register built-in providers
        $this->registerBuiltInProviders();

        // Load active provider ID from options
        // Default to no active provider until user explicitly enables one in settings.
        $this->activeProviderId = \get_option('fleekdash_ai_active_provider', '');

        $this->initialized = true;
    }

    /**
     * Register built-in providers
     *
     * @return void
     */
    private function registerBuiltInProviders(): void
    {
        // Register OpenAI provider
        // Load the class file if not already loaded
        $openai_provider_file = FLEEKDASH_PLUGIN_DIR . 'includes/AI/Providers/OpenAI/OpenAIProvider.php';
        if (file_exists($openai_provider_file) && !class_exists('\FleekDash\AI\Providers\OpenAI\OpenAIProvider')) {
            require_once $openai_provider_file;
        }

        if (class_exists('\FleekDash\AI\Providers\OpenAI\OpenAIProvider')) {
            $this->register(new \FleekDash\AI\Providers\OpenAI\OpenAIProvider());
        }

        // Future providers can be registered here:
        // if (class_exists('\FleekDash\AI\Providers\Claude\ClaudeProvider')) {
        //     $this->register(new \FleekDash\AI\Providers\Claude\ClaudeProvider());
        // }
    }

    /**
     * Register a provider
     *
     * @param AIProviderInterface $provider Provider instance
     * @return bool True on success
     */
    public function register(AIProviderInterface $provider): bool
    {
        $id = $provider->getId();

        if (empty($id)) {
            return false;
        }

        $this->providers[$id] = $provider;
        return true;
    }

    /**
     * Get active provider
     *
     * @return AIProviderInterface|null Active provider or null if none
     */
    public function getActiveProvider(): ?AIProviderInterface
    {
        if (!$this->initialized) {
            $this->init();
        }

        if (!$this->activeProviderId) {
            return null;
        }

        return $this->providers[$this->activeProviderId] ?? null;
    }

    /**
     * Get provider by ID
     *
     * @param string $id Provider ID
     * @return AIProviderInterface|null Provider or null if not found
     */
    public function getProvider(string $id): ?AIProviderInterface
    {
        if (!$this->initialized) {
            $this->init();
        }

        return $this->providers[$id] ?? null;
    }

    /**
     * Get all registered providers
     *
     * @return array<string, AIProviderInterface> All providers
     */
    public function getAllProviders(): array
    {
        if (!$this->initialized) {
            $this->init();
        }

        return $this->providers;
    }

    /**
     * Get all providers as array (for API responses)
     *
     * @return array Array of provider data
     */
    public function getAllProvidersData(): array
    {
        $providers = [];

        foreach ($this->getAllProviders() as $id => $provider) {
            $providers[] = [
                'id' => $id,
                'name' => $provider->getName(),
                'icon' => $provider->getIcon(),
                'description' => $provider->getDescription(),
                'is_configured' => $provider->isConfigured(),
                'is_active' => $id === $this->activeProviderId,
                'models' => $provider->getModels(),
                'settings_schema' => $provider->getSettingsSchema(),
                'settings' => $provider->getSettings(),
            ];
        }

        return $providers;
    }

    /**
     * Set active provider
     *
     * @param string $id Provider ID
     * @return bool True on success
     */
    public function setActiveProvider(string $id): bool
    {
        if (!$this->initialized) {
            $this->init();
        }

        if (!isset($this->providers[$id])) {
            return false;
        }

        $this->activeProviderId = $id;
        \update_option('fleekdash_ai_active_provider', $id);

        return true;
    }

    /**
     * Clear active provider (deactivate)
     *
     * @return bool True on success
     */
    public function clearActiveProvider(): bool
    {
        if (!$this->initialized) {
            $this->init();
        }

        $this->activeProviderId = null;
        \update_option('fleekdash_ai_active_provider', '');

        return true;
    }

    /**
     * Check if a provider is configured
     *
     * @param string $id Provider ID
     * @return bool True if configured
     */
    public function isProviderConfigured(string $id): bool
    {
        $provider = $this->getProvider($id);
        return $provider ? $provider->isConfigured() : false;
    }

    /**
     * Get active provider ID
     *
     * @return string|null Active provider ID
     */
    public function getActiveProviderId(): ?string
    {
        if (!$this->initialized) {
            $this->init();
        }

        return $this->activeProviderId;
    }
}
