<?php

namespace App\Modules\Bookings;

use App\Modules\Stock\StockTransaction;
use App\Modules\Stock\Stock;
use Exception;
use Illuminate\Support\Facades\Event;

class BuildTemplateCloned
{
    /**
     * The cloned stock.
     *
     * @var \App\Modules\Stock\Stock
     */
    protected $newStock;

    /**
     * The original stock.
     *
     * @var \App\Modules\Stock\Stock
     */
    protected $oldStock;

    /**
     * The build that is going to use the new cloned stock.
     *
     * @var \App\Modules\Bookings\Build
     */
    protected $build;

    /**
     * Subscribe to events.
     *
     * @param  mixed $events
     *
     * @return null
     */
    public function subscribe($events)
    {
        $events->listen('BuildTemplateCloned', 'App\Modules\Bookings\BuildTemplateCloned@fire');
    }

    /**
     * Fire the event.
     *
     * @param  \App\Modules\Bookings\Part $part
     *
     * @return bool
     */
    public function fire($oldStock, $newStock, $build)
    {
        $this->newStock = $newStock;
        $this->oldStock = $oldStock;
        $this->build = $build;

        foreach ($oldStock->composite_items as $stock) {
            if ($stock->unlimited) {
                $this->createTransaction($stock, $stock->pivot->quantity);
            } else {
                $this->detachComponent($stock);
            }
        }

        foreach ($build->stock->composite_items as $stock) {
            if ($stock->unlimited) {
                $this->createTransaction($stock, -1 * $stock->pivot->quantity);
            } else {
                $this->attachComponent($stock);
            }
        }
    }

    /**
     * Update the stock quantity and the quantity to order.
     *
     * @return bool
     */
    protected function detachComponent($component)
    {
        $ordered = $this->build->ordered_components()->where('stock_id', $component->id)->first();

        if ($ordered) {
                                Event::dispatch('CancelRequestedStock', [$component, $ordered->pivot->quantity]);
            $this->build->ordered_components()->detach($ordered->id);
        }

        $this->createTransaction($component, $this->build->quantity * $component->pivot->quantity - ($ordered ? $ordered->pivot->quantity : 0));
    }

    /**
     * Update the stock quantity and the quantity to order.
     *
     * @return bool
     */
    protected function attachComponent($component)
    {
        if ($component->quantity < $this->build->quantity * $component->pivot->quantity) {
            $quantity_needed = $this->build->quantity * $component->pivot->quantity - $component->quantity;
                                Event::dispatch('StockRequested', [$component, $quantity_needed]);
            $this->build->ordered_components()->attach([$component->id => ['quantity' => $quantity_needed]]);
        } else {
            $quantity_needed = 0;
        }

        if ($this->build->quantity * $component->pivot->quantity - $quantity_needed > 0) {
            $this->createTransaction($component, $this->build->quantity * $component->pivot->quantity - $quantity_needed);
        }
    }

    /**
     * Create a stock transaction that will
     * automatically update the stock.
     *
     * @return bool
     */
    protected function createTransaction($stock, $quantity)
    {
        $transaction = StockTransaction::create([
            'stock_id'     => $stock->id,
            'related_type' => $this->build->related_type,
            'related_id'   => $this->build->related_id,
            'quantity'     => $quantity,
        ]);

        if (! $transaction->exists) {
            throw new Exception('Failed to create stock transaction, '.json_encode($transaction->errors->all()));
        }

        return true;
    }
}
