<?php

namespace WPUltimateSecurity\UltimateSecurity\Bootstrap\Lifecycle\Migrations;

/**
 * Migration Runner
 *
 * Executes pending migrations in order and tracks their completion.
 * Includes error handling and logging for debugging migration issues.
 */
class MigrationRunner
{
    /**
     * Flag to prevent concurrent runs within the same request
     */
    private static bool $isRunning = false;

    /**
     * Run all pending migrations.
     *
     * Migrations are executed in the order they're registered in MigrationRegistry.
     * If a migration fails, execution stops and remaining migrations are skipped.
     *
     * @return array Results of migration execution
     */
    public static function run(): array
    {
        // Prevent concurrent runs within same request
        if (self::$isRunning) {
            return [
                'status' => 'already_running',
                'message' => 'Migration runner is already executing',
            ];
        }

        self::$isRunning = true;
        $results = [
            'status' => 'success',
            'migrations' => [],
            'errors' => [],
        ];

        try {
            $currentVersion = get_option('ultimate_security_db_version', '0');
            $pendingMigrations = MigrationRegistry::getPendingMigrations($currentVersion);

            if (empty($pendingMigrations)) {
                $results['status'] = 'no_pending_migrations';
                $results['message'] = 'No pending migrations to run';
                self::$isRunning = false;
                return $results;
            }

            foreach ($pendingMigrations as $migrationClass) {
                $migrationResult = self::executeMigration($migrationClass);
                $results['migrations'][$migrationClass] = $migrationResult;

                if ($migrationResult['status'] !== 'success') {
                    $results['status'] = 'partial_failure';
                    $results['errors'][] = [
                        'migration' => $migrationClass,
                        'error' => $migrationResult['message'] ?? 'Unknown error',
                    ];
                    // Stop on first failure
                    break;
                }
            }
        } catch (\Exception $e) {
            $results['status'] = 'error';
            $results['errors'][] = [
                'migration' => 'runner',
                'error' => $e->getMessage(),
            ];
            self::logError('Migration runner exception: ' . $e->getMessage());
        } finally {
            self::$isRunning = false;
        }

        return $results;
    }

    /**
     * Execute a single migration.
     *
     * @param string $migrationClass Fully qualified migration class name
     * @return array Result of migration execution
     */
    private static function executeMigration(string $migrationClass): array
    {
        $result = [
            'status' => 'pending',
            'version' => '',
            'description' => '',
        ];

        try {
            // Verify class exists and implements interface
            if (!class_exists($migrationClass)) {
                throw new \RuntimeException("Migration class not found: {$migrationClass}");
            }

            if (!in_array(MigrationInterface::class, class_implements($migrationClass), true)) {
                throw new \RuntimeException("Migration class must implement MigrationInterface: {$migrationClass}");
            }

            $result['version'] = $migrationClass::version();
            $result['description'] = $migrationClass::description();

            // Execute the migration
            $success = $migrationClass::up();

            if ($success) {
                MigrationRegistry::markCompleted($migrationClass);
                $result['status'] = 'success';
                $result['message'] = 'Migration completed successfully';

                self::logInfo("Migration completed: {$migrationClass} (v{$result['version']})");
            } else {
                $result['status'] = 'failed';
                $result['message'] = 'Migration returned false';

                self::logError("Migration failed: {$migrationClass} (v{$result['version']})");
            }
        } catch (\Exception $e) {
            $result['status'] = 'error';
            $result['message'] = $e->getMessage();

            self::logError("Migration error in {$migrationClass}: " . $e->getMessage());
        }

        return $result;
    }

    /**
     * Log an informational message.
     *
     * @param string $message Message to log
     * @return void
     */
    private static function logInfo(string $message): void
    {
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log('[Ultimate Security] ' . $message);
        }
    }

    /**
     * Log an error message.
     *
     * @param string $message Error message to log
     * @return void
     */
    private static function logError(string $message): void
    {
        error_log('[Ultimate Security ERROR] ' . $message);
    }

    /**
     * Check if the runner is currently executing.
     *
     * @return bool True if migrations are currently running
     */
    public static function isRunning(): bool
    {
        return self::$isRunning;
    }
}
