<?php
/**
 * Integration System Bootstrap
 *
 * Initializes the integration system and runs migrations.
 *
 * @package FleekDash\Integration
 * @since 2.3.0
 */

namespace FleekDash\Integration;

use FleekDash\Database\Migrations\CreateIntegrationSystemTables;
use FleekDash\Core\IntegrationManager;
use FleekDash\Services\IntegrationNormalizerService;

defined('ABSPATH') || exit;

// Load debug helpers
if (!function_exists('fleekdash_log_info')) {
    require_once FLEEKDASH_PLUGIN_DIR . 'includes/Core/debug-helpers.php';
}

class Bootstrap
{
    /**
     * Initialize integration system
     *
     * @return void
     */
    public static function init(): void
    {
        // Run migrations if needed
        \add_action('plugins_loaded', [self::class, 'runMigrations'], 5);
        \add_action('plugins_loaded', [self::class, 'syncInternalIntegrations'], 20);

        // Register cleanup cron
        \add_action('init', [self::class, 'scheduleCron']);
        \add_action('fleekdash_integration_cleanup', [self::class, 'cleanup']);

        // Register shutdown hook (save cache, cleanup)
        \add_action('shutdown', [self::class, 'shutdown']);
    }

    /**
     * Run database migrations
     *
     * @return void
     */
    public static function runMigrations(): void
    {
        if (!CreateIntegrationSystemTables::needsMigration()) {
            return;
        }

        // Use a lock to prevent concurrent migrations from multiple requests
        $lock_key = 'fleekdash_integration_migration_lock';
        if (\get_transient($lock_key)) {
            return;
        }

        // Set lock for 60 seconds
        \set_transient($lock_key, true, 60);

        try {
            CreateIntegrationSystemTables::migrate();

            fleekdash_log_info('[FleekDash Integration] Database migration completed successfully');
        } catch (\Exception $e) {
            fleekdash_log_error('[FleekDash Integration] Migration error: ' . $e->getMessage());
        } finally {
            \delete_transient($lock_key);
        }
    }

    /**
     * Sync filesystem integrations into the Registry so the Hub can list and configure them.
     */
    public static function syncInternalIntegrations(): void
    {
        if (!class_exists(IntegrationManager::class)) {
            return;
        }

        try {
            foreach (IntegrationManager::getInstance()->discover() as $id => $integration) {
                $manifest = self::buildInternalManifest((string) $id, $integration);

                if (Registry::get((string) $id)) {
                    self::updateInternalRegistryRow((string) $id, $manifest, $integration);
                    continue;
                }

                $result = Registry::register($manifest);
                if (empty($result['success'])) {
                    fleekdash_log_error(sprintf(
                        '[FleekDash Integration] Failed to register internal integration %s: %s',
                        $id,
                        implode(', ', $result['errors'] ?? ['Unknown error'])
                    ));
                }
            }
        } catch (\Throwable $e) {
            fleekdash_log_error('[FleekDash Integration] Internal sync failed: ' . $e->getMessage());
        }
    }

    /**
     * @param array<string, mixed> $integration
     * @return array<string, mixed>
     */
    private static function buildInternalManifest(string $id, array $integration): array
    {
        $config = is_array($integration['config'] ?? null) ? $integration['config'] : [];
        $source = ($integration['mode'] ?? '') === 'mu'
            ? IntegrationNormalizerService::SOURCE_MU_PLUGIN
            : IntegrationNormalizerService::SOURCE_INTERNAL;
        $icon = (string) ($config['icon'] ?? 'package');

        if (!ManifestValidator::isIconAllowed($icon)) {
            $icon = 'package';
        }

        return [
            'integration_id' => $id,
            'name' => $config['name'] ?? $integration['name'] ?? $id,
            'description' => $config['description'] ?? $integration['description'] ?? '',
            'version' => $config['version'] ?? $integration['version'] ?? '1.0.0',
            'author' => $config['author'] ?? 'FleekDash',
            'author_uri' => $config['author_uri'] ?? '',
            'integration_type' => $source === IntegrationNormalizerService::SOURCE_MU_PLUGIN ? 'mu-plugin' : 'internal',
            'plugin_file' => $config['plugin_file'] ?? "fleekdash-internal/{$id}.php",
            'icon' => $icon,
            'category' => $config['category'] ?? $integration['category'] ?? 'plugin',
            'source' => $source,
            'source_label' => IntegrationNormalizerService::sourceLabel($source),
            'settings_schema' => IntegrationNormalizerService::settingsSchema($config['settings_schema'] ?? ($config['settings'] ?? [])),
            'feature_key' => $config['feature_key'] ?? null,
            'license_required' => !empty($config['license_required']),
            'required_tier' => $config['required_tier'] ?? null,
            'allowed_roles' => IntegrationNormalizerService::roles($config['allowed_roles'] ?? null),
            'mode' => $config['mode'] ?? null,
            'preview_link' => $config['preview_link'] ?? null,
            'roadmap_link' => $config['roadmap_link'] ?? null,
            'tags' => $config['tags'] ?? [],
        ];
    }

