<?php

declare(strict_types=1);

namespace Macopedia\OrlenShipping\Model\Api;

use Macopedia\OrlenShipping\Helper\Data;
use Magento\Framework\DataObject;
use Magento\Framework\Event\ManagerInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Message\ManagerInterface as MessageManager;
use Magento\Sales\Model\Order;

class Pack
{
    /**
     * @param Client $client
     * @param Data $helper
     * @param ManagerInterface $eventManager
     * @param MessageManager $messageManager
     */
    public function __construct(
        protected readonly Client $client,
        protected readonly Data $helper,
        protected readonly ManagerInterface $eventManager,
        protected readonly MessageManager $messageManager,
    ) {
    }

    /**
     * Generate pack
     *
     * @param DataObject $request
     * @return Response
     * @throws LocalizedException
     * @throws OrlenApiException
     */
    public function generatePack(DataObject $request): Response
    {
        $this->validateProductsWeight($request);

        /** @var Order $order */
        $order = $request->getOrderShipment()->getOrder();
        $shipment = $request->getOrderShipment();
        $partnerId = $this->helper->getPartnerId();
        $partnerKey = $this->helper->getPartnerKey();

        $params = [
            'PartnerID' => $partnerId,
            'PartnerKey' => $partnerKey,
            'DestinationCode' => $order->getData('orlenpaczka_destination_code'),
            'EMail' => $request->getRecipientEmail(),
            'FirstName' => $request->getRecipientContactPersonFirstName(),
            'LastName' => $request->getRecipientContactPersonLastName(),
            'CompanyName' => $request->getRecipientContactCompanyName(),
            'StreetName' => $request->getRecipientAddressStreet(),
            'City' => $request->getRecipientAddressCity(),
            'PostCode' => $request->getRecipientAddressPostalCode(),
            'PhoneNumber' => $this->formatPhone($request->getRecipientContactPhoneNumber()),
            'SenderEMail' => $this->helper->getAddressEmail(),
            'SenderCompanyName' => $this->helper->getAddressPartnerName(),
            'SenderStreetName' => $this->helper->getAddressStreet(),
            'SenderBuildingNumber' => $this->helper->getAddressStreetNumber(),
            'SenderFlatNumber' => $this->helper->getAddressFlatNumber(),
            'SenderCity' => $this->helper->getAddressCity(),
            'SenderPostCode' => $this->helper->getAddressPostcode(),
            'SenderPhoneNumber' => $this->helper->getAddressPhoneNumber(),
            'PrintAdress' => 1,
            'PrintType' => 1,
            'SenderOrders' => $shipment->getData('sender_orders'),
            'TransferDescription' => $this->helper->getSystemInfo(),
            'BoxSize' => $shipment->getData('box_size')
        ];

        if ($shipment->getData('has_insurance')) {
            $params['Insurance'] = true;
            $params['PackValue'] = $shipment->getData('pack_value');
        }

        $this->eventManager->dispatch('macopedia_orlen_before_generate_label', [
            'order' => $order,
            'request' => $request,
        ]);

        $response = $this->client->generateLabelBusinessPackTwo($params);
        if ($response->isSoftError()) {
            $this->messageManager->addNoticeMessage($response->getErrorDescription());
        }
        return $response;
    }

    /**
     * Format phone number to 9 digits only
     *
     * @param string $subject
     * @return string
     */
    protected function formatPhone(string $subject): string
    {
        $subject = preg_replace('/\D/', '', $subject);
        if (strlen($subject) > 9) {
            $subject = substr(preg_replace('/^(0*)48/', '', $subject), 0, 9);
        }
        return $subject;
    }

    /**
     * Validate products weight
     *
     * @param DataObject $request
     * @return void
     * @throws LocalizedException
     */
    private function validateProductsWeight(DataObject $request): void
    {
        $isKg = ($request->getPackageParams()->getWeightUnits() == 'KILOGRAM');
        $kgRatio = $isKg ? 1.00 : 0.453592;
        $weight = ceil($request->getPackageWeight() * $kgRatio);

        if ($weight > Data::ORLEN_PACK_MAX_WEIGHT) {
            throw new LocalizedException(
                __('Package has too much weight! Weight cannot exceed %1 kg', Data::ORLEN_PACK_MAX_WEIGHT)
            );
        }
    }
}
