<?php

namespace App\Modules\Bookings;

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

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

    /**
     * The composite stock items that were removed.
     *
     * @var \App\Modules\Stock\Stock
     */
    protected $oldItems;

    /**
     * The composite stock items that were added.
     *
     * @var \App\Modules\Stock\Stock
     */
    protected $newItems;

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

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

        $items_changes = [];

        foreach ($oldItems as $item) {
            if (! isset($items_changes[$item->id])) {
                $items_changes[$item->id] = [];
            }
            $items_changes[$item->id]['old_quantity'] = $item->pivot->quantity;
        }

        foreach ($newItems as $item) {
            if (! isset($items_changes[$item->id])) {
                $items_changes[$item->id] = [];
            }
            $items_changes[$item->id]['new_quantity'] = $item->pivot->quantity;
        }

        foreach ($items_changes as $id => $change) {

            // If it is a new item, create a transaction with the full amoutn
            if (! isset($change['old_quantity'])) {
                $this->createTransaction($id, -1 * $part->quantity * $change['new_quantity']);
            }

            // If the item has been deleted remove the full amount
            elseif (! isset($change['new_quantity'])) {
                $this->createTransaction($id, $part->getOriginal('quantity') * $change['old_quantity']);
            } elseif ($part->getOriginal('quantity') != $part->quantity || $change['new_quantity'] != $change['old_quantity']) {
                $this->createTransaction($id, $part->getOriginal('quantity') * $change['old_quantity'] - $part->quantity * $change['new_quantity']);
            }
        }

        return true;
    }

    /**
     * Create a new stock transaction.
     *
     * @param  \App\Modules\Stock\Stock $stockItem
     * @param  int $quantity
     *
     * @return bool
     */
    protected function createTransaction($stock_id, $quantity)
    {
        $transaction = StockTransaction::create([
            'stock_id'     => $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, '.json_encode($transaction->errors->all()));
        }
    }
}
