<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Helpers\HelperController;
use App\Http\Controllers\Helpers\NotificationController;
use App\Http\Controllers\Helpers\SMSController;
use App\Http\Resources\ActionPlanResource;
use App\Http\Resources\CommentsResource;
use App\Http\Resources\LocationsResource;
use App\Http\Resources\LocationsWorkflowResource;
use App\Http\Resources\MaterialResource;
use App\Http\Resources\MyCommentResource;
use App\Http\Resources\StocksResource;
use App\Http\Resources\SummaryResource;
use App\Models\Action_plan;
use App\Models\Company;
use App\Models\Stage;
use App\Models\Location;
use App\Models\Location_comment;
use App\Models\Material_comment;
use App\Models\Material_type;
use App\Models\People;
use App\Models\Plant;
use App\Models\Stock_take;
use App\Models\Stock_take_material;
use App\Models\User;
use App\Models\Workflow;
use App\Models\Comment_tag;
use App\Models\Workflow_comment;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class WorkFlowController extends Controller
{
    private $request_code;
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $user_active_plants = [];
        $user = Auth::user();
        $types = Material_type::all();
        $role = HelperController::user_role();
        return view('workflow.index', compact('user', 'types', 'role'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        return view('workflow.index');
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        return view('workflow.stocks.material-stock');
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }


    public function get_stocks($date, $code)
    {
        $stocks = Stock_take_material::where([['storage_location_code', $code], ['proposed_date', $date]])->get();
        $location = Location::where('storage_location_code', $code)->first();
        return view('workflow.stocks.material-stock', compact('stocks', 'location'));
    }

    public function save_location_comments(Request $request)
    {
        try {
            $id = $request->mat_id;
            $variance = $request->variance;
            $stock = Location_comment::where('material_id', $id)->first();
            $stock = Location_comment::updateOrCreate([
                'material_id' => $id,
                'comment'  => $variance
            ]);
            $results = [
                'status' => 200,
                'message' => 'Comment saved successfully!'
            ];
            return response()->json($results);
        } catch (\Throwable $th) {
            return $th;
            $results = [
                'status' => 500,
                'message' => 'Some error occured'
            ];
            return response()->json($results);
        }
    }

    public function fetch_comment($id)
    {
        try {
            $material = Stock_take_material::where('id', $id)->first();
            $comment = Location_comment::where('material_id', $id)->first();
            $results = [
                'status' => 200,
                'comment' => $comment,
                'material' => $material->material_name
            ];
            return response()->json($results);
        } catch (\Throwable $th) {
            $results = [
                'status' => 500,
                'comment' => 'Something went wrong'
            ];
            return response()->json($results);
        }
    }

    public function fetch_plant_level()
    {
        try {
            $user = Auth::user();
            $locations = Stock_take::where([['plant_code', $user->plant_code], ['status', 'active']])->whereNotNull('doc_no')->with(['locations'])->get();
            $stocks = Stock_take_material::groupBY('material_type_code')
                ->with('stock_takes')
                ->whereRelation('stock_takes', 'status', 'active')
                ->where('plant_code', $user->plant_code)
                ->select('material_type_code', DB::raw('sum(current_stock) as total_current'), DB::raw('sum(sap_stock) as total_sap'), DB::raw('sum(unit_price) as total_price'))
                ->with(['types'])
                ->get();
            $comments = $this->fetch_other_comments();
            $my_comment = $this->fetch_my_comment();

            // dd($stocks);
            $res = [
                'status' => 200,
                'locations' => $locations,
                'stocks' => StocksResource::collection($stocks),
                'my_comments' => $my_comment ? MyCommentResource::collection($my_comment->comments) : "",
                'other_comments' => CommentsResource::collection($comments->comments),
                'workflow' => HelperController::track_workflow($user->plant_code),
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'response' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }
    public function fetch_plant_controller_level(Request $request)
    {
        try {
            $locations = Stock_take::where([['plant_code', $request->plant_code], ['status', 'active']])->whereNotNull('doc_no')->with(['locations'])->get();
            $stocks = Stock_take_material::groupBY('material_type_code')
                ->with('stock_takes')
                ->whereRelation('stock_takes', 'status', 'active')
                ->where('plant_code', $request->plant_code)
                ->select('material_type_code', DB::raw('sum(current_stock) as total_current'), DB::raw('sum(sap_stock) as total_sap'), DB::raw('sum(unit_price) as total_price'))
                ->with(['types'])
                ->get();
            $comments = $this->fetch_other_comments();
            $my_comment = $this->fetch_my_comment();
            $res = [
                'status' => 200,
                'locations' => $locations,
                'stocks' => StocksResource::collection($stocks),
                'my_comments' => $my_comment ? MyCommentResource::collection($my_comment->comments) : "",
                'other_comments' => $comments ? CommentsResource::collection($comments->comments) : [],
                'workflow' => HelperController::track_workflow($request->plant_code),
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'response' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }

    public function fetch_my_comment()
    {
        $user = Auth::user();
        if ($user->hasRole('Plant Accountant')) {
            return Stage::where([['plant_code', $user->plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', 'plant_accountant');
                })
                ->latest()->first();
        } elseif ($user->hasRole('Plant Controller')) {
            return Stage::where([['plant_code', $user->plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', 'plant_controller');
                })
                ->latest()->first();
        } elseif ($user->hasRole('Plant Manager')) {
            return Stage::where([['plant_code', $user->plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', 'plant_manager');
                })
                ->latest()->first();
        }
    }

    public function fetch_other_comments()
    {
        $user = Auth::user();
        if ($user->hasRole('Plant Controller')) {
            return Stage::where([['plant_code', $user->plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', '!=', 'plant_controller');
                })
                ->latest()->first();
        } elseif ($user->hasRole('Plant Manager')) {
            return Stage::where([['plant_code', $user->plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', '!=', 'plant_manager');
                })
                ->latest()->first();
        } elseif ($user->hasRole('Plant Accountant')) {
            return Stage::where([['plant_code', $user->plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', '!=', 'plant_accountant');
                })
                ->latest()->first();
        }
    }

    public function view_location_stocks($location_code)
    {
        try {
            if (!$location_code) {
                $materials = [];
                $res = [
                    'status' => 500,
                    'response' => 'Please select location'
                ];
                return response()->json($res, 500);
            } else {
                $location = Location::where('storage_location_code', $location_code)->first();
                $stock_take = Stock_take::where([['storage_location_code', $location_code], ['status', 'active']])->first();
                $materials = Stock_take_material::where('stock_take_id', $stock_take->id)->with(['materials', 'comments'])->get();
                $res = [
                    'status' => 200,
                    'location' => $location,
                    'stock_take' => $stock_take,
                    'materials' => MaterialResource::collection($materials)
                ];
                return response()->json($res, 200);
            }
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'response' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }

    public function load_by_type(Request $request)
    {
        try {
            $materials = Stock_take_material::where('material_type_code', $request->code)->whereRelation('stock_takes', 'status', 'active')->with('material_comments')->get();
            $type = Material_type::where('material_type_code', $request->code)->first();
            $res = [
                'status' => 200,
                'materials' => MaterialResource::collection($materials),
                'type' => $type
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'materials' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }

    public function fetch_company_plants($code)
    {
        try {
            $company = Company::where('company_code', $code)->first();
            $plants = Stock_take::where([['company_code', $code], ['status', 'active']])->whereNotNull('doc_no')->with('plants')->groupBy('plant_code')->get();
            $stocks = Stock_take_material::groupBY('material_type_code')
                ->with('stock_takes')
                ->whereRelation('stock_takes', 'status', 'active')
                ->whereRelation('stock_takes', 'company_code', $code)
                ->select('material_type_code', DB::raw('sum(current_stock) as total_current'), DB::raw('sum(sap_stock) as total_sap'), DB::raw('sum(unit_price) as total_price'))
                ->with(['types'])
                ->get();
            $res = [
                'status' => 200,
                'plants' => $plants,
                'company' => $company,
                'stocks' => StocksResource::collection($stocks)
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'message' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }

    public function filter_by_plant_level($code)
    {
        try {
            $this->request_code = $code;
            $user = Auth::user();
            $plant = Plant::where('plant_code', $code)->first();
            if ($user->hasRole('Business Controller|General Manager')) {
                $locations = Stock_take::where([['company_code', $user->company_code], ['plant_code', $code], ['status', 'active']])->whereNotNull('doc_no')->with(['locations'])->get();
                $stocks = Stock_take_material::groupBY('material_type_code')
                    ->with('stock_takes')
                    ->whereRelation('stock_takes', 'company_code', $user->company_code)
                    ->whereRelation('stock_takes', 'status', 'active')
                    ->whereRelation('stock_takes', 'plant_code', $code)
                    ->select('material_type_code', DB::raw('sum(current_stock) as total_current'), DB::raw('sum(sap_stock) as total_sap'), DB::raw('sum(unit_price) as total_price'))
                    ->with(['types'])
                    ->get();
            } else if ($user->hasRole('Inventory Accountant|Finance Controller|System Admin')) {
                $locations = Stock_take::where([['plant_code', $code], ['status', 'active']])->whereNotNull('doc_no')->with(['locations'])->get();
                $stocks = Stock_take_material::groupBY('material_type_code')
                    ->with('stock_takes', function ($q) {
                        $q->where([['status', 'active'], ['plant_code', $this->request_code]]);
                    })
                    ->select('material_type_code', DB::raw('sum(current_stock) as total_current'), DB::raw('sum(sap_stock) as total_sap'), DB::raw('sum(unit_price) as total_price'))
                    ->with(['types'])
                    ->get();
            }
            $other_comments = $this->fetch_global_other_comments($code);
            $mine = $this->fetch_global_my_comment($code);
            $res = [
                'status' => 200,
                'locations' => $locations,
                'my_comments' => $mine ? MyCommentResource::collection($mine->comments) : "",
                'other_comments' => CommentsResource::collection($other_comments->comments),
                'plant' => $plant->plant_name,
                'stocks' => StocksResource::collection($stocks),
                'workflow' => HelperController::track_workflow($code)
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'message' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }

    public function company_level()
    {
        try {
            $stocks = Stock_take_material::groupBY('material_type_code')
                ->with('stock_takes')
                ->whereRelation('stock_takes', 'status', 'active')
                ->select('material_type_code', DB::raw('sum(current_stock) as total_current'), DB::raw('sum(sap_stock) as total_sap'), DB::raw('sum(unit_price) as total_price'))
                ->with(['types'])
                ->get();
            $res = [
                'status' => 200,
                'stocks' => StocksResource::collection($stocks)
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'stocks' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }
    public function fetch_locations()
    {
        try {
            $user = Auth::user();
            $assigned_locations = People::where('user_id', $user->id)->whereNotNull('location_code')->get();
            $locs = [];
            foreach ($assigned_locations as $key => $loc) {
                $get_stock = Stock_take::where([['storage_location_code', $loc->location_code], ['status', 'active']])->whereNotNull('doc_no')->with('locations')->first();
                if ($get_stock) {
                    $locs[] = $get_stock;
                }
            }
            $res = [
                'status' => 200,
                'locations' => LocationsWorkflowResource::collection($locs)
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'locations' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }

    public function location_change($id)
    {
        try {
            $mats = Stock_take_material::where([['stock_take_id', $id], ['sap_variance', "!=", 0]])->get();
            // $mats = Stock_take_material::where('stock_take_id', $id)->get();
            $location = Stock_take::where("id", $id)->with('locations')->first();
            $res = [
                'status' => 200,
                'location' => $location,
                'materials' => MaterialResource::collection($mats),
                'raw_materials' => $mats
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'materials' => $th->getMessage(),
            ];
            return response()->json($res, 500);
        }
    }

    //fetch comment tags
    public function comment_tags()
    {
        
        try {

            $comment_tags = Comment_tag::get();

            $res = [
                'status' => 200,
                "comment_tags" => $comment_tags,
            ];

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

        } catch (\Throwable $th) {
            
            $res = [
                'status' => 500,
                'materials' => $th->getMessage(),
            ];
            return response()->json($res, 500);
        }
    }
    //end of comment tags

    public function supervisor_comment(Request $request)
    {
        try {
            $id = $request->mat_id;
            $comment = $request->comment;
            $check = Stock_take_material::where('id', $id)->first();
            $check1 = Stock_take_material::where('stock_take_id', $check->stock_take_id)->whereNull('comment')->get();
            if (is_null($check->comment)) :
                #create
                $check->update(['comment' => $comment]);
                $this->update_supervisor_stage($check->stock_take_id);
                if (count($check1) < 1) {
                    Stock_take::findOrFail($check->stock_take_id)->update(['clerk_approval' => 'approved']);
                }
                $res = [
                    'status' => 200,
                    'response' => 'Comment added successfully!',
                ];
                return response()->json($res, 200);
            else :
                #update
                $check->update(['comment' => $comment]);
                if (count($check1) < 1) {
                    Stock_take::findOrFail($check->stock_take_id)->update(['clerk_approval' => 'approved']);
                }
                $res = [
                    'status' => 200,
                    'response' => 'Comment updated successfully!',
                ];
                return response()->json($res, 200);
            endif;


            ///check and update stage
            $this->update_supervisor_stage($check->stock_take_id);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'response' => $th->getMessage(),
            ];
            return response()->json($res, 500);
        }
    }

    public function update_supervisor_stage($id)
    {
        $stock_take = Stock_take::where('id', $id)->first();
        $active_stocks = Stock_take::where([['plant_code', $stock_take->plant_code], ['status', 'active']])->whereNotNull('doc_no')->get();
        $find_uncommented = [];
        if (count($active_stocks) > 0) {
            foreach ($active_stocks as $key => $stock) {
                $check = Stock_take::where('id', $stock->id)->with('stock_counts', function ($q) {
                    return $q->where([['comment', '=', null], ['sap_variance', '!=', 0]]);
                })->first();
                if (count($check->stock_counts) > 0) {
                    $find_uncommented[] = $check;
                }
            }
        }

        if (count($find_uncommented) < 1) {
            $user = User::where([['plant_code', $stock_take->plant_code], ['role', 'plant_accountant']])->latest()->first();
            #update stage
            $stage = Stage::where([['plant_code', $stock_take->plant_code], ['status', 'active']])->first();
            $stage->update(['level' => 'Plant Accountant']);
            #send sms
            $text = 'Dear ' . $user->name . ', It is your turn to comment on workflow';
            SMSController::send_sms($user->phone, $text);
        }
    }

    public function store_plant_comment(Request $request)
    {
        try {
            $user = Auth::user();
            $plant_code = $request->plant_code ? $request->plant_code : $user->plant_code;
            $verdict = $request->verdict;
            $current_plant = Plant::where('plant_code', $request->plant_code)->first();
            $stage = Stage::where([['plant_code', $plant_code], ['status', 'active']])->latest()->first();

            if ($stage) {
                $data = [
                    'stage_id' => $stage->id,
                    'user_id' => $user->id,
                    'comment' => $request->comment,
                ];
                $check = Workflow_comment::where([['user_id', $user->id], ['stage_id', $stage->id]])->first();
                NotificationController::handle_notifications($user, $verdict, $check, $data, $stage, $plant_code, $current_plant);
                $res = [
                    'status' => 200,
                    'response' => 'Comment saved successfully!'
                ];
                return response()->json($res, 200);
            } else {
                $res = [
                    'status' => 500,
                    'response' => 'Workflow unrecognized!'
                ];
                return response()->json($res, 500);
            }
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'response' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }

    public function fetch_global_my_comment($plant_code)
    {
        $user = Auth::user();
        if ($user->hasRole('Inventory Accountant')) {
            return Stage::where([['plant_code', $plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', 'inventory_accountant');
                })
                ->latest()->first();
        } elseif ($user->hasRole('Business Controller')) {
            return Stage::where([['plant_code', $plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', 'business_controller');
                })
                ->latest()->first();
        } elseif ($user->hasRole('Finance Controller')) {
            return Stage::where([['plant_code', $plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', 'finance_controller');
                })
                ->latest()->first();
        } elseif ($user->hasRole('General Manager')) {
            return Stage::where([['plant_code', $plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', 'general_manager');
                })
                ->latest()->first();
        }
    }

    public function fetch_global_other_comments($plant_code)
    {
        $user = Auth::user();
        if ($user->hasRole('Inventory Accountant')) {
            return Stage::where([['plant_code', $plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', '!=', 'inventory_accountant');
                })
                ->latest()->first();
        } elseif ($user->hasRole('Business Controller')) {
            return Stage::where([['plant_code', $plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', '!=', 'business_controller');
                })
                ->latest()->first();
        } elseif ($user->hasRole('Finance Controller')) {
            return Stage::where([['plant_code', $plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', '!=', 'finance_controller');
                })
                ->latest()->first();
        } elseif ($user->hasRole('General Manager')) {
            return Stage::where([['plant_code', $plant_code], ['status', '!=', 'closed']])
                ->with('comments', function ($q) {
                    $q->where('role', '!=', 'general_manager');
                })
                ->latest()->first();
        }
    }

    private function format_comment()
    {
    }

    public function store_general_comments(Request $request)
    {
        try {
            $user = Auth::user();
            $check = Material_comment::where([['stock_take_material_id', $request->id], ['user_id', Auth::id()]])->first();
            $data = [
                'stock_take_material_id' => $request->id,
                'user_id' => Auth::id(),
                'comment' => $request->comment,
                'role' => $user->role,
            ];
            if ($check) {
                $check->update(array_merge($data));
            } else {
                Material_comment::create(array_merge($data));
            }
            $res = [
                'status' => 200,
                'message' => 'Comment added successfully!',
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'message' => $th->getMessage(),
            ];
            return response()->json($res, 500);
        }
    }

    public function save_action_plan(Request $request)
    {
        try {
            $workflow = Workflow::where([['plant_code', $request->plant_code], ['status', 'active']])->first();
            foreach ($request->actions as $key => $act) {
                $data = [
                    'workflow_id' => $workflow->id,
                    'action' => $act['action'],
                    'by_who' => $act['by'],
                    'by_when' => $act['when'],
                ];
                $check = Action_plan::where([['workflow_id', $workflow->id], ['by_who', $act['by']]])->first();
                if ($check) :
                    $check->update(array_merge($data));
                else :
                    Action_plan::create(array_merge($data));
                endif;
                $user = User::findOrFail($act['by']);
                $text = 'Dear ' . $user->name . ' You are required to ' . $act['action'] . ' by ' . $act['when'];
                SMSController::send_sms($user->phone, $text);
            }
            //send sms

            $res = [
                'status' => 200,
                'message' => 'Action plan created successfully',
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'message' => $th->getMessage(),
            ];
            return response()->json($res, 500);
        }
    }

    public function fetch_action_plan(Request $request)
    {
        try {
            $workflow = Workflow::where([['plant_code', $request->plant_code], ['status', '!=', 'closed']])->first();
            $plans = Action_plan::where('workflow_id', $workflow->id)->get();
            $res = [
                'status' => 200,
                'plans' => ActionPlanResource::collection($plans),
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'message' => $th->getMessage(),
            ];
            return response()->json($res, 500);
        }
    }
}