<?php

namespace Database\Factories;

use App\Enums\VisitorStatus;
use App\Enums\VisitorType;
use App\Models\Flat;
use App\Models\Guard;
use App\Models\User;
use App\Models\Visitor;
use App\Models\Wing;
use Illuminate\Database\Eloquent\Factories\Factory;

class VisitorFactory extends Factory
{
    protected $model = Visitor::class;

    public function definition(): array
    {
        $status = $this->faker->randomElement(VisitorStatus::cases());
        $entryTime = $this->faker->dateTimeBetween('-7 days', '+7 days');
        $exitTime = null;

        if (in_array($status, [VisitorStatus::CHECKED_OUT, VisitorStatus::EXPIRED])) {
            $exitTime = $this->faker->dateTimeBetween($entryTime, $entryTime->format('Y-m-d') . ' 23:59:59');
        }

        return [
            'wing_id' => Wing::factory(),
            'flat_id' => Flat::factory(),
            'approved_by' => $status !== VisitorStatus::PENDING ? User::factory() : null,
            'checked_in_by' => in_array($status, [VisitorStatus::CHECKED_IN, VisitorStatus::CHECKED_OUT]) ? Guard::factory() : null,
            'checked_out_by' => $status === VisitorStatus::CHECKED_OUT ? Guard::factory() : null,
            'name' => $this->faker->name(),
            'phone' => $this->faker->unique()->numerify('##########'),
            'email' => $this->faker->optional()->safeEmail(),
            'visitor_type' => $this->faker->randomElement(VisitorType::cases()),
            'purpose' => $this->getPurposeForType($this->faker->randomElement(VisitorType::cases())),
            'status' => $status,
            'entry_time' => $entryTime,
            'exit_time' => $exitTime,
            'approved_at' => $status !== VisitorStatus::PENDING ? $this->faker->dateTimeBetween('-1 day', 'now') : null,
            'approval_notes' => $status === VisitorStatus::APPROVED ? $this->faker->optional()->sentence() : null,
            'rejection_reason' => $status === VisitorStatus::REJECTED ? $this->faker->sentence() : null,
            'additional_info' => $this->faker->optional()->passthrough([
                'id_number' => $this->faker->numerify('############'),
                'emergency_contact' => $this->faker->numerify('##########'),
                'vehicle_number' => $this->faker->optional()->regexify('[A-Z]{2}[0-9]{2}[A-Z]{2}[0-9]{4}'),
            ]),
            'is_recurring' => $this->faker->boolean(20), // 20% chance of being recurring
        ];
    }

    private function getPurposeForType(VisitorType $type): string
    {
        $purposes = match ($type) {
            VisitorType::GUEST => ['Personal visit', 'Family gathering', 'Social visit', 'Birthday party'],
            VisitorType::SERVICE_PROVIDER => ['Plumbing service', 'Electrical work', 'AC repair', 'Cleaning service', 'Internet installation'],
            VisitorType::DELIVERY => ['Amazon delivery', 'Food delivery', 'Grocery delivery', 'Medicine delivery', 'Document delivery'],
            VisitorType::CONTRACTOR => ['Home renovation', 'Painting work', 'Interior design', 'Furniture installation', 'Construction work'],
            VisitorType::FAMILY => ['Parent visit', 'Sibling visit', 'Relative visit', 'Family function'],
            VisitorType::FRIEND => ['Friend visit', 'Study group', 'Social gathering', 'Birthday celebration'],
            VisitorType::OTHER => ['Official work', 'Business meeting', 'Survey', 'Inspection', 'Other purpose'],
        };

        return $this->faker->randomElement($purposes);
    }

    public function pending(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => VisitorStatus::PENDING,
            'approved_by' => null,
            'approved_at' => null,
            'approval_notes' => null,
            'rejection_reason' => null,
            'checked_in_by' => null,
            'checked_out_by' => null,
        ]);
    }

    public function approved(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => VisitorStatus::APPROVED,
            'approved_by' => User::factory(),
            'approved_at' => $this->faker->dateTimeBetween('-1 day', 'now'),
            'approval_notes' => $this->faker->optional()->sentence(),
            'rejection_reason' => null,
        ]);
    }

    public function rejected(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => VisitorStatus::REJECTED,
            'approved_by' => User::factory(),
            'approved_at' => $this->faker->dateTimeBetween('-1 day', 'now'),
            'approval_notes' => null,
            'rejection_reason' => $this->faker->sentence(),
        ]);
    }

    public function checkedIn(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => VisitorStatus::CHECKED_IN,
            'approved_by' => User::factory(),
            'approved_at' => $this->faker->dateTimeBetween('-1 day', '-1 hour'),
            'checked_in_by' => Guard::factory(),
            'entry_time' => $this->faker->dateTimeBetween('-8 hours', 'now'),
            'exit_time' => null,
        ]);
    }

    public function checkedOut(): static
    {
        return $this->state(function (array $attributes) {
            $entryTime = $this->faker->dateTimeBetween('-1 day', '-2 hours');
            return [
                'status' => VisitorStatus::CHECKED_OUT,
                'approved_by' => User::factory(),
                'approved_at' => $this->faker->dateTimeBetween('-2 days', $entryTime),
                'checked_in_by' => Guard::factory(),
                'checked_out_by' => Guard::factory(),
                'entry_time' => $entryTime,
                'exit_time' => $this->faker->dateTimeBetween($entryTime, 'now'),
            ];
        });
    }

    public function today(): static
    {
        return $this->state(fn (array $attributes) => [
            'entry_time' => $this->faker->dateTimeBetween('today', '+1 day'),
        ]);
    }

    public function recurring(): static
    {
        return $this->state(fn (array $attributes) => [
            'is_recurring' => true,
        ]);
    }

    public function guest(): static
    {
        return $this->state(fn (array $attributes) => [
            'visitor_type' => VisitorType::GUEST,
            'purpose' => $this->getPurposeForType(VisitorType::GUEST),
        ]);
    }

    public function delivery(): static
    {
        return $this->state(fn (array $attributes) => [
            'visitor_type' => VisitorType::DELIVERY,
            'purpose' => $this->getPurposeForType(VisitorType::DELIVERY),
        ]);
    }

    public function serviceProvider(): static
    {
        return $this->state(fn (array $attributes) => [
            'visitor_type' => VisitorType::SERVICE_PROVIDER,
            'purpose' => $this->getPurposeForType(VisitorType::SERVICE_PROVIDER),
        ]);
    }
}