    /**
     * @param array<string, mixed> $manifest
     * @param array<string, mixed> $integration
     */
    private static function updateInternalRegistryRow(string $id, array $manifest, array $integration): void
    {
        global $wpdb;

        $wpdb->update(
            $wpdb->prefix . 'fleekdash_integration_registry',
            [
                'name' => $manifest['name'],
                'description' => $manifest['description'],
                'version' => $manifest['version'],
                'author' => $manifest['author'],
                'author_uri' => $manifest['author_uri'],
                'integration_type' => $manifest['integration_type'],
                'plugin_file' => $manifest['plugin_file'],
                'icon' => $manifest['icon'],
                'category' => $manifest['category'],
                'source' => $manifest['source'],
                'source_label' => $manifest['source_label'],
                'manifest' => \wp_json_encode($manifest),
                'manifest_hash' => hash('sha256', \wp_json_encode($manifest)),
                'settings_schema' => \wp_json_encode($manifest['settings_schema'] ?? null),
                'allowed_roles' => \wp_json_encode($manifest['allowed_roles'] ?? null),
                'feature_key' => $manifest['feature_key'] ?? null,
                'license_required' => !empty($manifest['license_required']) ? 1 : 0,
                'required_tier' => $manifest['required_tier'] ?? null,
                'is_available' => !empty($integration['is_available']) ? 1 : 0,
                'is_active' => !empty($integration['is_active']) ? 1 : 0,
            ],
            ['integration_id' => $id],
            [
                '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s',
                '%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d',
            ],
            ['%s']
        );
    }

    /**
     * Schedule cleanup cron
     *
     * @return void
     */
    public static function scheduleCron(): void
    {
        if (!wp_next_scheduled('fleekdash_integration_cleanup')) {
            \wp_schedule_event(time(), 'daily', 'fleekdash_integration_cleanup');
        }
    }

    /**
     * Cleanup expired data
     *
     * @return void
     */
    public static function cleanup(): void
    {
        // Clean expired nonces
        MessageBusSecurity::cleanExpiredNonces();

        // Clean old backups (keep last 30 days)
        self::cleanOldBackups(30);
    }

    /**
     * Clean old backups
     *
     * @param int $days_to_keep Days to keep backups
     * @return int Number of backups deleted
     */
    private static function cleanOldBackups(int $days_to_keep): int
    {
        $backup_dir = Registry::BACKUP_DIR;

        if (!is_dir($backup_dir)) {
            return 0;
        }

        $files = glob($backup_dir . '*.json');
        $cutoff_time = time() - ($days_to_keep * DAY_IN_SECONDS);
        $deleted = 0;

        foreach ($files as $file) {
            if (filemtime($file) < $cutoff_time && unlink($file)) {
                $deleted++;
            }
        }

        if ($deleted > 0) {
            fleekdash_log_info(sprintf(
                '[FleekDash Integration] Cleaned %d old backup(s)',
                $deleted
            ));
        }

        return $deleted;
    }

    /**
     * Shutdown hook
     *
     * @return void
     */
    public static function shutdown(): void
    {
        // Flush route cache if needed
        // (automatically handled by WP object cache)
    }

    /**
     * Get system status
     *
     * For debugging and monitoring.
     *
     * @return array System status
     */
    public static function getStatus(): array
    {
        $tables_status = CreateIntegrationSystemTables::verifyTables();

        return [
            'database' => [
                'version' => \get_option('fleekdash_integration_db_version', 'not installed'),
                'migration_date' => \get_option('fleekdash_integration_migration_date', 'never'),
                'tables' => $tables_status,
            ],
            'integrations' => [
                'total' => count(Registry::getAll(false)),
                'active' => count(Registry::getAll(true)),
            ],
            'routes' => [
                'total' => count(RouteManager::getAll(false, false)),
                'active' => count(RouteManager::getAll(true, false)),
            ],
            'backups' => [
                'count' => count(Registry::listBackups()),
                'directory' => Registry::BACKUP_DIR,
            ],
        ];
    }
}
