<?php

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Inertia\Testing\AssertableInertia as Assert;

uses(RefreshDatabase::class);

/*
|--------------------------------------------------------------------------
| AUTHENTICATION
|--------------------------------------------------------------------------
*/

test('guests are redirected to the login page', function () {
    $response = $this->get(route('admin.hr.employees.index'));
    $response->assertRedirect(route('login'));
});

test('authenticated users can visit the employee index page', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->get(route('admin.hr.employees.index'));
    $response->assertOk();
});

/*
|--------------------------------------------------------------------------
| INDEX PAGE
|--------------------------------------------------------------------------
*/

test('employee index page displays employees', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $employeeUser = User::factory()->create();
    $employeeUser->userProfile()->create([
        'full_name' => 'Budi Santoso',
        'phone_number' => '08123456789',
        'gender' => 'male',
    ]);
    $employeeUser->employee()->create([
        'join_date' => '2024-01-15',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

    $response = $this->get(route('admin.hr.employees.index'));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 1)
        ->where('employees.total', 1)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
    );
});

test('index page works with zero employees', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->get(route('admin.hr.employees.index'));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 0)
        ->where('employees.total', 0)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
    );
});

test('index page does not display users without employee record', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    User::factory()->create();

    $response = $this->get(route('admin.hr.employees.index'));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 0)
        ->where('employees.total', 0)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
    );
});

test('index page displays correct count after delete', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $employeeUser = User::factory()->create();
    $employeeUser->userProfile()->create(['full_name' => 'Employee 1', 'gender' => 'male']);
    $employeeUser->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $employeeUser2 = User::factory()->create();
    $employeeUser2->userProfile()->create(['full_name' => 'Employee 2', 'gender' => 'female']);
    $employeeUser2->employee()->create(['join_date' => '2024-02-01', 'employment_status' => 'part_time', 'base_salary' => 3000000]);

    $this->delete(route('admin.hr.employees.destroy', $employeeUser));

    $response = $this->get(route('admin.hr.employees.index'));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 1)
        ->where('employees.total', 1)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
    );
});

/*
|--------------------------------------------------------------------------
| FILTER - EMPLOYMENT STATUS
|--------------------------------------------------------------------------
*/

test('index can filter by employment status full_time', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $ft = User::factory()->create();
    $ft->userProfile()->create(['full_name' => 'Full Time Employee', 'gender' => 'male']);
    $ft->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $pt = User::factory()->create();
    $pt->userProfile()->create(['full_name' => 'Part Time Employee', 'gender' => 'female']);
    $pt->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'part_time', 'base_salary' => 3000000]);

    $response = $this->get(route('admin.hr.employees.index', ['employment_status' => 'full_time']));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 1)
        ->where('employees.total', 1)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
        ->where('employees.data.0.user_profile.full_name', 'Full Time Employee')
    );
});

test('index can filter by employment status contract', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $contract = User::factory()->create();
    $contract->userProfile()->create(['full_name' => 'Contract Employee', 'gender' => 'male']);
    $contract->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'contract', 'base_salary' => 4000000]);

    $intern = User::factory()->create();
    $intern->userProfile()->create(['full_name' => 'Intern Employee', 'gender' => 'female']);
    $intern->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'internship', 'base_salary' => 2000000]);

    $response = $this->get(route('admin.hr.employees.index', ['employment_status' => 'contract']));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 1)
        ->where('employees.total', 1)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
        ->where('employees.data.0.user_profile.full_name', 'Contract Employee')
    );
});

test('index can filter by employment status resigned', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $active = User::factory()->create();
    $active->userProfile()->create(['full_name' => 'Active Employee', 'gender' => 'male']);
    $active->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $resigned = User::factory()->create();
    $resigned->userProfile()->create(['full_name' => 'Resigned Employee', 'gender' => 'female']);
    $resigned->employee()->create(['join_date' => '2024-01-01', 'resign_date' => '2024-06-01', 'employment_status' => 'resigned', 'base_salary' => 5000000]);

    $response = $this->get(route('admin.hr.employees.index', ['employment_status' => 'resigned']));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 1)
        ->where('employees.total', 1)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
        ->where('employees.data.0.user_profile.full_name', 'Resigned Employee')
    );
});

/*
|--------------------------------------------------------------------------
| FILTER - IS ACTIVE
|--------------------------------------------------------------------------
*/

