<?php
namespace App\Http\Controllers\Stock;

use App\Models\Stock\Sale;
use App\Models\Stock\Client;
use Illuminate\Http\Request;
use App\Models\Stock\Payment;
use App\Models\Stock\Product;
use App\Models\Stock\SaleItem;
use App\Models\Stock\DeriveryNote;
use Illuminate\Support\Facades\DB;
use App\Models\Stock\ProductChange;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use App\Notifications\ChannelServices;
use App\Models\Stock\DeriveryNoteItems;
use Illuminate\Support\Facades\Notification;

class DeliveryNoteController extends Controller
{
    /**
     * Return DeriveryNotes
     * @param Request $request
     * @return JsonResponse
     */
    public function index(Request $request, $reference = NULL)
    {
        $from = $request->input('from');
        $to = $request->input('to');
        if (empty($from)) {
            $from = date('Y-m-d');
        }
        
        $result = DeriveryNote::select('*')->with('creator', 'client');
        if (!empty($status = \request()->query('status'))) {
            $result->where('status', $status);
        }

        if (!empty($client = $request->input('client'))) {
            $result->where('client_id', $client);
        }

        if (!empty($status = $request->input('status'))) {
            if($status!="CANCELLED"){
                $result->where('status', $status);
            }else{
                $result->onlyTrashed();
            }

        }
        if (empty($reference)) {
            if (empty($to)) {
                $result->where('date_initiated', $from);
            } else {
                $result->where('date_initiated', '>=', $from)
                    ->where('date_initiated', '<=', $to);
            }
        } 

        if (!empty($reference)) {
            $result->where('reference', $reference);
        }

        return response()->json([
            'status' => 1,
            'rows'   =>  $result->orderBy('status', 'ASC')
                            ->orderBy('id', 'DESC')
                            ->paginate(\request()->query('per_page') ?? 45)
        ]);
    }

        /**
     * Return Generating invoice
     * @param Request $request
     * @return JsonResponse
     */
    public function generateInvoice(Request $request)
    {
        $reference = $request->input('reference');
        $DeriveryNote = DeriveryNote::where('reference', $reference)
                            ->with('client')
                            ->first();
        if (!$DeriveryNote) {
            return response()->json([
                'status'  => 0,
                'message' => 'Derivery Note not found. Try again'
            ], 404);
        }

        if($request->input('amount_paid') > $DeriveryNote->amount){
            return response()->json([
                'status'  => 0,
                'message' => 'Paid Amount must be less than or equal to total Derivery Amount!'
            ]);
        }

        if($request->input('amount_paid')<0){
            return response()->json([
                'status'  => 0,
                'message' => 'Amount paid must be greater than or equal to zero!'
            ]);
        }

        $data = [
            'total_amount'   =>   $DeriveryNote->amount,	
            'discounted_total' => $request->input('discounted_total'),	
            'create_user'      => auth()->id(),	
            'comment'          => $request->input('comment'),	
            'amount_paid'      => $request->input('amount_paid') ?? 0,
            'amount_remain'    => $request->input('amount_remain'),	
            'discount_perc'    => $request->input('discount'),
            'discount_amount'  => $request->input('discount_amount'),
            'payment_date'     => $request->input('payment_date'),
            'client_id'        => $DeriveryNote->client_id,	
            'paid'             => $request->input('amount_remain') == 0,
            'committed_date'   => $request->input('committed_date') ?? date('Y-m-d')
        ];

        $DeriveryNoteItems = DeriveryNoteItems::select('id', 'product_id', 'batch', 'requested_qty as quantity', 'price', 'received_qty')
                                      ->where('derivery_id', $DeriveryNote->id)
                                      ->get();

        $DeriveryNoteItems2 = DeriveryNoteItems::select('id', 'product_id', 'batch', 'requested_qty as quantity', 'price', 'received_qty')
                                      ->where('derivery_id', $DeriveryNote->id)
                                      ->get();
        $checkUpdateStatus = 0;

        foreach ($DeriveryNoteItems as $item){
            $product = Product::find($item->product_id);
            if($product->quantity<$item->quantity){
                $checkUpdateStatus +=1; 
                break;
            }else{
                $checkUpdateStatus = 0;
            }
        }

        if($checkUpdateStatus==0){

            $data = array_merge($data, [
                'type'        => 'FROM_DERIVERY_NOTE',
                'reference'   => generateRowCode(8),
                'origin_ref'  => $DeriveryNote->reference,
                'code' => createTransactCode('CI')
            ]);
            $order = Sale::create($data);
    
            if ($order) {
                $amountPaid = $request->input('amount_paid') ?? 0;
                Payment::create([
                    'committed_date' => $request->input('payment_date') ?? date('Y-m-d'),	
                    'transaction_id' => $order->id,	
                    'payment_type'   => $request->input('payment_method'),
                    'amount_paid'    => $amountPaid,	
                    'comment'        => $request->input('comment'),
                    'reference'      => $request->input('payment_ref') ?? generateRowCode(4),
                    'create_user'    => auth()->id()
                ]);
            }

            foreach ($DeriveryNoteItems2 as $item){
                SaleItem::create([
                    'sale_id'  => $order->id,
                    'item_id'  => $item->product_id,
                    'batch'    => $item->batch,
                    'quantity' => $item->quantity,
                    'price'    => $item->price,
                    'amount'   => $item->quantity * $item->price,
                    'comment'  => NULL
                ]);
                /**
                 * Remove products Qty
                 */
                $product = Product::find($item->product_id);
                $product->quantity -= $item->quantity;
                $product->save();

                $totalQuantity = 0;

                // Calculate the total quantity of all batches
                foreach ($product->ProductChanges as $productChange) {
                    $totalQuantity += $productChange->quantity;
                }

                if ($item->quantity <= $totalQuantity) {
                    $productChange = ProductChange::where('product_id', $item->product_id)
                    ->where('batch_nber', $item->batch)
                    ->first();
            
                    if (!$productChange) {
                        return response()->json([
                            'status'=>0,
                            'message'=> 'Batch are you trying search is unvailable!'
                        ]);
                    }
                
                    $remainingQuantity = $item->quantity;
                
                    if ($productChange->quantity >= $remainingQuantity) {
                        $productChange->decrement('quantity', $remainingQuantity);
                        $remainingQuantity = 0;
                    } else {
                        $remainingQuantity -= $productChange->quantity;
                        $productChange->update(['quantity' => 0]);
                    }

                    foreach($product->ProductChanges as $otherProductChange){
                        
                        if ($remainingQuantity <= 0) {
                            break;
                        }
                
                        if ($otherProductChange->quantity >= $remainingQuantity) {
                            $otherProductChange->decrement('quantity', $remainingQuantity);
                            $remainingQuantity = 0;
                        } else {
                            $remainingQuantity -= $otherProductChange->quantity;
                            $otherProductChange->update(['quantity' => 0]);
                        }
                    }
                }else{
                    return response()->json([
                        'status'=>0,
                        'message'=> 'Requested quantity is greater than available batches.'
                    ]);
                }
            }

            $DeriveryNote->status = "ACCEPTED";
            $DeriveryNote->save();

            return response()->json([
                'status' => 1,
                'row'    => $order,
                'message' => "Invoice Generated Successfuly"
            ]);

        }else{
            return response()->json([
                'status'  => 0,
                'message' => 'Invoice Can\'t be Generated because there must be higher requested qty than in-stock qty! try to make stock-in.'
            ]);
        }
    }

