<?php

use App\Enums\RedemptionStatus;
use App\Livewire\Studio\Loyalty\RedemptionVerification;
use App\Models\Redemption;
use Livewire\Livewire;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

beforeEach(function () {
    $this->setupUser();

    $role = Role::firstOrCreate(['name' => 'Owner']);
    Permission::firstOrCreate(['name' => 'view redemption']);
    Permission::firstOrCreate(['name' => 'update redemption']);
    $role->givePermissionTo(['view redemption', 'update redemption']);
    $this->user->assignRole($role);
});

it('renders the redemption verification page correctly', function () {
    $this->actingAs($this->user)
        ->get(route('studio.loyalty.redemption.index'))
        ->assertOk()
        ->assertSeeLivewire(RedemptionVerification::class);
});

it('can search for a redemption code', function () {
    $redemption = Redemption::factory()->create(['code' => 'ABC123XYZ']);

    Livewire::actingAs($this->user)
        ->test(RedemptionVerification::class)
        ->set('searchCode', 'abc123xyz ') // Testing case insensitivity and trimming
        ->call('search')
        ->assertSet('foundRedemption.id', $redemption->id);
});

it('shows error if redemption code not found', function () {
    Livewire::actingAs($this->user)
        ->test(RedemptionVerification::class)
        ->set('searchCode', 'NONEXISTENT')
        ->call('search')
        ->assertSet('foundRedemption', null);
});

it('can verify a redemption', function () {
    $redemption = Redemption::factory()->create([
        'code' => 'TESTCODE',
        'status' => RedemptionStatus::WAITING_PICKUP,
        'expires_at' => now()->addDay(),
    ]);

    Livewire::actingAs($this->user)
        ->test(RedemptionVerification::class)
        ->set('searchCode', 'TESTCODE')
        ->call('search')
        ->call('verify');

    $redemption->refresh();
    expect($redemption->status)->toBe(RedemptionStatus::PICKED_UP);
    expect($redemption->verified_by)->toBe($this->user->id);
});

it('cannot verify expired redemption', function () {
    $redemption = Redemption::factory()->create([
        'code' => 'EXPIRED',
        'status' => RedemptionStatus::WAITING_PICKUP,
        'expires_at' => now()->subDay(),
    ]);

    Livewire::actingAs($this->user)
        ->test(RedemptionVerification::class)
        ->set('searchCode', 'EXPIRED')
        ->call('search')
        ->call('verify');

    $redemption->refresh();
    expect($redemption->status)->toBe(RedemptionStatus::EXPIRED);
});

it('cannot verify already processed redemption', function () {
    $redemption = Redemption::factory()->verified($this->user)->create(['code' => 'PROCESSED']);

    Livewire::actingAs($this->user)
        ->test(RedemptionVerification::class)
        ->set('searchCode', 'PROCESSED')
        ->call('search')
        ->call('verify');

    $redemption->refresh();
    expect($redemption->status)->toBe(RedemptionStatus::PICKED_UP); // Remains picked up
});

it('cannot access redemption verification without permission', function () {
    $this->user->roles()->detach();
    $this->user->permissions()->detach();

    $this->actingAs($this->user)
        ->get(route('studio.loyalty.redemption.index'))
        ->assertForbidden();
});
