<?php

namespace App\Models;

use App\Builders\MemberBuilder;
use App\Traits\Blameable;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Altek\Accountant\Contracts\Recordable;

class Member extends Model
{
    use HasFactory, SoftDeletes, Blameable;

    protected $fillable = [
        "id",
        "person_id",
        "member_id",
        "record_type",
        "record_mode",
        "payor_id",
        "plan_id",
        "user_id",
        "name_prefix",
        "name",
        "name_suffix",
        "birth_date",
        "gender",
        "language",
        "race",
        "marital_status",
        "principal_id",
        "relation_with_principal",
        "bpjs_class",
        "active",
        "created_by",
        "updated_by",
        "deleted_by",

        "nric",
        "email",
        "bank_info",
        "agent_code",
        "address1",
        "address2",
        "address3",
        "address4",
        "city",
        "state",
        "postal_code",
        "passport_no",
        "passport_country",
        "identification_code",
        "pre_existing",
        "bpjs_id",
        "endorsement_date",
        "members_effective_date",
        "members_expire_date",
        "activation_date",
        "terminated_date",
        "remarks",
        "policy_in_force",
        "start_no_claim",
        "end_no_claim",
        "suspended",
        "active",
    ];

    protected $appends = [
        'full_name',
        'age',
        'gender_code',
        'relations',
        'status_marital'
        // 'relation_with_principal'
    ];

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

    public static function query(): MemberBuilder
    {
        return parent::query();
    }

    public function newEloquentBuilder($query): MemberBuilder
    {
        return new MemberBuilder($query);
    }

    /* -------------------------------------------------------------------------- */
    /*                                Relationship                                */
    /* -------------------------------------------------------------------------- */
    public function claims()
    {
        return $this->hasMany(Claim::class, 'member_id', 'id');
    }

    public function claimRequest()
    {
        return $this->hasMany(ClaimRequest::class, 'member_id', 'id')->where('claim_id', '!=', null);
    }


    public function postponedClaims()
    {
        return $this->hasMany(Claim::class, 'member_id', 'id')->where('status', 'postpone');
    }

    public function person()
    {
        return $this->belongsTo(Person::class, 'person_id', 'id');
    }

    public function employeds()
    {
        return $this->hasMany(CorporateEmployee::class, 'member_id');
    }

    public function corporates()
    {
        return $this
            ->belongsToMany(Corporate::class, 'corporate_employees', 'corporate_id', 'member_id')
            ->withPivot([
                'branch_code',
                'division_id',
                'nik',
                'status',
                'start',
                'end'
            ]);
    }

    public function currentCorporate()
    {
        return $this->hasOneThrough(Corporate::class, CorporateEmployee::class, 'member_id', 'id', 'id', 'corporate_id');
    }

    public function memberPlans()
    {
        return $this->hasMany(MemberPlan::class, 'member_id');
    }

    public function plans()
    {
        return $this->hasManyThrough(Plan::class, MemberPlan::class, 'member_id', 'id', 'id', 'plan_id');
    }

    public function currentPlans()
    {
        return $this->hasManyThrough(Plan::class, MemberPlan::class, 'member_id', 'id', 'id', 'plan_id');
    }

    public function currentPlan()
    {
        return $this->hasOneThrough(Plan::class, MemberPlan::class, 'member_id', 'id', 'id', 'plan_id',)
            ->latest();
    }

    public function currentEmployeds()
    {
        return $this->hasOneThrough(CorporateEmployee::class, Person::class, 'nik', 'id', 'id', 'nik')
            ->latest();
    }

    public function policies()
    {
        return $this->hasMany(MemberPolicy::class, 'member_id', 'member_id');
    }

    public function currentPolicy()
    {
        return $this->hasOneThrough(CorporatePolicy::class, MemberPolicy::class, 'member_id', 'code', 'member_id', 'policy_id')
            ->where('status', 'active')
            ->orderBy('end', 'DESC');
    }

    public function currentActivePolicy()
    {
        return $this->hasOneThrough(CorporatePolicy::class, MemberPolicy::class, 'member_id', 'code', 'member_id', 'policy_id')
            ->where('corporate_policies.start', '<', now())
            ->where('corporate_policies.end', '>', now())
            ->where('member_policies.start', '<', now())
            ->where('member_policies.end', '>', now());
    }

    public function division()
    {
        return $this->hasOneThrough(CorporateDivision::class, CorporateEmployee::class, 'member_id', 'id', 'id', 'division_id');
    }

    public function requestLogs()
    {
        return $this->hasMany(RequestLog::class);
    }
    /* -------------------------------------------------------------------------- */

    /* -------------------------------------------------------------------------- */
    /*                            Accessors & Mutators                            */
    /* -------------------------------------------------------------------------- */
    protected function age(): Attribute
    {
        return Attribute::make(
            get: fn () => Carbon::parse($this->birth_date)->diffInYears(now())
        );
    }

