<?php

namespace MintyPHP\Tests\Console;

use MintyPHP\Console\Commands\Database\MigrateCommand;
use PHPUnit\Framework\TestCase;

final class CoreCommandsTest extends TestCase
{
    public function testDbMigrateSuccessOutputAndExitCode(): void
    {
        $runner = new FakeModuleRunner();
        $runner->dbMigrateResult = [
            'command' => 'db:migrate',
            'status' => 'ok',
            'exit_code' => 0,
            'vendor_warnings_ignored' => 0,
            'message' => 'db-migrate: applied 3 migration(s).',
        ];

        $command = new MigrateCommand($runner);

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

        self::assertSame(0, $exitCode);
        self::assertStringContainsString('db-migrate: applied 3 migration(s).', $output);
    }

    public function testDbMigrateFailureWritesToStderrAndReturnsNonZero(): void
    {
        $runner = new FakeModuleRunner();
        $runner->dbMigrateResult = [
            'command' => 'db:migrate',
            'status' => 'failed',
            'exit_code' => 1,
            'vendor_warnings_ignored' => 0,
            'message' => 'db-migrate: failure: Core migration foo.sql failed: SQLSTATE[42S02]',
        ];

        $command = new MigrateCommand($runner);

        ob_start();
        $exitCode = $command->execute([], []);
        ob_end_clean();

        self::assertSame(1, $exitCode);
    }

    public function testDbMigrateStatusListsAppliedAndPending(): void
    {
        $runner = new FakeModuleRunner();
        $runner->dbMigrateStatusResult = [
            'command' => 'db:migrate --status',
            'applied' => [
                '2026-02-23-tenant-scope-global.sql',
                '2026-03-13-seed-default-roles.sql',
            ],
            'pending' => [
                '2026-04-29-core-migrations-table.sql',
            ],
        ];

        $command = new MigrateCommand($runner);

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

        self::assertSame(0, $exitCode);
        self::assertStringContainsString('2 applied, 1 pending', $output);
        self::assertStringContainsString('2026-02-23-tenant-scope-global.sql', $output);
        self::assertStringContainsString('2026-04-29-core-migrations-table.sql', $output);
        self::assertStringContainsString("applied:\n", $output);
        self::assertStringContainsString("pending:\n", $output);
    }

    public function testDbMigrateStatusHandlesEmptyLists(): void
    {
        $runner = new FakeModuleRunner();
        $runner->dbMigrateStatusResult = [
            'command' => 'db:migrate --status',
            'applied' => [],
            'pending' => [],
        ];

        $command = new MigrateCommand($runner);

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

        self::assertSame(0, $exitCode);
        self::assertStringContainsString('0 applied, 0 pending', $output);
        self::assertStringContainsString("applied:\n  (none)", $output);
        self::assertStringContainsString("pending:\n  (none)", $output);
    }
}
