<?php

namespace Alsendo\AlsendoWrapper\Api\Zaslat\Wrapper;


use Alsendo\AlsendoWrapper\Api\Zaslat\Model\Money;
use Alsendo\AlsendoWrapper\Api\Zaslat\Model\Rates\RatesGetRequest;
use Alsendo\AlsendoWrapper\Api\Zaslat\Model\Service;
use Alsendo\AlsendoWrapper\Exception\ValidationException;
use Alsendo\AlsendoWrapper\Model\Order\OrderRequest;
use Alsendo\AlsendoWrapper\Model\Shipment;
use DateTimeImmutable;

class OrderValuationRequestWrapper
{
    /**
     * @param OrderRequest $orderRequest
     * @return RatesGetRequest
     *
     * Wraps OrderRequest into RatesGetRequest
     * @throws ValidationException
     */
    public static function wrap(OrderRequest $orderRequest): RatesGetRequest
    {
        $request = new RatesGetRequest();
        $request->currency = $orderRequest->currency;
        $request->pickupDate = ! empty( $orderRequest->pickup->date ) ? (new DateTimeImmutable($orderRequest->pickup->date))->format('Y-m-d') : null;
        if(  ! empty( $orderRequest->pickup->type ) ) {
            $request->type = $orderRequest->pickup->type; // fix Zaslat
        }

        if ($orderRequest->address->sender->hasMapPoint) {
            $request->pickupBranch = 1;
        }
        $request->carrier = $orderRequest->carrier;
        $request->deliveryBranch = $orderRequest->address->receiver->mapPointId;

        if (!is_null($orderRequest->pickupRequest)) {
            if( ! empty( $orderRequest->carrier ) ) {
                if( 'BALIKOVNA' !== strtoupper( $orderRequest->carrier) && 'ZASILKOVNA' !== strtoupper( $orderRequest->carrier)  && 'PACKETA' !== strtoupper( $orderRequest->carrier) ) {
                    $request->pickupRequest = 1;
                }
            } else {
                $request->pickupRequest = 1;
            }

        }

        $request->from = ContactWrapper::wrap($orderRequest->address->sender);

        $request->to = ContactWrapper::wrap($orderRequest->address->receiver);

        // Validate that from contact has either id or country
        if (empty($request->from->id) && empty($request->from->country)) {
            throw new ValidationException(['address.sender' => 'Contact from must have either id or country']);
        }

        // Validate that to contact has either id or country
        if (empty($request->to->id) && empty($request->to->country)) {
            throw new ValidationException(['address.receiver' => 'Contact to must have either id or country']);
        }

        if (!empty($orderRequest->cod)) {
            $request->services[] = [
                'code' => 'cod',
                'data' => [
                    'value' => [
                        'value' => $orderRequest->cod->amount,
                        'currency' => $orderRequest->cod->currency ?? $orderRequest->currency
                    ]
                ]
            ];
        }

        if (!empty($orderRequest->options)) {
            foreach ($orderRequest->options as $option) {
                if (!$option instanceof Service) {
                    throw new ValidationException(['option.service' => 'Option must be instance of Alsendo\AlsendoWrapper\Model\Service']);
                }
                if (strtoupper($option->code) === 'INS') {
                    if (!$option->data instanceof Money) {
                        throw new ValidationException(['option.service.data' => 'Option data must be instance of Alsendo\AlsendoWrapper\Model\Money']);
                    }
                    $request->services[] = [
                        'code' => 'ins',
                        'data' => [
                            'value' => $option->data->value,
                            'currency' => $option->data->currency ?? $orderRequest->currency
                        ]
                    ];
                }

                if (strtoupper($option->code) === 'DSC') {
                    if (empty($option->data)) {
                        throw new ValidationException(['option.service.data' => 'Option data must be instance of Alsendo\AlsendoWrapper\Model\Money']);
                    }
                    $request->services[] = [
                        'code' => 'dsc',
                        'data' => $option['data']
                    ];
                }
            }
        }

        foreach ($orderRequest->shipment as $shipment) {
            if (!$shipment instanceof Shipment) {
                throw new ValidationException(['shipment' => 'Shipment must be instance of Alsendo\AlsendoWrapper\Model\Shipment']);
            }
            $request->packages[] = [
                'weight' => $shipment->weight,
                'width' => $shipment->dimension1,
                'height' => $shipment->dimension2,
                'length' => $shipment->dimension3,
            ];
        }

        return $request;
    }
}
