<?php

namespace Mtc\Modules\Members\Http\Controllers;

use App\SubscriptionBundleType;
use Carbon\Carbon;
use DateTime;
use DateTimeInterface;
use Exception;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\App;
use Illuminate\View\View;
use Item;
use Mtc\Core\Models\Country;
use Mtc\Core\Models\CountryState;
use Mtc\Modules\Members\Classes\Auth;
use Mtc\Modules\Members\Classes\MemberManager;
use Mtc\Modules\Members\Models\Member;
use Mtc\Plugins\NewsletterSignup\Classes\Newsletter;
use Mtc\Plugins\NHS\Classes\NHSMember;
use Mtc\Plugins\NHS\Classes\Prescription;
use Mtc\Shop\Basket;
use Mtc\Shop\Item\Size;
use Mtc\Shop\Item as ItemModel;
use Mtc\Shop\MedicalCondition;
use Mtc\Shop\Medication;
use Mtc\Shop\Order;
use MtcPharmacy\Bundles\Classes\BundleTypeItem;
use MtcPharmacy\Subscriptions\Classes\Subscription;
use MtcPharmacy\Subscriptions\Classes\SubscriptionItem;


class MembersController extends BaseController
{
    private Member $member;
    private $memberOrders;

    public function __construct()
    {
        $this->middleware(function ($request, $next) {
            $this->member = Auth::getLoggedInMember();

            if (!$this->member->id) {
                return redirect(route('members-login'));
            }
            return $next($request);
        });
    }

    /**
     * Member dashboard
     *
     * @return Factory|View
     */
    public function index()
    {
        $page_meta['title'] = config('app.name') . ' | Members Section';

        $orders = Order::query()
            ->with('items')
            ->where('paid', 1)
            ->where(function ($query) {
                $query->where('member', $this->member->id)
                    ->orWhereHas('info', function ($query) {
                        $query->where('email', $this->member->email);
                    });
            })
            ->orderBy('id', 'desc')
            ->get()
            ->map(function ($order) {
                $order->num_items = $order->items->sum('quantity');
                $order->status = Order::$statuses[$order->status];
                $order->date_long = Carbon::createFromFormat('Y-m-d H:i:s', $order->date)->format('j F Y');
                $order->date = Carbon::createFromFormat('Y-m-d H:i:s', $order->date)->format('d/m/Y');

                $order->can_reorder = true;

                /*
                 * Order categories
                 */
                $has_nhs_items = false;
                $has_online_doctor_items = false;
                $has_shop_items = false;

                foreach ($order->items as $item) {

                    if (!empty($item->assessment_id)) {
                        $has_online_doctor_items = true;
                    }

                    if (!empty($item->nhs_prescription)) {
                        $has_nhs_items = true;
                    }

                    if (empty($item->assessment_id) && empty($item->nhs_prescription)) {
                        $has_shop_items = true;
                    }
                }

                $order->has_shop_items = $has_shop_items;
                $order->has_nhs_items = $has_nhs_items;
                $order->has_online_doctor_items = $has_online_doctor_items;

                /*
                 * Get order postcode
                 */
                $addresses = $order->address->toArray();
                $shipping_postcode = false;
                $billing_postcode = false;

                foreach ($addresses as $address) {

                    if (!empty($address['type'])) {

                        if ($address['type'] == 'shipping') {

                            $shipping_postcode = $address['postcode'];

                        } elseif ($address['type'] == 'billing') {

                            $billing_postcode = $address['postcode'];
                        }

                    }

                }

                if (!empty($shipping_postcode)) {
                    $order->order_postcode = $shipping_postcode;
                } elseif (!empty($billing_postcode)) {
                    $order->order_postcode = $billing_postcode;
                }

                /*
                 * Order image
                 */
                $first_item = $order->items[0];
                $order->item_image = THEME_URL . '/images/placeholders/no-image.jpg';
                $order->no_image = true;

                if (!empty($first_item->item_id)) {

                    $temp_item = new Item();
                    $temp_item->Get_Item($first_item->item_id, true);
                    $item_images = collect($temp_item->images);

                    $item_image = $item_images->filter(function ($image) {
                        if (!empty($image['default'])) {
                            return $image;
                        }
                    })->first();

                    if (!empty($item_image['name'])) {
                        $order->item_image = $item_image['name'];
                        $order->no_image = false;
                    }
                }

                return $order;
            });


        /*
         * Tab navigation
         */
        $order_tabs = [
            'All' => [
                'data' => []
            ],
            'Online doctor' => [
                'data' => []
            ],
            'Shop' => [
                'data' => []
            ],
        ];


        /*
         * Build tab content
         */
        $limit = 3;

        foreach ($orders as $order) {

            if (count($order_tabs['All']['data']) < 4) {
                $order_tabs['All']['data'][] = $order;
            }

            if ($order->has_shop_items && count($order_tabs['Shop']['data']) <= $limit) {
                $order_tabs['Shop']['data'][] = $order;
            }

            if ($order->has_nhs_items && count($order_tabs['NHS prescriptions']['data']) <= $limit) {
                $order_tabs['NHS prescriptions']['data'][] = $order;
            }

            if ($order->has_online_doctor_items && count($order_tabs['Online doctor']['data']) <= $limit) {
                $order_tabs['Online doctor']['data'][] = $order;
            }

        }

        return template('members/index.twig', [
            'page_meta' => $page_meta,
            'name' => $this->member->addressBilling->firstname,
            'member' => $this->member,
            'orders' => $orders,
            'order_tabs' => $order_tabs,
            'success' => session()->has('success') ?
                session('success') :
                null,
        ]);
    }

