<?php

use App\Livewire\Studio\Loyalty\Tier;
use App\Models\Tier as TierModel;
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 tier']);
    Permission::firstOrCreate(['name' => 'create tier']);
    Permission::firstOrCreate(['name' => 'update tier']);
    Permission::firstOrCreate(['name' => 'delete tier']);
    $role->givePermissionTo(['view tier', 'create tier', 'update tier', 'delete tier']);
    $this->user->assignRole($role);
});

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

it('can open create modal', function () {
    Livewire::actingAs($this->user)
        ->test(Tier::class)
        ->dispatch('modal:open', method: 'create', modalTitle: 'Tambah Tier')
        ->assertSet('method', 'create')
        ->assertSet('modalTitle', 'Tambah Tier');
});

it('validates required fields on create', function () {
    Livewire::actingAs($this->user)
        ->test(Tier::class)
        ->call('create')
        ->assertHasErrors(['form.name' => 'required', 'form.min_spending' => 'required']);
});

it('can store a new tier', function () {
    // Ensure no tiers exist first
    TierModel::query()->delete();

    Livewire::actingAs($this->user)
        ->test(Tier::class)
        ->set('form.name', 'Bronze')
        ->set('form.min_spending', '0')
        ->call('create')
        ->assertHasNoErrors();

    $this->assertDatabaseHas('tiers', [
        'name' => 'Bronze',
        'min_spending' => 0,
    ]);
});

it('automatically reorders tier chain on create', function () {
    TierModel::query()->delete();

    // Create first tier manually
    TierModel::create(['name' => 'Bronze', 'min_spending' => 0]);

    // Create second tier via Livewire
    Livewire::actingAs($this->user)
        ->test(Tier::class)
        ->set('form.name', 'Silver')
        ->set('form.min_spending', '10.000') // 10,000
        ->call('create')
        ->assertHasNoErrors();

    // First tier should now have max_spending = 9999
    $bronze = TierModel::where('name', 'Bronze')->first();
    expect($bronze->max_spending)->toBe(9999);

    // Silver should have null max_spending
    $silver = TierModel::where('name', 'Silver')->first();
    expect($silver->max_spending)->toBeNull();
});

it('can open edit modal and load data', function () {
    $tier = TierModel::factory()->create([
        'name' => 'Gold',
        'min_spending' => 50000,
        'max_spending' => null,
    ]);

    Livewire::actingAs($this->user)
        ->test(Tier::class)
        ->call('openModal', 'update', 'Ubah Tier', $tier->hash_id)
        ->set('form.tier', $tier)
        ->set('form.name', 'Gold')
        ->set('form.min_spending', formatCurrencyNumber(50000))
        ->assertSet('method', 'update')
        ->assertSet('modalTitle', 'Ubah Tier')
        ->assertSet('form.name', 'Gold')
        ->assertSet('form.min_spending', formatCurrencyNumber(50000));
});

it('can update a tier', function () {
    $tier = TierModel::factory()->create(['name' => 'Old Name', 'min_spending' => 0]);

    Livewire::actingAs($this->user)
        ->test(Tier::class)
        ->call('openModal', 'update', 'Ubah Tier', $tier->hash_id)
        ->set('form.tier', $tier)
        ->set('form.name', 'New Name')
        ->set('form.min_spending', '0')
        ->call('update')
        ->assertHasNoErrors();

    $this->assertDatabaseHas('tiers', [
        'id' => $tier->id,
        'name' => 'New Name',
    ]);
});

it('can delete the last tier', function () {
    TierModel::query()->delete();
    $tier1 = TierModel::create(['name' => 'Bronze', 'min_spending' => 0]);
    $tier2 = TierModel::create(['name' => 'Silver', 'min_spending' => 10000]);
    TierModel::reorderTierChain();

    Livewire::actingAs($this->user)
        ->test(Tier::class)
        ->call('delete', $tier2->id); // Deleting highest tier (Silver)

    $this->assertSoftDeleted('tiers', ['id' => $tier2->id]);

    // Bronze should now be the last tier with null max_spending
    $tier1->refresh();
    expect($tier1->max_spending)->toBeNull();
});

it('cannot delete a middle tier', function () {
    TierModel::query()->delete();
    $tier1 = TierModel::create(['name' => 'Bronze', 'min_spending' => 0]);
    $tier2 = TierModel::create(['name' => 'Silver', 'min_spending' => 10000]);
    $tier3 = TierModel::create(['name' => 'Gold', 'min_spending' => 20000]);
    TierModel::reorderTierChain();

    Livewire::actingAs($this->user)
        ->test(Tier::class)
        ->call('delete', $tier2->id);

    $this->assertDatabaseHas('tiers', ['id' => $tier2->id]);
});

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

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