<?php

use App\Services\ProjectDoctor;
use Illuminate\Support\Facades\Process;

it('reports host and project checks for a prepared project', function () {
    Process::fake([
        'command -v docker' => Process::result(output: '/usr/local/bin/docker'),
        'docker compose version' => Process::result(output: 'Docker Compose version v2.0.0'),
        'git flow version' => Process::result(output: '1.12.3'),
    ]);

    $projectDir = sys_get_temp_dir() . '/probots-doctor-' . bin2hex(random_bytes(5));
    mkdir($projectDir . '/theme', 0777, true);
    file_put_contents($projectDir . '/.env.example', '');
    file_put_contents($projectDir . '/docker-compose.yml', 'services: {}');
    file_put_contents($projectDir . '/theme/functions.php', '<?php');
    file_put_contents($projectDir . '/theme/package.json', '{}');
    file_put_contents($projectDir . '/theme/composer.json', json_encode([
        'repositories' => [
            ['type' => 'composer', 'url' => 'https://packages.probots.io/'],
        ],
    ]));
    file_put_contents($projectDir . '/.env', implode("\n", [
        'VIRTUAL_HOST=test.prbts',
        'PORT_WP=8877',
        'PORT_DEV=8878',
        'DB_NAME=test',
        'DB_HOST=host.db.docker.internal:7689',
        'THEME_NAME=theme',
    ]));

    $homeDir = $projectDir . '/home';
    mkdir($homeDir . '/.composer', 0777, true);
    file_put_contents($homeDir . '/.composer/auth.json', '{}');
    putenv('HOME=' . $homeDir);

    $doctor = new ProjectDoctor();
    $results = array_merge($doctor->checkHost(), $doctor->checkProject($projectDir));

    expect($doctor->hasErrors($results))->toBeFalse();
    expect(containsDoctorResult($results, 'Composer access', 'ok'))->toBeTrue();
    expect(containsDoctorResult($results, 'PORT_WP', 'ok'))->toBeTrue();

    cleanupDoctorFixture($projectDir);
});

it('returns an error when a required starter file is missing', function () {
    Process::fake([
        'command -v docker' => Process::result(output: '/usr/local/bin/docker'),
        'docker compose version' => Process::result(output: 'Docker Compose version v2.0.0'),
        'git flow version' => Process::result(output: '1.12.3'),
    ]);

    $projectDir = sys_get_temp_dir() . '/probots-doctor-missing-' . bin2hex(random_bytes(5));
    mkdir($projectDir, 0777, true);

    $doctor = new ProjectDoctor();
    $results = $doctor->checkProject($projectDir);

    expect($doctor->hasErrors($results))->toBeTrue();
    expect(containsDoctorResult($results, 'theme/functions.php', 'error'))->toBeTrue();

    rmdir($projectDir);
});

it('reports host requirement failures separately', function () {
    Process::fake([
        'command -v docker' => Process::result(exitCode: 1),
        'docker compose version' => Process::result(exitCode: 1),
        'git flow version' => Process::result(exitCode: 1),
    ]);

    $doctor = new ProjectDoctor();
    $results = $doctor->checkHost();

    expect($doctor->hasErrors($results))->toBeTrue();
    expect(containsDoctorResult($results, 'Docker', 'error'))->toBeTrue();
    expect(containsDoctorResult($results, 'git-flow', 'error'))->toBeTrue();
});

function cleanupDoctorFixture(string $projectDir): void
{
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($projectDir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST,
    );

    foreach ($iterator as $item) {
        $item->isDir() ? rmdir($item->getPathname()) : unlink($item->getPathname());
    }

    rmdir($projectDir);
}

function containsDoctorResult(array $results, string $label, string $status): bool
{
    foreach ($results as $result) {
        if ($result['label'] === $label && $result['status'] === $status) {
            return true;
        }
    }

    return false;
}
