<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

namespace Shopware\Plugins\ViisonSetArticles\Subscribers\Frontend;

use Shopware\Plugins\ViisonCommon\Classes\Subscribers\Base;

/**
 * Manipulates set article availability information in the frontend checkout view.
 */
class CheckoutSubscriber extends Base
{
    /**
     * @inheritdoc
     */
    public static function getSubscribedEvents()
    {
        return [
            'Shopware_Controllers_Frontend_Checkout::addAccessoriesAction::before' => 'onBeforeAddAccessories',
        ];
    }

    /**
     * If a customer bought a set article in the past and is in the shop frontend:
     * My Account -> My Orders -> re-order
     * addAccessoriesAction will add all positions (set and sub articles) to the cart with current prices. We need to
     * filter all sub articles since they are added automatically after the checkout.
     *
     * This function removes all sub articles from being added to the cart.
     *
     * Remark: if a sub article was part of the order separately from the set article it should not be removed. These
     * positions are listed separately in the sAddAccessories ordernumber list. Therefore we only remove the sub article
     * once if it matches the sub article quantity. This check may not be 100% accurate, but it's the best it gets.
     *
     * @param \Enlight_Hook_HookArgs $args
     */
    public function onBeforeAddAccessories(\Enlight_Hook_HookArgs $args)
    {
        // $accessories array ordernumbers
        $articleNumbers = $args->getSubject()->Request()->getParam('sAddAccessories');
        $quantities = $args->getSubject()->Request()->getParam('sAddAccessoriesQuantity');
        $quantitiesByArticleNumber = array_combine($articleNumbers, $quantities);
        $subArticleInformation = [];

        // Find all set articles and their respective sub article ordernumbers
        $articleDetails = $this->get('models')->getRepository('Shopware\\Models\\Article\\Detail')->findBy([
            'number' => $articleNumbers,
        ]);
        foreach ($articleDetails as $articleDetail) {
            if (!$articleDetail->getAttribute() ||
                !$articleDetail->getAttribute()->getViisonSetarticleActive()
            ) {
                continue;
            }
            $setArticleQuantityInOrder = $quantitiesByArticleNumber[$articleDetail->getNumber()];
            $subArticleDefinitions = $this->get('models')->getRepository('Shopware\\CustomModels\\ViisonSetArticles\\SetArticle')->findBy([
                'setId' => $articleDetail->getId(),
            ]);
            $subArticleInformation = array_merge(
                $subArticleInformation,
                array_map(function ($subArticle) use ($setArticleQuantityInOrder) {
                    return [
                        'ordernumber' => $subArticle->getArticleDetail()->getNumber(),
                        'quantity' => $subArticle->getQuantity() * $setArticleQuantityInOrder,
                    ];
                }, $subArticleDefinitions)
            );
        }

        foreach ($subArticleInformation as $subInformation) {
            // Filter all articles (and quantities) that match with a sub article of this order ($subArticleInformation)
            $quantitiesByArticleNumber = array_filter(
                $quantitiesByArticleNumber,
                function ($orderNumber) use ($subInformation, $quantitiesByArticleNumber) {
                    return ((string) $orderNumber !== (string) $subInformation['ordernumber'])
                        || (int) $quantitiesByArticleNumber[$orderNumber] !== $subInformation['quantity'];
                },
                ARRAY_FILTER_USE_KEY
            );
        }

        // Separate article numbers and quantities again and update return parameters
        $args->getSubject()->Request()->setParam('sAddAccessories', array_keys($quantitiesByArticleNumber));
        $args->getSubject()->Request()->setParam('sAddAccessoriesQuantity', array_values($quantitiesByArticleNumber));
    }
}
