<?php

namespace Tests\Feature;

use App\Models\Kategori;
use App\Models\ObatMasuk;
use App\Models\Satuan;
use App\Models\Supplier;
use App\Models\User;
use Tests\DatabaseTestCase;

class ObatMasukTest extends DatabaseTestCase
{
    private User $user;

    protected function setUp(): void
    {
        parent::setUp();
        $this->user = User::factory()->create(['role' => 'apoteker']);
        $this->actingAs($this->user);
    }

    private function createKategori(): Kategori
    {
        return Kategori::create(['nama' => 'Antibiotik']);
    }

    private function createSatuan(): Satuan
    {
        return Satuan::create(['nama' => 'Tablet']);
    }

    private function validData(array $overrides = []): array
    {
        $kategori = Kategori::firstOrCreate(['nama' => 'Antibiotik']);
        $satuan   = Satuan::firstOrCreate(['nama' => 'Tablet']);

        return array_merge([
            'nama_obat'          => 'Amoxicillin',
            'kategori_id'        => $kategori->id,
            'satuan_id'          => $satuan->id,
            'kode_batch'         => 'BTH-001',
            'stok'               => 100,
            'tanggal_penerimaan' => now()->toDateString(),
            'tanggal_kadaluarsa' => now()->addYear()->toDateString(),
        ], $overrides);
    }

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

    public function test_index_returns_200(): void
    {
        $response = $this->get(route('obat-masuk.index'));
        $response->assertStatus(200);
    }

    public function test_index_guest_redirects_to_login(): void
    {
        auth()->logout();
        $response = $this->get(route('obat-masuk.index'));
        $response->assertRedirect(route('login'));
    }

    public function test_index_search_by_nama_obat(): void
    {
        $kategori = $this->createKategori();
        $satuan   = $this->createSatuan();

        ObatMasuk::create([
            'nama_obat'          => 'Amoxicillin',
            'kategori_id'        => $kategori->id,
            'satuan_id'          => $satuan->id,
            'kode_batch'         => 'BTH-001',
            'stok'               => 100,
            'tanggal_penerimaan' => now()->toDateString(),
            'tanggal_kadaluarsa' => now()->addYear()->toDateString(),
            'user_id'            => $this->user->id,
        ]);

        ObatMasuk::create([
            'nama_obat'          => 'Paracetamol',
            'kategori_id'        => $kategori->id,
            'satuan_id'          => $satuan->id,
            'kode_batch'         => 'BTH-002',
            'stok'               => 50,
            'tanggal_penerimaan' => now()->toDateString(),
            'tanggal_kadaluarsa' => now()->addYear()->toDateString(),
            'user_id'            => $this->user->id,
        ]);

        $response = $this->get(route('obat-masuk.index', ['search' => 'Amoxicillin']));
        $data = $response->viewData('obatMasuks');
        $names = $data->pluck('nama_obat')->toArray();
        $this->assertContains('Amoxicillin', $names);
        $this->assertNotContains('Paracetamol', $names);
    }

    public function test_index_filter_by_status_tersedia(): void
    {
        $kategori = $this->createKategori();
        $satuan   = $this->createSatuan();

        ObatMasuk::create([
            'nama_obat' => 'ObatA', 'kategori_id' => $kategori->id,
            'satuan_id' => $satuan->id, 'kode_batch' => 'B1', 'stok' => 10,
            'tanggal_penerimaan' => now()->toDateString(),
            'tanggal_kadaluarsa' => now()->addYear()->toDateString(),
            'user_id' => $this->user->id,
        ]);

        ObatMasuk::create([
            'nama_obat' => 'ObatB', 'kategori_id' => $kategori->id,
            'satuan_id' => $satuan->id, 'kode_batch' => 'B2', 'stok' => 0,
            'tanggal_penerimaan' => now()->toDateString(),
            'tanggal_kadaluarsa' => now()->addYear()->toDateString(),
            'user_id' => $this->user->id,
        ]);

        $response = $this->get(route('obat-masuk.index', ['status' => 'tersedia']));
        $data = $response->viewData('obatMasuks');
        $names = $data->pluck('nama_obat')->toArray();
        $this->assertContains('ObatA', $names);
        $this->assertNotContains('ObatB', $names);
    }

    public function test_index_filter_by_status_habis(): void
    {
        $kategori = $this->createKategori();
        $satuan   = $this->createSatuan();

        ObatMasuk::create([
            'nama_obat' => 'ObatA', 'kategori_id' => $kategori->id,
            'satuan_id' => $satuan->id, 'kode_batch' => 'B1', 'stok' => 10,
            'tanggal_penerimaan' => now()->toDateString(),
            'tanggal_kadaluarsa' => now()->addYear()->toDateString(),
            'user_id' => $this->user->id,
        ]);

        ObatMasuk::create([
            'nama_obat' => 'ObatHabis', 'kategori_id' => $kategori->id,
            'satuan_id' => $satuan->id, 'kode_batch' => 'B2', 'stok' => 0,
            'tanggal_penerimaan' => now()->toDateString(),
            'tanggal_kadaluarsa' => now()->addYear()->toDateString(),
            'user_id' => $this->user->id,
        ]);

        $response = $this->get(route('obat-masuk.index', ['status' => 'habis']));
        $data = $response->viewData('obatMasuks');
        $names = $data->pluck('nama_obat')->toArray();
        $this->assertContains('ObatHabis', $names);
        $this->assertNotContains('ObatA', $names);
    }

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

