<?php

use App\Enums\UserType;
use App\Models\SalaryCertificateRequest;
use App\Models\User;
use App\Notifications\SalaryCertificateRequested;
use App\Notifications\SalaryCertificateStatusUpdated;
use Illuminate\Support\Facades\Notification;

beforeEach(function () {
    $this->employee = User::factory()->create(['type' => UserType::EMPLOYEE]);
    $this->admin = User::factory()->create(['type' => UserType::SUPER_ADMIN]);
});

test('employee can request a salary certificate', function () {
    Notification::fake();

    $this->actingAs($this->employee)
        ->post(route('employee.salary-certificates.store'), [
            'reason' => 'Need it for bank loan application.',
        ])
        ->assertRedirect()
        ->assertSessionHas('success');

    expect(SalaryCertificateRequest::count())->toBe(1);

    $request = SalaryCertificateRequest::first();
    expect($request->user_id)->toBe($this->employee->id);
    expect($request->status)->toBe('pending');
    expect($request->reason)->toBe('Need it for bank loan application.');

    // Managers/Admins should be notified
    Notification::assertSentTo(
        [$this->admin], // This depends on who is considered a manager in the app
        SalaryCertificateRequested::class
    );
});

test('admin can approve a salary certificate request', function () {
    Notification::fake();

    $request = SalaryCertificateRequest::create([
        'user_id' => $this->employee->id,
        'reason' => 'Test reason',
        'status' => 'pending',
    ]);

    // Bypassing permission middleware for now by using actingAs with admin
    // If the permission middleware is strict, we might need to assign the permission
    $this->actingAs($this->admin)
        ->post(route('admin.payroll.certificate.approve', ['salaryCertificateRequest' => $request->id]))
        ->assertRedirect();

    $request->refresh();
    expect($request->status)->toBe('approved');
    expect($request->approved_by)->toBe($this->admin->id);

    Notification::assertSentTo(
        $this->employee,
        SalaryCertificateStatusUpdated::class
    );
});

test('admin can reject a salary certificate request with reason', function () {
    Notification::fake();

    $request = SalaryCertificateRequest::create([
        'user_id' => $this->employee->id,
        'reason' => 'Test reason',
        'status' => 'pending',
    ]);

    $this->actingAs($this->admin)
        ->post(route('admin.payroll.certificate.reject', ['salaryCertificateRequest' => $request->id]), [
            'rejection_reason' => 'Incomplete information provided.',
        ])
        ->assertRedirect();

    $request->refresh();
    expect($request->status)->toBe('rejected');
    expect($request->rejection_reason)->toBe('Incomplete information provided.');

    Notification::assertSentTo(
        $this->employee,
        SalaryCertificateStatusUpdated::class
    );
});

test('employee cannot download unapproved certificate', function () {
    $request = SalaryCertificateRequest::create([
        'user_id' => $this->employee->id,
        'reason' => 'Test reason',
        'status' => 'pending',
    ]);

    $this->actingAs($this->employee)
        ->get(route('employee.salary-certificates.download', ['salaryCertificateRequest' => $request->id]))
        ->assertRedirect()
        ->assertSessionHas('error');
});

test('employee can download approved certificate', function () {
    $request = SalaryCertificateRequest::create([
        'user_id' => $this->employee->id,
        'reason' => 'Test reason',
        'status' => 'approved',
    ]);

    $this->actingAs($this->employee)
        ->get(route('employee.salary-certificates.download', ['salaryCertificateRequest' => $request->id]))
        ->assertOk()
        ->assertHeader('Content-Type', 'application/pdf');
});
