<?php

declare(strict_types=1);

namespace Tests\Performance\Benchmarks;

use App\Framework\Performance\Contracts\PerformanceCollectorInterface;
use App\Framework\Performance\PerformanceCategory;
use App\Framework\Database\EntityManager;
use App\Framework\Database\QueryBuilder;
use Tests\Performance\PerformanceTestCase;
use Tests\Performance\PerformanceBenchmarkResult;

/**
 * Performance benchmarks for database operations
 *
 * Tests database performance including:
 * - Query execution speed
 * - Bulk operations
 * - Transaction performance
 * - N+1 query prevention
 */
final readonly class DatabaseBenchmark extends PerformanceTestCase
{
    public function __construct(
        PerformanceCollectorInterface $collector,
        private EntityManager $entityManager,
        private QueryBuilder $queryBuilder
    ) {
        parent::__construct($collector);
    }

    /**
     * Benchmark simple SELECT query
     */
    public function benchmarkSimpleSelect(): PerformanceBenchmarkResult
    {
        $result = $this->benchmark(
            operation: fn() => $this->queryBuilder
                ->select('*')
                ->from('users')
                ->where('id', '=', 1)
                ->first(),
            iterations: 1000,
            name: 'Simple SELECT Query'
        );

        // Simple queries should be very fast
        $this->assertPerformanceThreshold($result, maxAvgTimeMs: 1.0);

        $this->recordBenchmark($result, PerformanceCategory::DATABASE);

        return $result;
    }

    /**
     * Benchmark SELECT with JOIN
     */
    public function benchmarkSelectWithJoin(): PerformanceBenchmarkResult
    {
        $result = $this->benchmark(
            operation: fn() => $this->queryBuilder
                ->select('users.*, profiles.bio')
                ->from('users')
                ->join('profiles', 'users.id', '=', 'profiles.user_id')
                ->where('users.active', '=', true)
                ->limit(10)
                ->get(),
            iterations: 1000,
            name: 'SELECT with JOIN'
        );

        $this->assertPerformanceThreshold($result, maxAvgTimeMs: 5.0);

        $this->recordBenchmark($result, PerformanceCategory::DATABASE);

        return $result;
    }

    /**
     * Benchmark bulk INSERT operations
     */
    public function benchmarkBulkInsert(): PerformanceBenchmarkResult
    {
        $records = [];
        for ($i = 0; $i < 100; $i++) {
            $records[] = [
                'name' => "Test User {$i}",
                'email' => "test{$i}@example.com",
                'created_at' => date('Y-m-d H:i:s')
            ];
        }

        $result = $this->benchmark(
            operation: function() use ($records) {
                $this->entityManager->beginTransaction();
                try {
                    foreach ($records as $record) {
                        $this->queryBuilder
                            ->table('test_users')
                            ->insert($record);
                    }
                    $this->entityManager->commit();
                } catch (\Exception $e) {
                    $this->entityManager->rollback();
                    throw $e;
                }
            },
            iterations: 10,
            name: 'Bulk INSERT (100 records)'
        );

        // Bulk operations should be efficient
        $this->assertPerformanceThreshold(
            $result,
            maxAvgTimeMs: 50.0,
            maxMemoryBytes: 10 * 1024 * 1024 // 10MB
        );

        $this->recordBenchmark($result, PerformanceCategory::DATABASE);

        return $result;
    }

    /**
     * Benchmark transaction performance
     */
    public function benchmarkTransaction(): PerformanceBenchmarkResult
    {
        $result = $this->benchmark(
            operation: function() {
                $this->entityManager->beginTransaction();
                try {
                    $this->queryBuilder
                        ->table('users')
                        ->where('id', '=', 1)
                        ->update(['updated_at' => date('Y-m-d H:i:s')]);

                    $this->queryBuilder
                        ->table('audit_log')
                        ->insert([
                            'action' => 'user_updated',
                            'user_id' => 1,
                            'timestamp' => date('Y-m-d H:i:s')
                        ]);

                    $this->entityManager->commit();
                } catch (\Exception $e) {
                    $this->entityManager->rollback();
                    throw $e;
                }
            },
            iterations: 500,
            name: 'Transaction (2 queries)'
        );

        $this->assertPerformanceThreshold($result, maxAvgTimeMs: 10.0);

        $this->recordBenchmark($result, PerformanceCategory::DATABASE);

        return $result;
    }

    /**
     * Benchmark aggregate query (COUNT, AVG, SUM)
     */
    public function benchmarkAggregateQuery(): PerformanceBenchmarkResult
    {
        $result = $this->benchmark(
            operation: fn() => $this->queryBuilder
                ->select('COUNT(*) as total', 'AVG(age) as avg_age')
                ->from('users')
                ->where('active', '=', true)
                ->first(),
            iterations: 1000,
            name: 'Aggregate Query'
        );

        $this->assertPerformanceThreshold($result, maxAvgTimeMs: 2.0);

        $this->recordBenchmark($result, PerformanceCategory::DATABASE);

        return $result;
    }

    /**
     * Benchmark complex WHERE conditions
     */
    public function benchmarkComplexWhere(): PerformanceBenchmarkResult
    {
        $result = $this->benchmark(
            operation: fn() => $this->queryBuilder
                ->select('*')
                ->from('users')
                ->where('active', '=', true)
                ->where('age', '>=', 18)
                ->where('email', 'LIKE', '%@example.com')
                ->orWhere('role', '=', 'admin')
                ->orderBy('created_at', 'DESC')
                ->limit(20)
                ->get(),
            iterations: 1000,
            name: 'Complex WHERE Query'
        );

        $this->assertPerformanceThreshold($result, maxAvgTimeMs: 5.0);

        $this->recordBenchmark($result, PerformanceCategory::DATABASE);

        return $result;
    }

    /**
     * Run all database benchmarks and return summary
     */
    public function runAllBenchmarks(): array
    {
        return [
            'simple_select' => $this->benchmarkSimpleSelect(),
            'select_with_join' => $this->benchmarkSelectWithJoin(),
            'bulk_insert' => $this->benchmarkBulkInsert(),
            'transaction' => $this->benchmarkTransaction(),
            'aggregate_query' => $this->benchmarkAggregateQuery(),
            'complex_where' => $this->benchmarkComplexWhere(),
        ];
    }
}
