<?php
/**
 * Copyright since 2025 InPost S.A.
 *
 * For the full license information, please view the LICENSE file bundled with the module.
 *
 * @author InPost S.A.
 * @copyright since 2025 InPost S.A.
 * @license MIT
 */

declare(strict_types=1);

namespace InPost\International\Carrier;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

if (!defined('_PS_VERSION_')) {
    exit;
}

final class CarrierConfiguration
{
    /**
     * @var \Carrier
     */
    private $carrier;

    /**
     * @var Collection<int>
     */
    private $groups;

    /**
     * @var Collection<int>
     */
    private $zones;

    /**
     * @var Collection<\RangeWeight>
     */
    private $weightRanges;

    /**
     * @var Collection<\RangePrice>
     */
    private $priceRanges;

    /**
     * @var int[]
     */
    private $disallowedPaymentModuleIds = [];

    /**
     * @var int[]|null
     */
    private $allowedPaymentModuleIds;

    /**
     * @var int|null
     */
    private $taxRulesGroupId;

    /**
     * @var string|null
     */
    private $logoPath;

    public function __construct(\Carrier $carrier)
    {
        $this->carrier = $carrier;
        $this->groups = new ArrayCollection();
        $this->zones = new ArrayCollection();
        $this->weightRanges = new ArrayCollection();
        $this->priceRanges = new ArrayCollection();
    }

    public function getCarrier(): \Carrier
    {
        return $this->carrier;
    }

    /**
     * @return int[] IDs of {@see \Group}
     */
    public function getGroupIds(): array
    {
        return $this->groups->toArray();
    }

    /**
     * @param int $groupId ID of {@see \Group}
     */
    public function addGroup(int $groupId): void
    {
        if (!$this->groups->contains($groupId)) {
            $this->groups->add($groupId);
        }
    }

    /**
     * @param int $groupId ID of {@see \Group}
     */
    public function removeGroup(int $groupId): void
    {
        if ($this->groups->contains($groupId)) {
            $this->groups->removeElement($groupId);
        }
    }

    /**
     * @return int[] IDs of {@see \Zone}
     */
    public function getZoneIds(): array
    {
        return $this->zones->toArray();
    }

    /**
     * @param int $zoneId ID of {@see \Zone}
     */
    public function addZone(int $zoneId): void
    {
        if (!$this->zones->contains($zoneId)) {
            $this->zones->add($zoneId);
        }
    }

    /**
     * @param int $zoneId ID of {@see \Zone}
     */
    public function removeZone(int $zoneId): void
    {
        if ($this->zones->contains($zoneId)) {
            $this->zones->removeElement($zoneId);
        }
    }

    /**
     * @return \RangeWeight[]|\RangePrice[]
     */
    public function getRanges(): array
    {
        switch ($this->carrier->getShippingMethod()) {
            case \Carrier::SHIPPING_METHOD_WEIGHT:
                return $this->getWeightRanges();
            case \Carrier::SHIPPING_METHOD_PRICE:
                return $this->getPriceRanges();
            default:
                return [];
        }
    }

    /**
     * @return \RangeWeight[]
     */
    public function getWeightRanges(): array
    {
        return $this->weightRanges->toArray();
    }

    public function addWeightRange(\RangeWeight $range): void
    {
        if (!$this->weightRanges->contains($range)) {
            $this->weightRanges->add($range);
        }
    }

    public function removeWeightRange(\RangeWeight $range): void
    {
        if ($this->weightRanges->contains($range)) {
            $this->weightRanges->removeElement($range);
        }
    }

    /**
     * @return \RangePrice[]
     */
    public function getPriceRanges(): array
    {
        return $this->priceRanges->toArray();
    }

    public function addPriceRange(\RangePrice $range): void
    {
        if (!$this->priceRanges->contains($range)) {
            $this->priceRanges->add($range);
        }
    }

    public function removePriceRange(\RangePrice $range): void
    {
        if ($this->priceRanges->contains($range)) {
            $this->priceRanges->removeElement($range);
        }
    }

    /**
     * @return int[] IDs of {@see \PaymentModule}
     */
    public function getDisallowedPaymentModuleIds(): array
    {
        return $this->disallowedPaymentModuleIds;
    }

    /**
     * @param int[] $ids IDs of {@see \PaymentModule}
     */
    public function setDisallowedPaymentModuleIds(array $ids): void
    {
        $this->disallowedPaymentModuleIds = [];
        foreach ($ids as $id) {
            $this->addDisallowedPaymentModuleId($id);
        }
    }

    /**
     * @param int $id ID of {@see \PaymentModule}
     */
    public function addDisallowedPaymentModuleId(int $id): void
    {
        $this->disallowedPaymentModuleIds[$id] = $id;
        unset($this->allowedPaymentModuleIds[$id]);
    }

    /**
     * @param int $id ID of {@see \PaymentModule}
     */
    public function removeDisallowedPaymentModuleId(int $id): void
    {
        unset($this->disallowedPaymentModuleIds[$id]);
    }

    /**
     * @return int[]|null IDs of {@see \PaymentModule} or null if all except explicitly disallowed should be available
     */
    public function getAllowedPaymentModuleIds(): ?array
    {
        return $this->allowedPaymentModuleIds;
    }

    /**
     * @param int[]|null $ids IDs of {@see \PaymentModule} or null if all except explicitly disallowed should be available
     */
    public function setAllowedPaymentModulesIds(?array $ids): void
    {
        if (null === $ids) {
            $this->allowedPaymentModuleIds = null;

            return;
        }

        $this->allowedPaymentModuleIds = [];
        foreach ($ids as $id) {
            $this->addAllowedPaymentModuleId($id);
        }
    }

    /**
     * @param int $id ID of {@see \PaymentModule}
     */
    public function addAllowedPaymentModuleId(int $id): void
    {
        $this->allowedPaymentModuleIds[$id] = $id;
        unset($this->disallowedPaymentModuleIds[$id]);
    }

    /**
     * @param int $id ID of {@see \PaymentModule}
     */
    public function removeAllowedPaymentModuleId(int $id): void
    {
        unset($this->allowedPaymentModuleIds[$id]);
    }

    public function getTaxRulesGroupId(): ?int
    {
        return $this->taxRulesGroupId ?? null;
    }

    public function setTaxRulesGroupId(?int $taxRulesGroupId): void
    {
        $this->taxRulesGroupId = $taxRulesGroupId;
    }

    public function getLogoPath(): ?string
    {
        return $this->logoPath;
    }

    public function setLogoPath(?string $logoPath): void
    {
        $this->logoPath = $logoPath;
    }
}
