<?php

namespace Mtc\Plugins\DeliveryCouriers\Classes;

use Mtc\Plugins\BasketInsurance\Classes\Insurance;
use Mtc\Plugins\ShippingManager\Classes\ShippingZoneRate;
use Mtc\Shop\DeliveryServicesOption;
use Mtc\Shop\Item;

/**
 * Class OrderMap
 * Default integration for DeliveryCourierOrderMap Interface
 *
 * @author Martins Fridenbergs <martins.fridenbergs@mtcmedia.co.uk>
 */
class OrderMap implements DeliveryCourierOrderMap
{
    /**
     * Mapping class needs to be able to map the order to the format required by API
     *
     * @param \Order $order
     * @return array
     */
    public function map(\Order $order): array
    {
        $service = $this->deliveryServiceId($order);

        return [
            'id' => $order->getId(),
            'service_id' => $service ?: 252,
            'selected_delivery_method' => $order->getDelivery()->name,
            'items' => $this->mapItems($order->getItems()),
            'info' => [
                'email' => $order->info['email'],
                'contact_no' => $order->info['contact_no'],
            ],
            'order_total' => $order->getSubtotalCost(),
            'description' => $order->order_ref.' -  Merchandise',
            'dimensions' => $this->mapDimensions($order->getItems()),
            'address' => [
                'billing' => [
                    'organisation' =>
                        $order->address['billing']['firstname'].' '.$order->address['billing']['lastname'],
                    'first_name' => $order->address['billing']['firstname'],
                    'last_name' => $order->address['billing']['lastname'],
                    'address1' => $order->address['billing']['address1'],
                    'address2' => $order->address['billing']['address2'],
                    'city' => $order->address['billing']['city'],
                    'postcode' => $order->address['billing']['postcode'],
                    'country' => $order->address['billing']['country'],
                    'state' => $order->address['billing']['state'] ?? '',
                ],
                'shipping' => [
                    'organisation' =>
                        $order->address['shipping']['firstname'].' '.$order->address['shipping']['lastname'],
                    'first_name' => $order->address['shipping']['firstname'],
                    'last_name' => $order->address['shipping']['lastname'],
                    'address1' => $order->address['shipping']['address1'],
                    'address2' => $order->address['shipping']['address2'],
                    'city' => $order->address['shipping']['city'],
                    'postcode' => $order->address['shipping']['postcode'],
                    'country' => $order->address['shipping']['country'],
                    'state' => $order->address['shipping']['state'] ?? '',
                ],
            ],
            'additional_options' => array_merge(
                [
                    'shipment_detail' => [
                        'channel_shipservice_name' => $order->getDelivery()->name,
                        'instructions' => $order->getDelivery()->instructions ?? null ?: null,
                        'rules_metadata' => $_REQUEST['workstation_number'] ?? null,
                        'parcels' => ceil($order->getWeight() / 36000),
                        'weight' => $order->getWeight() / 1000,
                        'value' => $order->getTotalCost(),
                    ],
                ],
                $service ? [] : ['custom_delivery_service_code' => $order->getDelivery()->name],
            ),
        ];
    }

    /**
     * Map order dimensions from items
     * At this stage shop doesn't have item sizes so these will be added upon build
     *
     * @param $order_items
     * @return array
     */
    protected function mapDimensions($order_items)
    {
        // (optional) Add item dimensions
        return [
            'length' => null,
            'width' => null,
            'height' => null,
        ];
    }

    /**
     * Map order items for export to courier
     *
     * @param $items
     * @return array
     */
    protected function mapItems($items)
    {
        return collect($items)
            ->map(function ($item) {
                $shop_item = Item::query()->find($item['item_id']);

                return [
                    'name' => $item['item_name'],
                    'quantity' => $item['quantity'],
                    'price' => $item['price_paid'] > 0 ? $item['price_paid'] : $item['item_price'],
                    'weight' =>
                        $item['quantity']
                            * ($shop_item->custom->product_weight ?? null ?: DELIVERY_DEFAULT_ITEM_WEIGHT * 0.001),
                ];
            })->toArray();
    }

    /**
     * Find the delivery service id for this order
     *
     * @param \Order $order
     * @return mixed
     */
    protected function deliveryServiceId(\Order $order)
    {
        if (! empty($order->getDelivery()->service_id)) {
            return [$order->getDelivery()->service_id, 0];
        }

        $method = DeliveryServicesOption::query()
            ->whereHas('deliveryMethod', function ($delivery_method_query) use ($order): void {
                $delivery_method_query->where('id', $order->getDelivery()->id);
            })
            ->first();

        return $method->code ?? null;
    }
}
