<?php

namespace Tests\Feature;

use App\Services\InstallerService;
use Tests\TestCase;

/**
 * Covers the wizard's AJAX "Test connection" endpoint (InstallController::testDb).
 *
 * Note: InstallerService::isInstalled() always returns true when
 * app()->environment('testing') (see its docblock — the test suite manages
 * its own ephemeral DB per test and must never be redirected to /install).
 * That makes the "already installed" gate the only branch reachable without
 * a partial mock, so the success/failure/validation branches below swap in a
 * partial mock that reports not-installed, exactly like the real pre-install
 * request the browser QA (port 8002 + av_wizard_test) exercises for real.
 */
class InstallTestDbEndpointTest extends TestCase
{
    public function test_blocks_when_already_installed(): void
    {
        // Default testing-environment behavior: isInstalled() === true.
        $response = $this->postJson('/install/test-db', [
            'db_host' => '127.0.0.1',
            'db_port' => '3306',
            'db_database' => 'whatever',
            'db_username' => 'root',
            'db_password' => '',
        ]);

        $response->assertStatus(409);
        $response->assertJson(['ok' => false]);
    }

    public function test_returns_ok_true_on_successful_connection(): void
    {
        $this->partialMock(InstallerService::class, function ($mock) {
            $mock->shouldReceive('isInstalled')->andReturn(false);
            $mock->shouldReceive('testDatabaseConnection')
                ->once()
                ->andReturn(['ok' => true, 'message' => 'Connected successfully.']);
        });

        $response = $this->postJson('/install/test-db', [
            'db_host' => '127.0.0.1',
            'db_port' => '3306',
            'db_database' => 'av_wizard_test',
            'db_username' => 'root',
            'db_password' => '',
        ]);

        $response->assertOk();
        $response->assertJson(['ok' => true, 'message' => 'Connected successfully.']);
    }

    public function test_returns_ok_false_on_failed_connection(): void
    {
        $this->partialMock(InstallerService::class, function ($mock) {
            $mock->shouldReceive('isInstalled')->andReturn(false);
            $mock->shouldReceive('testDatabaseConnection')
                ->once()
                ->andReturn(['ok' => false, 'message' => 'Access denied — double-check the DB username/password.']);
        });

        $response = $this->postJson('/install/test-db', [
            'db_host' => '127.0.0.1',
            'db_port' => '3306',
            'db_database' => 'av_wizard_test',
            'db_username' => 'root',
            'db_password' => 'wrong-password',
        ]);

        $response->assertStatus(422);
        $response->assertJson(['ok' => false]);
        $response->assertJsonFragment(['message' => 'Access denied — double-check the DB username/password.']);
    }

    public function test_validates_required_fields(): void
    {
        $this->partialMock(InstallerService::class, function ($mock) {
            $mock->shouldReceive('isInstalled')->andReturn(false);
        });

        $response = $this->postJson('/install/test-db', [
            'db_host' => '',
            'db_port' => '',
            'db_database' => '',
            'db_username' => '',
        ]);

        $response->assertStatus(422);
        $response->assertJson(['ok' => false]);
        $response->assertJsonStructure(['ok', 'message']);
    }
}
