<?php

namespace App\Models;

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

class SpSiptCoordinate extends Model
{
    use HasFactory;

    /**
     * The table associated with the model.
     */
    protected $table = 'sp_sipt_coordinates';

    /**
     * The attributes that are mass assignable.
     */
    protected $fillable = [
        'sp_sipt_id',
        'point_order',
        'latitude',
        'longitude',
        'easting',
        'northing',
        'utm_zone'
    ];

    /**
     * The attributes that should be cast.
     */
    protected $casts = [
        'latitude' => 'decimal:8',
        'longitude' => 'decimal:8',
        'easting' => 'decimal:2',
        'northing' => 'decimal:2',
        'point_order' => 'integer'
    ];

    /**
     * Relationships
     */
    public function spSipt()
    {
        return $this->belongsTo(SpSipt::class, 'sp_sipt_id');
    }

    /**
     * Scopes
     */
    public function scopeOrdered($query)
    {
        return $query->orderBy('point_order', 'asc');
    }

    /**
     * Accessors
     */
    public function getFormattedLatitudeAttribute()
    {
        return number_format($this->latitude, 8, '.', '');
    }

    public function getFormattedLongitudeAttribute()
    {
        return number_format($this->longitude, 8, '.', '');
    }

    /**
     * Get coordinate as array
     */
    public function toCoordinateArray()
    {
        return [
            'lat' => (float) $this->latitude,
            'lng' => (float) $this->longitude,
            'easting' => $this->easting ? (float) $this->easting : null,
            'northing' => $this->northing ? (float) $this->northing : null,
            'utm_zone' => $this->utm_zone
        ];
    }

    /**
     * Static Methods
     */
    public static function savePolygonCoordinates($spSiptId, array $coordinates)
    {
        // Delete existing coordinates
        self::where('sp_sipt_id', $spSiptId)->delete();
        
        // Save new coordinates
        $order = 0;
        foreach ($coordinates as $coord) {
            if (isset($coord['lat']) && isset($coord['lng'])) {
                self::create([
                    'sp_sipt_id' => $spSiptId,
                    'point_order' => $order++,
                    'latitude' => $coord['lat'],
                    'longitude' => $coord['lng'],
                    'easting' => $coord['easting'] ?? null,
                    'northing' => $coord['northing'] ?? null,
                    'utm_zone' => $coord['utm_zone'] ?? null
                ]);
            }
        }
    }

    /**
     * Calculate polygon area using Shoelace formula
     */
    public static function calculateArea($spSiptId)
    {
        $coordinates = self::where('sp_sipt_id', $spSiptId)
            ->ordered()
            ->get();
        
        if ($coordinates->count() < 3) {
            return 0;
        }
        
        $area = 0;
        $n = $coordinates->count();
        
        for ($i = 0; $i < $n; $i++) {
            $j = ($i + 1) % $n;
            $area += $coordinates[$i]->latitude * $coordinates[$j]->longitude;
            $area -= $coordinates[$j]->latitude * $coordinates[$i]->longitude;
        }
        
        $area = abs($area / 2);
        
        // Convert to square meters (approximation for Indonesia)
        $latCenter = $coordinates->avg('latitude');
        $metersPerDegreeLng = 111319.9 * cos($latCenter * pi() / 180);
        $metersPerDegreeLat = 111319.9;
        
        $areaInSquareMeters = $area * $metersPerDegreeLat * $metersPerDegreeLng;
        
        return round($areaInSquareMeters, 2);
    }
}