<?php

namespace Tests\Feature;

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

class UserManagementTest extends DatabaseTestCase
{
    private User $superadmin;
    private User $dokter;
    private User $apoteker;

    protected function setUp(): void
    {
        parent::setUp();

        $this->superadmin = User::factory()->create(['role' => 'superadmin']);
        $this->dokter     = User::factory()->create(['role' => 'dokter', 'name' => 'Dr. Budi']);
        $this->apoteker   = User::factory()->create(['role' => 'apoteker', 'name' => 'Apt. Siti']);
    }

    // ─────────────────────────────────────────
    // Akses: hanya superadmin
    // ─────────────────────────────────────────

    public function test_superadmin_can_access_index(): void
    {
        $this->actingAs($this->superadmin);
        $response = $this->get(route('user-management.index'));
        $response->assertStatus(200);
    }

    public function test_dokter_cannot_access_index(): void
    {
        $this->actingAs($this->dokter);
        $response = $this->get(route('user-management.index'));
        $response->assertStatus(403);
    }

    public function test_apoteker_cannot_access_index(): void
    {
        $this->actingAs($this->apoteker);
        $response = $this->get(route('user-management.index'));
        $response->assertStatus(403);
    }

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

    // ─────────────────────────────────────────
    // index — filter & search
    // ─────────────────────────────────────────

    public function test_index_does_not_show_superadmin_users(): void
    {
        $this->actingAs($this->superadmin);
        $response = $this->get(route('user-management.index'));
        $response->assertDontSee($this->superadmin->email);
        $response->assertSee('Dr. Budi');
    }

    public function test_index_search_by_name(): void
    {
        $this->actingAs($this->superadmin);
        $response = $this->get(route('user-management.index', ['search' => 'Budi']));
        $response->assertSee('Dr. Budi');
        $response->assertDontSee('Apt. Siti');
    }

    public function test_index_filter_by_role(): void
    {
        $this->actingAs($this->superadmin);
        $response = $this->get(route('user-management.index', ['role' => 'dokter']));
        $response->assertSee('Dr. Budi');
        $response->assertDontSee('Apt. Siti');
    }

    // ─────────────────────────────────────────
    // create & store
    // ─────────────────────────────────────────

    public function test_superadmin_can_access_create_page(): void
    {
        $this->actingAs($this->superadmin);
        $response = $this->get(route('user-management.create'));
        $response->assertStatus(200);
    }

    public function test_store_creates_new_dokter(): void
    {
        $this->actingAs($this->superadmin);

        $response = $this->post(route('user-management.store'), [
            'name'                  => 'Dr. Andi',
            'email'                 => 'andi@example.com',
            'role'                  => 'dokter',
            'password'              => 'password123',
            'password_confirmation' => 'password123',
        ]);

        $response->assertRedirect(route('user-management.index'));
        $response->assertSessionHas('success');
        $this->assertDatabaseHas('users', [
            'email' => 'andi@example.com',
            'role'  => 'dokter',
        ]);
    }

    public function test_store_creates_new_apoteker(): void
    {
        $this->actingAs($this->superadmin);

        $response = $this->post(route('user-management.store'), [
            'name'                  => 'Apt. Rina',
            'email'                 => 'rina@example.com',
            'role'                  => 'apoteker',
            'password'              => 'password123',
            'password_confirmation' => 'password123',
        ]);

        $response->assertRedirect(route('user-management.index'));
        $this->assertDatabaseHas('users', [
            'email' => 'rina@example.com',
            'role'  => 'apoteker',
        ]);
    }

    public function test_store_fails_without_required_fields(): void
    {
        $this->actingAs($this->superadmin);

        $response = $this->post(route('user-management.store'), []);
        $response->assertSessionHasErrors(['name', 'email', 'role', 'password']);
    }

    public function test_store_fails_with_duplicate_email(): void
    {
        $this->actingAs($this->superadmin);

        $response = $this->post(route('user-management.store'), [
            'name'                  => 'Duplicate',
            'email'                 => $this->dokter->email,
            'role'                  => 'dokter',
            'password'              => 'password123',
            'password_confirmation' => 'password123',
        ]);

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

    public function test_store_cannot_create_superadmin_role(): void
    {
        $this->actingAs($this->superadmin);

        $response = $this->post(route('user-management.store'), [
            'name'                  => 'Fake Admin',
            'email'                 => 'fake@example.com',
            'role'                  => 'superadmin',
            'password'              => 'password123',
            'password_confirmation' => 'password123',
        ]);

        $response->assertSessionHasErrors('role');
        $this->assertDatabaseMissing('users', ['email' => 'fake@example.com']);
    }

    // ─────────────────────────────────────────
    // edit & update
    // ─────────────────────────────────────────

    public function test_superadmin_can_access_edit_page(): void
    {
        $this->actingAs($this->superadmin);
        $response = $this->get(route('user-management.edit', $this->dokter));
        $response->assertStatus(200);
    }

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

        $response = $this->get(route('user-management.edit', $otherAdmin));
        $response->assertStatus(403);
    }

