<?php

declare(strict_types=1);

use App\Enums\EmploymentStatus;
use App\Models\Department;
use App\Models\Employee;
use App\Models\Position;
use App\Models\Shift;
use App\Notifications\EmployeeTerminatedNotification;
use App\Services\Employee\EmployeeService;
use Carbon\Carbon;
use Illuminate\Support\Facades\Notification;

beforeEach(function (): void {
    seedRoles();
    Notification::fake();

    $this->hrManager = createUserWithRole('hr_manager');
    $this->service = app(EmployeeService::class);
});

it('creates an employee with the provided data', function (): void {
    $department = Department::factory()->create();
    $position = Position::factory()->create();
    $shift = Shift::factory()->create();

    $employee = $this->service->create([
        'full_name' => 'John Doe',
        'gender' => 'male',
        'birth_date' => '1990-05-15',
        'phone' => '+993 61 92 92 48',
        'department_id' => $department->id,
        'position_id' => $position->id,
        'shift_id' => $shift->id,
        'employment_status' => EmploymentStatus::Active,
        'hire_date' => '2024-01-01',
    ]);

    expect($employee)->toBeInstanceOf(Employee::class)
        ->and($employee->employee_number)->toBe('EMP-00001')
        ->and($employee->full_name)->toBe('John Doe')
        ->and($employee->employment_status)->toBe(EmploymentStatus::Active);

    $this->assertDatabaseHas('employees', [
        'employee_number' => 'EMP-00001',
        'full_name' => 'John Doe',
    ]);
});

it('creates an employee with an explicit employee number', function (): void {
    $department = Department::factory()->create();
    $position = Position::factory()->create();
    $shift = Shift::factory()->create();

    $employee = $this->service->create([
        'employee_number' => 'EMP-10001',
        'full_name' => 'Jane Doe',
        'gender' => 'female',
        'birth_date' => '1991-06-20',
        'phone' => '+993 61 92 92 48',
        'department_id' => $department->id,
        'position_id' => $position->id,
        'shift_id' => $shift->id,
        'employment_status' => EmploymentStatus::Active,
        'hire_date' => '2024-02-01',
    ]);

    expect($employee->employee_number)->toBe('EMP-10001');
});

it('terminates an employee and notifies hr managers', function (): void {
    $employee = Employee::factory()->active()->create();
    $terminationDate = Carbon::parse('2025-06-30');

    $result = $this->service->terminate($employee, $terminationDate);

    expect($result->employment_status)->toBe(EmploymentStatus::Terminated)
        ->and($result->termination_date->toDateString())->toBe('2025-06-30');

    Notification::assertSentTo(
        [$this->hrManager],
        EmployeeTerminatedNotification::class,
        fn (EmployeeTerminatedNotification $notification): bool => $notification->employee->is($result),
    );
});
