<?php

namespace App\Http\Controllers\Api\Manufacturing;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Models\MaterialRequestion;
use App\Models\MaterialRequestionApprove;
use App\Models\MaterialRequestionItem;
use App\Models\ManufacturingStore;
use App\Models\Item;
use App\Service\MaterialRequestionService;
use App\Service\StockEntryService;
use App\Service\SequenceService;
use App\Service\StaticMaster;
use Auth;

class RequisitionController extends Controller
{
    //  create MaterialRequestion record
    public function requisition_create(Request $request)
    {

        $validator=validator($request->all(),[
            'requestion_id'=>'required',
            'date'=>'required',
            // 'order_id'=>'required|integer',
            // 'item_id'=>'required|integer',
            // 'warehouse_id'=>'required|integer',
        ]);

        if ($validator->fails()) { 

            return [
                'success' => false, 
                'message' => $validator->errors()->first()
            ];

        } else {

            try {

                $obj['requestion_id'] = $request['requestion_id'];
                $obj['date'] = $request['date'];
                $obj['order_id'] = $request['order_id'];
                $obj['item_id'] = $request['item_id'] ?? 0;
                $obj['item_name'] = $request['item_name'] ?? 0;
                $obj['warehouse_id'] = $request['warehouse_id']?? 0;
                $obj['warehouse_name'] = $request['warehouse_name']?? 0;
                $obj['remarks'] = $request['remarks'];
                $obj['attachments'] = $request['attachments'];
                $obj['status'] = $request['status'];

                // Update MaterialRequestion with MaterialRequestion id
                if ($request->has('id') && $request['id'] > 0) {

                    $requisition = MaterialRequestion::where('id', $request['id'])->first();
                    $requisition->update($obj);

                    MaterialRequestionItem::where('requestion_id',$request['id'])->delete();

                    $requisitionItem=new MaterialRequestionService;
                    $requisitionItem->materialRequestionItem($request,$requisition);

                    return response()->json(['success' => true, 'message' => 'MaterialRequestion updated successfully', 'requisition' => $requisition], 200);

                } else {
                    // Creating new MaterialRequestion
                    $requisition = MaterialRequestion::create($obj);
                    
                    $requisitionItem=new MaterialRequestionService;
                    $requisitionItem->materialRequestionItem($request,$requisition);

                    $module='material_request';

                    // Update Sequence
                    $sequence=new SequenceService;
                    $sequence->updateSequence($module);

                    return response()->json(['success' => true, 'message' => 'MaterialRequestion  created successfully', 'requisition' => $requisition], 200);
                }
            } catch (\Exception $e) {
                return response()->json(['success' => false, 'message' => 'Failed to create MaterialRequestion ', 'error' => $e->getMessage()], 500);
            }
            
        }
    }

    public function requisition_list(Request $request){

        try{

            $requisition=MaterialRequestion::with('entry_by','order')->where('rolledback',0);

            if($request['search']!=null && $request['search']!=''){

                $requisition = $requisition->where(function ($q) use ($request) {
                    $q->where('requestion_id', 'LIKE', '%' . $request['search'] . '%')
                    ->orWhere('warehouse_name', 'LIKE', '%' . $request['search'] . '%')
                    ->orWhere('item_name', 'LIKE', '%' . $request['search'] . '%');
                    // ->orWhereHas('order_id',function($q) use ($search){
                    //     $q->where('order_id', 'LIKE', '%' . $search . '%');
                    // });
                });
            }

                // get custom_date 
            if ($request['custom_date']!='' && isset($request['custom_date'])) {
                $customDate = $request->custom_date;
                $requisition = $requisition->whereDate('date', $customDate);
            }

            if ($request['status']!='' && isset($request['status'])) {
                $status = $request->status;
                $requisition = $requisition->where('status', $status);
            }

            if ($request['warehouse_id']!='' && isset($request['warehouse_id'])) {
                $warehouse = $request->warehouse_id;
                $requisition = $requisition->where('warehouse_id', $warehouse);
            }

            if ($request['custom_date']!='' && isset($request['custom_date'])) {

                $customDate = $request->custom_date;
    
                $requisition = $requisition->whereDate('date', $customDate);
    
            }
    
            if ($request['from_date']!='' && isset($request['to_date'])) {
    
                $fromDate = $request->from_date;
    
                $toDate = $request->to_date;
    
                // 'fromDate' and 'toDate'
                $requisition = $requisition->whereBetween('date', [$fromDate, $toDate]);
    
            }

            // Count all the items
            $requisition_count=$requisition->count();

            if(isset($request['sort_by']) && $request['sort_by']!='' && $request['sort_by']!=null){
                
                $sort_order=$request['sort_order']==1?'asc':'desc';
    
                $requisition = $requisition->orderby($request['sort_by'],$sort_order);
    
            }else{
                $requisition = $requisition->orderby('id','desc');
            }

            // Pagination
            $requisition=$requisition->skip($request['noofrec']*($request['currentpage']-1))->take($request['noofrec']??100)
                // ->orderBy('id','desc')
                ->get();

        }catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return [
                'success' => false,
                'message' => 'MaterialRequestion Raw not found'
            ];
        }
            