    /**
     * Member orders
     *
     * @return Factory|View
     */
    public function orders()
    {
        $page_meta['title'] = config('app.name') . ' | Your Orders';

        $this->memberOrders = $this->member->orders()
            ->orderByDesc('id')
            ->get()
            ->filter(function ($order) {
                if ($order->paid) {
                    return true;
                }

                $subscription = $order->subscriptions->first();
                if ($subscription && $subscription->hasFailedPayment()) {
                    return true;
                }
                return false;
            });


        return template('/members/orders/index.twig', [
            'page_meta' => $page_meta,
            'member_orders' => $this->memberOrders
        ]);
    }

    /**
     * Member order
     *
     * @param $id
     * @return string
     */
    public function order($id): string
    {
        $page_meta['title'] = config('app.name') . ' | Order Details';

        $order = \Order::getById($id);

        if (!empty($order)) {
            $order->status = Order::$statuses[$order->status];

            $temp_order = Order::query()
                ->where('id', $id)
                ->first();

            $order->date_long = Carbon::createFromFormat('Y-m-d H:i:s', $temp_order->date)
                ->format('j F Y');
            $order->date = Carbon::createFromFormat('Y-m-d H:i:s', $temp_order->date)
                ->format('d/m/Y');
        }

        if ($this->member->id == 0 || ($order->member != $this->member->id && $order->info['email'] != $this->member->email)) {
            header("Location: " . route('members-orders', [], false));
            exit();
        }

        $items = $order->getItems();

        foreach ($items as $key => $line) {
            $item = new Item();
            $item->Get_Item($line['item_id']);

            // get image, checked if exists in item class
            $image = $item->get_basket_image();

            $items[$key]['item_url'] = $item->Generate_URL('');
            $items[$key]['image'] = $image;
        }

        // Get order info previously called via class methods
        $order->deliveryinfo = $order->getDelivery();

        $totals = [
            'subtotal' => $order->getSubtotalCost(),
            'total' => $order->getTotalCost(),
        ];


        return template('/members/orders/order.twig', [
            'page_meta' => $page_meta,
            'member_id' => $this->member->id,
            'order' => $order,
            'totals' => $totals,
            'items' => $items,
            'tracking_events' => [],
        ]);
    }

