<?php

namespace App\Http\Controllers\Stock;

use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Models\Stock\PurchaseOrder;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use App\Notifications\ChannelServices;
use App\Models\Stock\PurchaseOrderItem;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Notification;

class PurchaseOrderController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * Return PurchaseOrder
     * @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 = PurchaseOrder::select('*')->with('creator','supplier','currency', 'company');
        if (!empty($status = \request()->query('status'))) {
            $result->where('status', $status);
        }
        if (empty($reference)) {
            if (empty($to)) {
                $result->where('date_initiated', $from);
            } else {
                $result->where('date_initiated', '>=', $from)
                    ->where('date_initiated', '<=', $to);
            }
        }

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

        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)
        ]);
    }

    /**
     * Store Purchase Order Item
     * @param Request $request
     * @return JsonResponse
     */
    public function store(Request $request)
    {
        $items = json_decode($request->input('items'));
        $reference = generateRowCode(20);
        $PurchaseOrder = PurchaseOrder::create([
            'reference'      =>  $reference,	
            'code'      =>  createTransactCode('PO'),	
            'date_initiated' =>  $request->input('date_initiated'),
            'supplier_id' =>  $request->input('supplier_id'),
            'amount'        => $request->input('amount'),
            'currency'        => $request->input('currency'),
            'status'        => 'PENDING',
            'DocReference' => strtoupper($request->input('DocReference'))
        ]);
        $id = $PurchaseOrder->id;
        foreach($items as $item){
            PurchaseOrderItem::create([
                'order_id' => $id,
                'product_id'    => $item->id,
                'order_qty' => $item->quantity,
                'price' => $item->price,
                'requested_qty'  => $item->quantity
            ]);
        }

        if (!empty($file = $request->file('file'))) {
            $result = $this->storeFile($request,$id);
            $row = PurchaseOrder::find($id);
            $row->file_url = $result;
            $row->save();
        }

        $currentUser = auth()->user();
        $users = getNotifiableUsers($currentUser);
        $itemsCount = sizeof($items);
        $data = [
            'id'   => $id,
            'slug' => $PurchaseOrder->reference,
            'type' => 'Purchase Order',
            'link' => 'purchase-order',
            'message' => "New Purchase Order from <b>{$currentUser->name}</b> of <b>{$itemsCount}</b> items!</b>" 
        ];
        Notification::sendNow($users, new ChannelServices($data));
        return response()->json([
            'status' => 1,
            'ref' => $PurchaseOrder->reference,
            'message' => 'Purchase Order created successfully'
        ]);
    }

    /**
     * Upload file
    */
    private function storeFile($request,$orderId)
    {
        $file = $request->file('file');
        $folder = 'Proforma/';
        $id = Auth::id();
        if ($id) {
            $folder .= sprintf('%04d', (int)$id / 1000) . '/' . $id . '/';
        }

        $folder = $folder . date('Y/m/d');
        $originalFilename = $file->getClientOriginalName();
        $uniquePart = generateRowCode(8);
        $extension = $file->getClientOriginalExtension();
        $newFileName = 'RW-'.$uniquePart;

        if(empty($newFileName)) $newFileName = md5($file->getClientOriginalName());
        $i = 0;
        do {
            $newFileName2 = $newFileName . ($i ? $i : '');
            $testPath = $folder . '/' . $newFileName2 . '.' . $extension;
            $i++;
        } while (Storage::disk('public')->exists($testPath));

        $check = $file->storeAs( $folder, $newFileName2 . '.' . $extension,'public');
       
        $Order = PurchaseOrder::find($orderId);
        $fullPath = Storage::path('public/'.$Order->file_url);
        $pathToUnlink = str_replace('/','/',$fullPath);
        if(!empty($Order->file_url)) {
          unlink($pathToUnlink); 
        }
        
        $Order->file_url = $check;
        $Order->save();
        return $check;
    }

        /**
     * Update Purchase Order Item
     * @param Request $request
     * @return JsonResponse
     */

     public function editOrder(Request $request){
        $items = json_decode($request->input('items'));
        if (!empty($id = $request->input('order_id'))) {
            $record = PurchaseOrder::find($id);
            $record->date_initiated = $request->input('date_received');
            $record->amount = $request->input('amount');
            $record->supplier_id = $request->input('supplier_id');
            $record->currency = $request->input('currency');
            $record->save();

            foreach($items as $item){
                $row = PurchaseOrderItem::find($item->rowId);
                $row->order_qty = $item->quantity;
                $row->requested_qty = $item->quantity;
                $row->price = $item->price;
                $row->save();
            }
            
            if (!empty($file = $request->file('file'))) {
                $result = $this->storeFile($request,$id);
            }

            return response()->json([
                'status'  => 1,
                'ref'  => $record->reference,
                'message' => 'Purchase Order Updated successfully'
            ]);
        }else{
            return response()->json([
                'status'  => 0,
                'message' => 'Oops! Some Errors Occur.'
            ]);
        }
     } 


    /**
     * Get Purchase Items
     * @param string $reference
     * @return JsonResponse
     */
    public function getItems($reference)
    {
        $PurchaseOrder = PurchaseOrder::where('reference', $reference)
                                    ->with('creator','supplier', 'currency', 'company')
                                    ->first();
        if (!$PurchaseOrder) {
            return response()->json([
                'status'  => 0,
                'message' => 'Purchase Order not found. Try again'
            ], 404);
        }

        return response()->json([
            'status' => 1,
            'row'    => $PurchaseOrder,
            'items'  => PurchaseOrderItem::select('id', 'product_id', 'order_qty as quantity', 'price', 'requested_qty')
                                      ->where('order_id', $PurchaseOrder->id)
                                      ->with('product')
                                      ->get()
        ]);
    }

   /**
    * Delete Purchase Order
    * @param string $reference
     * @return JsonResponse
    */
    public function verifyPurchaseOrder($id)
    {   
        $row = PurchaseOrder::find($id);
        if(empty($row)){
            return response()->json([
                'status' =>0,
                'message'=>'No Order Found!'
            ],404);
        }

        $row->status = "VERIFIED";
        $row->save();

        return response()->json([
            'status' =>1,
            'message'=>'Purchase Order #'.$id.' Marked as Verified Successfuly!'
        ]);
    }

       /**
    * Delete Purchase Order
    * @param string $reference
     * @return JsonResponse
    */
    public function paidPurchaseOrder($id)
    {   
        $row = PurchaseOrder::find($id);
        if(empty($row)){
            return response()->json([
                'status' =>0,
                'message'=>'No Order Found!'
            ],404);
        }

        $row->status = "PAID";
        $row->save();

        return response()->json([
            'status' =>1,
            'message'=>'Purchase Order #'.$id.' Marked as Paid Successfuly!'
        ]);
    }

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

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

        $row->delete();

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

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

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

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

        $row->delete();

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