<?php

use App\Enums\IsShow;
use App\Enums\RewardCategory;
use App\Livewire\Member\RedeemPoint;
use App\Models\Membership;
use App\Models\Reward;
use App\Models\Tier;
use Livewire\Livewire;

beforeEach(function () {
    $this->setupUser();
    $this->tier = Tier::factory()->create(['min_spending' => 0]);
    $this->membership = Membership::factory()->for($this->user)->create([
        'tier_id' => $this->tier->id,
        'reward_points' => 1000,
    ]);
});

it('renders the redeem point page', function () {
    $this->actingAs($this->user);

    Livewire::test(RedeemPoint::class)
        ->assertStatus(200)
        ->assertSee('Hadiah');
});

it('shows rewards available for user tier', function () {
    $this->actingAs($this->user);

    $reward = Reward::factory()->create([
        'name' => 'Free Perfume',
        'points' => 100,
        'is_show' => IsShow::SHOW,
        'start_date' => now()->subDay(),
        'end_date' => now()->addDay(),
        'category' => RewardCategory::REGULAR,
    ]);
    $reward->tiers()->attach($this->tier->id);

    Livewire::test(RedeemPoint::class)
        ->assertSee('Free Perfume');
});

it('can redeem a reward', function () {
    $this->actingAs($this->user);

    $reward = Reward::factory()->create([
        'name' => 'Free Perfume',
        'points' => 100,
        'stock' => 10,
        'is_show' => IsShow::SHOW,
        'start_date' => now()->subDay(),
        'category' => RewardCategory::REGULAR,
    ]);
    $reward->tiers()->attach($this->tier->id);

    Livewire::test(RedeemPoint::class)
        ->call('redeem', $reward)
        ->assertHasNoErrors();

    $this->assertDatabaseHas('redemptions', [
        'user_id' => $this->user->id,
        'reward_id' => $reward->id,
        'points_spent' => 100,
    ]);

    $this->assertEquals(900, $this->user->refresh()->membership->reward_points);
    $this->assertEquals(9, $reward->refresh()->stock);
});

it('cannot redeem reward if points are insufficient', function () {
    $this->actingAs($this->user);
    $this->membership->update(['reward_points' => 50]);

    $reward = Reward::factory()->create([
        'points' => 100,
        'is_show' => IsShow::SHOW,
        'start_date' => now()->subDay(),
    ]);
    $reward->tiers()->attach($this->tier->id);

    Livewire::test(RedeemPoint::class)
        ->call('redeem', $reward);

    $this->assertEquals(50, $this->user->refresh()->membership->reward_points);
});

it('cannot redeem reward if stock is empty', function () {
    $this->actingAs($this->user);

    $reward = Reward::factory()->create([
        'points' => 100,
        'stock' => 0,
        'is_show' => IsShow::SHOW,
        'start_date' => now()->subDay(),
    ]);
    $reward->tiers()->attach($this->tier->id);

    Livewire::test(RedeemPoint::class)
        ->call('redeem', $reward);

    $this->assertEquals(1000, $this->user->refresh()->membership->reward_points);
});