    public function test_store_creates_obat_masuk_with_valid_data(): void
    {
        $response = $this->post(route('obat-masuk.store'), $this->validData());

        $response->assertRedirect(route('obat-masuk.index'));
        $response->assertSessionHas('success');
        $this->assertDatabaseHas('obat_masuks', ['nama_obat' => 'Amoxicillin', 'stok' => 100]);
    }

    public function test_store_fails_without_required_fields(): void
    {
        $response = $this->post(route('obat-masuk.store'), []);
        $response->assertSessionHasErrors(['nama_obat', 'kode_batch', 'stok', 'tanggal_penerimaan', 'tanggal_kadaluarsa']);
    }

    public function test_store_fails_when_kadaluarsa_before_penerimaan(): void
    {
        $response = $this->post(route('obat-masuk.store'), $this->validData([
            'tanggal_penerimaan' => now()->toDateString(),
            'tanggal_kadaluarsa' => now()->subDay()->toDateString(), // sebelum penerimaan
        ]));

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

    public function test_store_fails_with_zero_stok(): void
    {
        $response = $this->post(route('obat-masuk.store'), $this->validData(['stok' => 0]));
        $response->assertSessionHasErrors('stok');
    }

    public function test_store_sets_user_id_from_authenticated_user(): void
    {
        $this->post(route('obat-masuk.store'), $this->validData());
        $this->assertDatabaseHas('obat_masuks', ['user_id' => $this->user->id]);
    }

    // ─────────────────────────────────────────
    // show
    // ─────────────────────────────────────────

    public function test_show_returns_200(): void
    {
        $obat = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id]));
        $response = $this->get(route('obat-masuk.show', $obat));
        $response->assertStatus(200);
    }

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

    public function test_update_modifies_obat_masuk(): void
    {
        $obat     = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id]));
        $response = $this->put(route('obat-masuk.update', $obat), $this->validData(['nama_obat' => 'Paracetamol', 'stok' => 50]));

        $response->assertRedirect(route('obat-masuk.index'));
        $this->assertDatabaseHas('obat_masuks', ['id' => $obat->id, 'nama_obat' => 'Paracetamol', 'stok' => 50]);
    }

    public function test_update_fails_without_required_fields(): void
    {
        $obat     = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id]));
        $response = $this->put(route('obat-masuk.update', $obat), []);
        $response->assertSessionHasErrors(['nama_obat', 'kode_batch']);
    }

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

    public function test_destroy_deletes_obat_masuk(): void
    {
        $obat     = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id]));
        $response = $this->delete(route('obat-masuk.destroy', $obat));

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


    // ─────────────────────────────────────────
    // superadmin access
    // ─────────────────────────────────────────

    public function test_superadmin_can_access_index(): void
    {
        $superadmin = User::factory()->create(['role' => 'superadmin']);
        $this->actingAs($superadmin);
        
        $response = $this->get(route('obat-masuk.index'));
        $response->assertStatus(200);
    }

    public function test_superadmin_can_access_show(): void
    {
        $superadmin = User::factory()->create(['role' => 'superadmin']);
        $this->actingAs($superadmin);
        
        $obat = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id]));
        $response = $this->get(route('obat-masuk.show', $obat));
        $response->assertStatus(200);
    }

    public function test_superadmin_can_access_create_store_edit_update_destroy(): void
    {
        $superadmin = User::factory()->create(['role' => 'superadmin']);
        $this->actingAs($superadmin);
        
        $obat = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id]));
        
        $this->get(route('obat-masuk.create'))->assertStatus(200);

        $storePayload = $this->validData([
            'nama_obat' => 'Cefixime',
            'kode_batch' => 'BTH-003',
        ]);
        $this->post(route('obat-masuk.store'), $storePayload)->assertRedirect(route('obat-masuk.index'));
        $this->assertDatabaseHas('obat_masuks', ['nama_obat' => 'Cefixime']);

        $this->get(route('obat-masuk.edit', $obat))->assertStatus(200);

        $updatePayload = $this->validData(['nama_obat' => 'Paracetamol Superadmin']);
        $this->put(route('obat-masuk.update', $obat), $updatePayload)->assertRedirect(route('obat-masuk.index'));
        $this->assertDatabaseHas('obat_masuks', ['id' => $obat->id, 'nama_obat' => 'Paracetamol Superadmin']);

        $this->delete(route('obat-masuk.destroy', $obat))->assertRedirect(route('obat-masuk.index'));
        $this->assertDatabaseMissing('obat_masuks', ['id' => $obat->id]);
    }
}
