<?php

namespace Database\Factories;

use App\Models\ExpenseRequest;
use App\Models\ExpenseType;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\ExpenseRequest>
 */
class ExpenseRequestFactory extends Factory
{
    protected $model = ExpenseRequest::class;

    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'user_id' => User::factory(),
            'expense_type_id' => ExpenseType::factory(),
            'for_date' => fake()->dateTimeBetween('-30 days', 'now'),
            'amount' => fake()->randomFloat(2, 50, 2000),
            'remarks' => fake()->optional()->sentence(),
            'status' => 'pending',
            'document_url' => null,
            'approved_amount' => null,
            'approved_at' => null,
            'approved_by_id' => null,
            'rejected_at' => null,
            'rejected_by_id' => null,
            'admin_remarks' => null,
            'processed_in_payroll' => false,
            'payroll_record_id' => null,
            'payroll_processed_at' => null,
        ];
    }

    /**
     * Indicate that the expense request is pending.
     */
    public function pending(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => 'pending',
            'approved_at' => null,
            'approved_by_id' => null,
            'approved_amount' => null,
            'rejected_at' => null,
            'rejected_by_id' => null,
        ]);
    }

    /**
     * Indicate that the expense request is approved.
     */
    public function approved(): static
    {
        return $this->state(function (array $attributes) {
            $approvedAmount = $attributes['amount'] ?? fake()->randomFloat(2, 50, 2000);

            return [
                'status' => 'approved',
                'approved_at' => now(),
                'approved_by_id' => User::factory(),
                'approved_amount' => $approvedAmount,
                'rejected_at' => null,
                'rejected_by_id' => null,
            ];
        });
    }

    /**
     * Indicate that the expense request is rejected.
     */
    public function rejected(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => 'rejected',
            'rejected_at' => now(),
            'rejected_by_id' => User::factory(),
            'admin_remarks' => fake()->sentence(),
            'approved_at' => null,
            'approved_by_id' => null,
            'approved_amount' => null,
        ]);
    }

    /**
     * Indicate that the expense request is cancelled.
     */
    public function cancelled(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => 'cancelled',
            'approved_at' => null,
            'approved_by_id' => null,
            'approved_amount' => null,
            'rejected_at' => null,
            'rejected_by_id' => null,
        ]);
    }

    /**
     * Indicate that the expense request has a document.
     */
    public function withDocument(): static
    {
        return $this->state(fn (array $attributes) => [
            'document_url' => fake()->uuid().'.pdf',
        ]);
    }

    /**
     * Set a specific user for this expense request.
     */
    public function forUser(User $user): static
    {
        return $this->state(fn (array $attributes) => [
            'user_id' => $user->id,
        ]);
    }

    /**
     * Set a specific expense type for this expense request.
     */
    public function forExpenseType(ExpenseType $expenseType): static
    {
        return $this->state(fn (array $attributes) => [
            'expense_type_id' => $expenseType->id,
        ]);
    }

    /**
     * Set a specific amount for this expense request.
     */
    public function withAmount(float $amount): static
    {
        return $this->state(fn (array $attributes) => [
            'amount' => $amount,
        ]);
    }

    /**
     * Indicate that the expense has been processed in payroll.
     */
    public function processedInPayroll(): static
    {
        return $this->state(fn (array $attributes) => [
            'processed_in_payroll' => true,
            'payroll_processed_at' => now(),
        ]);
    }
}
