<?php

// ==========================================
// 1. Model SpSipt.php (Model Utama)
// ==========================================

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Carbon\Carbon;

class SpSipt extends Model
{
    use HasFactory, SoftDeletes;

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

    /**
     * The attributes that are mass assignable.
     */
    protected $guarded = [''];
    /**
     * The attributes that should be cast.
     */
    protected $casts = [
        'pemohon_tanggal_lahir' => 'date',
        'terlapor_tanggal_lahir' => 'date',
        'tanggal_sertifikat' => 'date',
        'luas_tanah' => 'decimal:2',
        'latitude' => 'decimal:8',
        'longitude' => 'decimal:8',
        'polygon_coordinates' => 'array',
        'pernyataan_kebenaran' => 'boolean',
        'kesediaan_mediasi' => 'boolean',
        'submitted_at' => 'datetime',
        'approved_at' => 'datetime',
    ];

    /**
     * Status constants
     */
    const STATUS_DRAFT = 'draft';
    const STATUS_SUBMITTED = 'submitted';
    const STATUS_IN_REVIEW = 'in_review';
    const STATUS_APPROVED = 'approved';
    const STATUS_REJECTED = 'rejected';

    /**
     * Status Tanah constants
     */
    const TANAH_HAK_MILIK = 'hak_milik';
    const TANAH_HGB = 'hak_guna_bangunan';
    const TANAH_HGU = 'hak_guna_usaha';
    const TANAH_HAK_PAKAI = 'hak_pakai';
    const TANAH_NEGARA = 'tanah_negara';
    const TANAH_LAINNYA = 'lainnya';

    /**
     * Boot method
     */
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            if (!$model->nomor_surat) {
                $model->nomor_surat = $model->generateNomorSurat();
            }

