<?php

namespace App\Classes\Modules\Orders\Services;


use App\Classes\ValueObjects\Constants\OrderSteps;
use App\Models\Order;
use App\Models\OrderWarehouse;
use App\Models\Schedule;
use App\Models\Warehouse;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Collection;

class ListsOrderHistory
{
    /** @var Collection */
    private $history;

    /**
     * ListsOrderHistory constructor.
     */
    public function __construct()
    {
        $this->history =  new Collection();
    }


    public function execute(string $orderId, Carbon $createdAt){
        /** @var Order $order */
        $order = Order::findOrFail($orderId);

        $orderSteps = $order->orderSteps()->where('complete', true)->orderBy('sequence')->get();

        $this->history->push(['type' => 1, 'date' => $createdAt->format('d-m-Y'), 'description' => 'Order number has been created']);

        $warehouse_id = OrderWarehouse::where('order_id', $orderId)->first()->warehouse_id;
        $warehouse = Warehouse::where('id', $warehouse_id)->first();
        foreach ($orderSteps as $step){
            $completeDate = Carbon::parse($step->complete_date)->format('d-m-Y');
            switch ($step->reference_id){
                case OrderSteps::ORDER_PROCESSING_STEP:
                    if($warehouse_id){
                        $this->history->push(['type' => 1, 'date' => $completeDate, 'description' => $warehouse->name.' confirmed as your order\'s warehouse']);
                    }
                    break;
                case OrderSteps::ORDER_NO_WAREHOUSE_PENDING_SUPPLIER:
                    $this->history->push(['type' => 1, 'date' => $completeDate, 'description' => 'Your Order has been loaded into container']);
                    break;
                case OrderSteps::ORDER_WAREHOUSE_RECEIVING_STEP:
                    $this->history->push(['type' => 1, 'date' => $completeDate, 'description' => 'Arrived at '. $warehouse->name .' warehouse in china']);
                    break;
                case OrderSteps::ORDER_WAREHOUSE_PACKING_STEP:
                    $packages = $order->packingLists()->firstOrFail()->packages()->selectRaw(DB::raw('((width/100) * (height/100) * (length/100)) * quantity as cbm, quantity'))->get();
                    $this->history->push(['type' => 1, 'date' => $completeDate, 'description' => '['.$packages->sum('quantity').' Packages, '.number_format((float)$packages->sum('cbm'), 2, '.', '').' CBM] Your order has been loaded into container']);
                    $this->history->push(['type' => 1, 'date' => $completeDate, 'description' => 'Invoice has been issued, waiting for shipping payment']);
                    break;
                case OrderSteps::ORDER_SHIPPING_STEP:
                    $this->shippingArrangment($order);
                    $this->history->push(['type' => 1, 'date' => $completeDate, 'description' => 'Arrived to Malaysian port']);
                    $this->history->push(['type' => 1, 'date' => $completeDate, 'description' => 'Custom clearance is successful']);
                    break;
                case OrderSteps::ORDER_WAREHOUSE_ARRIVAL_STEP:
                    $this->history->push(['type' => 1, 'date' => $completeDate, 'description' => 'Arrived at Malaysia\'s warehouse']);
                    break;
                case OrderSteps::ORDER_WAREHOUSE_UNPACKING_STEP:
                    $this->history->push(['type' => 1, 'date' => $completeDate, 'description' => 'Your Order has been unloaded and being prepared for delivery']);
                    break;
                case OrderSteps::ORDER_DELIVERY_STEP:
                    $this->deliveryArrangment($order);
                    $this->history->push(['type' => 2, 'date' => $completeDate, 'description' => 'Your Order has successfully been delivered']);
                    break;
            }
        }

        if($order->current_step === OrderSteps::ORDER_SHIPPING_STEP){
            $this->shippingArrangment($order);
        }

        if($order->current_step === OrderSteps::ORDER_DELIVERY_STEP){
            $this->deliveryArrangment($order);
        }

        return $this->history->reverse()->toArray();
    }

    private function shippingArrangment(Order $order){
        $shippingArrangement = $order->shippingArrangement()->first();
        if($shippingArrangement){
            $shippingSchedules = Schedule::where('arrangement_id', $shippingArrangement->id)->where('type', 0)->get();
            foreach ($shippingSchedules as $schedule){
                if((int)$schedule->status === 2){
                    $this->history->push(['type' => 0, 'date' => carbon::parse($schedule->ETD)->format('d-m-Y'), 'description' => $schedule->issue_remark ? 'Scheduled Shipping has failed due to: '.$schedule->issue_remark : 'Scheduled Shipping has failed']);
                } else {
                    $this->history->push(['type' => 1, 'date' => carbon::parse($schedule->ETD)->format('d-m-Y'), 'description' => '[ETD: '.carbon::parse($schedule->ETD)->format('d-m-Y').', ETA: '.carbon::parse($schedule->ETA)->format('d-m-Y').'] Your Order has been scheduled for shipping ']);
                }
            }
        }
    }

    private function deliveryArrangment(Order $order){
        $deliveryArrangement = $order->deliveryArrangement()->first();
        if($deliveryArrangement){
            $deliverySchedules = Schedule::where('arrangement_id', $deliveryArrangement->id)->where('type', 1)->get();
            foreach ($deliverySchedules as $schedule){
                if((int)$schedule->status === 2){
                    $this->history->push(['type' => 0, 'date' => carbon::parse($schedule->ETD)->format('d-m-Y'), 'description' => $schedule->issue_remark ? 'Scheduled delivery has failed due to: '.$schedule->issue_remark : 'Scheduled delivery has failed']);
                } else {
                    $this->history->push(['type' => 1, 'date' => carbon::parse($schedule->ETD)->format('d-m-Y'), 'description' => '[ETD: '.carbon::parse($schedule->ETD)->format('d-m-Y').', ETA: '.carbon::parse($schedule->ETA)->format('d-m-Y').'] Your Order has been scheduled for delivery ']);
                }
            }
        }
    }

}