<?php

namespace App\Models;

use App\Traits\Auditable;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;

/**
 * @property string $id
 * @property string $original_appointment_id
 * @property string $patients_id
 * @property int $users_id
 * @property string $especiality
 * @property int $days_interval
 * @property string $next_appointment_date
 * @property string $description
 * @property bool $is_active
 * @property bool $auto_schedule
 * @property int $reminder_days
 * @property bool $notification_sent
 * @property string $created_at
 * @property string $updated_at
 * @property Appointments $originalAppointment
 * @property Patients $patient
 * @property User $doctor
 * @property Especiality $especialityRelation
 */
class RecurringAppointment extends Model
{
    use Auditable;

    /**
     * The "type" of the auto-incrementing ID.
     * 
     * @var string
     */
    protected $keyType = 'string';

    /**
     * Indicates if the IDs are auto-incrementing.
     * 
     * @var bool
     */
    public $incrementing = false;

    /**
     * @var array
     */
    protected $fillable = [
        'id',
        'original_appointment_id',
        'patients_id',
        'users_id',
        'especiality',
        'days_interval',
        'next_appointment_date',
        'description',
        'is_active',
        'auto_schedule',
        'reminder_days',
        'notification_sent',
        'created_at',
        'updated_at'
    ];

    /**
     * @var array
     */
    protected $casts = [
        'is_active' => 'boolean',
        'auto_schedule' => 'boolean',
        'notification_sent' => 'boolean',
        'days_interval' => 'integer',
        'reminder_days' => 'integer',
        'next_appointment_date' => 'datetime'
    ];

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function originalAppointment()
    {
        return $this->belongsTo('App\Models\Appointments', 'original_appointment_id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function patient()
    {
        return $this->belongsTo('App\Models\Patients', 'patients_id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function doctor()
    {
        return $this->belongsTo('App\Models\User', 'users_id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function especialityRelation()
    {
        return $this->belongsTo('App\Models\Especiality', 'especiality');
    }

    /**
     * Obtener citas recurrentes que deben ser recordadas
     * Se obtienen las citas cuya fecha está entre hoy y (hoy + días de recordatorio) y no se ha enviado notificación
     * 
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public static function getPendingReminders()
    {
        $today = Carbon::now()->startOfDay();
        
        return self::where('is_active', true)
            ->where('notification_sent', false)
            ->where('next_appointment_date', '>=', $today)
            ->where('next_appointment_date', '<=', $today->copy()->addDays(5))
            ->get();
    }

    /**
     * Obtener citas recurrentes que deben ser agendadas automáticamente
     * 
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public static function getPendingAutoSchedule()
    {
        $today = Carbon::now()->startOfDay();
        
        return self::where('is_active', true)
            ->where('auto_schedule', true)
            ->where('notification_sent', true) // Ya se envió notificación
            ->where('next_appointment_date', '>=', $today)
            ->where('next_appointment_date', '<=', $today->copy()->addDays(5))
            ->get();
    }

    /**
     * Calcular y actualizar la fecha de la próxima cita
     * 
     * @param string|null $baseDate Fecha base para calcular el siguiente intervalo (null para usar next_appointment_date)
     * @return $this
     */
    public function calculateNextAppointmentDate($baseDate = null)
    {
        if ($baseDate) {
            $date = Carbon::parse($baseDate);
        } else {
            $date = $this->next_appointment_date ? Carbon::parse($this->next_appointment_date) : Carbon::now();
        }
        
        $this->next_appointment_date = $date->addDays($this->days_interval);
        $this->notification_sent = false;
        return $this;
    }
}
