<?php

namespace FleekDash\Integrations\Core;

defined('ABSPATH') || exit;

/**
 * High-performance Integration Discovery Engine
 *
 * Discovers and caches integrations efficiently
 */
class DiscoveryEngine
{
    private Container $container;
    private Cache $cache;
    private EventDispatcher $events;
    private string $integrationsPath;
    private array $discovered = [];

    public function __construct(Container $container, Cache $cache, EventDispatcher $events)
    {
        $this->container = $container;
        $this->cache = $cache;
        $this->events = $events;
        $this->integrationsPath = FLEEKDASH_PLUGIN_DIR . 'integrations';
    }

    /**
     * Discover all available integrations
     */
    public function discover(): array
    {
        // Try cache first
        if ($this->cache->isDiscoveryValid()) {
            $cached = $this->cache->getDiscovery();
            if ($cached !== null) {
                return $cached;
            }
        }

        // Perform fresh discovery
        $integrations = $this->performDiscovery();

        // Cache results
        $this->cache->cacheDiscovery($integrations);

        return $integrations;
    }

    /**
     * Perform actual discovery
     */
    private function performDiscovery(): array
    {
        $integrations = [];
        $dirs = glob($this->integrationsPath . '/*', GLOB_ONLYDIR);

        foreach ($dirs as $dir) {
            if (basename($dir) === 'Core')
                continue;

            $integration = $this->scanIntegration($dir);
            if ($integration) {
                $integrations[$integration['id']] = $integration;
            }
        }

        return $integrations;
    }

    /**
     * Scan single integration
     */
    private function scanIntegration(string $path): ?array
    {
        $configFile = $path . '/config.json';

        if (!file_exists($configFile)) {
            return null;
        }

        $config = json_decode(file_get_contents($configFile), true);
        if (!$config || empty($config['id'])) {
            return null;
        }

        return [
            'id' => $config['id'],
            'name' => $config['name'] ?? '',
            'description' => $config['description'] ?? '',
            'version' => $config['version'] ?? '1.0.0',
            'category' => $config['category'] ?? 'plugin',
            'requires' => $config['requires'] ?? [],
            'path' => $path,
            'config' => $config
        ];
    }

    /**
     * Load integration lazily
     */
    public function loadIntegration(string $integrationId): ?object
    {
        $integrations = $this->discover();

        if (!isset($integrations[$integrationId])) {
            return null;
        }

        $integration = $integrations[$integrationId];

        // Check if Integration.php exists
        $integrationFile = $integration['path'] . '/Integration.php';
        if (!file_exists($integrationFile)) {
            return null;
        }

        // Load the integration file
        require_once $integrationFile;

        // Get class name
        $className = $this->getIntegrationClassName($integrationId);

        // Check if class exists
        if (!class_exists($className)) {
            return null;
        }

        // Create instance with integration directory path
        try {
            return new $className($integration['path']);
        } catch (\Exception $e) {
            error_log("Error loading integration {$integrationId}: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Get integration class name
     */
    private function getIntegrationClassName(string $integrationId): string
    {
        // First try to detect the actual namespace from the Integration.php file
        $integrationPath = FLEEKDASH_PLUGIN_DIR . "integrations/{$integrationId}";
        $integrationFile = $integrationPath . '/Integration.php';

        if (file_exists($integrationFile)) {
            $content = file_get_contents($integrationFile);
            if ($content !== false) {
                // Look for namespace declaration
                if (preg_match('/namespace\s+([^;]+);/', $content, $matches)) {
                    $namespace = trim($matches[1]);
                    // Extract the class name from the namespace
                    // e.g., "FleekDash\Integrations\OpenAI" -> "OpenAI"
                    $parts = explode('\\', $namespace);
                    $actualNamespace = end($parts);

                    // Use the actual namespace case from the file
                    return "FleekDash\\Integrations\\{$actualNamespace}\\Integration";
                }
            }
        }

        // Fallback to the original method if namespace detection fails
        $className = str_replace(' ', '', ucwords(str_replace('-', ' ', $integrationId)));
        return "FleekDash\\Integrations\\{$className}\\Integration";
    }

    /**
     * Check integration requirements
     */
    public function checkRequirements(array $requires): bool
    {
        // Check PHP version
        if (isset($requires['php']) && version_compare(PHP_VERSION, $requires['php'], '<')) {
            return false;
        }

        // Check WordPress version
        if (isset($requires['wordpress']) && version_compare(get_bloginfo('version'), $requires['wordpress'], '<')) {
            return false;
        }

        // Check plugins
        if (isset($requires['plugins'])) {
            foreach ($requires['plugins'] as $plugin) {
                if (!is_plugin_active($plugin)) {
                    return false;
                }
            }
        }

        // Check theme
        if (isset($requires['theme'])) {
            $theme = wp_get_theme();
            if (
                $theme->get('TextDomain') !== $requires['theme'] &&
                $theme->get('Template') !== $requires['theme']
            ) {
                return false;
            }
        }

        return true;
    }

    /**
     * Check if integration is available
     */
    public function isAvailable(string $integrationId): bool
    {
        $integrations = $this->discover();

        if (!isset($integrations[$integrationId])) {
            return false;
        }

        $integration = $integrations[$integrationId];

        return $this->checkRequirements($integration['requires'] ?? []);
    }

    /**
     * Get integrations by category
     */
    public function getByCategory(string $category): array
    {
        $integrations = $this->discover();

        return array_filter($integrations, function ($integration) use ($category) {
            return ($integration['category'] ?? 'plugin') === $category;
        });
    }

    /**
     * Search integrations
     */
    public function search(string $query): array
    {
        $integrations = $this->discover();
        $query = strtolower($query);

        return array_filter($integrations, function ($integration) use ($query) {
            return strpos(strtolower($integration['name']), $query) !== false ||
                strpos(strtolower($integration['description'] ?? ''), $query) !== false;
        });
    }

    /**
     * Force rediscovery (clear cache)
     */
    public function rediscover(): array
    {
        $this->cache->delete('discovered_integrations');
        $this->cache->delete('discovery_timestamp');

        return $this->discover();
    }

    /**
     * Get discovery statistics
     */
    public function getStats(): array
    {
        $integrations = $this->discover();
        $stats = [
            'total' => count($integrations),
            'by_category' => [],
            'available' => 0,
            'requires_plugins' => 0,
            'requires_themes' => 0
        ];

        foreach ($integrations as $integration) {
            $category = $integration['category'] ?? 'plugin';
            $stats['by_category'][$category] = ($stats['by_category'][$category] ?? 0) + 1;

            if ($this->isAvailable($integration['id'])) {
                $stats['available']++;
            }

            if (!empty($integration['requires']['plugins'])) {
                $stats['requires_plugins']++;
            }

            if (!empty($integration['requires']['theme'])) {
                $stats['requires_themes']++;
            }
        }

        return $stats;
    }
}
