<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\MessageHandler\Carrier\Assembler;

use Gls\GlsPoland\Carrier\CarrierType;
use Gls\GlsPoland\DataProvider\ServiceInformationProvider;
use Gls\GlsPoland\PrestaShop\DTO;
use Gls\GlsPoland\PrestaShop\Message\CreateCarrierCommandInterface;

final class PriceRangesAssembler implements CarrierAssemblerInterface
{
    public function assemble(DTO\Carrier $carrier, CreateCarrierCommandInterface $command): void
    {
        $maxWeight = $carrier->getCarrier()->max_weight ?? ServiceInformationProvider::MAX_DOMESTIC_PARCEL_WEIGHT_KG;

        if (CarrierType::SHOP_DELIVERY !== (string) $command->getType()) {
            $range = $this->createRange(0., (float) $maxWeight);
            $carrier->addRange($range);

            return;
        }

        foreach ($this->getRanges((float) $maxWeight) as $range) {
            $carrier->addRange($range);
        }
    }

    /**
     * @return \Generator<\RangeWeight>
     */
    private function getRanges(float $maxWeight): \Generator
    {
        $lower = 0.;
        $delimiters = [31.5, 15., 8., 2., 1.];

        while ($delimiters && $maxWeight >= $upper = array_pop($delimiters)) {
            yield $this->createRange($lower, $upper);

            $lower = $upper;
        }

        if ($maxWeight > $lower) {
            yield $this->createRange($lower, $maxWeight);
        }
    }

    private function createRange(float $lower, float $upper): \RangeWeight
    {
        $range = new \RangeWeight();
        $range->delimiter1 = $lower;
        $range->delimiter2 = $upper;

        return $range;
    }
}
