<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

class DriverLocation extends Model
{
    use HasFactory;

    protected $fillable = [
        'driver_id',
        'latitude',
        'longitude',
        'accuracy',
        'speed',
        'heading',
        'is_online',
        'last_ping_at',
    ];

    protected $casts = [
        'latitude' => 'decimal:8',
        'longitude' => 'decimal:8',
        'accuracy' => 'decimal:2',
        'speed' => 'decimal:2',
        'heading' => 'decimal:2',
        'is_online' => 'boolean',
        'last_ping_at' => 'datetime',
    ];

    /**
     * Get the driver that owns the location
     */
    public function driver()
    {
        return $this->belongsTo(User::class, 'driver_id');
    }

    /**
     * Scope to get only online drivers
     */
    public function scopeOnline($query)
    {
        return $query->where('is_online', true)
            ->where('last_ping_at', '>=', Carbon::now()->subMinutes(5));
    }

    /**
     * Scope to get offline drivers
     */
    public function scopeOffline($query)
    {
        return $query->where(function($q) {
            $q->where('is_online', false)
              ->orWhere('last_ping_at', '<', Carbon::now()->subMinutes(5));
        });
    }

    /**
     * Update driver location
     */
    public static function updateDriverLocation($driverId, $data)
    {
        return self::updateOrCreate(
            ['driver_id' => $driverId],
            [
                'latitude' => $data['latitude'],
                'longitude' => $data['longitude'],
                'accuracy' => $data['accuracy'] ?? null,
                'speed' => $data['speed'] ?? null,
                'heading' => $data['heading'] ?? null,
                'is_online' => true,
                'last_ping_at' => Carbon::now(),
            ]
        );
    }

    /**
     * Calculate distance between two coordinates (in km)
     */
    public static function calculateDistance($lat1, $lon1, $lat2, $lon2)
    {
        $earthRadius = 6371; // km

        $dLat = deg2rad($lat2 - $lat1);
        $dLon = deg2rad($lon2 - $lon1);

        $a = sin($dLat/2) * sin($dLat/2) +
             cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
             sin($dLon/2) * sin($dLon/2);

        $c = 2 * atan2(sqrt($a), sqrt(1-$a));
        $distance = $earthRadius * $c;

        return round($distance, 2);
    }

    /**
     * Find nearby drivers
     */
    public static function findNearbyDrivers($latitude, $longitude, $radiusKm = 10)
    {
        return self::online()
            ->with('driver')
            ->get()
            ->filter(function($location) use ($latitude, $longitude, $radiusKm) {
                $distance = self::calculateDistance(
                    $latitude,
                    $longitude,
                    $location->latitude,
                    $location->longitude
                );
                return $distance <= $radiusKm;
            });
    }
}
