<?php

namespace App\Models;

use Carbon\CarbonInterface;
use Database\Factories\QrCodeScanFactory;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon;

/**
 * A single scan of a QR code, optionally enriched with device and geo data.
 *
 * @property int $id
 * @property int $qr_code_id
 * @property string|null $ip_address
 * @property string|null $visitor_hash
 * @property string|null $user_agent
 * @property string|null $device_type
 * @property string|null $browser
 * @property string|null $platform
 * @property string|null $country_code
 * @property string|null $country
 * @property string|null $region
 * @property string|null $city
 * @property string|null $latitude
 * @property string|null $longitude
 * @property string|null $referer
 * @property bool $is_bot
 * @property Carbon|null $enriched_at
 * @property Carbon $scanned_at
 * @property Carbon|null $created_at
 * @property Carbon|null $updated_at
 * @property-read QrCode $qrCode
 */
#[Fillable([
    'qr_code_id', 'ip_address', 'visitor_hash', 'user_agent', 'device_type',
    'browser', 'platform', 'country_code', 'country', 'region', 'city',
    'latitude', 'longitude', 'referer', 'is_bot', 'enriched_at', 'scanned_at',
])]
class QrCodeScan extends Model
{
    /** @use HasFactory<QrCodeScanFactory> */
    use HasFactory;

    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'qr_code_scans';

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'latitude' => 'decimal:7',
            'longitude' => 'decimal:7',
            'is_bot' => 'boolean',
            'enriched_at' => 'datetime',
            'scanned_at' => 'datetime',
        ];
    }

    /**
     * Get the QR code this scan belongs to.
     *
     * @return BelongsTo<QrCode, $this>
     */
    public function qrCode(): BelongsTo
    {
        return $this->belongsTo(QrCode::class);
    }

    /**
     * Scope a query to exclude bot/crawler traffic, matching the analytics
     * dashboard's default view.
     *
     * @param  Builder<QrCodeScan>  $query
     * @return Builder<QrCodeScan>
     */
    public function scopeHumans(Builder $query): Builder
    {
        return $query->where('is_bot', false);
    }

    /**
     * Scope a query to scans that occurred within the given date range,
     * inclusive of both bounds.
     *
     * @param  Builder<QrCodeScan>  $query
     * @return Builder<QrCodeScan>
     */
    public function scopeBetween(Builder $query, CarbonInterface $from, CarbonInterface $to): Builder
    {
        return $query->whereBetween('scanned_at', [$from, $to]);
    }
}