    /**
     * Reorder
     *
     * @param $id
     * @return void
     */
    public function reorder($id): RedirectResponse|string
    {
        $basket = new \Basket();
        $basket->Go_Basket();
        $order = Order::query()
            ->with(['items.item', 'items.item.ingredients', 'items.item_size', 'info'])
            ->find($id);



        if (
            empty($order) ||
            (
                $order->member != $this->member->id &&
                $order->info->email != $this->member->email
            )
        ) {
            return redirect(
                route('members-orders', ['error' => 'cannot_find'], false)
            );
        }

        $processedReorders = session()->get('processed_reorders', []);
        $reorderSessionData = $processedReorders[$order->id] ?? [];
        $processedPreviously = !empty($reorderSessionData);

        $trackedItems = $reorderSessionData['items'] ?? [];

        $basketQuantities = [];
        if (!empty($basket->items)) {
            foreach ($basket->items as $basketItem) {
                if (!isset($basketItem['item_id'])) {
                    continue;
                }
                $sizeId = (int)($basketItem['sizeid'] ?? 0);
                $key = $basketItem['item_id'] . '|' . $sizeId;
                $basketQuantities[$key] = ($basketQuantities[$key] ?? 0) + (int)($basketItem['quantity'] ?? 0);
            }
        }

        $unavailableItems = [];
        $assessments = [];
        $availableCount = 0;

        $controller = $this;

        $order->items
            ->each(function ($orderItem) use (
                $basket,
                &$assessments,
                &$unavailableItems,
                &$availableCount,
                $controller,
                &$trackedItems,
                $processedPreviously,
                &$basketQuantities
            ) {
                if (empty($orderItem->item) || empty($orderItem->item->id)) {
                    $unavailableItems[] = $controller->buildUnavailableOrderItemData($orderItem, 'no_longer_available');
                    return;
                }

                $legacyItem = new Item();
                $legacyItem->Get_Item($orderItem->item->id, true);

                $inStock = true;
                $reason = 'out_of_stock';

                if ($orderItem->item->sizes->isEmpty()) {
                    $inStock = (int) $orderItem->item->stock > 0;
                } else {
                    $sizeModel = $orderItem->item_size ?: Size::query()->find($orderItem->sizeid);
                    $inStock = $sizeModel && (int) $sizeModel->stock > 0;
                }

                if (! $inStock) {
                    $unavailableItems[] = $controller->buildUnavailableOrderItemData($orderItem, $reason, $legacyItem, $orderItem->item);
                    return;
                }

                $availableCount++;

                if ($orderItem->item->form_id > 0) {
                    $assessments[] = [
                        'form_id' => $orderItem->item->form_id,
                        'p' => $orderItem->item_id,
                        's' => $orderItem->sizeid,
                        'q' => $orderItem->quantity,
                    ];
                    return;
                }

                $sizeId = (int)($orderItem->sizeid ?? 0);
                $key = $orderItem->item_id . '|' . $sizeId;
                $orderQuantity = (int)$orderItem->quantity;

                $quantityToAdd = $orderQuantity;

                if ($processedPreviously) {
                    $expectedTotal = $trackedItems[$key] ?? 0;

                    if ($expectedTotal <= 0) {
                        $expectedTotal = $orderQuantity;
                        $trackedItems[$key] = $expectedTotal;
                    }

                    $currentQuantity = $basketQuantities[$key] ?? 0;

                    if ($currentQuantity >= $expectedTotal) {
                        $quantityToAdd = 0;
                    } else {
                        $quantityToAdd = $expectedTotal - $currentQuantity;
                    }
                } else {
                    $trackedItems[$key] = ($trackedItems[$key] ?? 0) + $orderQuantity;
                }

                if ($quantityToAdd <= 0) {
                    return;
                }

                $basket->Add_Item([
                    'id' => $orderItem->item_id,
                    'size_id' => $orderItem->sizeid,
                    'size' => $orderItem->size,
                    'PLU' => $orderItem->PLU,
                    'quantity' => $quantityToAdd,
                ]);

                $basketQuantities[$key] = ($basketQuantities[$key] ?? 0) + $quantityToAdd;
            });

        if (!$processedPreviously && !empty($trackedItems)) {
            $processedReorders[$order->id] = [
                'items' => $trackedItems,
                'added_at' => Carbon::now()->timestamp,
            ];
            session(['processed_reorders' => $processedReorders]);
        }

        if ($availableCount === 0) {
            \App\FlashMessage::set('error', 'Unfortunately none of the items from that order are currently available.');

            return redirect(route('members-orders', [], false));
        }

        $destinationUrl = count($assessments)
            ? route('assessment-form', $assessments[0], false)
            : '/shop/checkout/basket.php';

        if (!empty($unavailableItems)) {
            return template('members/orders/reorder_summary.twig', [
                'page_meta' => [
                    'title' => config('app.name') . ' | Reorder summary',
                ],
                'unavailable_items' => $unavailableItems,
                'proceed_url' => $destinationUrl,
                'proceed_label' => count($assessments) ? 'Continue to assessment' : 'Go to basket',
                'current_url' => request()->fullUrl(),
            ]);
        }

        return redirect($destinationUrl);
    }

