<?php

declare(strict_types=1);

use Builder\Core\Foundation\Registry;
use Builder\Core\Foundation\Resources\Resource;
use Builder\Core\Models\Revision;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

final class PruneCommandTestModel extends Model
{
    protected $table = 'prune_command_items';

    protected $guarded = [];
}

final class PruneCommandTestResource extends Resource
{
    public static function getSlug(): string
    {
        return 'prune-command-items';
    }

    public static function getLabel(): string
    {
        return 'Prune Command Items';
    }

    /** @return class-string<Model> */
    public static function getModel(): string
    {
        return PruneCommandTestModel::class;
    }

    /** @return array<string, mixed> */
    public function rules(string $action): array
    {
        return [];
    }

    public function isRevisable(): bool
    {
        return true;
    }

    public function getMaxRevisions(): int
    {
        return 3;
    }
}

beforeEach(function (): void {
    Schema::dropIfExists('prune_command_items');

    Schema::create('prune_command_items', function (Blueprint $table): void {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });

    if (! Schema::hasTable('revisions')) {
        Schema::create('revisions', function (Blueprint $table): void {
            $table->id();
            $table->string('revisable_type');
            $table->unsignedBigInteger('revisable_id');
            $table->unsignedBigInteger('user_id')->nullable();
            $table->json('revision_data');
            $table->timestamps();
        });
    }

    app(Registry::class)->resource(PruneCommandTestResource::class);
});

it('prunes revisions beyond the keep limit', function (): void {
    $record = PruneCommandTestModel::create(['name' => 'Test']);

    for ($i = 0; $i < 6; $i++) {
        Revision::create([
            'revisable_type' => PruneCommandTestModel::class,
            'revisable_id' => $record->id,
            'user_id' => null,
            'revision_data' => ['name' => "Version {$i}"],
        ]);
    }

    $this->artisan('builder:prune-revisions')->assertSuccessful();

    expect(Revision::where('revisable_type', PruneCommandTestModel::class)
        ->where('revisable_id', $record->id)
        ->count()
    )->toBe(3);
});

it('reports success when no revisable resources have revisions', function (): void {
    $this->artisan('builder:prune-revisions')
        ->expectsOutput('Done. Pruned 0 revision(s) in total.')
        ->assertSuccessful();
});

it('limits pruning to a single resource via --resource option', function (): void {
    $record = PruneCommandTestModel::create(['name' => 'Test']);

    for ($i = 0; $i < 5; $i++) {
        Revision::create([
            'revisable_type' => PruneCommandTestModel::class,
            'revisable_id' => $record->id,
            'user_id' => null,
            'revision_data' => ['name' => "V{$i}"],
        ]);
    }

    $this->artisan('builder:prune-revisions', ['--resource' => 'prune-command-items'])
        ->assertSuccessful();

    expect(Revision::count())->toBe(3);
});

it('exits with no resources message when --resource filter matches nothing', function (): void {
    $this->artisan('builder:prune-revisions', ['--resource' => 'non-existent-resource'])
        ->expectsOutput('No revisable resources found.')
        ->assertSuccessful();
});
