<?php

namespace App\Models;

# use Illuminate\Database\Eloquent\Model;

use DateTime;
use Illuminate\Support\Collection;

class CareMonth extends Model
{
    protected $table = 'care_month';

    public function patient(){
        return $this->hasOne(Client::class, 'id', 'client_id');
    }

    public function client(){
        return $this->hasOne(Client::class, 'id', 'client_id');
    }

    public function mcp(){
        return $this->hasOne(Pro::class, 'id', 'mcp_pro_id');
    }

    public function cmPro(){
        return $this->hasOne(Pro::class, 'id', 'cm_pro_id');
    }

    public function rmmPro(){
        return $this->hasOne(Pro::class, 'id', 'rmm_pro_id');
    }

    public function rmePro(){
        return $this->hasOne(Pro::class, 'id', 'rme_pro_id');
    }

    public function entries() {
        return $this->hasMany(CareMonthEntry::class, 'care_month_id', 'id')
            ->where('cm_or_rm_or_rtm_msk_or_rtm_lung', 'RM')
            ->orderBy('effective_date', 'DESC');
    }

    public function entriesByPro($_proId) {
        return CareMonthEntry::where('care_month_id', $this->id)
            ->where('pro_id', $_proId)
            ->where('cm_or_rm_or_rtm_msk_or_rtm_lung', 'RM')
            ->orderBy('effective_date', 'DESC')
            ->get();
    }

    public function entriesNotByPro($_proId) {
        return CareMonthEntry::where('care_month_id', $this->id)
            ->where('pro_id', '!=', $_proId)
            ->where('cm_or_rm_or_rtm_msk_or_rtm_lung', 'RM')
            ->orderBy('effective_date', 'DESC')
            ->get();
    }

    public function rtmEntries() {
        return $this->hasMany(CareMonthEntry::class, 'care_month_id', 'id')
            ->whereRaw("(cm_or_rm_or_rtm_msk_or_rtm_lung = 'RTM_MSK' OR cm_or_rm_or_rtm_msk_or_rtm_lung = 'RTM_LUNG')")
            ->orderBy('effective_date', 'DESC');
    }

    public function bills() {
        return $this->hasMany(Bill::class, 'care_month_id', 'id');
    }

    public function claims() {
        return $this->hasMany(Claim::class, 'care_month_id', 'id')->where('status', '<>', 'CANCELLED');
    }

    public function getBillsOfType($_type) {
        $bills = $this->bills;
        $targetBills = new Collection();
        foreach ($bills as $bill) {
            if($bill->cm_or_rm === $_type) {
                $targetBills->add($bill);
            }
        }
        return $targetBills;
    }

    public function rmBill(){
        return $this->hasOne(Bill::class, 'id', 'rm_bill_id');
    }

    public function companyPro()
    {
        return $this->hasOne(CompanyPro::class, 'id', 'company_pro_id');
    }

    public function company()
    {
        return $this->hasOne(Company::class, 'id', 'company_id');
    }

    public function companyProPayer()
    {
        return $this->hasOne(CompanyProPayer::class, 'id', 'company_pro_payer_id');
    }

    public function companyLocation()
    {
        return $this->hasOne(CompanyLocation::class, 'id', 'company_location_id');
    }


    public function cmReasons()
    {
        return $this->hasMany(CareMonthCmRmReason::class, 'care_month_id', 'id')
            ->where('cm_or_rm', 'CM')
            ->orderBy('position_index', 'ASC')
            ->orderBy('code', 'ASC');
    }

    public function rmReasons()
    {
        return $this->hasMany(CareMonthCmRmReason::class, 'care_month_id', 'id')
            ->where('cm_or_rm', 'RM')
            ->orderBy('position_index', 'ASC')
            ->orderBy('code', 'ASC');
    }

    public function rmSetupClaim()
    {
        return $this->hasOne(Claim::class, 'id', 'rm_setup_claim_id')
            ->where('status', '<>', 'CANCELLED');
    }

    public function mostRecentMcpNote()
    {
        return $this->hasOne(Note::class, 'id', 'most_recent_mcp_note_id');
    }

    public function note()
    {
        return $this->hasOne(Note::class, 'id', 'note_id');
    }

    public function mcpRmGenericBill()
    {
        return $this->hasOne(Bill::class, 'id', 'mcp_rm_generic_bill_id')->where('is_cancelled', false)->where('is_cancelled_by_administrator', false);
    }
    public function rmmRmGenericBill()
    {
        return $this->hasOne(Bill::class, 'id', 'rmm_rm_generic_bill_id')->where('is_cancelled', false)->where('is_cancelled_by_administrator', false);
    }

    public function showMeasurementDaysWarning(){
        return ($this->daysSinceLastMeasurement() >= 2) || (16 - $this->number_of_days_with_remote_measurements) >= $this->daysTillEndOfMonth();
    }

    public function daysSinceLastMeasurement(){

        if(!$this->most_recent_cellular_measurement_at) {
            return 999;
        }

        $d1 = new DateTime($this->most_recent_cellular_measurement_at);
        return $d1->diff(new DateTime())->days;
    }

