<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class BusinessTripLocation extends Model
{
    use HasFactory;

    protected $fillable = [
        'company_id',
        'name',
        'code',
        'type',
        'city',
        'province',
        'address',
        'latitude',
        'longitude',
        'radius',
        'is_active',
        'is_primary',
        'sort_order',
    ];

    protected function casts(): array
    {
        return [
            'latitude' => 'decimal:6',
            'longitude' => 'decimal:6',
            'radius' => 'integer',
            'is_active' => 'boolean',
            'is_primary' => 'boolean',
            'sort_order' => 'integer',
        ];
    }

    public function company(): BelongsTo
    {
        return $this->belongsTo(Company::class);
    }

    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    public function scopeForCompany($query, $companyId)
    {
        return $query->where('company_id', $companyId);
    }

    /**
     * Scope untuk sorting: primary first, lalu by sort_order, lalu by name
     */
    public function scopeOrdered($query)
    {
        return $query->orderBy('is_primary', 'desc')
                     ->orderBy('sort_order', 'asc')
                     ->orderBy('name', 'asc');
    }

    /**
     * Scope untuk lokasi primary
     */
    public function scopePrimary($query)
    {
        return $query->where('is_primary', true);
    }

    /**
     * Calculate distance from given coordinates in meters
     */
    public function distanceFrom(float $latitude, float $longitude): float
    {
        if (!$this->latitude || !$this->longitude) {
            return PHP_INT_MAX;
        }

        $earthRadius = 6371000; // meters

        $latFrom = deg2rad($this->latitude);
        $lonFrom = deg2rad($this->longitude);
        $latTo = deg2rad($latitude);
        $lonTo = deg2rad($longitude);

        $latDelta = $latTo - $latFrom;
        $lonDelta = $lonTo - $lonFrom;

        $a = sin($latDelta / 2) * sin($latDelta / 2) +
            cos($latFrom) * cos($latTo) *
            sin($lonDelta / 2) * sin($lonDelta / 2);
        $c = 2 * atan2(sqrt($a), sqrt(1 - $a));

        return $earthRadius * $c;
    }

    /**
     * Check if coordinates are within the location radius
     */
    public function isWithinRadius(float $latitude, float $longitude): bool
    {
        return $this->distanceFrom($latitude, $longitude) <= $this->radius;
    }

    /**
     * Get nearby locations sorted by distance
     */
    public static function getNearbyLocations(int $companyId, float $latitude, float $longitude, int $limit = 5)
    {
        $locations = static::active()
            ->forCompany($companyId)
            ->whereNotNull('latitude')
            ->whereNotNull('longitude')
            ->get();

        return $locations->map(function ($location) use ($latitude, $longitude) {
            $location->distance = $location->distanceFrom($latitude, $longitude);
            return $location;
        })
        ->sortBy('distance')
        ->take($limit)
        ->values();
    }

    public function getTypeLabel(): string
    {
        return match ($this->type) {
            'bpkp' => 'BPKP',
            'pemda' => 'Pemda',
            'kementerian' => 'Kementerian',
            'lembaga' => 'Lembaga',
            'other' => 'Lainnya',
            default => $this->type,
        };
    }
}