    private function buildUnavailableOrderItemData($orderItem, string $reason, ?Item $legacyItem = null, ?ItemModel $eloquentItem = null): array
    {
        $productName = $legacyItem->name
            ?? optional($orderItem->item)->name
            ?? $orderItem->item_name
            ?? 'Item';

        $url = '';
        if ($legacyItem) {
            $url = $legacyItem->Generate_URL('');
        } elseif ($eloquentItem) {
            $url = $eloquentItem->url;
        }

        if ($eloquentItem) {
            $eloquentItem->loadMissing('active_substances');
        }

        $ingredientNames = $eloquentItem ? $eloquentItem->active_substances->pluck('name')->toArray() : [];
        $ingredientIds = $eloquentItem ? $eloquentItem->active_substances->pluck('id')->toArray() : [];

        return [
            'name' => $productName,
            'size' => $orderItem->size,
            'url' => $url,
            'reason' => $reason,
            'ingredients' => $ingredientNames,
            'alternatives' => ($ingredientIds && $eloquentItem && $eloquentItem->product_type === ItemModel::TYPE_PHARMACY)
                ? $this->findAlternativeProducts($ingredientIds, $eloquentItem->id)
                : [],
        ];
    }

    private function findAlternativeProducts(array $ingredientIds, ?int $excludeItemId = null): array
    {
        if (empty($ingredientIds)) {
            return [];
        }

        $alternatives = ItemModel::query()
            ->with([
                'sizes' => function ($query) {
                    $query->select('items_sizes.id', 'items_sizes.item_id', 'items_sizes.size', 'items_sizes.stock', 'items_sizes.hide')
                        ->where('hide', 0);
                },
                'images' => function ($query) {
                    $query->select('id', 'item_id', 'name', 'default', 'hover', 'zoom');
                },
            ])
            ->select(['id', 'name', 'stock', 'hidden', 'product_type'])
            ->where('product_type', ItemModel::TYPE_PHARMACY)
            ->where('hidden', 0)
            ->whereHas('active_substances', function ($query) use ($ingredientIds) {
                $query->whereIn('active_substances.id', $ingredientIds);
            })
            ->when($excludeItemId, function ($query) use ($excludeItemId) {
                $query->where('id', '!=', $excludeItemId);
            })
            ->limit(20)
            ->get();

        $alternatives = $alternatives->filter(function ($item) {
            if ($item->sizes->count()) {
                return $item->sizes->contains(function ($size) {
                    return (int)$size->stock > 0;
                });
            }

            return (int)$item->stock > 0;
        });

        return $alternatives->map(function (ItemModel $item) {
            $sizes = $item->sizes
                ->filter(function ($size) {
                    return (int)$size->stock > 0;
                })
                ->map(function ($size) {
                    return [
                        'id' => $size->id,
                        'label' => $size->size,
                        'stock' => (int)$size->stock,
                    ];
                })
                ->values()
                ->all();

            $imagePath = $item->getImagePath('default', 'thumbs') ?: $item->getImagePath('default');

            return [
                'id' => $item->id,
                'name' => $item->name,
                'url' => $item->url,
                'stock' => (int)$item->stock,
                'sizes' => $sizes,
                'image' => $imagePath,
            ];
        })->values()->all();
    }

