<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Mtc\Shop\Item as ShopItem;
use Mtc\Shop\Item\Size as ShopItemSize;
use MtcPharmacy\Bundles\Classes\BundleType;
use MtcPharmacy\Subscriptions\Classes\SubscriptionPreference;
use MtcPharmacy\Subscriptions\Classes\Subscription;
use Basket;
use App\SizeRestriction;
use Illuminate\Support\Facades\DB;
use Mtc\Shop\Assessment\Assessment;
use Mtc\Shop\Category;
use App\ShopHelper;


class ShopController extends Controller
{

    public function subscription_create_choice(Request $request)
    {
        $bundle_type = BundleType::find($request->input('bundletype_id'));

        $template_data = [
            'edit_existing_url' => route('members-orders-subscriptions'),
            'return_url' => $request->input('return_url'),
            'bundle_type_name' => $bundle_type->name ?? '',
        ];

        return template('shop/subscription_create_choice.twig', $template_data);
    }


    public function staggered_checkout__select_strength(Request $request, $shop_item_id)
    {
        $shop_item = ShopItem::findOrFail($shop_item_id);

        // if (! $shop_item->canBePurchasedByUser()) abort();

        if ($shop_item->sizes->count() > 0) {

            $options = [];
            foreach ($shop_item->sizes as $shop_item_size) {

                if (SizeRestriction::isSizeRestricted($shop_item_size)) continue;

                if (! isset($options[$shop_item_size->strength])) {
                    $options[$shop_item_size->strength] = [
                        'title' => $shop_item_size->strength,
                        'subtitle' => $shop_item->name,
                        'button' => [
                            'label' => 'Select...',
                        ],
                        'item_size_ids' => [],
                    ];
                }
                $options[$shop_item_size->strength]['item_size_ids'][] = $shop_item_size->id;
            }

            foreach ($options as &$option) {
                $option['button']['url'] = route('shop-select-packsize', [
                    $shop_item->id,
                    'allowed_size_ids' => $option['item_size_ids'],
                ]);
            }

            return template('shop/staggered_checkout/select_variation.twig', [
                'go_back_url' => $shop_item->getMainCategoryUrl() . '?fullscreen=true',
                'option_cards' => $options,
            ]);

        } else {

            return redirect()->route('shop-addtobasket', [
                'id' => $shop_item->id,
                'url_redirect' => route('shop-select-subscription', [ $shop_item->id ]),
            ]);

        }
    }


    public function staggered_checkout__select_packsize(Request $request, $shop_item_id)
    {
        $shop_item = ShopItem::findOrFail($shop_item_id);

        if ($shop_item->sizes->count() > 0) {

            $allowed_size_ids = $request->input('allowed_size_ids');

            $options = [];
            foreach ($shop_item->sizes as $shop_item_size) {
                if (! in_array($shop_item_size->id, $allowed_size_ids)) continue;

                $options[$shop_item_size->pack_size] = [
                    'title' => $shop_item_size->pack_size,
                    'subtitle' => $shop_item->name,
                    'button' => [
                        'label' => 'Select...',
                        'url' => route('shop-addtobasket', [
                            'id' => $shop_item->id,
                            'size' => $shop_item_size->id,
                            'url_redirect' => route('shop-select-subscription', [ $shop_item->id, $shop_item_size->id ]),
                        ]),
                    ],
                ];
            }

            return template('shop/staggered_checkout/select_variation.twig', [
                'go_back_url' => route('shop-select-strength', [ $shop_item_id ]),
                'option_cards' => $options,
            ]);

        } else {

            return redirect()->route('shop-addtobasket', [
                'id' => $shop_item->id,
                'url_redirect' => route('shop-select-subscription', [ $shop_item->id ]),
            ]);

        }
    }


