<?php

namespace Mtc\Plugins\NHS\Classes;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Validator;
use Mtc\Modules\Members\Models\Member;


class PrescriptionItem extends Model
{
    /**
     * The table associated with the model.
     */
    protected $table = 'nhs_prescription_items';

    /**
     * Average Number of days for the medication to be delivered to the customer
     */
    const DAYS_TO_SHIP = 7;

    /**
     * Number of days that the customer should reorder their medication before it runs out.
     */
    const DAYS_TO_REORDER_BEFORE_COMPLETION_DATE = 9;

    protected $fillable = [
        'name',
        'quantity',
        'refill_date',
        'refill_date_new',
        'one_off_prescription',
        'frequency_days',
        'nhs_unilexicon_product_id',
    ];

    protected $hidden = [
    ];


    protected $casts = [
        'one_off_prescription' => 'integer',
        'nhs_unilexicon_product_id' => 'string',
    ];


    private $rules = [
        'name' => 'required',
        'quantity' => 'required | integer | min:1',
        'refill_date' => 'nullable | date',
        'one_off_prescription',
        'additional_info',
        'frequency_days' => 'nullable | integer',
    ];

    public function validate()
    {
        return Validator::make($this->attributes, $this->rules);
    }


    public function prescription()
    {
        return $this->belongsTo(Prescription::class);
    }

    public function unilexiconProduct()
    {
        return $this->belongsTo(NHSUnilexiconProduct::class, 'nhs_unilexicon_product_id', 'id');
    }


    /**
     * Gets a refill date of member's NHS prescription
     *
     * @param $item
     * @param Member $member
     * @return false|string
     */
    public static function getRefillDate($item, Member $member)
    {
        // Find out how many days does the member have of this medication left, if no date specified for the current medication
        $refill_after_days = self::getMedicationDaysRemaining($item, $member);

        // As the medication is started next day after it ends, add one day
        $refill_after_days++;

        // If there's less days of medication available than days to ship, we set days to ship as the base
        $refill_after_days = max(self::DAYS_TO_SHIP, $refill_after_days);

        $refill_after_days += self::daysMedicationLasts($item);
        // Return the refill date
        return (new Carbon())->addDays($refill_after_days)->format('Y-m-d');
    }

    /**
     * Calculates the number of days the medication lasts, depending on pack size, dose and quantity per dose
     *
     * @param $item
     * @return float|int
     */
    public static function daysMedicationLasts($item)
    {
        // Now calculate the number of days the selected medication would last and add that to the medication days left
        $dosage = Dosage::query()->find($item['dosage_id']);
        if (
            (float)$dosage->quantity_per_day > 0 &&
            (float)$item['quantity_per_dose'] > 0 &&
            (float)$item['quantity'] > 0
        ) {
            return floor($item['quantity'] / (float)$item['quantity_per_dose'] / (float)$dosage->quantity_per_day);
        }
        return 0;
    }

    /**
     * Gets the number of days that are remaining of this medication based on order history.
     *
     * @param array $item
     * @param Member $member
     * @return int
     */
    public static function getMedicationDaysRemaining($item, Member $member)
    {
        if (!empty($item['refill_date'])) {
            if ($item['refill_date'] < (new Carbon())->format('Y-m-d')) {
                return 0;
            }
            // Add +1 to the date diff. E.g., if medication ends tomorrow, it's still 2 days left.
            return (new Carbon($item['refill_date']))->diffInDays(Carbon::now()) + 1;
        }
        if ($nhs_order_item = self::getLastPrescriptionOrdered($item['name'], $member)) {
            $refill_date_time = (new Carbon($nhs_order_item->reminder_date))->format('Y-m-d');
            if ($refill_date_time > (new Carbon())->format('Y-m-d')) {
                // Add +1 to the date diff. E.g., if medication ends tomorrow, it's still 2 days left.
                return (new Carbon($refill_date_time))->diffInDays(Carbon::now()) + 1;
            }
            return 0;
        }
        return 0;
    }

    /**
     * @param $item_name
     * @param Member $member
     * @return Model|null|static
     */
    public static function getLastPrescriptionOrdered($item_name, Member $member)
    {
        return \Mtc\Shop\Order\Item::query()
            ->join('order', function ($join) use ($member) {
                $join->on('order.id', '=', 'order_items.order_id')
                    ->where('order.member', '=', $member->id)
                    ->where('order.paid', '=', '1');
            })
            ->where('order_items.item_name', 'LIKE', $item_name . '%')
            ->where('order_items.nhs_prescription', '1')
            ->orderBy('reminder_date', 'DESC')
            ->first();
    }

    /**
     * Gets the reorder date. Return today if calculates past date.
     *
     * @param string $refill_date
     * @return string
     */
    public static function getReorderDate($refill_date)
    {
        return Carbon::createFromFormat('Y-m-d', $refill_date)
            ->subDays(self::DAYS_TO_REORDER_BEFORE_COMPLETION_DATE)
            ->format('Y-m-d');
    }


    public function get_price()
    {
        $price = 0;

        $multiplier = (int)($this->unilexiconProduct->number_of_charges ?? 1);
        $price *= $multiplier;
        $price = round($price, 2);

        return $price;
    }


    public function get_payable_price()
    {
        if ($this->prescription->nhs_member->is_pay_for_prescriptions) {
            return $this->get_price();
        } else {
            return 0;
        }
    }

}

