<?php

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

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

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

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

it('validates volume must be less than or equal to size', function () {
    Livewire::actingAs($this->user)
        ->test(Formula::class)
        ->set('form.size', '30')
        ->set('form.volume', '35')
        ->call('create')
        ->assertHasErrors(['form.volume' => 'lte']);
});

it('can store a new formula', function () {
    Livewire::actingAs($this->user)
        ->test(Formula::class)
        ->set('form.quality', 'Premium')
        ->set('form.size', '30')
        ->set('form.volume', '25')
        ->call('create')
        ->assertHasNoErrors();

    $this->assertDatabaseHas('formulas', [
        'quality' => 'Premium',
        'size' => 30,
        'volume' => 25,
    ]);
});

it('prevents duplicate quality and size on create', function () {
    FormulaModel::factory()->create(['quality' => 'Premium', 'size' => 30]);

    Livewire::actingAs($this->user)
        ->test(Formula::class)
        ->set('form.quality', 'Premium')
        ->set('form.size', '30')
        ->set('form.volume', '20')
        ->call('create');
    // It returns early with a toast

    expect(FormulaModel::where('quality', 'Premium')->where('size', 30)->count())->toBe(1);
});

it('can open edit modal and load data', function () {
    $formula = FormulaModel::factory()->create(['quality' => 'Super Premium', 'size' => 50, 'volume' => 40]);

    Livewire::actingAs($this->user)
        ->test(Formula::class)
        ->call('openModal', 'update', 'Ubah Rumus', $formula->hash_id)
        ->set('form.formula', $formula)
        ->set('form.quality', 'Super Premium')
        ->set('form.size', 50)
        ->set('form.volume', 40)
        ->assertSet('method', 'update')
        ->assertSet('modalTitle', 'Ubah Rumus')
        ->assertSet('form.quality', 'Super Premium')
        ->assertSet('form.size', 50)
        ->assertSet('form.volume', 40);
});

it('can update a formula', function () {
    $formula = FormulaModel::factory()->create(['quality' => 'Murni', 'size' => 100, 'volume' => 90]);

    Livewire::actingAs($this->user)
        ->test(Formula::class)
        ->call('openModal', 'update', 'Ubah Rumus', $formula->hash_id)
        ->set('form.formula', $formula)
        ->set('form.quality', $formula->quality)
        ->set('form.size', $formula->size)
        ->set('form.volume', '85')
        ->call('update')
        ->assertHasNoErrors();

    $this->assertDatabaseHas('formulas', [
        'id' => $formula->id,
        'volume' => 85,
    ]);
});

it('can delete a formula', function () {
    $formula = FormulaModel::factory()->create();

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

    $this->assertSoftDeleted('formulas', ['id' => $formula->id]);
});

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

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