<?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\ViisonPickwareMobile\Components\PickingOrderFilter;

use DateTime;
use Shopware\Plugins\ViisonCommon\Components\Localization\SnippetManagerService;
use Shopware\Plugins\ViisonPickwareMobile\Components\PickingOrderFilter\UnfulfilledPickingOrderFilterConditions;

class PickingOrderFilterConditionLocalizationService
{
    /**
     * @var SnippetManagerService
     */
    private $snippetNamespace;

    /**
     * @param SnippetManagerService $snippetManagerService
     */
    public function __construct(SnippetManagerService $snippetManagerService)
    {
        $this->snippetNamespace = $snippetManagerService->getNamespace(
            'viison_pickware_mobile/picking_order_filter/picking_order_filter_conditions'
        );
    }

    /**
     * Returns an array containing localized descriptions of all conditions that are unfulfilled by the order having the
     * passed `$orderId`.
     *
     * @param UnfulfilledPickingOrderFilterConditions $unfulfilledConditions
     * @param int $orderId
     * @return string[]
     */
    public function getLocalizedUnfilledConditionsForOrderWithId(
        UnfulfilledPickingOrderFilterConditions $unfulfilledConditions,
        $orderId
    ) {
        $unfulfilledOrderConditions = $unfulfilledConditions->getUnfulfilledConditionsForOrderWithId($orderId);
        $stockFilterMode = $unfulfilledConditions->getStockBasedFilterConfig();

        return array_values(array_filter(array_map(
            function ($conditionAlias) use ($unfulfilledOrderConditions, $stockFilterMode) {
                // Skip custom pick profile filter sub conditions, because they will be included in their main condition
                // localization
                if (UnfulfilledPickingOrderFilterConditions::isCustomPickProfileSubCondition($conditionAlias)) {
                    return null;
                }

                if ($conditionAlias === PickingOrderFilterService::CONDITION_ALIAS_ORDER_PASSES_CUSTOM_FILTER) {
                    return $this->getLocalizedCustomPickProfileCondition($unfulfilledOrderConditions);
                }

                // Modify some conditions aliases based on the stock filter mode
                if ($stockFilterMode->isModeAllReleasedItemsMustHaveAllRequiredStock() && $conditionAlias === UnfulfilledPickingOrderFilterConditions::DERIVED_CONDITION_ALIAS_ORDER_MEETS_STOCK_BASED_FILTER) {
                    $conditionAlias .= '_modeAllReleasedItemsMustHaveAllRequiredStock';
                } elseif ($stockFilterMode->isModeAllItemsMustHaveAllRequiredStock() && in_array($conditionAlias, [UnfulfilledPickingOrderFilterConditions::DERIVED_CONDITION_ALIAS_ORDER_MEETS_STOCK_BASED_FILTER, UnfulfilledPickingOrderFilterConditions::DERIVED_CONDITION_ALIAS_ALL_ITEMS_ARE_RELEASED])) {
                    $conditionAlias .= '_modeAllItemsMustHaveAllRequiredStock';
                }

                return $this->snippetNamespace->get('condition/' . $conditionAlias);
            },
            $unfulfilledOrderConditions
        )));
    }

    /**
     * Returns an array containing localized descriptions of all conditions that are unfulfilled by the order item
     * having the passed `$orderItemId`.
     *
     * @param UnfulfilledPickingOrderFilterConditions $unfulfilledConditions
     * @param int $orderItemId
     * @param DateTime $earliestPreOrderDate
     * @return string[]
     */
    public function getLocalizedUnfulfilledConditionsForOrderItemWithId(
        UnfulfilledPickingOrderFilterConditions $unfulfilledConditions,
        $orderItemId,
        DateTime $earliestPreOrderDate
    ) {
        return array_map(
            function ($condition) use ($unfulfilledConditions, $earliestPreOrderDate) {
                // Modify some conditions keys
                $stockFilterMode = $unfulfilledConditions->getStockBasedFilterConfig();
                if ($stockFilterMode->isModeAtLeastOneItemMustHaveSomeStock() && $condition === PickingOrderFilterService::CONDITION_ALIAS_ORDER_ITEM_HAS_SUFFICIENT_STOCK) {
                    $condition .= '_modeAtLeastOneItemMustHaveSomeStock';
                }

                $localizedCondition = $this->snippetNamespace->get('condition/' . $condition);
                if ($localizedCondition && $condition === PickingOrderFilterService::CONDITION_ALIAS_ORDER_ITEM_IS_RELEASED) {
                    $localizedCondition = sprintf($localizedCondition, $earliestPreOrderDate->format('d.m.Y'));
                }

                return $localizedCondition;
            },
            $unfulfilledConditions->getUnfulfilledConditionsForOrderItemWithId($orderItemId)
        );
    }

    /**
     * @param string[] $unfulfilledOrderConditions
     * @return string
     */
    private function getLocalizedCustomPickProfileCondition(array $unfulfilledOrderConditions)
    {
        // Include all unfulfilled sub conditions in the localization
        $unfulfilledSubConditions = array_filter(
            $unfulfilledOrderConditions,
            [
                UnfulfilledPickingOrderFilterConditions::class,
                'isCustomPickProfileSubCondition',
            ]
        );
        $rulePrefix = $this->snippetNamespace->get('condition/orderPassesCustomPickProfileFilter/rule_prefix');
        $unfulfilledSubConditionNames = array_map(
            function ($subConditionAlias) use ($rulePrefix) {
                // Parse the rule path from the condition alias
                preg_match('/(_\\d+)+/', $subConditionAlias, $matches);
                $parts = explode('_', trim($matches[0], '_'));
                $parts = array_map(
                    function ($part) {
                        return intval($part) + 1;
                    },
                    $parts
                );

                return $rulePrefix . ' ' . implode('.', $parts);
            },
            $unfulfilledSubConditions
        );

        return $this->snippetNamespace->get('condition/orderPassesCustomPickProfileFilter') . implode(', ', $unfulfilledSubConditionNames);
    }
}
