<?php

namespace App\Modules\Stock;

use Illuminate\Support\Facades\DB;
use App\Models\Status;

use Exception;

class StockPurchaseOrderItemObserver
{
    public function created($model)
    {
        $this->updateStockOrderedAndToOrderQuantities($model, 'create');
    }

    public function updating($model)
    {
        $this->createTransaction($model);
        $this->updateStockOrderedAndToOrderQuantities($model, 'update');
    }

    public function updated($model)
    {
        $this->updateOrderStatus($model);
    }

    /**
     * ------------------------------------------------
     * PROTECTED FUNCTIONS BELOW
     * ------------------------------------------------.
     */

    /**
     *	Creates a "purchase_order" Transaction if there are items marked as received.
     *
     * @return void
     */
    protected function createTransaction($model)
    {
        if ($model->isDirty('received_quantity')) {
            $items_received = $model->received_quantity - $model->getOriginal('received_quantity');
            $transaction = StockTransaction::create([
                'related_type' => 'purchase_order',
                'stock_id'     => $model->stock_id,
                'related_id'   => $model->stock_purchase_order_id,
                'quantity'     => $items_received,
            ]);

            if (! $transaction) {
                throw new Exception(json_encode($transaction->errors->all()), 1);
            }
        }
    }

    /**
     *	Updating quantity to order and ordered quantity from stock.
     *
     * @return void
     */
    protected function updateStockOrderedAndToOrderQuantities($model, $action)
    {
        switch ($action) {
            case 'create':
                if ($stock = $model->stock) {
                    $stock->ordered_quantity = $stock->ordered_quantity + $model->quantity;
                    $stock->quantity_to_order = ($stock->quantity_to_order - $model->quantity) < 0 ? 0 :  $stock->quantity_to_order - $model->quantity;

                    // Skip validation when just updating quantity to avoid model_number uniqueness issues
                    $stock->timestamps = false; // Don't update timestamps for quantity changes
                    if (! $stock->saveQuietly()) {
                        throw new Exception("Failed to update stock quantity for stock ID: {$stock->id}", 1);
                    }
                }
                break;
            case 'update':
                if ($model->isDirty('refused_quantity')) {
                    $stock = $model->stock;
                    $stock->ordered_quantity -= $model->refused_quantity - $model->getOriginal('refused_quantity');

                    // Skip validation when just updating quantity to avoid model_number uniqueness issues
                    $stock->timestamps = false; // Don't update timestamps for quantity changes
                    if (! $stock->saveQuietly()) {
                        throw new Exception("Failed to update stock quantity for stock ID: {$stock->id}", 1);
                    }
                }
                if ($model->isDirty('received_quantity')) {
                    $stock = $model->stock;
                    $stock->ordered_quantity -= $model->received_quantity - $model->getOriginal('received_quantity');

                    // Skip validation when just updating quantity to avoid model_number uniqueness issues
                    $stock->timestamps = false; // Don't update timestamps for quantity changes
                    if (! $stock->saveQuietly()) {
                        throw new Exception("Failed to update stock quantity for stock ID: {$stock->id}", 1);
                    }
                }
                break;
        }
    }

    /**
     * It automatically updates the status to delivered if all the items
     * have been received on a purchase order.
     *
     * @param  $model
     *
     * @return null
     */
    protected function updateOrderStatus($model)
    {
        if ($order = $model->order) {
            $totalItems = $order->items()->count();

            // Get a count of all the purchase order items that have been completed
            $completedItems = $order->items()->where('quantity', '=', DB::raw('received_quantity + refused_quantity'))->count();

            if ($totalItems == $completedItems) {
                $refusedItems = $order->items()->sum('refused_quantity');

                if ($order->items()->sum('quantity') == $refusedItems) {
                    $status = Status::query()->where('for', 'orders')->where('name', 'Cancelled')->first();
                } else {
                    $status = Status::query()->where('for', 'orders')->where('name', 'Delivered')->first();
                }

                if ($status->id) {
                    $order->status_id = $status->id;

                    if (! $order->save()) {
                        throw new Exception(json_encode($order->errors->all()), 1);
                    }
                }
            }
        }
    }
}