    /**
     * Get DeriveryNote Items
     * @param string $reference
     * @return JsonResponse
     */
    public function getItems($reference)
    {
        $DeriveryNote = DeriveryNote::select("*")->where('reference', $reference)
                                    ->with('client','company')
                                    ->first();
        if (!$DeriveryNote) {
            return response()->json([
                'status'  => 0,
                'message' => 'Derivery Note not found. Try again'
            ], 404);
        }

        return response()->json([
            'status' => 1,
            'row'    => $DeriveryNote,
            'items'  => DeriveryNoteItems::select('id', 'product_id', 'batch', 'requested_qty as quantity', 'price', 'received_qty')
                                      ->where('derivery_id', $DeriveryNote->id)
                                      ->with('product','expiry')
                                      ->get()
        ]);
    }

   /**
    * Delete DeriveryNote
    * @param int $id
     * @return JsonResponse
    */
    public function destroy($id) 
    {
        $row = DeriveryNote::find($id);
        if (empty($row)) {
            return response()->json([
                'status'  => 0,
                'error' => 'No records found'
            ], 404);
        }

        $items = DeriveryNoteItems::where('derivery_id', $row->id)->get();
        foreach($items as $item) {
            $item->delete();
        }

        $row->status = "CANCELLED";
        $row->save();
        $row->delete();

        return response()->json([
            'status'  => 1,
            'message'   => 'Record have deleted successfully'
        ]);
    }

    /**
     * Update DeriveryNote status
     * @param int $id
     * @return JsonResponse
     */
    public function updateStatus($id)
    {
        $DeriveryNote = DeriveryNote::findOrFail($id);

        if(!empty($DeriveryNote)) {
            $DeriveryNote->status = "CANCELLED";
            $DeriveryNote->save();
        }
        return response()->json([
            'status'  => 1,
            'message' => 'Status Changed Successfully'
        ]);
    }

    /**
     * Delete Single item
     * @param int itemId
     * @return JsonResponse
     */
    public function deleteItem($itemId)
    {
        $row = DeriveryNoteItems::findOrFail($itemId);
        if (!$row) {
            return response()->json([
                'status' => 0,
                'error'  => 'Item not found'
            ], 404);
        }
        $DeriveryNote = DeriveryNote::find($row->derivery_id);
        $DeriveryNote->amount -= ($row->price * $row->requested_qty);
        $DeriveryNote->save();

        $row->delete();

        return response()->json([
            'status' => 1,
            'message'  => 'Deleted successfully'
        ]);
    }
}