<?php

namespace App\Models;

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

class Pasien extends Model
{
    use HasFactory, SoftDeletes;

    protected $table = 'pasien';

    protected $fillable = [
        'id_eksternal',
        'no_rekam_medis',
        'nik',
        'nama_lengkap',
        'jenis_kelamin',
        'tanggal_lahir',
        'tempat_lahir',
        'usia',
        'alamat_lengkap',
        // TAMBAHKAN KOLOM RELASI
        'province_id',
        'regency_id', 
        'district_id',
        'village_id',
        // KOLOM TEKS LAMA (opsional, bisa dihapus)
        'kelurahan',
        'kecamatan',
        'kota',
        'provinsi',
        'kode_pos',
        'no_telepon',
        'no_wa',
        'email',
        'golongan_darah',
        'tinggi_badan',
        'berat_badan',
        'riwayat_penyakit',
        'alergi',
        'catatan_khusus',
        'wajah_terdaftar',
        'tanggal_registrasi_wajah',
        'foto_profil',
        'status_pasien',
        'keterangan_status',
        'didaftarkan_oleh',
        'tanggal_registrasi',
    ];
    protected $casts = [
        'tanggal_lahir' => 'date',
        'tinggi_badan' => 'decimal:2',
        'berat_badan' => 'decimal:2',
        'wajah_terdaftar' => 'boolean',
        'tanggal_registrasi_wajah' => 'datetime',
        'tanggal_registrasi' => 'datetime',
    ];

    /**
     * RELATIONSHIPS
     */

    // Belongs to User (pendaftar)
    public function pendaftar()
    {
        return $this->belongsTo(User::class, 'didaftarkan_oleh');
    }

    // Many-to-many dengan Dokter via dokter_pasien
    public function dokter()
    {
        return $this->belongsToMany(Dokter::class, 'dokter_pasien')
            ->withPivot([
                'tanggal_mulai_menangani',
                'tanggal_selesai_menangani',
                'status_penanganan',
                'diagnosis_utama',
                'rencana_perawatan',
                'jumlah_kunjungan',
                'tanggal_kontrol_berikutnya',
                'catatan',
            ])
            ->withTimestamps();
    }

    // Dokter yang sedang menangani (status AKTIF)
    public function dokterAktif()
    {
        return $this->belongsToMany(Dokter::class, 'dokter_pasien')
            ->wherePivot('status_penanganan', 'AKTIF')
            ->withPivot([
                'tanggal_mulai_menangani',
                'diagnosis_utama',
                'tanggal_kontrol_berikutnya',
            ])
            ->withTimestamps();
    }

    // Embedding wajah pasien (one-to-many)
    public function embeddingWajah()
    {
        return $this->hasMany(EmbeddingWajah::class);
    }

    // Embedding wajah yang aktif (one-to-one)
    public function embeddingWajahAktif()
    {
        return $this->hasOne(EmbeddingWajah::class)->where('status_embedding', 'AKTIF');
    }

    // Pemeriksaan kesehatan pasien (one-to-many)
    public function pemeriksaanKesehatan()
    {
        return $this->hasMany(PemeriksaanKesehatan::class);
    }

    // Pemeriksaan terbaru
    public function pemeriksaanTerbaru()
    {
        return $this->hasOne(PemeriksaanKesehatan::class)->latestOfMany('waktu_pemeriksaan');
    }

    // Analisis AI pasien (one-to-many)
    public function analisisAi()
    {
        return $this->hasMany(AnalisisAi::class);
    }

    // Log notifikasi pasien (one-to-many)
    public function logNotifikasi()
    {
        return $this->hasMany(LogNotifikasi::class);
    }

    // Relasi via dokter_pasien (one-to-many)
    public function dokterPasien()
    {
        return $this->hasMany(DokterPasien::class);
    }

    /**
     * SCOPES
     */

    // Pasien aktif
    public function scopeAktif($query)
    {
        return $query->where('status_pasien', 'AKTIF');
    }

    // Pasien dengan wajah terdaftar
    public function scopeWajahTerdaftar($query)
    {
        return $query->where('wajah_terdaftar', true);
    }

    // Pencarian pasien
    public function scopeSearch($query, $keyword)
    {
        return $query->where(function ($q) use ($keyword) {
            $q->where('nama_lengkap', 'like', "%{$keyword}%")
                ->orWhere('no_rekam_medis', 'like', "%{$keyword}%")
                ->orWhere('nik', 'like', "%{$keyword}%")
                ->orWhere('no_telepon', 'like', "%{$keyword}%");
        });
    }

