<?php

namespace App\Models;

use App\Models\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;

class Patient extends Model
{
    use BelongsToTenant, HasFactory, SoftDeletes;

    protected $fillable = [
        'tenant_id', 'full_name', 'phone', 'email', 'gender', 'dob',
        'address', 'allergies', 'medical_history', 'notes', 'source',
        'whatsapp_opt_in',
    ];

    protected function casts(): array
    {
        return [
            'dob' => 'date',
            'last_visit_at' => 'datetime',
            'whatsapp_opt_in' => 'boolean',
            'medical_history' => 'encrypted', // PHI at rest
        ];
    }

    protected static function booted(): void
    {
        static::saving(function (Patient $patient) {
            $patient->phone_normalized = self::normalizePhone($patient->phone);
        });
    }

    /** Digits only; Iraqi local 07xx becomes 9647xx so WhatsApp lookups match. */
    public static function normalizePhone(?string $phone): string
    {
        $digits = preg_replace('/\D+/', '', (string) $phone);

        if (str_starts_with($digits, '00')) {
            $digits = substr($digits, 2);
        }
        if (str_starts_with($digits, '07') && strlen($digits) === 11) {
            $digits = '964'.substr($digits, 1);
        }

        return $digits;
    }

    public function appointments(): HasMany
    {
        return $this->hasMany(Appointment::class);
    }

    public function scopeSearch(Builder $query, ?string $term): Builder
    {
        $term = trim((string) $term);
        if ($term === '') {
            return $query;
        }

        $phone = preg_replace('/\D+/', '', $term);

        return $query->where(function (Builder $q) use ($term, $phone) {
            if (strlen($phone) >= 4) {
                $q->orWhere('phone_normalized', 'like', '%'.$phone.'%');
            }
            if (DB::getDriverName() === 'mysql') {
                $q->orWhereRaw(
                    'MATCH(full_name) AGAINST(? IN BOOLEAN MODE)',
                    [preg_replace('/[+\-><()~*"@]+/', ' ', $term).'*']
                );
            }
            $q->orWhere('full_name', 'like', '%'.$term.'%');
        });
    }

    public function age(): ?int
    {
        return $this->dob?->age;
    }
}