    /**
     * Member account
     *
     * @return string
     */
    public function account(): string
    {
        $page_meta['title'] = config('app.name') . ' | My Account';

        if ($this->member->nhs_member && $this->member->nhs_member->dob == '0000-00-00') {
            $this->member->nhs_member->dob = '';
        }

        if (!empty($this->member->dob)) {
            $dobDate = Carbon::parse($this->member->dob);
            $this->member->dob_date = $dobDate->format('d');
            $this->member->dob_month = $dobDate->format('m');
            $this->member->dob_year = $dobDate->format('Y');
        }

        $settings['PAF_ENABLED'] = false;

        return template('members/details.twig', [
            'page_meta' => $page_meta,
            'member_id' => $this->member->id,
            'member' => $this->member,
            'countries' => Country::getFullCountryList(),
            'state_list' => CountryState::getStateList("US"),
            'self' => $_SERVER['REQUEST_URI'],
            'titles' => Member::$titles,
            'genders' => Member::$genders,
            'paf_enabled' => $settings['PAF_ENABLED'],
            'dob' => Member::getDobOptions(),
            'newsletter' => Newsletter::checkIfExists($this->member->email),
        ]);
    }

    /**
     * Save account
     */
    public function accountStore(Request $request)
    {
        $success = [];
        $errors = [];

        $memberManager = new MemberManager();
        $data = $request->all();
        if (
            $memberManager->save($data, $this->member, [
                MemberManager::PARAM_CHECK_SESSION => true,
            ])
        ) {
            if (!empty($data['newsletter'])) {
                Newsletter::signUp($data['email'], [
                    'first_name' => $data['billing_firstname'],
                    'last_name' => $data['billing_lastname'],
                    'skip_double_opt_in' => true,
                ]);
            } else {
                Newsletter::unsubscribe($data['email']);
            }
            $success['message'] = '<p class="success">We have successfully saved your details</p>';
        } else {
            $errors = $memberManager->getErrors();
        }

        return json_encode([
            'errors' => $errors,
            'success' => $success,
        ]);
    }

    /**
     * Member account
     *
     * @return string
     */
    public function healthProfile(): string
    {
        $page_meta['title'] = config('app.name') . ' | My Health Profile';

        $this->member->medications_json = empty($this->member->medications) ? '' : clean_page(implode(',', (array) json_decode($this->member->medications)));
        $this->member->medical_conditions_json = empty($this->member->conditions) ? '' : clean_page(implode(',', (array) json_decode($this->member->conditions)));

        $doctor_surgery = !empty($this->member->doctor_surgery) ?
            json_decode($this->member->doctor_surgery) :
            (object) [
                'manual_doctor_surgery' => 0,
                'id' => 0,
                'practice_name' => '',
                'city' => '',
                'address_1' => '',
                'address_2' => '',
                'postcode' => '',
                'phone' => '',
            ];


        return template('members/health_profile.twig', [
            'page_meta' => $page_meta,
            'member' => $this->member,
            'doctor_surgery' => $doctor_surgery,
            'all_medications' => json_encode(\Mtc\Shop\Medication::query()->pluck('name')->toArray()),
            'all_medical_conditions' => json_encode(\Mtc\Shop\MedicalCondition::query()->pluck('name')->toArray()),
            'self' => $_SERVER['REQUEST_URI']
        ]);
    }

    /**
     * Save account
     */
    public function healthProfileStore(Request $request)
    {
        $success = [];
        $errors = [];

        $this->member->setMedications(explode(',', $request->input('medications')));
        $this->member->setConditions(explode(',', $request->input('conditions')));
        $this->member->setAllergies(explode(',', $request->input('allergies')));
        $this->member->doctor_surgery = json_encode($request->input('doctor_surgery'));

        $this->member->save();

        if ($uploaded_proof = $request->file('exemption_proof')) {
            $proof_file_dir = NHSMember::get_exemption_proof_file_dir();
            $proof_file_name = uniqid() . '.' . $uploaded_proof->getClientOriginalExtension();
            $uploaded_proof->storeAs($proof_file_dir, $proof_file_name);
            $this->member->nhs_member->exemption_proof_file = $proof_file_name;
            $this->member->nhs_member->save();
        }

        $success['message'] = '<p class="success">We have successfully saved your health profile</p>';

        return json_encode([
            'errors' => $errors,
            'success' => $success,
        ]);
    }

    /**
     * Logs out member
     *
     * @return Factory|View
     */
    public function logout()
    {
        Auth::logout();

        $page_meta['title'] = config('app.name') . ' | Logout';

        return template('members/logout.twig', [
            'page_meta' => $page_meta,
            'member' => new Member(),
            'is_login_page' => true
        ]);
    }


    public function log_in_as_member(int $member_id)
    {
        $member = Member::findOrFail($member_id);

        $member->try_to_log_in();

        return redirect(route('members-dashboard', [], false));
    }


