<?php

namespace MintyPHP\Tests\Console;

use MintyPHP\Console\Commands\DoctorCommand;
use MintyPHP\Console\Runner\Doctor\DoctorRunnerInterface;
use PHPUnit\Framework\TestCase;

final class DoctorCommandTest extends TestCase
{
    public function testDoctorJsonFormatOutputsStableShapeAndExitCode(): void
    {
        $runner = new FakeDoctorRunner([
            'command' => 'doctor',
            'status' => 'fail',
            'checks' => [
                ['status' => 'ok', 'name' => 'A', 'message' => 'B'],
            ],
            'ok_count' => 1,
            'warn_count' => 0,
            'fail_count' => 1,
            'exit_code' => 1,
            'duration_ms' => 12,
        ]);

        $command = new DoctorCommand($runner);

        ob_start();
        $exitCode = $command->execute([], ['format' => 'json']);
        $output = (string) ob_get_clean();

        self::assertSame(1, $exitCode);

        /** @var array<string, mixed> $decoded */
        $decoded = json_decode($output, true, 512, JSON_THROW_ON_ERROR);
        self::assertSame('doctor', $decoded['command']);
        self::assertSame('fail', $decoded['status']);
        self::assertSame(1, $decoded['exit_code']);
        self::assertSame(12, $decoded['duration_ms']);
        self::assertArrayHasKey('checks', $decoded);
        self::assertIsArray($decoded['checks']);
    }

    public function testDoctorInvalidFormatReturnsOne(): void
    {
        $command = new DoctorCommand(new FakeDoctorRunner([
            'command' => 'doctor',
            'status' => 'ok',
            'checks' => [],
            'ok_count' => 0,
            'warn_count' => 0,
            'fail_count' => 0,
            'exit_code' => 0,
            'duration_ms' => 0,
        ]));

        $exitCode = $command->execute([], ['format' => 'xml']);
        self::assertSame(1, $exitCode);
    }
}

final class FakeDoctorRunner implements DoctorRunnerInterface
{
    /** @var array<string, mixed> */
    private array $result;

    /**
     * @param array<string, mixed> $result
     */
    public function __construct(array $result)
    {
        $this->result = $result;
    }

    public function run(): array
    {
        return $this->result;
    }
}
