<?php

namespace Mtc\Plugins\NHS\Classes;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Mtc\Modules\Members\Models\Member;
use Mtc\Shop\Basket\Address as BasketAddress;
use Mtc\Shop\Basket\Info as BasketInfo;
use Mtc\Shop\Basket\Item as BasketItem;


class Prescription extends Model
{

    const STATUS_DRAFT = 'draft';
    const STATUS_PENDING = 'pending';
    const STATUS_COMPLETE = 'complete';

    protected $table = 'nhs_prescriptions';

    protected $fillable = [
        'unio_internal_id',
        'is_external',
        'status',
    ];


    public static function create($member, $unio_internal_id = null)
    {
        $prescription = new self();
        $prescription->uuid = (string)Str::uuid();
        if ($unio_internal_id) {
            $prescription->unio_internal_id = $unio_internal_id;
            $prescription->is_external = true;
        } else {
            $prescription->is_external = false;
        }
        $prescription->save();

        if ($member->id) {
            if ($member->nhs_member->is_patient) {
                $prescription->nhs_member()->associate($member->nhs_member)->save();
            } else {
                // Referrer does not create prescriptions for herself.
            }
        }

        return $prescription;
    }


    public static function get_by_uuid($uuid)
    {
        $prescription = self::query()
            ->where('uuid', $uuid)
            ->first()
        ;

        if (! $prescription) {
            abort(404);
        }

        return $prescription;
    }


    public static function get_allowed_statuses()
    {
        return [
            Prescription::STATUS_DRAFT,
            Prescription::STATUS_PENDING,
            Prescription::STATUS_COMPLETE,
        ];
    }


    public static function get_status_label($status)
    {
        switch ($status) {
            case self::STATUS_DRAFT:
                $status_label = 'In Progress';
                break;

            case self::STATUS_COMPLETE:
                $status_label = 'Received';
                break;

            default:
                $status_label = 'Pending';
                break;
        }

        return $status_label;
    }


    public function nhs_member()
    {
        return $this->belongsTo(\Mtc\Plugins\NHS\Classes\NHSMember::class);
    }


    public function items()
    {
        return $this->hasMany(PrescriptionItem::class);
    }


    public function save_status($status, $revert_complete_status = false)
    {
        if ($this->status != Prescription::STATUS_COMPLETE || $revert_complete_status) {
            $this->status = $status;
            $this->save();
        }

        return $this;
    }


    public function authorise_access_by(Member $member)
    {
        $can_access = false;


        if ($member->id) { // Known member.

            if (! $this->nhs_member) { // Prescription is not linked to any member.

                $can_access = true;

            } else {

                if ($member->nhs_member->is_patient) { // $member is patient.
                    if ($this->nhs_member->member->id == $member->id) {
                        $can_access = true;
                    }
                } else { // $member is referrer.
                    if ($this->nhs_member->member->referrer->id == $member->id) {
                        $can_access = true;
                    }
                }

            }


        } else { // Anonymous member.

            if (! $this->nhs_member) { // Prescription is not linked to any member.
                $can_access = true;
            }

        }


        if (! $can_access) {
            abort(403, 'You have no permissions to see this prescription.');
        }
    }


    public function get_delivery_method()
    {
        // NHS Free Collection; TODO: make dynamic.
        $delivery_method_id = 64;

        $delivery_method = \DeliveryMethod::query()
            ->where('id', $delivery_method_id)
            ->first();

        return $delivery_method;
    }


    public function get_payment_totals()
    {
        $totals = [
            'original' => 0,
            'payable' => 0,
        ];

        foreach ($this->items as &$prescription_item) {
            $totals['original'] += $prescription_item->get_price();
            $totals['payable'] += $prescription_item->get_payable_price();
        }

        $totals['original'] = round($totals['original'], 2);
        $totals['payable'] = round($totals['payable'], 2);

        return $totals;
    }


