<?php

namespace Mtc\Plugins\NHS\Classes;

die('do not use (r)');

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\App;
use Mtc\Modules\BasketRecovery\Classes\BasketRecovery;
use Mtc\Modules\BasketRecovery\Classes\BasketRecoveryEmail;
use Mtc\Modules\Members\Models\Member;
use Mtc\Plugins\SMS\Classes\SMS;
use Mtc\Shop\Events\OrderPaidEvent;
use Mtc\Shop\Item;
use Mtc\Shop\Order;

/**
 * Class Reminder
 *
 * @package Mtc\Plugins\NHS\Classes
 * Martins Fridenbergs <martins.fridenbergs@mtcmedia.co.uk>
 */
class Reminder extends Model
{
    const REFILL_NOTIFICATION_DAYS = 7;

    /**
     * The table associated with the model.
     */
    protected $table = 'nhs_reminders';

    /**
     * @var string[] $fillable Mass assignable variables
     */
    protected $fillable = [
        'order_id',
        'order_item_id',
        'member_id',
        'medication_name',
        'send_sms',
        'send_email',
        'refill_date',
    ];

    /**
     * @var string[] $casts cast variables to specific types
     */
    protected $casts = [
        'refill_date' => 'datetime'
    ];

    /**
     * Relationship with order
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function order()
    {
        return $this->belongsTo(Order::class);
    }

    /**
     * Relationship with order item
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function orderItem()
    {
        return $this->belongsTo(Order\Item::class);
    }

    /**
     * Relationship with member
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function member()
    {
        return $this->belongsTo(Member::class);
    }

    /**
     * Fetch the reminder_date attribute which sets how many days before refill date a reminder will be sent
     *
     * @return mixed
     */
    public function getReminderDateAttribute()
    {
        return clone($this->refill_date)->subDays(Prescription::DAYS_TO_REORDER_BEFORE_COMPLETION_DATE);
    }

    /**
     * Do a batch send-out for NHS reminders
     * This checks orders that are due to go this minute and sends them out
     */
    public static function runBatchSendOut()
    {
        $recovery_template = BasketRecovery::query()
            ->where('is_active', '=', 1)
            ->where('trigger', 'prescription_reminder')
            ->first();

        if (!$recovery_template) {
            error_log('No Follow-Up template, unable to proceed with NHS notifications');
            return;
        }

        self::query()
            ->where('refill_date', '>', Carbon::now()->format('Y-m-d 00:00:00'))
            ->where('refill_date', '<', Carbon::now()->addDays(Prescription::DAYS_TO_REORDER_BEFORE_COMPLETION_DATE)->format('Y-m-d 00:00:00'))
            ->whereNull('sent_at')
            ->with([
                'member',
                'order',
                'orderItem'
            ])
            ->get()
            ->groupBy('member_id')
            ->each(function ($member_notifications) use ($recovery_template) {
                /** @var self $notification */
                $notification = $member_notifications->first();
                if ($notification->triggerSend($recovery_template)) {
                    Reminder::query()
                        ->whereIn('id', $member_notifications->pluck('id'))
                        ->update([
                            'sent_at' => Carbon::now()
                        ]);
                }

            });

    }

    /**
     * Trigger a send of the notification
     * This will send a NHS notification based on users requirements
     *
     * @return boolean whether send-out was successful
     */
    private function triggerSend($recovery)
    {
        if ($this->member->prescription_reminder_email) {
            $email = $this->member->email;

            $twig = App::make('twig');

            $html = $twig->render('Modules/BasketRecovery/email_body.twig', [
                'recovery' => $recovery,
            ]);

            $body = BasketRecoveryEmail::formatEmailLinks(str_replace(
                [
                    '{customer_name}',
                ],
                [
                    $this->member->addressBilling->firstname,
                ],
                $html
            ), $recovery->id);

            email($email, $recovery->subject, $body);
            email(DEV_EMAIL, $recovery->subject, $body);
        }

        if ($this->member->prescription_reminder_sms) {
            try {
                SMS::sendMessage($this->member->phone_prefix . $this->member->contact_no, $recovery->sms_content);
            } catch (\Exception $e) {
                error_log('SMS Follow-up failure: ' . $e->getMessage());
            }
        }
        return true;
    }

    /**
     * Check if order is a NHS order
     * @param Order $order
     * @return bool
     */
    public static function isOrderWithNHSItems(Order $order)
    {
        return $order->items->where('nhs_prescription', 1)->count() > 0;
    }

    /**
     * Process a new order that has NHS items in it
     *
     * @param OrderPaidEvent $event
     * @throws \Exception
     */
    public static function processNHSOrder(OrderPaidEvent $event)
    {
        /** @var Order $order */
        $order = Order::query()
            ->with('items')
            ->find($event->getOrder()->getId());

        // We don't care if we don't have any prescriptions, so return if that's the case.
        if (!self::isOrderWithNHSItems($order)) {
            return;
        }

        /**
         * Make sure member is registered as a NHS member
         * @var Member $member
         */
        $member = Member::query()->find($order->member);
        if (empty($member->nhs_member)) {
            return;
        }

        $dosages = \Mtc\Plugins\NHS\Classes\Dosage::all();

        // Loop through the orders matching the name to the prescriptions
        $order->items->where('nhs_prescription', 1)
            ->each(function ($order_item) use ($dosages, $member) {
                // Only set the reminder if it's not a one-off prescription.
                foreach ($member->nhs_member->prescriptions as $prescription) {
                    /** @var Prescription $prescription */
                    if (strpos($order_item->item_name, $prescription->name) !== false) {
                        if (!$prescription->one_off_prescription) {
                            // Update reminder refill date
                            // Set the sent_at to null so that reminder is sent out.
                            self::query()
                                ->where('member_id', '=', $member->id)
                                ->where('medication_name', '=', $prescription->name)
                                ->update([
                                    'refill_date' => $prescription->refill_date_new,
                                    'sent_at' => null,
                                ]);
                            $prescription->update([
                                'refill_date' => $prescription->refill_date_new,
                                'refill_date_new' => null,
                            ]);
                        }
                    }
                }
            })
            ->each(function ($order_item) {
                /**
                 * After the order has been placed we delete the temporary item and its sizes
                 * This is done do avoid spamming items table with temporary products
                 * As NHS items have their own table and are not managed as regular items
                 * @var Item $item
                 */
                $item = \Mtc\Shop\Item::query()
                    ->where('hidden', 1)
                    ->where('id', $order_item->item_id)
                    ->first();

                if ($item) {
                    $item->sizes()->delete();
                    $item->delete();
                }
            });

        // Remove the one-off prescriptions
        foreach ($member->nhs_member->prescriptions as $prescription) {
            if ($prescription->one_off_prescription) {
                $prescription->delete();
            }
        }
    }


    /**
     * Get all the upcoming follow-ups
     * These are stored in NHS reminders table
     * Discarding sent entries
     */
    public static function getUpcomingPrescriptionNotifications()
    {
        return self::query()
            ->orderBy('refill_date', 'asc')
            ->where('refill_date', '>', Carbon::now()->addDays(Prescription::DAYS_TO_REORDER_BEFORE_COMPLETION_DATE))
            ->whereNull('sent_at')
            ->take(150)
            ->with([
                'member',
                'order',
                'orderItem'
            ])
            ->get();
    }
}
