<?php

namespace WPUltimateSecurity\UltimateSecurity\Bootstrap\Lifecycle\Migrations;

/**
 * Migration Registry
 *
 * Tracks which migrations have been completed and provides methods
 * to query pending migrations. Uses a dedicated WordPress option
 * to store completion status.
 *
 * ============================================================================
 * WHEN TO USE MIGRATIONS (RARE!)
 * ============================================================================
 *
 * Migrations are ONLY needed for:
 * - Moving data from one storage to another (e.g., wp_options to custom table)
 * - Renaming option keys (breaking changes)
 * - Transforming data format
 * - One-time data cleanup
 *
 * You DO NOT need migrations for:
 * - Adding new database tables → Just add to DatabaseSchema.php
 * - Adding new options → Just add to Utils::ultimate_security_get_default_options()
 *
 * The system automatically handles new tables (via dbDelta) and new options
 * (via mergeDefaultOptions) when you bump ULTIMATE_SECURITY_DB_VERSION.
 *
 * ============================================================================
 * HOW TO CREATE A MIGRATION
 * ============================================================================
 *
 * 1. Create a new class in this directory:
 *    php/src/Bootstrap/Lifecycle/Migrations/V{VERSION}_{Description}.php
 *
 * 2. Implement MigrationInterface:
 *    - version(): Return the DB version this migration applies to
 *    - description(): Human-readable description
 *    - up(): The migration logic (return true on success)
 *    - down(): Rollback logic (optional, can return true)
 *
 * 3. Register in getMigrations() below
 *
 * 4. Bump ULTIMATE_SECURITY_DB_VERSION in ultimate-security.php
 *
 * Example:
 * ```php
 * class V1020_MigrateActivityLogs implements MigrationInterface {
 *     public static function version(): string { return '1.0.20'; }
 *     public static function description(): string {
 *         return 'Move activity logs from wp_options to custom table';
 *     }
 *     public static function up(): bool {
 *         // Migration logic here
 *         return true;
 *     }
 *     public static function down(): bool { return true; }
 * }
 * ```
 */
class MigrationRegistry
{
    /**
     * Option key for storing completed migrations
     */
    private const OPTION_KEY = 'ultimate_security_completed_migrations';

    /**
     * Get list of all migration classes in order.
     *
     * Add new migrations here in chronological order.
     * Remember: Only use migrations for data transformations!
     *
     * @return array List of fully qualified migration class names
     */
    public static function getMigrations(): array
    {
        return [
            // Add data transformation migrations here as needed:
            // V1020_MigrateActivityLogs::class,
            // V1025_RenameOptionKeys::class,
        ];
    }

    /**
     * Check if a migration has been completed.
     *
     * @param string $migrationClass Fully qualified class name
     * @return bool True if migration has been completed
     */
    public static function isCompleted(string $migrationClass): bool
    {
        $completed = get_option(self::OPTION_KEY, []);
        return isset($completed[$migrationClass]);
    }

    /**
     * Mark a migration as completed.
     *
     * @param string $migrationClass Fully qualified class name
     * @return void
     */
    public static function markCompleted(string $migrationClass): void
    {
        $completed = get_option(self::OPTION_KEY, []);
        $completed[$migrationClass] = [
            'completed_at' => gmdate('Y-m-d H:i:s'),
            'version' => $migrationClass::version(),
        ];
        update_option(self::OPTION_KEY, $completed);
    }

    /**
     * Mark all migrations as completed.
     *
     * Used for fresh installations where migrations are not needed
     * (the database is already at the latest schema).
     *
     * @return void
     */
    public static function markAllCompleted(): void
    {
        $completed = get_option(self::OPTION_KEY, []);

        foreach (self::getMigrations() as $migrationClass) {
            if (!isset($completed[$migrationClass])) {
                $completed[$migrationClass] = [
                    'completed_at' => gmdate('Y-m-d H:i:s'),
                    'version' => $migrationClass::version(),
                    'skipped' => true, // Mark as skipped (fresh install)
                ];
            }
        }

        update_option(self::OPTION_KEY, $completed);
    }

    /**
     * Get pending migrations that need to run.
     *
     * Returns migrations that:
     * 1. Have not been marked as completed
     * 2. Have a version greater than the current DB version
     *
     * @param string $currentDbVersion Current database version
     * @return array List of migration class names that need to run
     */
    public static function getPendingMigrations(string $currentDbVersion): array
    {
        $pending = [];

        foreach (self::getMigrations() as $migrationClass) {
            // Skip if already completed
            if (self::isCompleted($migrationClass)) {
                continue;
            }

            // Only run migrations for versions newer than current
            if (version_compare($migrationClass::version(), $currentDbVersion, '>')) {
                $pending[] = $migrationClass;
            }
        }

        return $pending;
    }

    /**
     * Get all completed migrations.
     *
     * @return array Associative array of completed migrations with metadata
     */
    public static function getCompletedMigrations(): array
    {
        return get_option(self::OPTION_KEY, []);
    }

    /**
     * Reset migration tracking (use with caution).
     *
     * This will cause all migrations to run again on next update check.
     *
     * @return void
     */
    public static function reset(): void
    {
        delete_option(self::OPTION_KEY);
    }
}