    public function staggered_checkout__select_subscription(Request $request, $shop_item_id, $shop_item_size_id = null)
    {
        $shop_item = ShopItem::findOrFail($shop_item_id);
        if ($shop_item_size_id) {
            $shop_item_size = ShopItemSize::findOrFail($shop_item_size_id);
        }

        $sub_config = SubscriptionPreference::init($shop_item_id, $shop_item_size_id);

        if ($sub_config) {
            if ($sub_config->is_required) {

                return redirect()->route('shop-request-subscription', [ $shop_item_id, $shop_item_size_id ]);

            } else if ($sub_config->is_allowed) {

                return template('shop/staggered_checkout/select_subscription.twig', [
                    'sub_config' => $sub_config,
                    'accept_url' => route('shop-request-subscription', [ $shop_item_id, $shop_item_size_id ]),
                    'decline_url' => route('shop-remove-subscription', [ $shop_item_id, $shop_item_size_id ]),
                    'go_back_url' => route('shop-select-strength', [ $shop_item_id ]),
                ]);

            }
        }

        return redirect()->route('shop-checkout-basket');
    }


    public function staggered_checkout__request_subscription(Request $request, $shop_item_id, $shop_item_size_id = null)
    {
        $basket = Basket::getCurrent();
        foreach ($basket->eloquent()->items as $basket_item) {
            if ($basket_item->item_id == $shop_item_id && $basket_item->sizeid == $shop_item_size_id) {
                $basket_item->has_requested_subscription = true;
                $basket_item->quantity = 1;
                $basket_item->save();
                break;
            }
        }

        return redirect()->route('shop-checkout-basket');
    }


    public function staggered_checkout__remove_subscription(Request $request, $shop_item_id, $shop_item_size_id = null)
    {
        $basket = Basket::getCurrent();
        foreach ($basket->eloquent()->items as $basket_item) {
            if ($basket_item->item_id == $shop_item_id && $basket_item->sizeid == $shop_item_size_id) {
                $basket_item->has_requested_subscription = false;
                $basket_item->save();
                break;
            }
        }

        return redirect()->route('shop-checkout-basket');
    }


    public function get_basket_allowed_products(Request $request)
    {
        $products_to_return = [];

        $category = Category::find((int)$request->input('category_id'));
        $product = ShopItem::find((int)$request->input('product_id'));
        $assessment_ids = $this->normaliseAssessmentIds($request->input('assessment_ids', []));

        $available_products = collect([]);
        if ($category) {
            $available_products = CategoryController::getDisplayItems($category, [], true);
        } elseif ($product) {
            $product->load('images');
            $available_products = collect([ $product ]);
        }

        $assessmentMap = Assessment::query()
            ->whereIn('id', array_filter($assessment_ids))
            ->get()
            ->keyBy('id');

        // Every per-patient group decorates clones of the same product set, so
        // resolve the upsell map once here rather than re-querying per group.
        $upsells_by_item = ShopHelper::resolveUpsells($available_products);

        foreach ($assessment_ids as $assessment_id) {
            $a = $assessmentMap->get($assessment_id);
            if (!$a) {
                continue;
            }

            $customer_name = $a->customer_name;

            if($customer_name == '-') {
                $customer_name = false;
            }

            $key = $customer_name ? Assessment::encodeCustomerName($customer_name) : 0;
            $products_to_return[$key] = collect([]);

            foreach ($available_products as $available_product) {
                $products_to_return[$key]->push(clone $available_product);
            }

            ShopHelper::decorateWithMinimumQuantity($products_to_return[$key], $a);
            ShopHelper::forgetNotAllowed($products_to_return[$key], $a);
            ShopHelper::applyUpsells($products_to_return[$key], $upsells_by_item);
        }

        return $products_to_return;
    }


    public function test_add_to_basket_multiple(Request $request)
    {
        //$body = '{"products_grouped":[{"products":[{"id":"23_28","name":"Product A (1)","quantity":2},{"id":"23_29","name":"Product A (2)","quantity":3},{"id":11,"name":"Product B","quantity":1}],"user_full_name":"user a"},{"products":[{"id":"23_28","name":"Product A (1)","quantity":20},{"id":"23_29","name":"Product A (2)","quantity":30},{"id":11,"name":"Product B","quantity":10}],"user_full_name":"user B"}],"assessment_ids":[{"id":162},{"id":163}]}';


        //$body = '{"products_grouped":[{"products":[{"id":36,"name":"Import Product 3","quantity":7}],"user_full_name":"User One"},{"products":[{"id":36,"name":"Import Product 3","quantity":6}],"user_full_name":"User Two"}],"assessment_ids":[{"id":132},{"id":133}]}';

        // Single user
        $body = '{"products_grouped":[{"products":[{"id":119,"name":"Co-codamol Effervescent Strong Pain Relief Tablets x 32","quantity":1,"minQuantity":1}],"user_full_name":""}],"assessment_ids":[{"id":139}]}';


        $bbb = json_decode($body, true);

        $r = new Request();
        $r->merge($bbb);

        return $this->add_to_basket_multiple($r);
    }