    public function referred_members(Request $request)
    {
        $page_meta['title'] = config('app.name') . ' | Patients';

        return template('members/referred_members.twig', [
            'member' => $this->member,
            'page_meta' => $page_meta,
            'current_page' => 'members-referred',
        ]);
    }



    public function get_prescription_data(Request $request)
    {
        if ($this->member->nhs_member->is_patient) {
            $prescriptions = $this->member->nhs_member->prescriptions();
        } else {
            $referred_prescriptions = $this->member->nhs_member->get_referred_prescriptions();
            $prescriptions = Prescription::query()->whereIn('id', $referred_prescriptions->pluck('id'));
        }

        $prescriptions = $prescriptions
            ->with('items')
            ->with('nhs_member.member')
            ->orderBy('updated_at', 'desc')
        ;

        if ($request->input('status')) {
            $prescriptions = $prescriptions->where('status', $request->input('status'));
        }

        $prescriptions = $prescriptions
            ->paginate($request->input('page_size', 0))
            ->appends($request->input())
        ;

        foreach ($prescriptions as $prescription) {
            $prescription->status_label = Prescription::get_status_label($prescription->status);
            $prescription->member_display_id = $prescription->nhs_member->get_member_ref();
            $prescription->patient_full_name = $prescription->nhs_member->get_full_name();

            $prescription->is_editable = $prescription->is_editable();
            $prescription->prescription_edit_url = route('nhs-prescriptions-edit', [$prescription->uuid], false);

            $prescription->can_be_reordered = $prescription->can_be_reordered();
            $prescription->prescription_copy_url = route('nhs-prescriptions-copy', [$prescription->uuid], false);
        }

        return $prescriptions;
    }


    public function orders__nhs_prescriptions(Request $request)
    {
        $page_meta['title'] = config('app.name') . ' | NHS Prescriptions';

        $order_tabs = [
            'a' => [
                'label' => Prescription::get_status_label(Prescription::STATUS_DRAFT),
                'data' => [],
                'pagination' => true,
                'dataUrl' => route('members-orders-nhs-prescriptions-data', [
                    'status' => Prescription::STATUS_DRAFT,
                    'page_size' => 20,
                ]),
                'isActive' => true,
            ],
            'b' => [
                'label' => Prescription::get_status_label(Prescription::STATUS_PENDING),
                'data' => [],
                'pagination' => true,
                'dataUrl' => route('members-orders-nhs-prescriptions-data', [
                    'status' => Prescription::STATUS_PENDING,
                    'page_size' => 20,
                ]),
            ],
            'c' => [
                'label' => Prescription::get_status_label(Prescription::STATUS_COMPLETE),
                'data' => [],
                'pagination' => true,
                'dataUrl' => route('members-orders-nhs-prescriptions-data', [
                    'status' => Prescription::STATUS_COMPLETE,
                    'page_size' => 20,
                ]),
            ],
        ];

        return template('members/nhs_prescriptions/index.twig', [
            'page_meta' => $page_meta,
            'member_id' => $this->member->id,
            'member' => $this->member,
            'tabs_config' => json_encode($order_tabs),
            'current_page' => 'members-orders-nhs-prescriptions',
        ]);
    }


    public function orders__subscriptions(Request $request)
    {
        $page_meta['title'] = config('app.name') . ' | Subscriptions';

        $subscriptions = Subscription::query()
            ->where('member_id', $this->member->id)
            ->orderByRaw("FIELD(status, 'active', 'paused', 'pending', 'payment-failed', 'expired', 'completed', 'cancelled')")
            ->orderBy('id', 'desc')
            ->get()
        ;

        foreach ($subscriptions as $sub) {
            $sub->append('edit_url');
            if (SubscriptionBundleType::isSubscriptionEditable($sub)) {
                $sub->edit_url = route('members-orders-subscription-edit', [$sub->id]);
            }

            if (config('subscription.enabled')) {
                $sub->items->map(function ($sub) {
                    $sub->shop_item = false;
                    $item = \Mtc\Shop\Item::find((int) $sub->shop_item_id);

                    if (!empty($item)) {
                        //Add subscription prices to sizes
                        $item->mapSizePricesToSubscriptions();
                        $sub->shop_item = $item;
                    }
                    return $sub;
                });
            }
        }

        return template('members/subscriptions/index.twig', [
            'page_meta' => $page_meta,
            'cancellation_reasons' => Subscription::CANCELLATION_REASONS,
            'subscriptions' => $subscriptions,
            'current_page' => 'members-orders-subscriptions',
            'active_nav_item' => 'subscriptions',
        ]);
    }


