<?php

namespace App\Models;

use App\Traits\Auditable;

use Illuminate\Database\Eloquent\Model;
use App\Models\Interfaces\IPostCreateAppointmentStructure;
use Exception;
use DateTime;
use App\Helper\Helper;

/**
 * @property string $id
 * @property string $firstname
 * @property string $lastname
 * @property string $age
 * @property string $gender
 * @property string $email
 * @property string $phone
 * @property string $birthday
 * @property string $created_at
 * @property string $updated_at
 * @property Appointment[] $appointments
 * @property History[] $histories
 * @property Relationship[] $relationships
 */
class Patients extends Model implements IPostCreateAppointMentStructure
{
    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','identification','firstname', 'lastname', 'age', 'gender','address', 'email', 'phone', 'birthday','blood_type','created_at', 'updated_at'];

    // Modelo User.php
protected $dateFormat = 'Y-m-d H:i:s.u'; // Formato con microsegundos

    /**
     * Mutador para blood_type que convierte el valor a minúsculas
     */
    public function setBloodTypeAttribute($value)
    {
        $this->attributes['blood_type'] = strtolower($value);
    }

    /**
     * Accesor para blood_type que convierte el valor a mayúsculas
     */
    public function getBloodTypeAttribute($value)
    {
        return strtoupper($value);
    }

    /**
     * Mutador para gender que convierte el valor a minúsculas
     */
    public function setGenderAttribute($value)
    {
        $this->attributes['gender'] = strtolower($value);
    }

    /**
     * Accesor para gender que convierte el valor a mayúsculas
     */
    public function getGenderAttribute($value)
    {
        return strtoupper($value);
    }

    /**
     * 
     */
    public function fullName(){
        return $this->firstname." ".$this->lastname;
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function appointments()
    {
        return $this->hasMany('App\Models\Appointments', 'patients_id');
    }
    
    /**
     * Get the custom field values for this patient
     * 
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function customFieldValues()
    {
        return $this->hasMany(PatientCustomFieldValue::class, 'patient_id');
    }
    
    /**
     * Get a specific custom field value by field id
     * 
     * @param int $fieldId
     * @return PatientCustomFieldValue|null
     */
    public function getCustomFieldValue($fieldId)
    {
        return $this->customFieldValues()->where('field_id', $fieldId)->first();
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function histories()
    {
        return $this->hasMany('App\Models\History', 'patients_id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function relationships()
    {
        return $this->hasMany('App\Models\RelationShip', 'patients_id');
    }

    /**
     * 
     */
    public function getAreas(){
        $areas = [];
        if(isset($this->histories()->get()[0])){
            $history = $this->histories()->get()[0];
            array_push($areas,$history->especiality);
            foreach($history->controlHistories()->get() as $controlHistory){
               if(!in_array($controlHistory->especiality,$areas)){
                    array_push($areas,$controlHistory->especiality);
               }
            }  
        }
        return $areas; 
    }

    /**
     * 
     */
    public static function getStructureFromRequest(array $data,array $extras=[]):array{
        $patient = [];       
        $patient["id"]               = Helper::createId(); 
        $patient["identification"]   = isset($patient["identification"]) ? $patient["identification"] : "N/A";
        $patient["firstname"]        = $data["firstname"] or $data["patientFirstName"];
        $patient["lastname"]         = $data["lastname"] or $data["patientLastName"];
        $patient["age"]              = $data["age"] or $data["patientAge"];
        $patient["gender"]           = $data["gender"] or $data["patientGender"];
        $patient["email"]            = NULL;
        $patient["phone"]            = NULL;
        $patient["birthday"]         =  date_create_from_format('d/m/Y',$data["birthday"]);
        return $patient;
    }

    /**
     * 
     */
    public static function createOrGetPatient($patients):Patients{
        try {
            $patients = Patients::findOrFail($patients["id"]);
        } catch (\Throwable $th) {
            $patients = Patients::create($patients);
        }
        return $patients;
    }

    /**
     * 
     */
    public static function getRepresentatives($patient){
        $representantivesData = [];
        $relationships = $patient->relationships()->get();
        foreach($relationships as $relationship){
            foreach($relationship->representative()->get() as $representative){
                array_push($representantivesData,$representative->firstname ." ".$representative->lastname. " (".strtoupper(config("app.parents")()[$relationship->title]).")");
            }
        }
        return implode(", ",$representantivesData);
    }

    /**
     * 
     */
    public static function getIdentificationByRepresentatives($patient){
        $representantivesData = [];
        $relationships = $patient->relationships()->get();
        foreach($relationships as $relationship){
            foreach($relationship->representative()->get() as $representative){
                array_push($representantivesData,$representative->identification);
            }
        }
        return implode(",",$representantivesData);
    }

    /**
     * 
     */
    public static function getAddressForRepresentatives($patient){
        $representantivesData = "";
        $relationships = $patient->relationships()->get();
        foreach($relationships as $relationship){
            foreach($relationship->representative()->get() as $representative){
                $representantivesData .= $representative->address.", ";
            }
        }
        return $representantivesData;
    }

    /**
     * 
     */
    public static function getPhoneForRepresentatives($patient){
        $representantivesData = [];
        $relationships = $patient->relationships()->get();
        foreach($relationships as $relationship){
            foreach($relationship->representative()->get() as $representative){
                array_push($representantivesData, $representative->phone);
            }
        }
        return $representantivesData;
    }

    /**
     * 
     */
    public static function getEmailForRepresentatives($patient){
        $representantivesData = [];
        $relationships = $patient->relationships()->get();
        foreach($relationships as $relationship){
            foreach($relationship->representative()->get() as $representative){
                array_push($representantivesData, $representative->email);
            }
        }
        return $representantivesData;
    }

    /**
     * 
     */
    public static function getListAddressOfRepresentatives($patient){
        $representantivesData = [];
        $relationships = $patient->relationships()->get();
        foreach($relationships as $relationship){
            foreach($relationship->representative()->get() as $representative){
                array_push($representantivesData,$representative->address);
            }
        }
        return $representantivesData;
    }

    /**
     * 
     */
    public function haveHistories(){
        $histories = $this->histories()->get()->all();
        return (count($histories) > 0);
    }

    /**
     * 
     */
    public function loadModelFromRequest($data){
        foreach($data as $key =>$value){
            if(in_array($key,$this->fillable)){
                if($key === "birthday"){
                    $value = date_create_from_format('d/m/Y',$value);
                }
                $this[$key] = $value;
            }            
        }
    }

    /**
     * 
     */
    public function createModelFromRequest($data){
        return Helper::getFieldsFromRequest($data,$this->fillable);
    }

    /**
     * 
     */
    public static function getPatientsMinorThat18(){
        $patient = NULL;
        $patient = Patients::get()->where("age", "<", 18);
        return $patient;
    }

    /**
     * 
     */
    public static function getPatientsMajorThat18(){
        $patient = NULL;
        $patient = Patients::get()->where("age", ">", 17);
        return $patient;
    }

}