    public function daysTillEndOfMonth(){
        return  date('t') - date('j');

    }

    public function calculateBillabilityForMcp(){


        $strategy = $this->mcp_rpm_payment_strategy;
        if(!$strategy){
            return [
                'billable' => false, 
                'reason' => 'MCP RPM strategy has not been set.'
            ];
        }
        
        $mcpRpmPaymentAmount =  $this->mcp_rpm_payment_amount;
        $has16PlusDays = $this->number_of_days_with_remote_measurements >= 16;
        $hasMcpBilled20Minutes = $this->rm_total_time_in_seconds_by_mcp >= 1200;
        $hasMcpInteracted = $this->has_mcp_interacted_with_client_about_rm;

        if (is_null($this->days_between_most_recent_mcp_note_date_and_end_of_care_month) || $this->days_between_most_recent_mcp_note_date_and_end_of_care_month > config('app.maxDaysSinceLastVisit')) {
            return [
                'billable' => false,
                'reason' => "Patient has not had a visit recent enough to bill for RPM"
            ];
        }

        if($strategy == 'X16_DAYS'){
            //only check for 16 days
            if($has16PlusDays){
                return [
                    'billable' => true, 
                    'amount' => $mcpRpmPaymentAmount
                ];
            } else {
                //not billable
                return [
                    'billable' => false, 
                    'reason' => "This care month does not have 16 or more measurement days."
                ];
            }
        }
    
        if($strategy == 'X16_DAYS_20_MINS_ON_OWN_MCP_COM_DURING_CM'){
            if ($has16PlusDays && $hasMcpBilled20Minutes && $hasMcpInteracted) {
                return [
                    'billable' => true, 
                    'amount' => $mcpRpmPaymentAmount
                ];
            } else {
                if(!$has16PlusDays){
                    return [
                        'billable' => false, 
                        'reason' => 'Care month does not have 16 or more measurement days.'
                    ];
                }
                if(!$hasMcpBilled20Minutes){
                    return [
                        'billable' => false, 
                        'reason' => 'Care month does not have 20 minutes billed time.'
                    ];
                }
                if(!$hasMcpInteracted){
                    return [
                        'billable' => false, 
                        'reason' => 'Care month does MCP interaction.'
                    ];
                }
                
            }
        }
    
    }

    public function calculateBillabilityForRmm(){

        if(!$this->rmmPro) {
            return [
                'billable' => false,
                'reason' => 'RMM not set on the care month.'
            ];
        }

        $strategy = $this->rmm_payment_strategy;
        if(!$strategy){
            return [
                'billable' => false,
                'reason' => 'RPM strategy has not been set.'
            ];
        }

        $rmmRpmPaymentAmount =  $this->rmm_payment_amount;
        $has16PlusDays = $this->number_of_days_with_remote_measurements >= 16;
        $hasRmmBilled20Minutes = $this->rm_total_time_in_seconds_by_rmm_pro >= 1200;
        $hasMcpInteracted = $this->has_mcp_interacted_with_client_about_rm;

        if (is_null($this->days_between_most_recent_mcp_note_date_and_end_of_care_month) || $this->days_between_most_recent_mcp_note_date_and_end_of_care_month > config('app.maxDaysSinceLastVisit')) {
            return [
                'billable' => false,
                'reason' => "Patient has not had a visit recent enough to bill for RPM"
            ];
        }

        if($strategy == 'X16_DAYS'){
            //only check for 16 days
            if($has16PlusDays){
                return [
                    'billable' => true,
                    'amount' => $rmmRpmPaymentAmount
                ];
            } else {
                //not billable
                return [
                    'billable' => false,
                    'reason' => "This care month does not have 16 or more measurement days."
                ];
            }
        }

        if($strategy == 'X16_DAYS_20_MINS_ON_OWN_MCP_COM_DURING_CM'){
            if ($has16PlusDays && $hasRmmBilled20Minutes && $hasMcpInteracted) {
                return [
                    'billable' => true,
                    'amount' => $rmmRpmPaymentAmount
                ];
            } else {
                if(!$has16PlusDays){
                    return [
                        'billable' => false,
                        'reason' => 'Care month does not have 16 or more measurement days.'
                    ];
                }
                if(!$hasRmmBilled20Minutes){
                    return [
                        'billable' => false,
                        'reason' => 'Care month does not have 20 minutes in entries.'
                    ];
                }
                if(!$hasMcpInteracted){
                    return [
                        'billable' => false,
                        'reason' => 'Care month does not have MCP interaction.'
                    ];
                }

            }
        }

    }

    public function rtmMskTransmissions() {
        return $this->hasMany(ClientRtmTransmission::class, 'care_month_id', 'id')
            ->where('msk_or_lung', 'MSK')
            ->orderBy('effective_date', 'DESC')
            ->orderBy('created_at', 'DESC');
    }

    public function rtmLungTransmissions() {
        return $this->hasMany(ClientRtmTransmission::class, 'care_month_id', 'id')
            ->where('msk_or_lung', 'LUNG')
            ->orderBy('effective_date', 'DESC')
            ->orderBy('created_at', 'DESC');
    }
}
