<?php

namespace App\Modules\Bookings;

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

class PartUpdating
{
    /**
     * The part that was updated.
     *
     * @var \App\Modules\Bookings\Part
     */
    protected $part;

    /**
     * The part in the original state.
     *
     * @var \App\Modules\Bookings\Part
     */
    protected $oldPart;

    /**
     * The quantity that has been updated.
     *
     * @var int
     */
    protected $quantity;

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

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

        // Get the quantity difference
        $this->quantity = $part->quantity - $oldPart->quantity;

        if ($part->stock->unlimited) {
            return $this->createTransaction($this->quantity);
        }

        // Process the part that is not on order
        return $this->processNormalFlow();
    }

    /**
     * Update the part quantity when this is not on order.
     *
     * @return bool
     */
    protected function processNormalFlow()
    {
        // If the quantity on order is different, update the stock quantity to order
        $on_order_quantity_diff = $this->oldPart->quantity_on_order - $this->part->quantity_on_order;

        if ($on_order_quantity_diff > 0) {
            Event::dispatch('CancelRequestedStock', [$this->part->stock, $on_order_quantity_diff]);
        }

        if ($on_order_quantity_diff < 0) {
            Event::dispatch('StockRequested', [$this->part->stock, abs($on_order_quantity_diff)]);
        }

        // If the used quantity is different create a transaction 
        $used_quantity_diff = ($this->oldPart->quantity - $this->oldPart->quantity_on_order) - ($this->part->quantity - $this->part->quantity_on_order);

        if ($used_quantity_diff != 0) {
            return $this->createTransaction($used_quantity_diff);
        }

        return true;
    }

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

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

        return true;
    }
}