        $response=[
            'success'=>true,
            'count'=>$requisition_count,
            'requisition'=>$requisition,
            'message'=>'MaterialRequestion List Fetch Successfully'
        ];

        return response()->json($response, 200);
        
    }

    public function requisition_delete(Request $request){

        $user=Auth::user();
        // Validate Item
        $validator=validator($request->all(),[
           'requestion_id'=>'required|integer'
       ]);

       if ($validator->fails()) { 
           return [
               'success' => false, 
               'message' => $validator->errors()->first(),
           ];

       } else {

           try{
               $requisition = MaterialRequestion::where('id',$request->input('requestion_id'))->first();
               $requisitionItem = MaterialRequestionItem::where('requestion_id',$request->input('requestion_id'))->first();

               if($requisition['status']=='Pending'){
                    $requisition['rolledback']=1;
                    $requisition->update();
                    
                    $requisitionItem['rolledback']=1;
                    $requisitionItem->update();

                    $response=[
                        'success'=>true,
                        'message'=>'MaterialRequestion Deleted successfully.'
                    ];
               }else{
                    $response=[
                        'success'=>false,
                        'message'=>'You can not Delete MaterialRequestion in Partially and Completed Status.'
                    ];
               }
               
           } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
               // Return error message in JSON if ID not found
               return response()->json(['success'=>false,'message' => 'Invalid Id found'], 404);
           }

           return response()->json($response);

       }
    }

    public function requisition_show(Request $request)
    {
        $validator=validator($request->all(),[
            'requestion_id'=>'required'
        ]);

        if ($validator->fails()) { 

            return [
                'success' => false, 
                'message' => $validator->errors()->first()
            ];

        } else {

            $requestion_id = $request->requestion_id;

            $requisition =  MaterialRequestion::where('id', $requestion_id)
                            ->with('requisition_items','order')
                            ->first();

            $response = [
                'message'=>'Requisition Details Listed Successfully',
                'success'=>true,
                'requisition' => $requisition,
            ];

            return response()->json($response, 200);
        }
    }


    // Display all the list of items to be approved from accounts
    public function requestion_approval_list(Request $request){
     
        $material_request=MaterialRequestionItem::where('rolledback',0)
            ->with('item','material_request');

        if($request['search']!=null && $request['search']!=''){

            $material_request = $material_request->where(function ($q) use ($request) {
                $q->where('requestion_id', 'LIKE', '%' . $request['search'] . '%')
                // ->orWhere('warehouse_name', 'LIKE', '%' . $request['search'] . '%')
                ->orWhere('item_name', 'LIKE', '%' . $request['search'] . '%');
            });
        }
        if($request['status']!=null && $request['status']!=''){
            $material_request=$material_request->where('status',$request['status']);
        }

        if ($request['custom_date']!='' && isset($request['custom_date'])) {

            $customDate = $request->custom_date;

            // $material_request = $material_request->whereDate('date', $customDate);
            $material_request= $material_request->whereHas('material_request',function($query) use ($customDate){
                $query->whereDate('date', $customDate);
            });

        }

        if ($request['from_date']!='' && isset($request['to_date'])) {

            $fromDate = $request->from_date;

            $toDate = $request->to_date;

            // 'fromDate' and 'toDate'
            // $material_request = $material_request->whereBetween('date', [$fromDate, $toDate]);
            $material_request= $material_request->whereHas('material_request',function($query) use ($fromDate, $toDate){
                $query->whereBetween('date', [$fromDate, $toDate]);
            });
        }

        // Count all the items
        $material_request_count=$material_request->count();

        if(isset($request['sort_by']) && $request['sort_by']!='' && $request['sort_by']!=null){
                
            $sort_order=$request['sort_order']==1?'asc':'desc';

            $material_request = $material_request->orderby($request['sort_by'],$sort_order);

        }else{
            $material_request = $material_request->orderby('id','desc');
        }

        // Pagination
        $material_request=$material_request->skip($request['noofrec']*($request['currentpage']-1))->take($request['noofrec']??100)
            // ->orderBy('id','desc')
            ->get();

        foreach ($material_request as $key => $value) {
            $to_be_receive=MaterialRequestionApprove::where('requestion_item_id',$value['id'])
            ->where('is_received',0)
            ->sum('quantity');

            $value['to_be_received']=$to_be_receive;
        }

        $response=[
            'success'=>true,
            'count'=>$material_request_count,
            'material_request_item'=>$material_request,
            'message'=>'Material Requestion List Fetch Successfully'
        ];

        return response()->json($response, 200);
    }


    // Request of Order Approval from the accounts
    public function requisition_approval(Request $request){
        $user=Auth::user();
        // Validate Item
        $validator=validator($request->all(),[
           'requestion_item_id'=>'required|integer',
           'warehouse_id'=>'required|integer',
           'item_id'=>'required|integer',
           'transaction_date'=>'required',
           'quantity'=>'required' 
       ]);

       if ($validator->fails()) { 
           return [
               'success' => false, 
               'message' => $validator->errors()->first(),
           ];

       } else {

            try{

                $obj['requestion_item_id']=$request['requestion_item_id'];
                $obj['item_id']=$request['item_id']??0;
                $obj['transaction_date']=$request['transaction_date'];
                $obj['unit_id']=$request['unit_id']??0;
                $obj['warehouse_id']=$request['warehouse_id']??0;
                $obj['zone_id']=$request['zone_id']??0;
                $obj['rack_id']=$request['rack_id']??0;
                $obj['bin_id']=$request['bin_id']??0;
                $obj['goods_condition_type']=1;
                $obj['quantity']=$request['quantity']??0;   //Approved Quantity
                $obj['remarks']=$request['remarks'];
                $obj['upload_documents']=$request['upload_documents'];

                $requisition_item = MaterialRequestionItem::where('id',$request->input('requestion_item_id'))->first();

                if($requisition_item['quantity']==$request['quantity']){
                    $requisition_item['status']='Approved';
                }else if($requisition_item['quantity']>$request['quantity']){
                    $requisition_item['status']='Partially Approved';
                }

                // Creating Transaction of approved order
                $transaction=MaterialRequestionApprove::create($obj);

                // Update existing quantity
                $requisition_item['approved_qty']=intval($requisition_item['approved_qty']) + intval($request['quantity']);

                //Update status of the Requestion item
                if($requisition_item['quantity']==$requisition_item['approved_qty']){
                    $requisition_item['status']='Completed';
                }else if($requisition_item['quantity']>$requisition_item['approved_qty']){
                    $requisition_item['status']='Partially Approved';
                }

                $requisition_item->update();

                // check status for all items and update Requestion status
                $all_material_items=MaterialRequestionItem::where('requestion_id',$requisition_item['requestion_id'])->get();

                $check_stat=false;
                foreach ($all_material_items as $key => $value) {
                    if($value['status']!='Completed'){
                        $check_stat=true;
                        break;
                    }
                }

                if($check_stat){
                    $requestion=MaterialRequestion::where('id',$requisition_item['requestion_id'])->first();
                    $requestion['status']='Partially';
                    $requestion->update();
                }else{
                    $requestion=MaterialRequestion::where('id',$requisition_item['requestion_id'])->first();
                    $requestion['status']='Completed';
                    $requestion->update();
                }

                //Set Item move to store
                $item=Item::where('id',$request['item_id'])->lockForUpdate()->first();
                if($item){
                    $item['in_store']=1; // Set item in store
                    $item->update();
                }

                // Saving Stock Entries
                $stockEntryService = new StockEntryService;
                $stockEntryService->mannualStockMove($request,$transaction,StaticMaster::$MANUFACTURING_TRANSFER,2);
                
                $response=[
                    'success'=>true,
                    'message'=>'MaterialRequestion Approved successfully.',
                    'material_request_approval'=>$transaction
                ];

            } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
               // Return error message in JSON if ID not found
               return response()->json(['message' => 'Invalid Id found'], 404);
           }

           return response()->json($response);

       }
    }


    // request receive from the manufacturing to the default store
    public function requisition_receive(Request $request){

        $user=Auth::user();
        // Validate Item
        $validator=validator($request->all(),[
           'transaction_date'=>'required',
           'requestion_item_id'=>'required',
           'item_id'=>'required',
           'fy'=>'required',
           'quantity'=>'required'
        ]);

        if ($validator->fails()) { 
            return [
                'success' => false, 
                'message' => $validator->errors()->first(),
            ];

        } else {

            //We are treating item level wise from requestion item table
            $obj['transaction_date']=$request['transaction_date'];
            $obj['transaction_id']=$request['requestion_item_id']??0;
            $obj['item_id']=$request['item_id']??0;
            $obj['unit_id']=$request['unit_id']??0;
            $obj['store_id']=1;    //default store 
            $obj['fy']=$request['fy'];
            $obj['quantity']=$request['quantity']??0;
            $obj['transaction_type']=StaticMaster::$MANUFACTURING_TRANSFER;
            $obj['taken_by']=$request['taken_by'];
            $obj['issued_by']=$request['issued_by'];
            $obj['vehicle_no']=$request['vehicle_no'];
            $obj['driver_name']=$request['driver_name'];
            $obj['driver_contact']=$request['driver_contact'];
            $obj['attachments']=$request['attachments'];
            $obj['notes']=$request['notes'];
            $obj['inout']=1;

            // Stock added in store
            $store=ManufacturingStore::create($obj);

            //Updating stock value from the source end i.e. requestion item table
            $material_item=MaterialRequestionItem::where('id',$request['requestion_item_id'])->first();

            if($material_item){
                //Updating the received quantity and status on requestion item table
                $material_item['received_qty']=$material_item['received_qty'] + $request['quantity'];

                if($material_item['quantity']==$material_item['received_qty']){

                    $material_item['status']='Completed';

                }else{
                    $material_item['status']='Partially Received';
                }

                $material_item->update();
            }

            // checking the all status in Requestion Item Table
            $check_stat=false;
            $all_material_items=MaterialRequestionItem::where('requestion_id',$material_item['requestion_id'])->get();

            if(!$all_material_items->isEmpty()){
                
                foreach ($all_material_items as $key => $value) {
                    if($value['status']!='Completed'){
                        $check_stat=true;
                        break;
                    }
                }

                if($check_stat){
                    $requestion=MaterialRequestion::where('id',$material_item['requestion_id'])->first();
                    $requestion['status']='Partially';
                    $requestion->update();
                }else{
                    $requestion=MaterialRequestion::where('id',$material_item['requestion_id'])->first();
                    $requestion['status']='Completed';
                    $requestion->update();
                }
            }else{
                $requestion=MaterialRequestion::where('id',$material_item['requestion_id'])->first();
                $requestion['status']='Partially';
                $requestion->update();
            }


            // Updating Store quantity in item table
            $item=Item::where('id',$request['item_id'])->first();

            if($item){
                $item['manufacturing_store']=$item['manufacturing_store']+$request['quantity'];

                $item->update();
            }

            $response=[
                'success'=>true,
                'message'=>'Stock Received successfully',
            ];
            
            return response()->json($response);
        }
    }
}
