<?php

namespace CouponsPlus\App\Coupon\Tree\ItemSetsToDiscount;

use WC_Product;
use JsonException;
use CouponsPlus\App\Conditions\ItemsSet;
use CouponsPlus\Original\Collections\Collection;
use CouponsPlus\Original\Collections\JSONMapper;
use CouponsPlus\Original\Characters\StringManager;
use CouponsPlus\Original\Collections\Mapper\Types;
use CouponsPlus\App\Conditions\BuiltIn\Filters\Products;
use CouponsPlus\App\Coupon\Tree\Abilities\ItemToDiscount;
use CouponsPlus\App\Conditions\Abilities\TestableComposite;
use CouponsPlus\App\Coupon\Tree\Abilities\ItemsInCartFinderStrategy;
use CouponsPlus\App\Coupon\Tree\ItemSetsToDiscount\Actions\CartAction;

class SpecificItemsInCartFinderStrategy implements ItemsInCartFinderStrategy
{
    /**
     * @var Collection of see BuyXGetY::GetOptions()::products for the format
     */
    protected Collection $productsData;
    protected JSONMapper $mapper;

    public function __construct(Collection $productsData)
    {
        $this->productsData = $productsData;
        $this->mapper = new JSONMapper($this->map());
    }

    public function map(): array
    {
        return  array_merge([
            'id' => Types::INTEGER(),
            'isVariable' => Types::BOOLEAN(),
            'discount' => [
                'type' => Types::STRING()->withDefault('free')->allowed(['free' ,'percentage' ,'amount' ,'fixed-price']),
                'amount' => Types::FLOAT()
            ],
            'missingItemsInCart' => [
                'mode' => Types::STRING()->withDefault('auto-add')->allowed(['auto-add' ,'manual-add'])
            ]
        ], static::getQuantityOptions());
    }

    public static function getQuantityOptions(): array
    {
        return [
            'quantity' => Types::INTEGER()->withDefault(1),
            'qtyType' => Types::STRING()->withDefault('simple')->allowed([
                 'simple', // this is the default 'quantity' and is always 1
                 'advanced' // this one is the "qty", it was added later after the initial implementation hence the disparate quantity vs qty
             ]),
            'qty' => [
                'type' => Types::STRING()->withDefault('any')->allowed([
                                                                              'any',
                                                                              // soon: fixed, min, max, range
                                                                          ]),
                'amount' => Types::INTEGER()->withDefault(1)
            ],
        ];
    }

    public function getProductsToDiscount(): Collection
    {
        return $this->productsData->map(function ($data) {
            /**
             * Format:
             * {
             *      'id': number,
             *      'isVariable': bool,
             *      'quantity': 1,
             *       'discount': {
             *           type: 'free' | 'percentage' | 'amount' | 'fixed-price',
             *           amount: number,
             *       }
             *  }
             */

            $data = $this->mapper->smartMap($data);

            /** @noinspection PhpUnhandledExceptionInspection */
            (object) $productToDiscount =  new ProductToDiscount(
                $data->id,
                new ProductDiscountOptions(
                    new StringManager($data->discount->type),
                    $data->discount->amount,
                    $data->qtyType->is('simple')? $data->quantity : $data->qty
                ),
                $data->isVariable,
                new CartActions([
                    // just in case i dont get the time to finish ts
                    new CartAction('auto_apply', [])
                ]),
                function (int $id) : WC_Product {
                    return wc_get_product($id);
                }
            );

            $productToDiscount->setMode($data->missingItemsInCart->mode);
            
            return $productToDiscount;
        });
    }

    public function getFinder(ItemToDiscount $productToDiscount): TestableComposite {
        return new Products([
            'mode' => 'short',
            'ids' => [$productToDiscount->getSubject()]
        ]);
            /*this was moved to CartItemsToDiscountFinder::findItemsToDiscount()

            *return $productsFilter
            // from all cart items
            ->filterSet(ItemsSet::createFromAllCartItems())
            // without the items passed to this offer (the "buy" part of the BOGO)
            ->without($itemsSetPassedToThisOffer)
            // without the items already selected for discount
            ->without($setsToDiscount->flattenedItems())
            ->selectQuantity('maximum', $productToDiscount->getDiscountOptions()->quantity);*/
    }
}