<?php

namespace Tests\Feature;

use App\Models\Satuan;
use App\Models\User;
use Tests\DatabaseTestCase;

class SatuanTest extends DatabaseTestCase
{
    private function actingAsUser(): User
    {
        $user = User::factory()->create(['role' => 'apoteker']);
        $this->actingAs($user);
        return $user;
    }

    // ─────────────────────────────────────────
    // index
    // ─────────────────────────────────────────

    public function test_index_returns_200_for_authenticated_user(): void
    {
        $this->actingAsUser();
        $response = $this->get(route('satuan.index'));
        $response->assertStatus(200);
    }

    public function test_index_redirects_guest(): void
    {
        $response = $this->get(route('satuan.index'));
        $response->assertRedirect(route('login'));
    }

    // ─────────────────────────────────────────
    // store
    // ─────────────────────────────────────────

    public function test_store_creates_satuan_with_valid_data(): void
    {
        $this->actingAsUser();

        $response = $this->post(route('satuan.store'), [
            'nama'       => 'Tablet',
            'keterangan' => 'Satuan tablet',
        ]);

        $response->assertRedirect(route('satuan.index'));
        $response->assertSessionHas('success');
        $this->assertDatabaseHas('satuans', ['nama' => 'Tablet']);
    }

    public function test_store_fails_without_nama(): void
    {
        $this->actingAsUser();

        $response = $this->post(route('satuan.store'), ['nama' => '']);
        $response->assertSessionHasErrors('nama');
    }

    public function test_store_fails_with_duplicate_nama(): void
    {
        $this->actingAsUser();
        Satuan::create(['nama' => 'Tablet']);

        $response = $this->post(route('satuan.store'), ['nama' => 'Tablet']);
        $response->assertSessionHasErrors('nama');
    }

    // ─────────────────────────────────────────
    // update
    // ─────────────────────────────────────────

    public function test_update_modifies_satuan(): void
    {
        $this->actingAsUser();
        $satuan = Satuan::create(['nama' => 'Tablet']);

        $response = $this->put(route('satuan.update', $satuan), [
            'nama'       => 'Kapsul',
            'keterangan' => 'Satuan kapsul',
        ]);

        $response->assertRedirect(route('satuan.index'));
        $this->assertDatabaseHas('satuans', ['nama' => 'Kapsul']);
        $this->assertDatabaseMissing('satuans', ['nama' => 'Tablet']);
    }

    public function test_update_allows_same_nama_for_same_satuan(): void
    {
        $this->actingAsUser();
        $satuan = Satuan::create(['nama' => 'Tablet']);

        $response = $this->put(route('satuan.update', $satuan), [
            'nama'       => 'Tablet',
            'keterangan' => 'Updated',
        ]);

        $response->assertRedirect(route('satuan.index'));
        $this->assertDatabaseHas('satuans', ['id' => $satuan->id, 'nama' => 'Tablet']);
    }

    public function test_update_fails_with_duplicate_nama_of_other_satuan(): void
    {
        $this->actingAsUser();
        Satuan::create(['nama' => 'Kapsul']);
        $satuan = Satuan::create(['nama' => 'Tablet']);

        $response = $this->put(route('satuan.update', $satuan), [
            'nama' => 'Kapsul',
        ]);

        $response->assertSessionHasErrors('nama');
    }

    // ─────────────────────────────────────────
    // destroy
    // ─────────────────────────────────────────

    public function test_destroy_deletes_satuan(): void
    {
        $this->actingAsUser();
        $satuan = Satuan::create(['nama' => 'Tablet']);

        $response = $this->delete(route('satuan.destroy', $satuan));

        $response->assertRedirect(route('satuan.index'));
        $this->assertDatabaseMissing('satuans', ['id' => $satuan->id]);
    }

    public function test_superadmin_can_crud_satuan(): void
    {
        $superadmin = User::factory()->create(['role' => 'superadmin']);
        $this->actingAs($superadmin);

        $this->get(route('satuan.create'))->assertStatus(200);
        $this->post(route('satuan.store'), ['nama' => 'Botol'])->assertRedirect(route('satuan.index'));
        $satuan = Satuan::where('nama', 'Botol')->firstOrFail();
        $this->get(route('satuan.edit', $satuan))->assertStatus(200);
        $this->put(route('satuan.update', $satuan), ['nama' => 'Botol Update'])->assertRedirect(route('satuan.index'));
        $this->delete(route('satuan.destroy', $satuan))->assertRedirect(route('satuan.index'));
    }
}
