<?php

namespace App\Classes\Modules\Orders\Services\Steps;


use App\Classes\Objects\Orders\OrderStepObject;
use App\Classes\ValueObjects\Constants\OrderSteps;
use App\Models\Order;
use App\Models\OrderWarehouse;
use Illuminate\Support\Collection;

class GenerateOrderSteps
{
    /**
     * @var Order
     */
    private $repository;

    /** @var CreatesOrderSteps */
    private $createsOrderSteps;


    /** @var Collection */
    protected $steps;

    /**
     * GenerateOrderSteps constructor.
     */
    public function __construct()
    {
        $this->repository = new Order();
        $this->steps = new Collection();
        $this->createsOrderSteps = new CreatesOrderSteps();
    }

    /**
     * @param int $orderId
     * @throws \App\Classes\Modules\Accounts\Exceptions\CannotCreateOrderStepsException
     */
    public function execute(int $orderId){
        $this->primarySteps(array_merge(OrderSteps::ORDER_PRIMARY_STEPS, OrderSteps::ORDER_PRIMARY_MODULAR_STEPS));
        $this->modularSteps([OrderWarehouse::where('order_id', $orderId)->get()->isEmpty() ? OrderSteps::ORDER_MODULE_NO_WAREHOUSE : OrderSteps::ORDER_MODULE_WAREHOUSE]);

        $orderSteps = $this->steps->sortBy('sequence');

        $this->createsOrderSteps->execute($orderId, $orderSteps->toArray());
    }


    public function modularSteps(array $modules){
        foreach ($modules as $module){
            foreach(OrderSteps::ORDER_MODULAR_STEPS[$module] as $group){
                $i = 0;
                foreach ($group['steps'] as $reference_id => $step){
                    $i++;
                    if(array_key_exists($group['previous'], OrderSteps::ORDER_PRIMARY_STEPS)){
                        $sequence =  OrderSteps::ORDER_PRIMARY_STEPS[$group['previous']]['sequence'] + ($i/10);
                    }

                    if(array_key_exists($group['previous'], OrderSteps::ORDER_PRIMARY_MODULAR_STEPS)){
                        $sequence =  OrderSteps::ORDER_PRIMARY_MODULAR_STEPS[$group['previous']]['sequence'] + ($i/10);
                    }

                    $this->addSteps((new OrderStepObject(false,  $reference_id, $sequence)));
                }
            }
        }
    }

    private function primarySteps($array){
        array_walk($array, function($step, $reference_id){
            $this->addSteps((new OrderStepObject(
                true,
                $reference_id,
                $step['sequence'])));
        });
    }

    private function addSteps(OrderStepObject $step){
        $this->steps->push([
            'primary' => $step->isPrimary(),
            'reference_id' => $step->getReferenceId(),
            'sequence' => $step->getSequence()
        ]);
    }
}