    public function orders__subscription_edit($subscription_id, Request $request)
    {
        $page_meta['title'] = config('app.name') . ' | Subscriptions';

        $sub = Subscription::findOrFail($subscription_id);

        $sub->authoriseAccessByCurrentUser();

        $sbt = SubscriptionBundleType::query()
            ->where('subscription_id', $sub->id)
            ->firstOrFail()
        ;

        if (!$sbt->bundleType->url) {
            abort(404);
        }

        $preselected = collect([]);
        foreach ($sub->items as $sub_item) {
            $preselected->push($sbt->bundleType->findByShopItemId(
                $sub_item->shop_item_id,
                $sub_item->shop_item_size_id
            ));
        }

        $query_params = [
            'force' => 1,
            'preselected_items' => $preselected->pluck('id')->toArray(),
            'submit_items_url' => route('members-orders-subscription', [$subscription_id], false),
            'submit_items_button_label' => 'Update subscription',
        ];

        $url = $sbt->bundletype->url . '?' . http_build_query($query_params);

        return redirect($url);
    }


    public function orders__subscription_update($subscription_id, Request $request)
    {
        $sub = Subscription::find($subscription_id);
        $sub->items()->delete();

        foreach ($request->input('item_ids') as $bti_id) {
            $bti = BundleTypeItem::find($bti_id);
            if ($bti) {
                $si = new SubscriptionItem();
                $si->shop_item_id = $bti->shop_item_id;
                $si->shop_item_size_id = $bti->shop_item_size_id;
                $si->subscription()->associate($sub);
                $si->save();
            }
        }

        return [
            'success' => true,
            'redirect_url' => route('members-orders-subscriptions'),
        ];
    }

    /**
     * View verification page
     *
     * @param Request $request
     * @return string
     */
    public function verify(Request $request): string
    {
        $page_meta['title'] = 'Verify your account';

        return template('members/verify.twig', [
            'page_meta' => $page_meta,
            'error' => session('error'),
            'name' => $this->member->addressBilling->firstname,
            'self' => $_SERVER['REQUEST_URI']
        ]);
    }

    /**
     * Sends verification code
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function sendVerificationCode(Request $request): JsonResponse
    {
        $errors = [];
        $messages = [];
        $send_to = $request->input('method') === 'email' ?
            $request->input('email') :
            $request->input('contact_no');
        try {
            $sent = App::make(MemberManager::class)->sendVerification(request()->input('method'), $send_to);
            if ($sent) {
                $device = request()->input('method') === 'email' ?
                    'email' :
                    'phone';
                $messages[] = "Please check your {$device} for verification code";
                // Update member's email address
                if ($device === 'email') {
                    $this->member->email = $request->input('email');
                    $this->member->save();
                }
            } else {
                $errors[] = 'Failed to send verification code. Please check your details and try again';
            }
        } catch (\Exception $exception) {
            $errors = [
                $exception->getMessage()
            ];
        }

        return response()->json([
            'messages' => $messages,
            'errors' => $errors,
        ]);
    }

    /**
     * Sends verification code
     *
     * @param Request $request
     * @return RedirectResponse
     */
    public function verifyCode(Request $request): RedirectResponse
    {
        $expiry = Carbon::createFromFormat('Y-m-d H:i:s', $this->member->verification_code_expiry);

        if ($request->input('code') !== $this->member->verification_code) {
            session()->flash('error', 'Verification code did not match');
            return redirect()->back();
        }

        if (Carbon::now() > $expiry) {
            session()->flash('error', 'Verification code has expired');
            return redirect()->back();
        }

        $this->member->verification_code = '';
        $this->member->account_verified = Carbon::now();
        $this->member->save();

        session()->flash('success', 'Your account has been verified');
        return redirect()->route('members-dashboard');
    }
}