test('index can filter by is_active true', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $active = User::factory()->create(['is_active' => true]);
    $active->userProfile()->create(['full_name' => 'Active Employee', 'gender' => 'male']);
    $active->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $inactive = User::factory()->create(['is_active' => false]);
    $inactive->userProfile()->create(['full_name' => 'Inactive Employee', 'gender' => 'female']);
    $inactive->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $response = $this->get(route('admin.hr.employees.index', ['is_active' => '1']));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 1)
        ->where('employees.total', 1)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
        ->where('employees.data.0.user_profile.full_name', 'Active Employee')
    );
});

test('index can filter by is_active false', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $active = User::factory()->create(['is_active' => true]);
    $active->userProfile()->create(['full_name' => 'Active Employee', 'gender' => 'male']);
    $active->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $inactive = User::factory()->create(['is_active' => false]);
    $inactive->userProfile()->create(['full_name' => 'Inactive Employee', 'gender' => 'female']);
    $inactive->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $response = $this->get(route('admin.hr.employees.index', ['is_active' => '0']));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 1)
        ->where('employees.total', 1)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
        ->where('employees.data.0.user_profile.full_name', 'Inactive Employee')
    );
});

/*
|--------------------------------------------------------------------------
| FILTER - GENDER
|--------------------------------------------------------------------------
*/

test('index can filter by gender male', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $male = User::factory()->create();
    $male->userProfile()->create(['full_name' => 'Male Employee', 'gender' => 'male']);
    $male->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $female = User::factory()->create();
    $female->userProfile()->create(['full_name' => 'Female Employee', 'gender' => 'female']);
    $female->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $response = $this->get(route('admin.hr.employees.index', ['gender' => 'male']));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 1)
        ->where('employees.total', 1)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
        ->where('employees.data.0.user_profile.full_name', 'Male Employee')
    );
});

test('index can filter by gender female', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $male = User::factory()->create();
    $male->userProfile()->create(['full_name' => 'Male Employee', 'gender' => 'male']);
    $male->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $female = User::factory()->create();
    $female->userProfile()->create(['full_name' => 'Female Employee', 'gender' => 'female']);
    $female->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $response = $this->get(route('admin.hr.employees.index', ['gender' => 'female']));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 1)
        ->where('employees.total', 1)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
        ->where('employees.data.0.user_profile.full_name', 'Female Employee')
    );
});

/*
|--------------------------------------------------------------------------
| FILTER - COMBINED
|--------------------------------------------------------------------------
*/

test('index can filter by multiple criteria combined', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $match = User::factory()->create(['is_active' => true]);
    $match->userProfile()->create(['full_name' => 'Match Employee', 'gender' => 'male']);
    $match->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $noMatch1 = User::factory()->create(['is_active' => true]);
    $noMatch1->userProfile()->create(['full_name' => 'Female FT', 'gender' => 'female']);
    $noMatch1->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $noMatch2 = User::factory()->create(['is_active' => false]);
    $noMatch2->userProfile()->create(['full_name' => 'Male Inactive', 'gender' => 'male']);
    $noMatch2->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $noMatch3 = User::factory()->create(['is_active' => true]);
    $noMatch3->userProfile()->create(['full_name' => 'Male Contract', 'gender' => 'male']);
    $noMatch3->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'contract', 'base_salary' => 4000000]);

    $response = $this->get(route('admin.hr.employees.index', [
        'employment_status' => 'full_time',
        'is_active' => '1',
        'gender' => 'male',
    ]));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 1)
        ->where('employees.total', 1)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
        ->where('employees.data.0.user_profile.full_name', 'Match Employee')
    );
});

test('index passes filters to view', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->get(route('admin.hr.employees.index', [
        'employment_status' => 'full_time',
        'is_active' => '1',
        'gender' => 'male',
    ]));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->where('filters.employment_status', 'full_time')
        ->where('filters.is_active', '1')
        ->where('filters.gender', 'male')
    );
});

/*
|--------------------------------------------------------------------------
| CREATE / STORE
|--------------------------------------------------------------------------
*/

test('employee can be created', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'newemployee@example.com',
        'username' => 'newemployee',
        'full_name' => 'New Employee',
        'phone_number' => '08123456789',
        'gender' => 'male',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

    $response
        ->assertSessionHasNoErrors()
        ->assertRedirect(route('admin.hr.employees.index'));

    $this->assertDatabaseHas('users', [
        'email' => 'newemployee@example.com',
        'username' => 'newemployee',
    ]);
    $this->assertDatabaseHas('user_profiles', [
        'full_name' => 'New Employee',
        'gender' => 'male',
    ]);
    $this->assertDatabaseHas('employees', [
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);
});

test('employee can be created without optional fields', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'minimal@example.com',
        'username' => 'minimal',
        'full_name' => 'Minimal Employee',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

    $response->assertSessionHasNoErrors();
});

