<?php

declare(strict_types=1);

namespace Tests\Unit;

use App\Http\Controllers\Api\Pwa\PaymentController;
use Illuminate\Database\QueryException;
use PDOException;
use PHPUnit\Framework\Attributes\Test;
use ReflectionMethod;
use Tests\TestCase;

/**
 * #92 — La race de idempotencia (dos requests con la misma key) debe tratarse
 * como duplicado, no como error 500. La detección se basa en el código de error
 * MySQL 1062 (violación de clave única). Aquí se fija ese criterio.
 */
class PaymentDuplicateKeyDetectionTest extends TestCase
{
    private function detect(QueryException $e): bool
    {
        $controller = app(PaymentController::class);
        $method = new ReflectionMethod(PaymentController::class, 'isDuplicateKeyViolation');
        $method->setAccessible(true);

        return $method->invoke($controller, $e);
    }

    private function queryException(string $sqlState, int $driverCode): QueryException
    {
        $pdo = new PDOException('error simulado');
        $pdo->errorInfo = [$sqlState, $driverCode, 'mensaje'];

        return new QueryException('mysql', 'insert into payments ...', [], $pdo);
    }

    #[Test]
    public function duplicate_entry_1062_is_detected(): void
    {
        $this->assertTrue($this->detect($this->queryException('23000', 1062)));
    }

    #[Test]
    public function other_query_errors_are_not_treated_as_duplicate(): void
    {
        $this->assertFalse($this->detect($this->queryException('HY000', 1213))); // deadlock
        $this->assertFalse($this->detect($this->queryException('42S22', 1054))); // unknown column
    }
}
