<?php

namespace CouponsPlus\App\Conditions\BuiltIn\Filters;

use CouponsPlus\App\Conditions\CartItem;
use CouponsPlus\App\Conditions\Filter;
use CouponsPlus\App\Conditions\IntersectionFilter;
use CouponsPlus\App\Conditions\ItemsSet;
use CouponsPlus\App\Coupon\Tree\Data\SelectOption;
use CouponsPlus\App\Conditions\Utilities\ProductUtilities;
use CouponsPlus\App\Validators\InclusionValueValidator;
use CouponsPlus\Original\Collections\Collection;
use CouponsPlus\Original\Collections\Mapper\Types;
use CouponsPlus\Original\Environment\Env;
use CouponsPlus\App\Coupon\Tree\Data\Abilities\PreloadableData;

#[\AllowDynamicProperties]
Class InTags extends Filter implements PreloadableData
{
    const TYPE = 'InTags';
    const SET = IntersectionFilter::class;
    
    public static function getName() : string
    {
        return __('Tags', 'coupons-plus-for-woocommerce');
    }

    public static function getDescription() : string
    {
        return '';
    }

    public static function getOptions() : Collection
    {
        return InclusionValueValidator::getOptions(
            $expectedValues = [
                'meta' => [
                    'name' => __('Tags', 'coupons-plus-for-woocommerce'),
                ],
                'allowed' => [
                    'type' => 'remote',
                    'category' => 'tags',
                    'where' => 'rest.WooCommerce',
                    'path' => 'products/tags',
                    'searchArgumentName' => 'search',
                    'excludeIdsArgumentName' => 'exclude',
                    'arguments' => [
                        'context' => 'edit',
                    ]
                ]
            ],
            $inclusionType = [
                'meta' => [
                    'extraLabels' => [
                        'allowed' => [
                            'placeholder' => __('Search tags to include...', 'coupons-plus-for-woocommerce'),
                            'aboveList' => __('Will pick items with any of these tags:', 'coupons-plus-for-woocommerce')
                        ],
                        'forbidden' => [
                            'placeholder' => __('Search tags to exclude...', 'coupons-plus-for-woocommerce'),
                            'aboveList' => __("Will pick items that don't have any of these tags:", 'coupons-plus-for-woocommerce')
                        ]
                    ],
                    'notes' => [
                        'allowed' => [
                            'id' => 'InCategories.inclusionType',
                            'title' => __('Any combination of tags', 'coupons-plus-for-woocommerce'),
                            'content' => [
                                __('Will take any combination of products with any of the specified tags.', 'coupons-plus-for-woocommerce'),
                                __('Not all of these tags need to be present in the items, only at least one of them', 'coupons-plus-for-woocommerce'),
                                __('For example, if you have a clothing store and you set the tags: "Casual" and "Formal". This will take items that have the tags "Casual" and/or "Formal". The user may add only "Casual" items, or only "Formal" items or BOTH.', 'coupons-plus-for-woocommerce'),
                            ]
                        ],
                        'forbidden' => [
                            'id' => 'InCategories.inclusionType',
                            'title' => __('Any combination of tags except those specified', 'coupons-plus-for-woocommerce'),
                            'content' => [__("Will take products that don't have any of the specified tags", 'coupons-plus-for-woocommerce')]
                        ],
                    ]
                ]
            ]
        );
    }

    public static function preloadedData() : Collection
    {
        return new Collection([
            'category' => 'tags',
            'data' => function (array $ids) : array {
                // convert the ids into formatted data from the database
                return Collection::create($ids)->map(function (int $id): SelectOption {
                    $term = get_term($id, 'product_tag');

                    return new SelectOption(
                        $id, // id
                        $id,// value
                        $term->name//label
                    );
                })->asArray();
            }
        ]);
    }

    public function onOptionsLoaded()
    {
        do_action(Env::getWithPrefix('IDsLoaded'), [
            'type' => 'productTags',
            'ids' => $this->options->expectedValues
        ]);
    }

    public function filterSet(ItemsSet $itemsSet) : ItemsSet
    {
        (object) $inclusionValueValidator = new InclusionValueValidator($this->options->asArray());

        return new ItemsSet($itemsSet->getItems()->filter(function(CartItem $cartItem) use ($inclusionValueValidator) : bool {
            (object) $originalFinalproductUtilities = new ProductUtilities(
                $cartItem->getProductUtilities()->getOrignalFinalProduct()
            );

            $inclusionValueValidator->setValueToValidate(
                $originalFinalproductUtilities->getAllTranslationTagIds()
            );

            return $inclusionValueValidator->isValid();
        })->asArray());

        (object) $inclusionValueValidator = new InclusionValueValidator($this->options->asArray());

        return new ItemsSet($itemsSet->getItems()->filter(function(CartItem $cartItem) use ($inclusionValueValidator) : bool {
           (array) $categoryIds = [];

            if ($cartItem->getProduct()->get_type() === 'variation') {
                $categoryIds = wc_get_product($cartItem->getProduct()->get_parent_id($context = 'edit'))->get_tag_ids($context = 'edit');
            } else {
                $categoryIds = $cartItem->getProduct()->get_tag_ids($context = 'edit');
            }

            $inclusionValueValidator->setValueToValidate(
                $categoryIds
            );

            return $inclusionValueValidator->isValid();
        })->asArray());
    }
}