<?php

declare(strict_types=1);

namespace FiloBlu\Refilo\Model;

use Magento\Directory\Helper\Data;
use Magento\Directory\Model\Region;
use Magento\Directory\Model\ResourceModel\Region\CollectionFactory;
use Magento\Quote\Api\Data\AddressInterfaceFactory;
use Magento\Quote\Api\Data\CartInterface;
use Magento\Quote\Model\Quote\Address\Rate;

/**
 *
 */
class ShippingEstimationCountryAndRegion implements ShippingEstimationStrategyInterface
{
    /**
     * @var AddressInterfaceFactory
     */
    private $addressFactory;

    /**
     * @var Data
     */
    private $data;

    /**
     * @var CollectionFactory
     */
    private $collectionFactory;

    /**
     * @param AddressInterfaceFactory $addressFactory
     * @param Data $data
     * @param CollectionFactory $collectionFactory
     */
    public function __construct(
        AddressInterfaceFactory $addressFactory,
        Data $data,
        CollectionFactory $collectionFactory
    ) {
        $this->addressFactory = $addressFactory;
        $this->data = $data;
        $this->collectionFactory = $collectionFactory;
    }

    /**
     * @param \Magento\Quote\Api\Data\CartInterface $cart
     * @return \Magento\Quote\Api\Data\CartInterface
     * @throws \Exception
     */
    public function estimate(CartInterface $cart): CartInterface
    {
        $shippingAddress = $cart->getShippingAddress();

        if (!$shippingAddress) {
            $shippingAddress = $this->addressFactory->create();
        }

        if (!$shippingAddress->getCountryId()) {
            $defaultCountry = $this->data->getDefaultCountry($cart->getStoreId());
            $shippingAddress->setCountryId($defaultCountry);
            if ($this->data->isRegionRequired($defaultCountry)) {
                /** @var Region $region */
                $region = $this->collectionFactory->create()
                    ->addCountryFilter($defaultCountry)
                    ->getFirstItem();
                $shippingAddress->setRegion($region->getName());
                $shippingAddress->setRegionId($region->getId());
            }
        }

        if (!$shippingAddress->getShippingMethod()) {
            $shippingAddress
                ->setCollectShippingRates(true)
                ->collectShippingRates();
            $shippingMethods = $shippingAddress->getAllShippingRates();
            /** @var Rate $first */
            $first = reset($shippingMethods);

            if (!$first) {
                return $cart;
            }

            $shippingAddress->setShippingMethod($first->getCode());
            $shippingAddress->setShippingDescription($first->getMethodDescription());
            $cart->setShippingAddress($shippingAddress);
            $cart->setTriggerRecollect(1);
            $cart->setTotalsCollectedFlag(false);
            $cart->collectTotals();
            $cart->save();
        }

        return $cart;
    }
}
