<?php

namespace Tests\Feature;

use App\Jobs\SyncPackageToPaddle;
use App\Models\Package;
use Illuminate\Console\Command;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Bus as BusFacade;
use Tests\TestCase;

class PaddleSyncPackagesCommandTest extends TestCase
{
    use RefreshDatabase;

    public function test_command_dispatches_jobs_for_packages(): void
    {
        Package::factory()->count(2)->create([
            'paddle_product_id' => 'pro_test',
            'paddle_price_id' => 'pri_test',
        ]);

        BusFacade::fake();

        $this->artisan('paddle:sync-packages', [
            '--dry-run' => true,
            '--queue' => true,
        ])->assertExitCode(0);

        BusFacade::assertDispatched(SyncPackageToPaddle::class, 2);
    }

    public function test_command_filters_packages_by_id(): void
    {
        $package = Package::factory()->create();
        Package::factory()->create();

        BusFacade::fake();

        $this->artisan('paddle:sync-packages', [
            '--dry-run' => true,
            '--queue' => true,
            '--package' => [$package->id],
        ])->assertExitCode(0);

        BusFacade::assertDispatched(SyncPackageToPaddle::class, function (SyncPackageToPaddle $job) use ($package) {
            return $this->getJobPackageId($job) === $package->id;
        });
    }

    public function test_command_blocks_bulk_sync_with_unmapped_packages(): void
    {
        Package::factory()->create([
            'paddle_product_id' => null,
            'paddle_price_id' => null,
        ]);

        BusFacade::fake();

        $this->artisan('paddle:sync-packages', [
            '--dry-run' => true,
            '--queue' => true,
        ])->assertExitCode(Command::FAILURE);

        BusFacade::assertNotDispatched(SyncPackageToPaddle::class);
    }

    public function test_command_allows_unmapped_packages_when_overridden(): void
    {
        Package::factory()->create([
            'paddle_product_id' => null,
            'paddle_price_id' => null,
        ]);

        BusFacade::fake();

        $this->artisan('paddle:sync-packages', [
            '--dry-run' => true,
            '--queue' => true,
            '--allow-unmapped' => true,
        ])->assertExitCode(Command::SUCCESS);

        BusFacade::assertDispatched(SyncPackageToPaddle::class, 1);
    }

    protected function getJobPackageId(SyncPackageToPaddle $job): int
    {
        $reflection = new \ReflectionClass($job);
        $property = $reflection->getProperty('packageId');
        $property->setAccessible(true);

        return (int) $property->getValue($job);
    }
}
