<?php

declare(strict_types=1);

namespace Database\Factories;

use App\Enums\AssetCondition;
use App\Enums\AssignmentStatus;
use App\Models\Asset;
use App\Models\AssetAssignment;
use App\Models\Employee;
use DateTimeInterface;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * Test data only.
 *
 * Unlike a real assignment, this factory writes rows directly rather than
 * going through AssignmentService, so it does not touch the asset's own
 * `status` / `current_*` pointers. Tests that exercise those invariants (one
 * active assignment, legal status routing on return) call the service
 * itself; this factory is for tests that only need assignment rows to exist
 * — listings, relations, history.
 *
 * @extends Factory<AssetAssignment>
 */
class AssetAssignmentFactory extends Factory
{
    // The return shape is inherited from Factory<AssetAssignment>::definition().
    public function definition(): array
    {
        return [
            'asset_id' => Asset::factory(),
            'employee_id' => Employee::factory(),
            'status' => AssignmentStatus::Active,
            'assigned_at' => fake()->dateTimeBetween('-6 months', 'now'),
            'assigned_by' => null,
            'expected_return_at' => null,
            'assignment_location_id' => null,
            'condition_on_issue' => AssetCondition::Good,
            'issue_notes' => null,
            'acknowledgement_ref' => null,
            'returned_at' => null,
            'received_by' => null,
            'condition_on_return' => null,
            'return_notes' => null,
        ];
    }

    public function returned(): static
    {
        return $this->state(function (array $attributes): array {
            /** @var DateTimeInterface $assignedAt */
            $assignedAt = $attributes['assigned_at'] ?? now()->subMonth();

            return [
                'status' => AssignmentStatus::Returned,
                'returned_at' => fake()->dateTimeBetween($assignedAt, 'now'),
                'condition_on_return' => AssetCondition::Good,
            ];
        });
    }

    public function forAsset(Asset $asset): static
    {
        return $this->state(fn (array $attributes): array => ['asset_id' => $asset->getKey()]);
    }

    public function forEmployee(Employee $employee): static
    {
        return $this->state(fn (array $attributes): array => ['employee_id' => $employee->getKey()]);
    }

    public function expectedBack(DateTimeInterface $date): static
    {
        return $this->state(fn (array $attributes): array => ['expected_return_at' => $date]);
    }
}
