<?php

declare(strict_types=1);

use App\Framework\Database\Indexing\IndexMigrationGenerator;
use App\Framework\Database\Indexing\ValueObjects\IndexRecommendation;
use App\Framework\Database\Indexing\ValueObjects\IndexType;
use App\Framework\Database\Indexing\ValueObjects\RecommendationPriority;
use App\Framework\Database\PdoConnection;

describe('IndexMigrationGenerator', function () {
    beforeEach(function () {
        $pdo = new PDO('sqlite::memory:');
        $connection = new PdoConnection($pdo, 'sqlite');

        $this->generator = new IndexMigrationGenerator($connection);
    });

    it('generates migration for adding indexes', function () {
        $recommendations = [
            new IndexRecommendation(
                tableName: 'users',
                columns: ['email'],
                indexType: IndexType::BTREE,
                reason: 'Frequent WHERE email lookups',
                priority: RecommendationPriority::HIGH,
                estimatedSpeedup: 5.0,
                affectedQueries: 100
            ),
            new IndexRecommendation(
                tableName: 'users',
                columns: ['status', 'created_at'],
                indexType: IndexType::BTREE,
                reason: 'WHERE status + ORDER BY created_at',
                priority: RecommendationPriority::CRITICAL,
                estimatedSpeedup: 10.0,
                affectedQueries: 250
            )
        ];

        $migration = $this->generator->generateAddIndexMigration($recommendations, 'users');

        expect($migration)->toBeString();
        expect($migration)->toContain('extends Migration');
        expect($migration)->toContain('public function up(Schema $schema)');
        expect($migration)->toContain('public function down(Schema $schema)');
        expect($migration)->toContain('users');
        expect($migration)->toContain('$table->index');
    });

    it('generates migration for removing indexes', function () {
        $unusedIndexes = [
            [
                'index_name' => 'idx_users_old_column',
                'columns' => ['old_column']
            ],
            [
                'index_name' => 'idx_users_deprecated',
                'columns' => ['deprecated_field']
            ]
        ];

        $migration = $this->generator->generateRemoveIndexMigration($unusedIndexes, 'users');

        expect($migration)->toBeString();
        expect($migration)->toContain('extends Migration');
        expect($migration)->toContain('$table->dropIndex');
        expect($migration)->toContain('idx_users_old_column');
        expect($migration)->toContain('idx_users_deprecated');
    });

    it('generates optimization migration (add + remove)', function () {
        $toAdd = [
            new IndexRecommendation(
                tableName: 'orders',
                columns: ['customer_id', 'status'],
                indexType: IndexType::BTREE,
                reason: 'WHERE customer_id + status filter',
                priority: RecommendationPriority::HIGH,
                estimatedSpeedup: 8.0,
                affectedQueries: 150
            )
        ];

        $toRemove = [
            [
                'index_name' => 'idx_orders_unused',
                'columns' => ['unused_column']
            ]
        ];

        $migration = $this->generator->generateOptimizationMigration($toAdd, $toRemove, 'orders');

        expect($migration)->toBeString();
        expect($migration)->toContain('extends Migration');
        expect($migration)->toContain('$table->dropIndex(\'idx_orders_unused\')');
        expect($migration)->toContain('$table->index');
    });

    it('includes proper up/down migration methods', function () {
        $recommendations = [
            new IndexRecommendation(
                tableName: 'products',
                columns: ['category'],
                indexType: IndexType::BTREE,
                reason: 'Category filtering',
                priority: RecommendationPriority::MEDIUM,
                estimatedSpeedup: 3.0,
                affectedQueries: 50
            )
        ];

        $migration = $this->generator->generateAddIndexMigration($recommendations, 'products');

        // Check UP method
        expect($migration)->toContain('public function up(Schema $schema)');
        expect($migration)->toContain('$schema->table(\'products\'');

        // Check DOWN method (should reverse the UP actions)
        expect($migration)->toContain('public function down(Schema $schema)');
        expect($migration)->toContain('$table->dropIndex');
    });

    it('validates migration content structure', function () {
        $recommendations = [
            new IndexRecommendation(
                tableName: 'test_table',
                columns: ['test_column'],
                indexType: IndexType::BTREE,
                reason: 'Test',
                priority: RecommendationPriority::LOW,
                estimatedSpeedup: 1.5,
                affectedQueries: 10
            )
        ];

        $migration = $this->generator->generateAddIndexMigration($recommendations, 'test_table');

        // Validate required components
        expect($migration)->toContain('declare(strict_types=1)');
        expect($migration)->toContain('use App\Framework\Database\Migration\Migration');
        expect($migration)->toContain('use App\Framework\Database\Schema\Schema');
        expect($migration)->toContain('final class');
    });

    it('handles composite indexes correctly', function () {
        $recommendations = [
            new IndexRecommendation(
                tableName: 'posts',
                columns: ['author_id', 'published_at', 'status'],
                indexType: IndexType::BTREE,
                reason: 'Complex WHERE + ORDER BY',
                priority: RecommendationPriority::CRITICAL,
                estimatedSpeedup: 15.0,
                affectedQueries: 300
            )
        ];

        $migration = $this->generator->generateAddIndexMigration($recommendations, 'posts');

        expect($migration)->toContain('author_id');
        expect($migration)->toContain('published_at');
        expect($migration)->toContain('status');
    });
});
