<?php

namespace App\Models;

use App\Events\ClaimApproved;
use App\Events\ClaimDeclined;
use App\Events\ClaimPaid;
use App\Events\ClaimPostpone;
use App\Events\ClaimReceived;
use App\Events\ClaimRequested;
use App\Traits\Blameable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;

class Claim extends Model
{
    use HasFactory, Blameable, SoftDeletes;
    
    protected static $code_prefix = 'CLM';

    protected $fillable = [
        'claim_request_id',
        'code',
        'member_id',
        'total_claim',
        'currency',
        'plan_id',
        'benefit_id',
        'organization_id',
        'status',
        'service_code',
        'benefit_code',
        'benefit_desc',
        'amount_incurred',
        'amount_approved',
        'amount_not_approved',
        'excess_paid',
    ];

    protected $hidden = [
        // 'created_at',
        'updated_at',
        'deleted_at',
        'created_by',
        'updated_by',
        'deleted_by',
    ];

    public static $status = [
        'draft' => 'Draft',
        'requested' => 'Requested',
        'received' => 'Received',
        'approved' => 'Approved',
        'postpone' => 'Postpone',
        'paid' => 'Paid',
        'declined' => 'Declined'
    ];

    public static $listing_doc_headers = [
        //		Pharmacy permit number	Pharmacy Address	Pharmacy phone number	Delivery Address	Claimable Status	Benefit Code
        'Count of Usage',
        'Claim Number',
        'Insurar Code',
        'Policy no',
        'Corporate Name',
        'Plan Code',
        'Member Name',
        'Member Status',
        'DOB', // date of brith
        'Member Number',
        'Institution Code',
        'Invoice Line Number',
        'Claim Status',
        'Admission Date',
        'Discharge Date',
        'Date Of Service',
        'Place Of Service',
        'Los',
        'Provider code',
        'Treating Doctor Code',
        'Treating Doctor Name',
        'Doctor Title',
        'Diagnosis',
        'ServiceCode',
        'ServiceType',
        'ServiceDescription',
        'UnitPrice',
        'Quantity',
        'Tarif',
        'Claimable amount',
        'Paid by customer',
        'HD Disc',
        'Doctor Notes',
        'ConsultationID Date',
        'Pharmacy Code',
        'Pharmacy Name',
        'Pharmacy Permit Number',
        'Pharmacy Address',
        'Pharmacy Phone number',
        'Delivery Address',
        'Claimable Status',
        'Benefit Code',
    ];
    
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            try {
                $model->uuid = (string) Str::orderedUuid(); // generate uuid
                $model->code = self::getNextCode();
            } catch (\Exception $e) {
                abort(500, $e->getMessage());
            }
        });

        static::created(function ($model) {
            try {
                if (!empty($model->status)) {
                    $model->statusHistories()->create([
                        'status' => $model->status
                    ]);
                }
            } catch (\Exception $e) {
                abort(500, $e->getMessage());
            }
        });

        static::updated(function ($model) {
            if ($model->hasChanges(['status'])) {
                $model->statusHistories()->create([
                    'status' => $model->status
                ]);

                // if ($model->status == 'requested') {
                //     ClaimRequested::dispatch($model);
                // }

                if ($model->status == 'received') {
                    ClaimReceived::dispatch($model);
                }

                if ($model->status == 'approved') {
                    ClaimApproved::dispatch($model);
                }

                if ($model->status == 'postpone') {
                    ClaimPostpone::dispatch($model);
                }

                if ($model->status == 'paid') {
                    ClaimPaid::dispatch($model);
                }

                if ($model->status == 'declined') {
                    ClaimDeclined::dispatch($model);
                }
            }
        });
    }
    
    public static function getNextCode()
    {
        $last_number = self::withTrashed()->max('code');
        $next_number = empty($last_number) ? 1 : ((int) explode('-', $last_number)[1] + 1);

        return self::makeCode($next_number);
    }

    public static function makeCode($next_number)
    {
        return (string) self::$code_prefix .'-'. str_pad($next_number, 5, 0, STR_PAD_LEFT);
    }

    // Current ClaimRequest that refer to the claim
    public function claimRequest()
    {
        return $this->belongsTo(ClaimRequest::class, 'claim_request_id');
    }

    // Possibilities of ClaimRequest that refer to the claim
    public function claimRequests()
    {
        return $this->hasMany(ClaimRequest::class, 'claim_id');
    }

    public function files()
    {
        return $this->morphMany(File::class, 'fileable');
    }

    public function items()
    {
        return $this->hasMany(ClaimItem::class, 'claim_id');
    }

    public function member()
    {
        return $this->belongsTo(Member::class, 'member_id');
    }

    public function organization()
    {
        return $this->belongsTo(Organization::class, 'organization_id');
    }

    public function encounters()
    {
        return $this->belongsToMany(Encounter::class, 'claim_encounter');
    }

    public function finalEncounter()
    {
        return $this->belongsTo(Encounter::class, 'final_encounter_id');
    }

    public function diagnoses()
    {
        return $this->hasMany(ClaimDiagnosis::class, 'claim_id');
    }

    // TODO Remove this !, Sementara
    public function diagnosis()
    {
        return $this->hasOne(ClaimDiagnosis::class, 'claim_id')->ofMany([
            'id' => 'min',
        ], function ($query) {
            $query->where('type', 'primary');
        });
    }

    public function plan()
    {
        return $this->belongsTo(Plan::class, 'plan_id');
    }
    
    public function curentCorporate()
    {
        return $this->hashOne(Corporate::class, 'corporate_id', 'id');
    }

    public function benefit()
    {
        return $this->belongsTo(Benefit::class, 'benefit_id');
    }

    public function statusHistories()
    {
        return $this->morphMany(StatusHistory::class, 'statusable');
    }

    public function scopeUsed($query, $startDate, $endDate)
    {
        return $query
                ->whereIn('status', ['approved', 'paid']);
                // ->whereBetween('requested_at', [$startDate, $endDate]);
    }

    public function getTotalTagihanAttribute()
    {
        return $this->items->sum('nominal_ditagihkan');
    }

    public function historyHospitalCare()
    {
        return $this->hasMany(ClaimHistoryCare::class, 'claim_id');
    }

    
}
