<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Helpers\HelperController;
use App\Http\Controllers\Helpers\SMSController;
use App\Http\Controllers\Mails\EmailsController;
use App\Http\Controllers\Service\ServiceController;
use App\Http\Resources\AssignedClerksResource;
use App\Models\Location;
use App\Models\Location_clerks;
use App\Models\Material;
use App\Models\Plant;
use App\Models\Stage;
use App\Models\Stock_take;
use App\Models\Stock_take_material;
use App\Models\User;
use App\Models\Workflow;
use Illuminate\Http\Request;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Support\Facades\Auth;

class StockTakeController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //get stocks
        $user = Auth::user();
        if ($user->hasRole('Plant Accountant|Plant Controller|Plant Manager')) {
            $stocks = Stock_take::where([['plant_code', $user->plant_code], ['status', 'active']])->with(['plants', 'locations'])->latest()->get();
        } else {
            $stocks = Stock_take::with(['plants', 'locations'])->latest()->get();
        }
        $plant = Plant::where('plant_code', $user->plant_code)->first();
        return view('stock.index', compact('stocks', 'plant'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $user = Auth::user();
        $plant = Plant::where('plant_code', $user->plant_code)->first();
        $locations = Location::where('plant_code', $user->plant_code)->get();
        return view('stock.create', compact('plant', 'locations'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        try {
            $user = Auth::user();
            $url = '196.41.87.26/stock-take-test/initiate';
            $token = $user->token;
            $stock_take_date = date('Y-m-d', strtotime($request->stocktake_proposed_date));
            $month = date('Y-m', strtotime($request->stocktake_proposed_date));

            //locations to be initiated
            $location_codes = $request->location_codes;

            //locations already initiated
            $locations_already_initiated = array();

            //locations failed to initiate
            $locations_failed_to_initiate = array();

            //locations successfully initiated
            $locations_initiated = array();

            //loop through each location code initiating
            foreach ($location_codes as $location_code) {

                $check = Stock_take::where([['month', $month], ['storage_location_code', $location_code]])->first();

                if(!$check){

                    //post to sap
                    $company = Plant::where('plant_code', $request->plant_code)->first();

                    $data = [
                        'company_code' => $company->company_code,
                        'stocktake_proposed_date' => $stock_take_date,
                        'plant_code' => $request->plant_code,
                        'storage_location_code' => $location_code
                    ];

                    $response = HelperController::auth_http_post_request($url, $data, $token);

                    if($response->status == 200){

                        //save to local db
                        Stock_take::create(array_merge($data, ['month' => $month, 'stocktake_proposed_date' => $stock_take_date]));

                        //location initiated successfully
                        $locations_initiated[] = $location_code;

                    } else{

                        $locations_failed_to_initiate[] = $location_code;

                    }


                } else{

                    //locations already initiated
                    $locations_already_initiated[] = $location_code;
                }

            }

            if(!empty($locations_initiated)){

                $imploded_locations = implode(",", $locations_initiated);

                $res = [
                    'status' => 200,
                    'message' => 'Stock take for these locations '.$imploded_locations.' initiated successfully!',
                    // 'res' => $res
                ];

            } else if(!empty($locations_failed_to_initiate)){

                $imploded_locations = implode(",", $locations_failed_to_initiate);

                $res = [
                    'status' => 500,
                    'message' => 'Stock take for these locations '.$imploded_locations.' failed to initiate!',
                    // 'res' => $res
                ];

            } else {

                $imploded_locations = implode(",", $locations_already_initiated);

                $res = [
                    'status' => 500,
                    'message' => 'Stock take for these locations '.$imploded_locations.' already initiated!',
                    // 'res' => $res
                ];

            }

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

            //check if stock is initiated
            // $check = Stock_take::where([['month', $month], ['storage_location_code', $request->storage_location_code]])->first();
            // if ($check) {
            //     $res = [
            //         'status' => 500,
            //         'message' => 'Stock already initiated for the selected location!'
            //     ];
            //     return response()->json($res, 500);
            // } else {
            //     //post to Sap
            //     $company = Plant::where('plant_code', $request->plant_code)->first();
            //     $data = [
            //         'company_code' => $company->company_code,
            //         'stocktake_proposed_date' => $stock_take_date,
            //         'plant_code' => $request->plant_code,
            //         'storage_location_code' => $request->storage_location_code
            //     ];
            //     $res = HelperController::auth_http_post_request($url, $data, $token);

            //     // dd($res);
            //     switch ($res->status) {
            //         case '200':
            //             Stock_take::create(array_merge($data, ['month' => $month, 'stocktake_proposed_date' => $stock_take_date]));
            //             // workflow table
            //             $res = [
            //                 'status' => 200,
            //                 'message' => 'Stock take initiated successfully!',
            //                 'res' => $res
            //             ];
            //             return response()->json($res, 200);
            //             break;

            //         default:
            //             $res = [
            //                 'status' => 500,
            //                 'message' => 'Something went wrong!'
            //             ];
            //             return response()->json($res, 200);
            //             break;
            //     }
                
            // }
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'message' => $th->getMessage(),
            ];
            return response()->json($res, 500);
        }
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $header = "";
        $items = [];
        $user = Auth::user();
        $token = $user->token;
        //fetch stock materials
        $stock = Stock_take::findOrFail($id);
        $url = '196.41.87.26/stock-take-test/inventory?plant_code=' . $stock->plant_code . '&storage_location_code=' . $stock->storage_location_code . '';

        //dd($url);
        $res = HelperController::auth_http_get_request($url, $token);

        switch ($res->status) {
            case '200':
                $header = $res->message->header;
                $items = $res->message->items;
                if (count($items) > 0) {
                    //save materials
                    ServiceController::save_materials($header, $items);
                    $response = $this->confirm_materials($header->storage_location_code, $header->doc_no, $items);
                    $mes = "";
                    switch ($response["status"]) {
                        case 'exists':
                            $mes = $response["message"];
                            # code...
                            break;
                        case 'success':
                            $mes = $response["message"];
                            break;
                        case 'error':
                            $mes = $response["message"];
                        default:
                            $mes = $response["message"];
                            break;
                    }
                    $res = [
                        'status' => 200,
                        'response' => $mes,
                    ];
                    return response()->json($res, 200);
                } else {
                    $res = [
                        'status' => 500,
                        'response' => 'No materials found for this location, try again later',
                    ];
                    return response()->json($res, 500);
                }
                break;
            case '403':
                Auth::logout();
                return redirect()->route('login.index');
            default:
                return view('stock.add-materials', compact('header', 'items'));
                break;
        }
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * 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 fetch()
    {
        try {
            $user = Auth::user();
            if ($user->hasRole('Plant Accountant|Plant Controller|Plant Manager')) {
                $stocks = Stock_take::where([['plant_code', $user->plant_code], ['status', 'active']])->with(['plants', 'locations', 'clerks'])->latest()->get();
            } else {
                $stocks = Stock_take::with(['plants', 'locations', 'clerks'])->latest()->get();
            }
            $res = [
                'status' => 200,
                'stocks' => $stocks
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'stocks' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }


    public function clerks()
    {
        try {
            // $clerks = User::with(['assigned_locations' => function ($q) {
            //     return $q->where('status', 'active');
            // }])->get();
            $clerks = User::where([['status', 'active'], ['role', 'counting_clerk']])->get();
            $res = [
                'status' => 200,
                'clerks' => AssignedClerksResource::collection($clerks)
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 200,
                'clerks' => $th->getMessage()
            ];
            return response()->json($res, 200);
        }
    }

    public function otherClerks()
    {
        try {
            // $clerks = User::with(['assigned_locations' => function ($q) {
            //     return $q->where([['status', 'active'], ['role', 'counting_clerk']]);
            // }])->get();
            $clerks = User::where([['status', 'active'], ['role', '!=', 'counting_clerk']])->get();
            $res = [
                'status' => 200,
                'clerks' => AssignedClerksResource::collection($clerks)
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'clerks' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }

    public function assign_clerk(Request $request)
    {

        try {
            $user = Auth::user();
            $clerk = User::where('id', $request->clerk_id)->first();
            $location = Location::where('storage_location_code', $request->location_code)->first();

            $stock_take = Stock_take::where('id', $request->stock_take_id)->first();
            $plant = Plant::where('plant_code', $request->plant_code)->first();
            $check_assigned = Location_clerks::where([['user_id', $request->clerk_id], ['status', 'active']])->latest()->first();
            if ($check_assigned) {

                //check if plant is different
                if ($check_assigned->plant_code !== $stock_take->plant_code) {
                    $res = [
                        'status' => 500,
                        'response' => 'Clerk already assigned to another plant'
                    ];
                    return response()->json($res, 500);
                }
                if ($check_assigned->team !==  $request->team_id && $check_assigned->location_code !== $request->location_code ) {
                    $res = [
                        'status' => 500,
                        'response' => 'Clerk can only be assigned to one team in one location'
                    ];
                    return response()->json($res, 500);
                }

                if ($check_assigned->team_lead == '1' && !is_null($request->team_lead) && $check_assigned->location_code == $request->location_code) {

                    //before logic
                    // && !is_null($request->team_lead)
                    $res = [
                        'status' => 500,
                        'response' => 'A team can only have one team lead here'
                    ];
                    return response()->json($res, 500);
                }
            }
            $check_leads = Location_clerks::where([['user_id', $request->clerk_id], ['location_code', $request->location_code], ['team', $request->team_id], ['team_lead', '1'], ['status', 'active']])->latest()->first();
            if ($check_leads) {
                $res = [
                    'status' => 500,
                    'response' => 'A team can only have one team lead',
                ];
                return response()->json($res, 500);
            }

            if(Location_clerks::where([['team_lead', "1"], ['location_code', $request->location_code], ['team', $request->team_id]])->first() != null && $request->team_lead == true){

                // SQLSTATE[42S22]: Column not found: 1054 Unknown column '0' in 'where clause' (SQL: select * from `location_clerks` where (`0` = team_lead and `1` = 1) limit 1)

                $res = [
                    'status' => 500,
                    'response' => 'A team can only have one team lead',
                ];
                return response()->json($res, 500);

            }
            $data = [
                'user_id' => $request->clerk_id,
                'stock_take_id' => $request->stock_take_id,
                'location_code' => $request->location_code,
                'stock_take_date' => $stock_take->month,
                'plant_code' => $request->plant_code,
                'team' => $request->team_id,
                'team_lead' => $request->team_lead ? '1' : '0',
            ];
            $message = 'Dear ' . $clerk->name . ', you have been assigned to location ' . $location->storage_location_code . ' ~ ' . $location->storage_location_name . ' to participate in stock take process on ' . $this->pretty_date($stock_take->stocktake_proposed_date);
            $check = Location_clerks::where([['stock_take_id', $request->stock_take_id], ['user_id', $request->clerk_id], ['status', 'active']])->first();
            if ($check) {

                $res = [
                    'status' => 500,
                    'response' => 'Clerk already assigned to this location'
                ];
                return response()->json($res, 500);
            } elseif ($stock_take->doc_no == null) {
                $res = [
                    'status' => 500,
                    'response' => 'Please confirm the materials for this location first!'
                ];
                return response()->json($res, 500);

            } else {

                $clerks = Location_clerks::where([['stock_take_id', $request->stock_take_id], ['location_code', $request->location_code], ['status', 'active']])->get();


                Location_clerks::create(array_merge($data));
                //sent email
                EmailsController::stock_take_mail($clerk->email, $message);
                //send sms
                SMSController::send_sms($clerk->phone, $message);
                $res = [
                    'status' => 200,
                    'response' => 'Clerk assigned successfully!'
                ];
                return response()->json($res, 200);
            }
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'response' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }

    public function fetch_all()
    {
        try {
            $users = User::latest()->get();
            $res = [
                'status' => 200,
                'users' => $users
            ];
            return response()->json($res, 200);
        } catch (\Throwable $th) {
            $res = [
                'status' => 500,
                'users' => $th->getMessage()
            ];
            return response()->json($res, 500);
        }
    }

    private function pretty_date($date)
    {
        return date('M d, Y', strtotime($date));
    }

    private function confirm_materials($location_code, $doc_no, $materials)
    {
        try {
            $check = Stock_take::where([['status', 'active'], ['storage_location_code', $location_code]])->first();
            if ($check) {
                $exist = Stock_take_material::where('stock_take_id', $check->id)->first();
                if ($exist) {
                    // Toastr::error('Stock Take already initiated!', 'Failed');
                    $res = [
                        'status' => 'exists',
                        'message' => 'Materials are already confirmed'
                    ];
                    return $res;
                } else {
                    $check->update(['doc_no' => $doc_no, 'mat_status' => '1']);
                    foreach ($materials as $key => $m) {
                        $material = Material::where('material_no', $m->material_no)->first();
                        //save materials
                        $mat = new Stock_take_material();
                        $mat->company_code = $check->company_code;
                        $mat->plant_code = $check->plant_code;
                        $mat->location_code = $check->storage_location_code;
                        $mat->stock_take_id = $check->id;
                        $mat->material_no = $m->material_no;
                        $mat->doc_no = $doc_no;
                        $mat->unit_price = $m->unit_price;
                        $mat->unit_of_measure = $m->unit_of_measure;
                        $mat->sap_stock = $material->sap_stock;
                        $mat->material_group_code = $material->material_group_code;
                        $mat->material_type_code = $material->material_type_code;
                        $mat->save();
                    }
                    $data = [
                        'plant_code' => $check->plant_code,
                        'stock_take_date' => $check->stocktake_proposed_date,
                    ];
                    //create stage
                    $find = Stage::where([['plant_code', $check->plant_code], ['status', 'active']])->first();
                    if (is_null($find)) {
                        Stage::create(array_merge($data));
                    }
                    //create workflow
                    $workflow = Workflow::where([['plant_code', $check->plant_code], ['status', 'active']])->first();
                    if (is_null($workflow)) {
                        Workflow::create(array_merge($data));
                    }

                    $res = [
                        'status' => 'success',
                        'message' => 'Materials confirmed successfully!',
                    ];
                    return $res;
                }
            } else {
                $res = [
                    'status' => 'error',
                    'message' => 'Something went wrong!',
                ];
                return $res;
            }
        } catch (\Throwable $th) {
            $res = [
                'status' => 'success',
                'message' => $th->getMessage(),
            ];
            return $res;
        }
    }
}