    public function test_update_changes_user_data(): void
    {
        $this->actingAs($this->superadmin);

        $response = $this->put(route('user-management.update', $this->dokter), [
            'name'  => 'Dr. Budi Updated',
            'email' => $this->dokter->email,
            'role'  => 'dokter',
        ]);

        $response->assertRedirect(route('user-management.index'));
        $response->assertSessionHas('success');
        $this->assertEquals('Dr. Budi Updated', $this->dokter->fresh()->name);
    }

    public function test_update_can_change_role(): void
    {
        $this->actingAs($this->superadmin);

        $response = $this->put(route('user-management.update', $this->dokter), [
            'name'  => $this->dokter->name,
            'email' => $this->dokter->email,
            'role'  => 'apoteker',
        ]);

        $response->assertRedirect(route('user-management.index'));
        $this->assertEquals('apoteker', $this->dokter->fresh()->role);
    }

    public function test_update_without_password_keeps_old_password(): void
    {
        $this->actingAs($this->superadmin);
        $oldPassword = $this->dokter->password;

        $this->put(route('user-management.update', $this->dokter), [
            'name'  => $this->dokter->name,
            'email' => $this->dokter->email,
            'role'  => 'dokter',
        ]);

        $this->assertEquals($oldPassword, $this->dokter->fresh()->password);
    }

    public function test_update_with_new_password_changes_password(): void
    {
        $this->actingAs($this->superadmin);
        $oldPassword = $this->dokter->password;

        $this->put(route('user-management.update', $this->dokter), [
            'name'                  => $this->dokter->name,
            'email'                 => $this->dokter->email,
            'role'                  => 'dokter',
            'password'              => 'newpassword123',
            'password_confirmation' => 'newpassword123',
        ]);

        $this->assertNotEquals($oldPassword, $this->dokter->fresh()->password);
    }

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

        $response = $this->put(route('user-management.update', $otherAdmin), [
            'name'  => 'Hacked',
            'email' => $otherAdmin->email,
            'role'  => 'dokter',
        ]);

        $response->assertStatus(403);
    }

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

    public function test_destroy_deletes_user(): void
    {
        $this->actingAs($this->superadmin);
        $userId = $this->dokter->id;

        $response = $this->delete(route('user-management.destroy', $this->dokter));

        $response->assertRedirect(route('user-management.index'));
        $response->assertSessionHas('success');
        $this->assertDatabaseMissing('users', ['id' => $userId]);
    }

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

        $response = $this->delete(route('user-management.destroy', $otherAdmin));
        $response->assertStatus(403);
        $this->assertDatabaseHas('users', ['id' => $otherAdmin->id]);
    }

    public function test_destroy_cannot_delete_self(): void
    {
        $this->actingAs($this->superadmin);

        $response = $this->delete(route('user-management.destroy', $this->superadmin));

        $response->assertRedirect(route('user-management.index'));
        $response->assertSessionHas('error');
        $this->assertDatabaseHas('users', ['id' => $this->superadmin->id]);
    }

    // ─────────────────────────────────────────
    // Non-superadmin cannot store/update/destroy
    // ─────────────────────────────────────────

    public function test_dokter_cannot_store_user(): void
    {
        $this->actingAs($this->dokter);

        $response = $this->post(route('user-management.store'), [
            'name'                  => 'Unauthorized',
            'email'                 => 'unauth@example.com',
            'role'                  => 'dokter',
            'password'              => 'password123',
            'password_confirmation' => 'password123',
        ]);

        $response->assertStatus(403);
        $this->assertDatabaseMissing('users', ['email' => 'unauth@example.com']);
    }

    public function test_apoteker_cannot_delete_user(): void
    {
        $this->actingAs($this->apoteker);

        $response = $this->delete(route('user-management.destroy', $this->dokter));
        $response->assertStatus(403);
        $this->assertDatabaseHas('users', ['id' => $this->dokter->id]);
    }
}
