<?php

declare(strict_types=1);

namespace External\HannahBundle\SAP\Util\DataFactory;

use External\HannahBundle\SAP\MappingType;
use External\HannahBundle\SAP\Util\PricingUtil;
use External\HannahBundle\SAP\Util\SAPUtil;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Context\LanguageContext;
use KupShop\KupShopBundle\Context\UserContext;
use KupShop\OrderingBundle\Entity\Purchase\PurchaseState;
use KupShop\SellerBundle\Utils\SellerUtil;

class CartDataFactory extends AbstractDataFactory
{
    private $currencyContext;

    private $languageContext;

    private $userContext;

    private $sapUtil;

    private SellerUtil $sellerUtil;

    public function __construct(
        CurrencyContext $currencyContext,
        LanguageContext $languageContext,
        UserContext $userContext,
        SellerUtil $sellerUtil,
        SAPUtil $sapUtil,
    ) {
        $this->currencyContext = $currencyContext;
        $this->languageContext = $languageContext;
        $this->userContext = $userContext;
        $this->sapUtil = $sapUtil;
        $this->sellerUtil = $sellerUtil;
    }

    public static function getRequiredArguments(): array
    {
        return [
            'purchaseState' => PurchaseState::class,
            'promoCoupons' => self::TYPE_ARRAY,
        ];
    }

    protected function createData(array $arguments): array
    {
        return $this->getCart(
            $arguments['purchaseState'],
            $arguments['promoCoupons'],
            $arguments['type'] ?? PricingUtil::ORDER_TYPE_PRICING,
            $arguments['sellerId'] ?? null,
            $arguments['orderId'] ?? '',
        );
    }

    private function getCart(PurchaseState $purchaseState, array $promoCoupons, string $orderType, ?int $sellerId, string $orderId = ''): array
    {
        return [
            'OrderId' => $orderId,
            'OrderType' => $orderType,
            'PurchaseDate' => '',
            'ExpectedExpeditionDate' => '',
            'TotalPrice' => $purchaseState->getTotalPrice()->getPriceWithVat()->asFloat(),
            'CurrencyCode' => $this->currencyContext->getActiveId(),
            'CodPrice' => '',
            'CodCurrency' => $this->currencyContext->getActiveId(),
            'Language' => $this->languageContext->getActiveId(),
            'PaymentMethod' => '',
            'ShippingMethod' => '',
            'ShippingPoint' => $sellerId ? $this->getShippingPoint($sellerId) : '',
            'PaymentState' => null,
            'PaymentTransactionId' => '',
            'Note' => '',
            'Partners' => $this->getPartners(),
            'Items' => $this->getCartItems($purchaseState),
            'PromoCoupons' => $this->getPromoCoupons($promoCoupons),
            'PaymentCoupons' => [],
            'Additionals' => [],
        ];
    }

    /**
     * Pouziva se jen v pripade kontroly disponbility u rezervaci.
     */
    private function getShippingPoint(int $sellerId): string
    {
        if ($seller = $this->sellerUtil->getSeller($sellerId)) {
            if ($sapStoreId = $this->sapUtil->getSapId(MappingType::STORES, (int) $seller['id_store'])) {
                return (string) $sapStoreId;
            }
        }

        return '';
    }

    private function getPromoCoupons(array $promoCoupons): array
    {
        $coupons = [];
        foreach ($promoCoupons as $coupon) {
            $coupons[] = [
                'CouponId' => $coupon,
                'CouponUsed' => '',
                'PromoId' => $coupon,
                'PromoName' => '',
                'CouponInfo' => '',
            ];
        }

        return $coupons;
    }

    private function getCartItems(PurchaseState $purchaseState): array
    {
        $items = [];

        foreach ($purchaseState->getProducts() as $item) {
            if ($sapId = $this->sapUtil->getItemSapId((int) $item->getIdProduct(), $item->getIdVariation() ? (int) $item->getIdVariation() : null)) {
                $unit = 'PCE';
                //                if ($product = $item->getProduct()) {
                //                    $unit = $product->getData()['sap']['unit'] ?? 'PCE';
                //                }

                $items[] = [
                    'ItemId' => $sapId,
                    'OrderItemId' => $item->getId(),
                    'ItemPrice' => $item->getPriceWithVat()->asFloat(),
                    'ItemBasePrice' => $item->getPriceWithVat()->asFloat(),
                    'ItemQuantity' => $item->getPieces(),
                    'ItemUom' => $unit,
                    'ItemName' => '',
                    'ItemVatId' => $item->getPrice()->getVat()->asFloat(),
                    'PromoConditions' => [],
                    'Additionals' => [],
                ];
            }
        }

        return $items;
    }

    private function getPartners(): array
    {
        $customerId = null;
        if ($user = $this->userContext->getActive()) {
            $customerId = $this->sapUtil->getSapId(MappingType::USERS, (int) $user->id);
        }

        return [
            array_merge(
                [
                    'PartnerType' => 'MAIN',
                    'CustomerId' => $customerId ?: '',
                    'Additionals' => [],
                ],
                $this->getUserAddress($user ?: null)
            ),
        ];
    }

    private function getUserAddress(?\User $user): array
    {
        if ($user) {
            $user->fetchAddresses();
        }

        return [
            'FirstName' => $user ? mb_substr($user->invoice['name'] ?? '', 0, 40) : 'PJ',
            'Surname' => $user ? mb_substr($user->invoice['name'] ?? '', 0, 40) : '',
            'Address1' => $user ? $user->invoice['street'] : '',
            'Address2' => '',
            'Address3' => '',
            'City' => $user ? $this->sapUtil->formatCity($user->invoice['city'] ?? '') : '',
            'Zip' => $user && !empty($user->invoice['zip']) ? $this->sapUtil->formatZip($user->invoice['zip'] ?? '', $user->invoice['country'] ?? '') : '',
            'Country' => $user ? $user->invoice['country'] : 'CZ',
            'CompanyName' => '',
            'Email' => $user ? $user->email : '',
            'Phone' => $user ? $user->invoice['phone'] : '',
            'VatIdentNumber' => $user ? $user->invoice['ico'] : '',
            'CompRegNumber' => $user ? $user->invoice['dic'] : '',
        ];
    }
}