    protected function fullName(): Attribute
    {
        $arr = [];

        if ($this->relationLoaded('person')) {
            if (!empty($this->person->name_prefix)) {
                $arr[] = $this->person->name_prefix;
            }

            $arr[] = $this->person->name;

            if (!empty($this->person->name_suffix)) {
                $arr[] = $this->person->name_suffix;
            }
        } else {
            if (!empty($this->name_prefix)) {
                $arr[] = $this->name_prefix;
            }

            $arr[] = $this->name;

            if (!empty($this->name_suffix)) {
                $arr[] = $this->name_suffix;
            }
        }

        return Attribute::make(
            get: fn () => $arr ? ucwords(strtolower(implode(' ', $arr))) : null
        );
    }

    protected function genderCode(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->gender ? ($this->gender == 'Female' ? 'F' : 'M') : $this->gender
        );
    }

    protected function relationship(): Attribute
    {
        $relation = null;

        if ($this->relation_with_principal === 'S') {
            $relation = 'Son';
        } elseif ($this->relation_with_principal === 'H') {
            $relation = 'Husband';
        } elseif ($this->relation_with_principal === 'D') {
            $relation = 'Daughter';
        } elseif ($this->relation_with_principal === 'Wife') {
            $relation = 'Wife';
        }

        return Attribute::make(
            get: fn () => $relation
        );
    }


    protected function relations(): Attribute
    {
        $relation = '-';
        if ($this->relation_with_principal == 'H') {
            $relation = 'Husbund';
        } else if ($this->relation_with_principal == 'W') {
            $relation = 'Wife';
        } else if ($this->relation_with_principal == 'S') {
            $relation = 'Son';
        } else if ($this->relation_with_principal == 'D') {
            $relation = 'Daughter';
        }
        return Attribute::make(
            get: fn () => $relation
        );
    }

    protected function statusMarital(): Attribute
    {
        $maritalStatus = '-';
        if ($this->marital_status == 'M') {
            $maritalStatus = 'Married';
        } else if ($this->relation_with_principal == 'D') {
            $maritalStatus = 'Divorced';
        } else if ($this->relation_with_principal == 'S') {
            $maritalStatus = 'Single';
        }
        return Attribute::make(
            get: fn () => $maritalStatus
        );
    }

    // protected function birthDate(): Attribute
    // {
    //     // $date = $this->person->birth_date ?? ($this->birth_date ?? null);
    //     $date = $this->birth_date ?? ($this->person->birth_date ?? null);
    //     return Attribute::make(
    //         get: fn () => !empty($date) ? Carbon::parse($date)->format('Y-m-d') : null
    //     );
    // }

    protected function birthDateeCard(): Attribute
    {
        // $date = $this->person->birth_date ?? ($this->birth_date ?? null);
        if ($this->birth_date) {
            $date = $this->birth_date;
            return Attribute::make(
                get: fn () => !empty($date) ? Carbon::parse($date)->format('d / M / Y') : null
            );
        } else if ($this->person->birth_date) {
            return Attribute::make(
                get: fn () => !empty($date) ? Carbon::parse($date)->format('d / M / Y') : null
            );
        } else {
            return Attribute::make(
                get: fn () => '-'
            );
        }
    }

    protected function birthDateCard(): Attribute
    {
        $date = $this->birth_date;

        if ($date) {
            return Attribute::make(
                get: fn () => !empty($date) ? Carbon::parse($date)->format('d / M / Y') : '-'
            );
        } else if ($this->relationLoaded('person')) {
            $date = $this->person->birth_date;
            return Attribute::make(
                get: fn () => !empty($date) ? Carbon::parse($date)->format('d / M / Y') : '-'
            );
        } else {
            return Attribute::make(
                get: fn () => '-'
            );
        }
    }

    protected function startDate(): Attribute
    {
        $date = $this->members_effective_date;
        return Attribute::make(
            get: fn () => !empty($date) ? Carbon::parse($date)->format('d / M / Y') : null
        );
    }

    protected function endDate(): Attribute
    {
        $date = $this->members_expire_date;
        return Attribute::make(
            get: fn () => !empty($date) ? Carbon::parse($date)->format('d / M / Y') : null
        );
    }

    // protected function relationWithPrincipal(): Attribute
    // {
    //     $relation = null;

    //     if ($this->relation_with_principal === 'S') {
    //         $relation = 'Son';
    //     } elseif ($this->relation_with_principal === 'H') {
    //         $relation = 'Husband';
    //     } elseif ($this->relation_with_principal === 'D') {
    //         $relation = 'Daughter';
    //     } elseif ($this->relation_with_principal === 'Wife') {
    //         $relation = 'Wife';
    //     }

    //     return Attribute::make(
    //         get: fn () => $relation
    //     );
    // }

    // protected function gender(): Attribute
    // {
    //     return Attribute::make(
    //         get: fn () => ucfirst($this->person->gender) ?? null
    //     );
    // }

    // protected function corporateLogo(): Attribute
    // {
    //     $avatar = null;

    //     if ($this->relationLoaded('currentPolicy')) {
    //         $corporateId = $this->currentPolicy->corporate->id;
    //         $avatar = File::where(['type' => 'avatar', 'fileable_id' => $corporateId])
    //             ->orderBy('id', 'desc')
    //             ->first();
    //     }

    //     $path = $avatar ? $_ENV['LMS_APP_STORAGE'] . $avatar->path : '';

    //     return Attribute::make(
    //         get: fn () => $path
    //     );
    // }
    /* -------------------------------------------------------------------------- */
}