    /**
     * ACCESSORS & MUTATORS
     */

    // Auto calculate usia
    protected static function boot()
    {
        parent::boot();

        static::saving(function ($pasien) {
            if ($pasien->tanggal_lahir) {
                // abs() mencegah nilai negatif jika tanggal_lahir > hari ini (input salah)
                $pasien->usia = abs(now()->diffInYears($pasien->tanggal_lahir));
            }
        });
    }

    /**
     * Accessor: hitung usia on-the-fly dari tanggal_lahir
     * Sebagai fallback jika kolom usia di DB belum terupdate / null
     */
    public function getUsiaAttribute($value): ?int
    {
        if ($value !== null && $value > 0) {
            return (int) $value;
        }

        if ($this->tanggal_lahir) {
            return abs(now()->diffInYears($this->tanggal_lahir));
        }

        return null;
    }

    // Get nama dengan jenis kelamin
    public function getNamaLengkapDenganJkAttribute()
    {
        $jk = $this->jenis_kelamin == 'L' ? 'Laki-laki' : 'Perempuan';
        return "{$this->nama_lengkap} ({$jk})";
    }

   // Get alamat lengkap formatted - DIUPDATE
    public function getAlamatLengkapFormattedAttribute()
    {
        $alamat = $this->alamat_lengkap;
        
        // Gunakan data dari relasi jika ada
        if ($this->village) $alamat .= ", Desa/Kel. " . $this->village->name;
        if ($this->district) $alamat .= ", Kec. " . $this->district->name;
        if ($this->regency) $alamat .= ", " . $this->regency->name;
        if ($this->province) $alamat .= ", " . $this->province->name;
        
        // Fallback ke kolom teks jika relasi tidak ada
        if (!$this->village && $this->kelurahan) $alamat .= ", Kel. {$this->kelurahan}";
        if (!$this->district && $this->kecamatan) $alamat .= ", Kec. {$this->kecamatan}";
        if (!$this->regency && $this->kota) $alamat .= ", {$this->kota}";
        if (!$this->province && $this->provinsi) $alamat .= ", {$this->provinsi}";
        
        if ($this->kode_pos) $alamat .= " {$this->kode_pos}";

        return $alamat;
    }
    // Get BMI (Body Mass Index)
    public function getBmiAttribute()
    {
        if (!$this->tinggi_badan || !$this->berat_badan) {
            return null;
        }

        $tinggiMeter = $this->tinggi_badan / 100;
        return round($this->berat_badan / ($tinggiMeter * $tinggiMeter), 2);
    }

    // Get kategori BMI
    public function getKategoriBmiAttribute()
    {
        $bmi = $this->bmi;

        if (!$bmi) return null;

        if ($bmi < 18.5) return 'Kurus';
        if ($bmi < 25) return 'Normal';
        if ($bmi < 30) return 'Gemuk';
        return 'Obesitas';
    }

    // Check if pasien has alergi
    public function hasAlergi()
    {
        return !empty($this->alergi);
    }

    // Check if pasien has riwayat penyakit
    public function hasRiwayatPenyakit()
    {
        return !empty($this->riwayat_penyakit);
    }
    public function province()
     {
         return $this->belongsTo(Province::class);
     }

    public function regency()  
     { 
        return $this->belongsTo(Regency::class); 
     }

    public function district() 
    { 
        return $this->belongsTo(District::class); 
    }

    public function village()  
    { 
        return $this->belongsTo(Village::class); 
    }

    /**
     * DELETION HISTORY RELATIONSHIP & METHODS
     */

    // Riwayat penghapusan pasien
    public function riwayatPenghapusan()
    {
        return $this->hasMany(RiwayatPenghapusanPasien::class);
    }