    /**
     * Normalise a posted assessment_ids payload to a flat list of unique, positive
     * integer IDs. AssessmentCheckoutController returns created_assessments as
     * [{id: N}, ...] and the front end posts that straight through, so entries can
     * be {id: N} objects rather than bare ids. A non-scalar value would crash
     * Collection::get() (array_key_exists rejects array offsets) and pollutes
     * whereIn() lookups, so coerce here before either is used.
     *
     * @return int[]
     */
    private function normaliseAssessmentIds($assessment_ids): array
    {
        return collect($assessment_ids)
            ->map(fn ($entry) => is_array($entry) ? ($entry['id'] ?? null) : $entry)
            ->filter(fn ($id) => is_scalar($id))
            ->map(fn ($id) => (int) $id)
            ->filter()
            ->unique()
            ->values()
            ->all();
    }


    private function getAssessmentFromGroup(array $group, array $assessment_ids)
    {
        $the_assessment = null;

        $assessments = Assessment::query()
            ->whereIn('id', $assessment_ids)
            ->get()
        ;

        $user_full_name = $group['user_full_name'];
        if (! $user_full_name) {
            $user_full_name = '-';
        }

        foreach ($assessments as $temp_assessment) {
            if ($temp_assessment->customer_name == $user_full_name) {
                $the_assessment = $temp_assessment;
                break;
            }
        }

        return $the_assessment;
    }


    public function add_to_basket_multiple(Request $request)
    {
        $form_data = $request->all();
        $errors = [];
        $added_item_ids = [];

        $products_grouped = $request->input('products_grouped', []);
        $assessment_ids = $this->normaliseAssessmentIds($request->input('assessment_ids', []));

        if (! $products_grouped) {
            $errors[] = 'No items given.';
        }

        $basket = Basket::getCurrent();

        $itemIds = [];
        $sizeIds = [];
        foreach ($products_grouped as $group) {
            foreach ($group['products'] as $product) {
                list($iid, $sid) = array_pad(explode('_', $product['id']), 2, 0);
                if ($iid) {
                    $itemIds[] = (int) $iid;
                }
                if ($sid) {
                    $sizeIds[] = (int) $sid;
                }
            }
        }
        $itemMap = ShopItem::query()->whereIn('id', $itemIds ?: [0])->get()->keyBy('id');
        $sizeMap = ShopItemSize::query()->whereIn('id', $sizeIds ?: [0])->get()->keyBy('id');

        foreach ($products_grouped as $group) {

            $assessment = $this->getAssessmentFromGroup($group, $assessment_ids);

            foreach ($group['products'] as $product) {

                list($item_id, $size_id) = array_pad(explode('_', $product['id']), 2, 0);

                $item = $itemMap->get((int) $item_id);
                if (!$item) {
                    $errors[] = "Product not found: {$item_id}";
                    continue;
                }
                $size = $sizeMap->get((int) $size_id);

                $basket_params = [
                    'id' => $item->id,
                    'size_id' => $size->id ?? 0,
                    'size' => $size->size ?? 'One Size',
                    'PLU' => ($item->epos_code ?: ($size->PLU ?? '')),
                    'quantity' => ((int) ($product['quantity']) ?: 1),
                    'recommended_quantity' => ((int) ($product['minQuantity'] ?? 0)),
                    'assessment_id' => ($assessment->id ?? 0),
                ];

                $basket_item_id = $basket->Add_Item($basket_params, false);

                if ($basket_item_id) {
                    $added_item_ids[] = $basket_item_id;
                } else {
                    $errors[] = 'Failed to add item(s) to basket.';
                }
            }
        }

        $basket->set_expiry_time();

        $basket_eloquent = $basket->eloquent();
        $basket_eloquent->info->assessment_ids = json_encode($assessment_ids);
        $basket_eloquent->info->save();


        $response = [
            'success' => count($errors) < 1,
            'errors' => $errors,
            'added_item_ids' => $added_item_ids
        ];

        return $response;
    }

}