            if (auth()->check()) {
                $model->created_by = auth()->id();
            }
        });

        static::updating(function ($model) {
            if (auth()->check()) {
                $model->updated_by = auth()->id();
            }
        });
    }

    /**
     * Relationships
     */
    public function coordinates()
    {
        return $this->hasMany(SpSiptCoordinate::class, 'sp_sipt_id')->ordered();
    }
    public function dokumen()
    {
        return $this->hasMany(SpSiptDokumen::class, 'sp_sipt_id');
    }

    public function statusHistory()
    {
        return $this->hasMany(SpSiptStatusHistory::class, 'sp_sipt_id');
    }

    public function catatan()
    {
        return $this->hasMany(SpSiptCatatan::class, 'sp_sipt_id');
    }

    public function jadwal()
    {
        return $this->hasMany(SpSiptJadwal::class, 'sp_sipt_id');
    }

    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    public function dataKampung()
    {
        return $this->belongsTo(Kampung::class, 'kampung');
    }

     public function kecamatan()
    {
        return $this->belongsTo(Kecamatan::class, 'kecamatan_id');
    }

    public function updater()
    {
        return $this->belongsTo(User::class, 'updated_by');
    }

    public function approver()
    {
        return $this->belongsTo(User::class, 'approved_by');
    }

    /**
     * Scopes
     */
    public function scopeDraft($query)
    {
        return $query->where('status', self::STATUS_DRAFT);
    }

    public function scopeSubmitted($query)
    {
        return $query->where('status', self::STATUS_SUBMITTED);
    }

    public function scopeInReview($query)
    {
        return $query->where('status', self::STATUS_IN_REVIEW);
    }

    public function scopeApproved($query)
    {
        return $query->where('status', self::STATUS_APPROVED);
    }

    public function scopeRejected($query)
    {
        return $query->where('status', self::STATUS_REJECTED);
    }

    /**
     * Accessors & Mutators
     */
    protected function pemohonAlamatLengkap(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->formatAlamat('pemohon')
        );
    }

    protected function terlaportAlamatLengkap(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->formatAlamat('terlapor')
        );
    }

    protected function lokasiTanahLengkap(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->formatAlamat('lokasi')
        );
    }

    protected function statusLabel(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->getStatusLabel()
        );
    }

    protected function statusBadgeClass(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->getStatusBadgeClass()
        );
    }

    public function getCoordinatesArrayAttribute()
    {
        return $this->coordinates->map(function($coord) {
            return [
                'lat' => (float) $coord->latitude,
                'lng' => (float) $coord->longitude
            ];
        })->toArray();
    }

    /**
     * Get coordinates as JSON
     */
    public function getCoordinatesJsonAttribute()
    {
        return json_encode($this->coordinates_array);
    }

    /**
     * Check if has valid polygon (minimum 3 points)
     */
    public function hasValidPolygon()
    {
        return $this->coordinates()->count() >= 3;
    }

    /**
     * Calculate and update area
     */
    public function updateCalculatedArea()
    {
        if ($this->hasValidPolygon()) {
            $this->luas_terukur = SpSiptCoordinate::calculateArea($this->id);
            $this->save();
        }
    }

    /**
     * Get polygon bounds
     */
    public function calculatePolygonBounds()
    {
        if (!$this->hasValidPolygon()) {
            return null;
        }

        $lats = $this->coordinates->pluck('latitude');
        $lngs = $this->coordinates->pluck('longitude');

        return [
            'north' => $lats->max(),
            'south' => $lats->min(),
            'east' => $lngs->max(),
            'west' => $lngs->min(),
            'center' => [
                'lat' => $lats->avg(),
                'lng' => $lngs->avg()
            ]
        ];
    }

    /**
     * Save polygon data
     */
    public function savePolygonData(array $coordinates, $mapImage = null)
    {
        // Save coordinates
        SpSiptCoordinate::savePolygonCoordinates($this->id, $coordinates);

        // Calculate area
        $this->luas_terukur = SpSiptCoordinate::calculateArea($this->id);

        // Calculate bounds
        $this->polygon_bounds = $this->calculatePolygonBounds();

        // Save map image if provided
        if ($mapImage) {
            $this->map_image = $mapImage;
        }

        $this->save();
    }
     // Scope untuk pencarian
    public function scopeSearch($query, $search)
    {
        return $query->where(function ($q) use ($search) {
            $q->where('nomor_surat', 'LIKE', "%{$search}%")
              ->orWhere('nomor_tanggal_surat_penguasaan_tanah', 'LIKE', "%{$search}%")
              ->orWhere('pemohon_nik', 'LIKE', "%{$search}%")
              ->orWhere('pemohon_alamat', 'LIKE', "%{$search}%")
            ->orWhere('terlapor_nama', 'LIKE', "%{$search}%")
              ->orWhere('terlapor_nik', 'LIKE', "%{$search}%")
              ->orWhere('terlapor_alamat', 'LIKE', "%{$search}%")

              ->orWhere('pemohon_nama', 'LIKE', "%{$search}%");
        });
    }
    /**
     * Methods
     */
    public static function generateNomorSurat()
    {
        $tahun = date('Y');
        $bulan = date('n'); // 1 - 12 (tanpa leading zero)

        // Konversi bulan ke angka Romawi
        $bulanRomawi = [
            1 => 'I', 2 => 'II', 3 => 'III', 4 => 'IV',
            5 => 'V', 6 => 'VI', 7 => 'VII', 8 => 'VIII',
            9 => 'IX', 10 => 'X', 11 => 'XI', 12 => 'XII'
        ];

        // Ambil nomor urut terakhir dari nomor_surat yang sudah ada
        // Format: SPMPT/001/BA/X/2025
        $lastRecord = self::withTrashed()
                        ->whereYear('created_at', $tahun)
                        ->whereMonth('created_at', $bulan)
                        ->whereNotNull('nomor_surat')
                        ->orderByRaw('CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(nomor_surat, "/", 2), "/", -1) AS UNSIGNED) DESC')
                        ->first();

        $lastNumber = 0;
        if ($lastRecord && $lastRecord->nomor_surat) {
            // Extract nomor urut dari format SPMPT/001/BA/X/2025
            $parts = explode('/', $lastRecord->nomor_surat);
            if (count($parts) >= 2) {
                $lastNumber = (int) $parts[1]; // Ambil '001' dan convert ke integer
            }
        }

        $newNumber = $lastNumber + 1;

        // hasil: No. BA: 001/BA/IX/2025
        return sprintf('SPMPT/%03d/BA/%s/%d', $newNumber, $bulanRomawi[$bulan], $tahun);
    }

    public function formatAlamat($prefix)
    {
        $parts = [];

        if ($this->{$prefix . '_alamat'}) {
            $parts[] = $this->{$prefix . '_alamat'};
        }

        if ($this->{$prefix . '_rt'} && $this->{$prefix . '_rw'}) {
            $parts[] = "RT {$this->{$prefix . '_rt'}}/RW {$this->{$prefix . '_rw'}}";
        }

        if ($this->{$prefix . '_kelurahan'}) {
            $parts[] = "Kel. {$this->{$prefix . '_kelurahan'}}";
        }

        if ($this->{$prefix . '_kecamatan'}) {
            $parts[] = "Kec. {$this->{$prefix . '_kecamatan'}}";
        }

        if ($this->{$prefix . '_kota'}) {
            $parts[] = $this->{$prefix . '_kota'};
        }

        if ($this->{$prefix . '_provinsi'}) {
            $parts[] = $this->{$prefix . '_provinsi'};
        }

        if ($this->{$prefix . '_kode_pos'}) {
            $parts[] = $this->{$prefix . '_kode_pos'};
        }

        return implode(', ', $parts);
    }

    public function getStatusLabel()
    {
        return match($this->status) {
            self::STATUS_DRAFT => 'Draft',
            self::STATUS_SUBMITTED => 'Diajukan',
            self::STATUS_IN_REVIEW => 'Sedang Ditinjau',
            self::STATUS_APPROVED => 'Disetujui',
            self::STATUS_REJECTED => 'Ditolak',
            default => 'Unknown'
        };
    }

    public function getStatusBadgeClass()
    {
        return match($this->status) {
            self::STATUS_DRAFT => 'badge-secondary',
            self::STATUS_SUBMITTED => 'badge-info',
            self::STATUS_IN_REVIEW => 'badge-warning',
            self::STATUS_APPROVED => 'badge-success',
            self::STATUS_REJECTED => 'badge-danger',
            default => 'badge-light'
        };
    }

    public function updateStatus($newStatus, $catatan = null, $userId = null)
    {
        $oldStatus = $this->status;
        $this->status = $newStatus;

        if ($newStatus == self::STATUS_SUBMITTED && !$this->submitted_at) {
            $this->submitted_at = now();
        }

        if ($newStatus == self::STATUS_APPROVED) {
            $this->approved_at = now();
            $this->approved_by = $userId ?: auth()->id();
        }

        $this->save();

        // Record status history
        $this->statusHistory()->create([
            'status_from' => $oldStatus,
            'status_to' => $newStatus,
            'catatan' => $catatan,
            'changed_by' => $userId ?: auth()->id(),
            'changed_at' => now()
        ]);

        return $this;
    }

    public function canBeEdited()
    {
        return in_array($this->status, [self::STATUS_DRAFT, self::STATUS_REJECTED]);
    }

    public function canBeSubmitted()
    {
        return $this->status == self::STATUS_DRAFT
               && $this->pemohon_nama
               && $this->pemohon_nik
               && $this->terlapor_nama;
    }

    public function canBeApproved()
    {
        return in_array($this->status, [self::STATUS_SUBMITTED, self::STATUS_IN_REVIEW]);
    }

    public function hasRequiredDocuments()
    {
        $requiredDocs = ['ktp_pemohon', 'sertifikat_tanah'];
        $uploadedDocs = $this->dokumen->pluck('jenis_dokumen')->toArray();

        return !array_diff($requiredDocs, $uploadedDocs);
    }

    public function getProgressPercentage()
    {
        $fields = [
            'pemohon_nama', 'pemohon_nik', 'pemohon_alamat',
            'terlapor_nama', 'lokasi_kelurahan', 'luas_tanah',
            'kronologi'
        ];

        $filled = 0;
        foreach ($fields as $field) {
            if ($this->$field) {
                $filled++;
            }
        }

        return round(($filled / count($fields)) * 100);
    }
}