test('employee email is required', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'username' => 'noemail',
        'full_name' => 'No Email',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

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

test('employee email must be valid', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'not-an-email',
        'username' => 'bademail',
        'full_name' => 'Bad Email',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

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

test('employee email must be unique', function () {
    $user = User::factory()->create(['email' => 'existing@example.com']);
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'existing@example.com',
        'username' => 'duplicate',
        'full_name' => 'Duplicate Email',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

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

test('employee username is required', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'nousername@example.com',
        'full_name' => 'No Username',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

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

test('employee username must be alpha_dash', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'badusername@example.com',
        'username' => 'has spaces!',
        'full_name' => 'Bad Username',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

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

test('employee username must be unique', function () {
    $user = User::factory()->create(['username' => 'existinguser']);
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'new@example.com',
        'username' => 'existinguser',
        'full_name' => 'Duplicate Username',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

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

test('employee full_name is required', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'noname@example.com',
        'username' => 'noname',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

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

test('employee join_date is required', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'nojoindate@example.com',
        'username' => 'nojoindate',
        'full_name' => 'No Join Date',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

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

test('employee join_date must be valid date', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'baddate@example.com',
        'username' => 'baddate',
        'full_name' => 'Bad Date',
        'join_date' => 'not-a-date',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

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

test('employee employment_status is required', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'nostatus@example.com',
        'username' => 'nostatus',
        'full_name' => 'No Status',
        'join_date' => '2024-06-01',
        'base_salary' => 5000000,
    ]);

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

test('employee employment_status must be valid', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'badstatus@example.com',
        'username' => 'badstatus',
        'full_name' => 'Bad Status',
        'join_date' => '2024-06-01',
        'employment_status' => 'invalid_status',
        'base_salary' => 5000000,
    ]);

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

test('employee base_salary is required', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'nosalary@example.com',
        'username' => 'nosalary',
        'full_name' => 'No Salary',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
    ]);

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

test('employee base_salary must be integer', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'badsalary@example.com',
        'username' => 'badsalary',
        'full_name' => 'Bad Salary',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 'not-a-number',
    ]);

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

test('employee base_salary must not be negative', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'negsalary@example.com',
        'username' => 'negsalary',
        'full_name' => 'Negative Salary',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => -1000,
    ]);

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

test('employee gender must be valid enum', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'badgender@example.com',
        'username' => 'badgender',
        'full_name' => 'Bad Gender',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
        'gender' => 'other',
    ]);

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

test('employee resign_date must be after or equal join_date', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'badresigndate@example.com',
        'username' => 'badresigndate',
        'full_name' => 'Bad Resign Date',
        'join_date' => '2024-06-01',
        'resign_date' => '2024-01-01',
        'employment_status' => 'resigned',
        'base_salary' => 5000000,
    ]);

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

test('store flashes success toast via Inertia', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'toast@example.com',
        'username' => 'toast',
        'full_name' => 'Toast Employee',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

    $response->assertRedirect();
});

test('store creates user, profile, and employee in database', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $this->post(route('admin.hr.employees.store'), [
        'email' => 'full@example.com',
        'username' => 'fullcreate',
        'full_name' => 'Full Create',
        'phone_number' => '08123456789',
        'gender' => 'female',
        'join_date' => '2024-06-01',
        'employment_status' => 'part_time',
        'base_salary' => 3000000,
    ]);

    $this->assertDatabaseCount('users', 2);
    $this->assertDatabaseHas('users', ['email' => 'full@example.com']);
    $this->assertDatabaseHas('user_profiles', ['full_name' => 'Full Create', 'gender' => 'female']);
    $this->assertDatabaseHas('employees', ['employment_status' => 'part_time', 'base_salary' => 3000000]);
});

/*
|--------------------------------------------------------------------------
| EDIT / UPDATE
|--------------------------------------------------------------------------
*/

test('employee can be updated', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $employeeUser = User::factory()->create(['username' => 'original_user']);
    $employeeUser->userProfile()->create(['full_name' => 'Original Name', 'gender' => 'male']);
    $employeeUser->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $response = $this->put(route('admin.hr.employees.update', $employeeUser), [
        'email' => $employeeUser->email,
        'username' => 'original_user',
        'full_name' => 'Updated Name',
        'phone_number' => '0987654321',
        'gender' => 'female',
        'join_date' => '2024-01-01',
        'employment_status' => 'part_time',
        'base_salary' => 3000000,
    ]);

    $response
        ->assertSessionHasNoErrors()
        ->assertRedirect(route('admin.hr.employees.index'));

    $employeeUser->refresh();
    expect($employeeUser->userProfile->full_name)->toBe('Updated Name');
    expect($employeeUser->userProfile->gender->value)->toBe('female');
    expect($employeeUser->employee->employment_status->value)->toBe('part_time');
    expect($employeeUser->employee->base_salary)->toBe(3000000);
});

test('employee update email must be unique excluding itself', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $employeeUser = User::factory()->create(['email' => 'first@example.com']);
    $employeeUser->userProfile()->create(['full_name' => 'First', 'gender' => 'male']);
    $employeeUser->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $other = User::factory()->create(['email' => 'second@example.com']);

    $response = $this->put(route('admin.hr.employees.update', $employeeUser), [
        'email' => 'second@example.com',
        'username' => $employeeUser->username,
        'full_name' => 'First',
        'join_date' => '2024-01-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

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

test('employee update username must be unique excluding itself', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $employeeUser = User::factory()->create(['username' => 'firstuser']);
    $employeeUser->userProfile()->create(['full_name' => 'First', 'gender' => 'male']);
    $employeeUser->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $other = User::factory()->create(['username' => 'seconduser']);

    $response = $this->put(route('admin.hr.employees.update', $employeeUser), [
        'email' => $employeeUser->email,
        'username' => 'seconduser',
        'full_name' => 'First',
        'join_date' => '2024-01-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

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

test('updating non-existent employee returns 404', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->put(route('admin.hr.employees.update', 999999), [
        'email' => 'ghost@example.com',
        'username' => 'ghost',
        'full_name' => 'Ghost',
        'join_date' => '2024-01-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

    $response->assertStatus(404);
});

/*
|--------------------------------------------------------------------------
| DELETE / DESTROY
|--------------------------------------------------------------------------
*/

test('employee can be deleted', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $employeeUser = User::factory()->create();
    $employeeUser->userProfile()->create(['full_name' => 'To Delete', 'gender' => 'male']);
    $employeeUser->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $response = $this->delete(route('admin.hr.employees.destroy', $employeeUser));

    $response
        ->assertSessionHasNoErrors()
        ->assertRedirect(route('admin.hr.employees.index'));

    $this->assertSoftDeleted('users', ['id' => $employeeUser->id]);
    $this->assertSoftDeleted('user_profiles', ['user_id' => $employeeUser->id]);
    $this->assertSoftDeleted('employees', ['user_id' => $employeeUser->id]);
});

test('delete flashes success toast via Inertia', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $employeeUser = User::factory()->create();
    $employeeUser->userProfile()->create(['full_name' => 'Toast Delete', 'gender' => 'male']);
    $employeeUser->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $response = $this->delete(route('admin.hr.employees.destroy', $employeeUser));

    $response->assertRedirect();
});

test('deleting non-existent employee returns 404', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->delete(route('admin.hr.employees.destroy', 999999));

    $response->assertStatus(404);
});

/*
|--------------------------------------------------------------------------
| TOGGLE ACTIVE
|--------------------------------------------------------------------------
*/

test('employee can be toggled active', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $employeeUser = User::factory()->create(['is_active' => true]);
    $employeeUser->userProfile()->create(['full_name' => 'Toggle Me', 'gender' => 'male']);
    $employeeUser->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $response = $this->post(route('admin.hr.employees.toggle-active', $employeeUser));

    $response->assertRedirect();

    $employeeUser->refresh();
    expect($employeeUser->is_active)->toBeFalse();
});

test('employee can be toggled back to active', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $employeeUser = User::factory()->create(['is_active' => false]);
    $employeeUser->userProfile()->create(['full_name' => 'Toggle Back', 'gender' => 'female']);
    $employeeUser->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $this->post(route('admin.hr.employees.toggle-active', $employeeUser));

    $employeeUser->refresh();
    expect($employeeUser->is_active)->toBeTrue();
});

/*
|--------------------------------------------------------------------------
| RESET PASSWORD
|--------------------------------------------------------------------------
*/

test('employee password can be reset', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $employeeUser = User::factory()->create(['password' => 'old-password']);
    $employeeUser->userProfile()->create(['full_name' => 'Reset Me', 'gender' => 'male']);
    $employeeUser->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $response = $this->post(route('admin.hr.employees.reset-password', $employeeUser));

    $response->assertRedirect();

    $employeeUser->refresh();
    expect($employeeUser->password)->not->toBe('old-password');
});

/*
|--------------------------------------------------------------------------
| AUTHORIZATION - GUEST CANNOT PERFORM ACTIONS
|--------------------------------------------------------------------------
*/

test('guest cannot create employee', function () {
    $response = $this->post(route('admin.hr.employees.store'), [
        'email' => 'unauthorized@example.com',
        'username' => 'unauthorized',
        'full_name' => 'Unauthorized',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

    $response->assertRedirect(route('login'));
});

test('guest cannot update employee', function () {
    $employeeUser = User::factory()->create();
    $employeeUser->userProfile()->create(['full_name' => 'Protected', 'gender' => 'male']);
    $employeeUser->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $response = $this->put(route('admin.hr.employees.update', $employeeUser), [
        'email' => 'hacked@example.com',
        'username' => 'hacked',
        'full_name' => 'Hacked',
        'join_date' => '2024-01-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

    $response->assertRedirect(route('login'));
});

test('guest cannot delete employee', function () {
    $employeeUser = User::factory()->create();
    $employeeUser->userProfile()->create(['full_name' => 'Protected', 'gender' => 'male']);
    $employeeUser->employee()->create(['join_date' => '2024-01-01', 'employment_status' => 'full_time', 'base_salary' => 5000000]);

    $response = $this->delete(route('admin.hr.employees.destroy', $employeeUser));

    $response->assertRedirect(route('login'));
    $this->assertDatabaseHas('users', ['id' => $employeeUser->id]);
});

/*
|--------------------------------------------------------------------------
| DATA INTEGRITY
|--------------------------------------------------------------------------
*/

test('created employee has correct timestamps', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $this->post(route('admin.hr.employees.store'), [
        'email' => 'timestamp@example.com',
        'username' => 'timestamp',
        'full_name' => 'Timestamp Employee',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

    $employeeUser = User::where('email', 'timestamp@example.com')->first();
    expect($employeeUser->created_at)->not->toBeNull();
    expect($employeeUser->employee->created_at)->not->toBeNull();
});

test('employee factory creates valid employee', function () {
    $employeeUser = User::factory()->create();
    $employeeUser->userProfile()->create(['full_name' => fake()->name(), 'gender' => 'male']);
    $employeeUser->employee()->create([
        'join_date' => fake()->date(),
        'employment_status' => fake()->randomElement(['full_time', 'part_time', 'contract', 'internship', 'resigned']),
        'base_salary' => fake()->numberBetween(1000000, 10000000),
    ]);

    expect($employeeUser->employee)->not->toBeNull();
    expect($employeeUser->userProfile)->not->toBeNull();
});

/*
|--------------------------------------------------------------------------
| REALISTIC USER SCENARIOS
|--------------------------------------------------------------------------
*/

test('user creates employee then immediately edits it', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $this->post(route('admin.hr.employees.store'), [
        'email' => 'draft@example.com',
        'username' => 'draftemp',
        'full_name' => 'Draft Employee',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

    $employeeUser = User::where('email', 'draft@example.com')->first();

    $this->put(route('admin.hr.employees.update', $employeeUser), [
        'email' => 'final@example.com',
        'username' => 'draftemp',
        'full_name' => 'Final Employee',
        'join_date' => '2024-06-01',
        'employment_status' => 'full_time',
        'base_salary' => 6000000,
    ]);

    $employeeUser->refresh();
    expect($employeeUser->email)->toBe('final@example.com');
    expect($employeeUser->userProfile->full_name)->toBe('Final Employee');
    expect($employeeUser->employee->base_salary)->toBe(6000000);
});

test('user creates multiple employees and deletes one', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $this->post(route('admin.hr.employees.store'), [
        'email' => 'emp1@example.com',
        'username' => 'emp1',
        'full_name' => 'Employee 1',
        'join_date' => '2024-01-01',
        'employment_status' => 'full_time',
        'base_salary' => 5000000,
    ]);

    $this->post(route('admin.hr.employees.store'), [
        'email' => 'emp2@example.com',
        'username' => 'emp2',
        'full_name' => 'Employee 2',
        'join_date' => '2024-01-01',
        'employment_status' => 'part_time',
        'base_salary' => 3000000,
    ]);

    $toDelete = User::where('email', 'emp1@example.com')->first();
    $this->delete(route('admin.hr.employees.destroy', $toDelete));

    $response = $this->get(route('admin.hr.employees.index'));
    $response->assertOk();
    $response->assertInertia(fn (Assert $page) => $page
        ->component('admin/hr/employee/index')
        ->has('employees.data', 1)
        ->where('employees.total', 1)
        ->where('employees.current_page', 1)
        ->where('employees.per_page', 25)
    );
});

test('user tries to create employee without submitting any data', function () {
    $user = User::factory()->create();
    $this->actingAs($user);

    $response = $this->post(route('admin.hr.employees.store'), []);

    $response->assertSessionHasErrors(['email', 'username', 'full_name', 'join_date', 'employment_status', 'base_salary']);
});