    public function create_basket()
    {
        if (isset($_SESSION)) {
            unset($_SESSION['basket']);
            unset($_SESSION['basket_id']);
        }

        $basket = new \Mtc\Shop\Basket();
        $basket->customer()->associate($this->nhs_member->member);
        if ($delivery_method = $this->get_delivery_method()) {
            $basket->delivery = $delivery_method->id;
        }
        $basket->save();

        $basket_info = new BasketInfo();
        $basket_info->email = $basket->customer->email;
        $basket_info->contact_no = $basket->customer->contact_no;
        $basket->info()->save($basket_info);


        // Items.

        foreach ($this->items as $prescription_item) {
            $basket_item = new BasketItem();
            $basket_item->item_id = 0;
            $basket_item->PLU = $prescription_item->name;
            $basket_item->prescription_item()->associate($prescription_item);
            $basket_item->save();
            $basket->items()->save($basket_item);
        }


        // Addresses.

        $shipping_address_data = $this->nhs_member->member->addressShipping->toArray();
        $order_shipping_address = new BasketAddress($shipping_address_data);
        $basket->shippingAddress()->save($order_shipping_address);

        if ($this->nhs_member->member->referrer) {
            // Use referrer's billing address.
            $billing_address_data = $this->nhs_member->member->referrer->addressBilling->toArray();
        } else {
            // Use patient's billing address.
            $billing_address_data = $this->nhs_member->member->addressBilling->toArray();
        }

        $order_billing_address = new BasketAddress($billing_address_data);
        $basket->billingAddress()->save($order_billing_address);


        // Final object.

        $basket_legacy = $basket->legacy();
        //$basket_legacy->resetSession();

        return $basket_legacy;

    }


    private static function get_editable_statuses()
    {
        return [
            self::STATUS_DRAFT,
            self::STATUS_PENDING
        ];
    }


    public function is_editable()
    {
        $is_editable = false;

        if (in_array($this->status, self::get_editable_statuses())) {
            $is_editable = true;
        }

        return $is_editable;
    }


    public function can_be_reordered()
    {
        $can_be_reordered = false;

        if (! in_array($this->status, self::get_editable_statuses())) {
            $can_be_reordered = true;
        }

        return $can_be_reordered;
    }


    public function is_ready_for_checkout()
    {
        $is_ready = false;

        if ($this->status == self::STATUS_PENDING) {
            $is_ready = true;
        }

        return $is_ready;
    }


    public function save_items_from_input(array $items = []) : array
    {
        $processed_items = [];

        if ($items) {
            $this->items()->delete();
        }

        foreach ($items as $item) {
            if (! is_array($item)) continue;

            $item_obj = PrescriptionItem::query()
                ->where('prescription_id', $this->id)
                ->where('name', $item['name'])
                ->first()
            ;

            if (! $item_obj) {
                $item_obj = new PrescriptionItem();
            }

            $item_obj->name = $item['name'];
            $item_obj->quantity = $item['quantity'];
            $item_obj->additional_info = Arr::get($item, 'additional_info');
            $item_obj->one_off_prescription = Arr::get($item, 'one_off_prescription', 0);
            $item_obj->refill_date = Arr::get($item, 'refill_date');
            if ($item_obj->one_off_prescription) {
                $item_obj->frequency_days = 0;
            } else {
                $item_obj->frequency_days = (int)Arr::get($item, 'frequency_days');
            }

            $errors_bag = $item_obj->validate()->errors();
            if ($errors_bag->isEmpty()) {
                $item_obj->nhs_unilexicon_product_id = NHSUnilexiconProduct::getIdFromName($item_obj->name);
                $this->items()->save($item_obj);
            }

            $item_obj->errors = \App\FlashMessage::getImplodedMessages($errors_bag);

            $processed_items[] = $item_obj;
        }

        return $processed_items;
    }


    public function get_dummy_email_address()
    {
        return "patient@{$this->uuid}.mtc";
    }
}