    /**
     * Simpan data pasien ke riwayat_penghapusan_pasien sebelum soft delete
     * Juga menghitung jumlah data terkait yang ada
     */
    public function saveToRiwayat(int $userId, string $alasan = '', string $tipePenghapusan = 'SOFT_DELETE'): RiwayatPenghapusanPasien
    {
        // Hitung jumlah data terkait
        $jumlahPemeriksaan = $this->pemeriksaanKesehatan()->count();
        $jumlahPembayaran = Pembayaran::where('pasien_id', $this->id)->count();
        $jumlahAnalisisAi = $this->analisisAi()->count();
        $jumlahEmbeddingWajah = $this->embeddingWajah()->count();

        // Snapshot data pasien sebagai JSON
        $dataSnapshot = [
            'id' => $this->id,
            'id_eksternal' => $this->id_eksternal,
            'no_rekam_medis' => $this->no_rekam_medis,
            'nik' => $this->nik,
            'nama_lengkap' => $this->nama_lengkap,
            'jenis_kelamin' => $this->jenis_kelamin,
            'tanggal_lahir' => $this->tanggal_lahir,
            'usia' => $this->usia,
            'no_telepon' => $this->no_telepon,
            'no_wa' => $this->no_wa,
            'email' => $this->email,
            'alamat_lengkap' => $this->alamat_lengkap,
            'status_pasien' => $this->status_pasien,
            'golongan_darah' => $this->golongan_darah,
            'tinggi_badan' => $this->tinggi_badan,
            'berat_badan' => $this->berat_badan,
        ];

        // Create atau update riwayat penghapusan
        $riwayat = RiwayatPenghapusanPasien::create([
            'pasien_id' => $this->id,
            'nama_pasien' => $this->nama_lengkap,
            'nik' => $this->nik,
            'no_rekam_medis' => $this->no_rekam_medis,
            'dihapus_oleh' => $userId,
            'tipe_penghapusan' => $tipePenghapusan,
            'alasan_penghapusan' => $alasan,
            'waktu_penghapusan' => now(),
            'data_snapshot' => $dataSnapshot,
            'jumlah_pemeriksaan' => $jumlahPemeriksaan,
            'jumlah_pembayaran' => $jumlahPembayaran,
            'jumlah_analisis_ai' => $jumlahAnalisisAi,
            'jumlah_embedding_wajah' => $jumlahEmbeddingWajah,
            'status_pemulihan' => $tipePenghapusan === 'SOFT_DELETE' ? 'DAPAT_DIPULIHKAN' : 'TIDAK_REVERSIBLE',
        ]);

        return $riwayat;
    }

    /**
     * Cek apakah pasien bisa dihapus
     * Returns: [bool, string] - [canDelete, errorMessage]
     */
    public function canBeDeleted(): array
    {
        // 1. Cek: ada pemeriksaan kesehatan dalam status DALAM_PROSES?
        $activePemeriksaan = $this->pemeriksaanKesehatan()
            ->where('status_pemeriksaan', 'DALAM_PROSES')
            ->exists();
        
        if ($activePemeriksaan) {
            return [false, 'Tidak dapat menghapus pasien karena ada pemeriksaan kesehatan yang sedang berlangsung (DALAM_PROSES).'];
        }

        // 2. Cek: ada konsultasi aktif dengan dokter?
        $konsultasiAktif = $this->dokterAktif()->exists();
        
        if ($konsultasiAktif) {
            return [false, 'Tidak dapat menghapus pasien karena masih ada konsultasi aktif dengan dokter.'];
        }

        // 3. Cek: ada pembayaran dengan status MENUNGGU?
        $pembayaranPending = Pembayaran::where('pasien_id', $this->id)
            ->where('status_pembayaran', 'MENUNGGU')
            ->exists();
        
        if ($pembayaranPending) {
            return [false, 'Tidak dapat menghapus pasien karena ada pembayaran yang masih menunggu konfirmasi.'];
        }

        // 4. Cek: ada analisis AI dalam review (status PENDING)?
        $analisisaiPending = $this->analisisAi()
            ->where('status_analisis', 'PENDING')
            ->exists();
        
        if ($analisisaiPending) {
            return [false, 'Tidak dapat menghapus pasien karena ada analisis AI yang masih dalam review.'];
        }

        // 5. Cek: ada jadwal kontrol berikutnya yang belum lewat?
        $jadwalKontrol = $this->dokterPasien()
            ->where('status_penanganan', 'AKTIF')
            ->where('tanggal_kontrol_berikutnya', '>', now())
            ->exists();
        
        if ($jadwalKontrol) {
            return [false, 'Tidak dapat menghapus pasien karena ada jadwal kontrol berikutnya yang belum dilalui.'];
        }

        // Jika semua validasi lolos
        return [true, ''];
    }

}