<?php

namespace KupShop\GTMBundle\Utils\DataLoaders;

use KupShop\GTMBundle\Utils\PriceComputer;
use KupShop\OrderingBundle\Entity\Purchase;
use KupShop\OrderingBundle\Entity\Purchase\DiscountPurchaseItem;
use Order;
use Symfony\Contracts\Service\Attribute\Required;

class PurchaseState
{
    #[Required]
    public PriceComputer $priceComputer;

    public static function shaEmail($email): string
    {
        $dbcfg = \Settings::getDefault();

        return hash('sha256', $email.($dbcfg->analytics['google_tag_manager']['sha_salt'] ?? false ?: ''));
    }

    /**
     * Discount list.
     *
     * @return array<int, array{
     *     id: int,
     *     name: string,
     *     valueWithVat: float,
     *     valueWithoutVat: float
     * }>
     */
    public function getDiscounts(Purchase\PurchaseState $purchaseState)
    {
        $discounts = [];
        foreach ($purchaseState->getDiscounts() as $discount) {
            if ($discount instanceof DiscountPurchaseItem) {
                $discounts[] = [
                    'id' => $discount->getIdDiscount(),
                    'name' => $discount->getName(),
                    'valueWithVat' => $discount->getPriceWithVat()->round(2),
                    'valueWithoutVat' => $discount->getPriceWithoutVat()->round(2),
                ];
            }
        }

        return $discounts;
    }

    public function getDiscountsForFE(Purchase\PurchaseState $purchaseState)
    {
        $discounts = [];
        foreach ($purchaseState->getDiscounts() as $discount) {
            if ($discount instanceof DiscountPurchaseItem) {
                $discounts[] = [
                    'id' => $discount->getIdDiscount(),
                    'name' => $discount->getName(),
                    'value' => $this->priceComputer->getPrice($discount->getPrice()),
                    'value_with_tax' => $discount->getPriceWithVat()->round(2),
                    'value_without_tax' => $discount->getPriceWithoutVat()->round(2),
                ];
            }
        }

        return $discounts;
    }

    /**
     * Creates item's price object for dataLayer.
     *
     * @return array{
     *     price: string,
     *     priceWithVat: string,
     *     priceWithoutVat: string,
     *     priceVat: string,
     *     vatRate: int|string
     * }
     */
    public function getPrices($item): array
    {
        return [
            'price' => $this->priceComputer->getPrice($item['piece_price']),
            'priceWithVat' => $this->priceComputer->getPrice($item['piece_price'], true),
            'priceWithoutVat' => $this->priceComputer->getPrice($item['piece_price'], false),
            'priceVat' => $this->priceComputer->getPrice($item['piece_price']['value_vat'], false, false),
            'vatRate' => $item['piece_price']['vat'] ?? '',
        ];
    }

    /**
     * Charges array for order/item type.
     *
     * @return array<int, array{
     *     id: int,
     *     type: string,
     *     item_title: string|null,
     *     quantity: int,
     *     price: float,
     *     price_with_vat: float,
     *     price_without_vat: float,
     *     price_vat: float,
     *     vat_rate: float
     * }>
     */
    public function getCharges(\Order $order): array
    {
        $charges = [];
        foreach ($order->fetchItems() as $item) {
            $id = $item['note']['id_charge'] ?? $item['note']['charge']['id_charge'] ?? null;

            if (isset($item['product']) || $id === null) {
                continue;
            }
            $itemType = null;
            $additional = [];

            // ORDER CHARGE
            if ($item['note']['item_type'] ?? false) {
                $itemType = 'order_charge';
            }

            // PRODUCT CHARGE
            if ($item['note']['charge']['id_charge'] ?? false) {
                $itemType = 'product_charge';
                $additional = $item['note']['charge'] ?? [];
            }

            if ($itemType) {
                $prices = $this->getPrices($item);
                $charges[] = $additional + [
                    'id' => $id,
                    'type' => $itemType,
                    'item_title' => $item['descr'] ?? null,
                    'quantity' => $item['pieces'] ?? 1,
                    'price' => $prices['price'],
                    'price_with_vat' => $prices['priceWithVat'],
                    'price_without_vat' => $prices['priceWithoutVat'],
                    'price_vat' => $prices['priceVat'],
                    'vat_rate' => $prices['vatRate'],
                ];
            }
        }

        return $charges;
    }

    /**
     * Get sold out ratio of variation (for products is nullable).
     */
    public function getSoldOut($product): ?float
    {
        $result = null;
        $variations = $product instanceof \Product ? ($product->variations['variations'] ?? $product->variations ?? []) : null;
        if (!empty($variations)) {
            $soldOutVariationCount = count(array_filter($variations, function ($variation) { return !$variation['in_store']; }));
            $result = round($soldOutVariationCount / count($variations) * 100);
        }

        return $result;
    }

    public function getPaymentObject(\Order $order): array
    {
        $data = $order->getDeliveryType()->getPayment();

        return [
            'type' => $data['class'] ?? '',
            'method' => [
                'id' => $data['method'] ?? null,
            ],
        ];
    }
}
