<?php

namespace Database\Factories;

use App\Models\QrCode;
use App\Models\QrCodeScan;
use Carbon\CarbonInterface;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends Factory<QrCodeScan>
 */
class QrCodeScanFactory extends Factory
{
    /**
     * Device types recorded for a scan, mirroring Matomo DeviceDetector's
     * output values.
     *
     * @var array<int, string>
     */
    private const DEVICE_TYPES = ['smartphone', 'tablet', 'desktop', 'tv', 'console'];

    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        $scannedAt = fake()->dateTimeBetween('-3 months', 'now');

        return [
            'qr_code_id' => QrCode::factory(),
            'ip_address' => fake()->ipv4(),
            'visitor_hash' => hash('sha256', fake()->uuid()),
            'user_agent' => fake()->userAgent(),
            'device_type' => fake()->randomElement(self::DEVICE_TYPES),
            'browser' => fake()->randomElement(['Chrome', 'Safari', 'Firefox', 'Edge']),
            'platform' => fake()->randomElement(['Android', 'iOS', 'Windows', 'macOS']),
            'country_code' => 'IN',
            'country' => 'India',
            'region' => 'Gujarat',
            'city' => 'Surat',
            'latitude' => fake()->latitude(21, 22),
            'longitude' => fake()->longitude(72, 73),
            'referer' => fake()->optional()->url(),
            'is_bot' => false,
            'enriched_at' => $scannedAt,
            'scanned_at' => $scannedAt,
        ];
    }

    /**
     * Indicate that the scan came from a bot/crawler, not a real visitor.
     */
    public function bot(): static
    {
        return $this->state(fn (array $attributes) => [
            'device_type' => 'bot',
            'browser' => null,
            'is_bot' => true,
        ]);
    }

    /**
     * Indicate that the scan came from a smartphone.
     */
    public function mobile(): static
    {
        return $this->state(fn (array $attributes) => [
            'device_type' => 'smartphone',
            'platform' => fake()->randomElement(['Android', 'iOS']),
        ]);
    }

    /**
     * Indicate that the scan came from a desktop browser.
     */
    public function desktop(): static
    {
        return $this->state(fn (array $attributes) => [
            'device_type' => 'desktop',
            'platform' => fake()->randomElement(['Windows', 'macOS']),
        ]);
    }

    /**
     * Indicate that the scan originated from the given ISO-3166 alpha-2
     * country code.
     */
    public function fromCountry(string $code): static
    {
        return $this->state(fn (array $attributes) => [
            'country_code' => strtoupper($code),
            'country' => fake()->country(),
        ]);
    }

    /**
     * Indicate the exact timestamp the scan occurred at.
     */
    public function scannedAt(CarbonInterface $at): static
    {
        return $this->state(fn (array $attributes) => [
            'scanned_at' => $at,
            'enriched_at' => $at,
        ]);
    }
}
