<?php

namespace App\Http\Controllers\StockInventory\request_stock;

use App\Model\setup\BranchModel;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Model\stock_inventory\ItemRequestDetailModel;
use Auth;
use App\Fun\Fun;
use App\Model\stock_inventory\ItemRequestModel;
use App\Model\product\ProductModel;
use App\Model\product\ProductUnitModel;
use App\Model\stock_inventory\StockModel;
use App\Model\setup\WarehouseModel;
use App\Model\people\DriverModel;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
use Yajra\DataTables\DataTables;
use Illuminate\Support\Facades\Gate;

class RequestStockController extends Controller
{
    function __construct()
    {
        $this->middleware('permission:Request Stock List', ['only' => ['index']]);
        $this->middleware('permission:Request Stock Create', ['only' => ['create', 'store']]);
        $this->middleware('permission:Request Stock Show', ['only' => ['show']]);
    }

    public function index(Request $request)
    {

        if ($request->ajax()) {
            Fun::lang();
            $search = $request->input('search.value');
            $request_by = $request->request_by;
            $type = $request['type'];
            $data = ItemRequestModel::where(function ($query) use ($request_by) {
                    if ($request_by) {
                        $query->Where('nso007_item_request.request_by', $request_by);
                    }
                })
                ->where(function ($query) use ($type) {
                    $branch_id = Auth::user()->branch_id;
                    if ($type === 'stock_in') {
                        $query->where('branch_id', $branch_id);
                        $query->where('confirm_status', 1);
                    } elseif ($type === 'purchase_list') {
                        $query->where('branch_id', $branch_id);
                    } elseif ($type === 'request_order') {
                        $query->where('request_to', $branch_id);
                    } else {
                        $query->where('branch_id', 'no_data');
                    }
                })
                ->where(function ($query) use ($search) {
                    $query->orWhere('nso007_item_request.invoice_number', 'LIKE', '%' . $search . '%');
                })
                ->orderBy('nso007_item_request.id', 'DESC');
                return DataTables::of($data)
                    ->addColumn('request_by', function ($item) {
                        return findUser($item->request_by)->name;
                    })
                    ->addColumn('request_to', function ($item) {
                        return findBranch($item->request_to)->name;
                    })
                    ->addColumn('date', function ($item) {
                        return myDate($item->date);
                    })
                    ->addColumn('approve_date', function ($item) {
                        if($item->approve_date)
                        return myDate($item->approve_date);
                    })
                    ->editColumn('delivery_status', function ($item) {
                        return checkRequestStatus($item->delivery_status);
                    })
                    ->editColumn('delivery_fee', function ($item) {
                        if ($item->delivery_fee) {
                            return '$' . $item->delivery_fee;
                        }
                    })
                    ->editColumn('driver_id', function ($item) {
                        $driver = DriverModel::find($item->driver_id);
                        return $driver ? $driver->name : '';
                    })
                    ->addColumn('status', function ($item) {
                        return checkRequestStatus($item->status);
                    })
                    ->editColumn('confirm_status', function ($item) {

                        return checkRequestStatus($item->confirm_status);
                    })
                    ->addColumn('action', function ($item) use ($type) {
                        $show_item = '';
                        if (Gate::check('Request Stock Show')) {
                            $can = $item->request_to === Auth::user()->branch_id && $item->status == 0 ? 1 : 0;
                            $show_item = '<a data-href="' . route("request-stock.show", $item->id) . '"
                            data-id="' . $item->id . '"
                            data-user_id="' . $item->request_by . '"
                            data-can="' . $can . '"
                            data-status="' . $item->status . '"
                            data-confirm_status="' . $item->confirm_status . '"
                            title="' . __('administrator.show') . '"
                            class="button_info show_request">' . __('administrator.show') . '</a>';
                        }
                        if ($item->status === 0 && $item->request_by == Auth::user()->id) {
                            $show_item .= '<a href="' . route("request-stock.edit", $item->id) . '"
                            class="button_warning">' . __('administrator.edit') . '</a>';
                        }
                        $check = $item->status === 1;
                        $btn = 'button_danger';
                        $text = __('administrator.return');
                        if ($type === 'purchase_list') {
                            $check = $item->status !== 1;
                            $btn = 'button_warning';
                            $text = __('administrator.edit');
                        }
                        if ($item->confirm_status === 1 && $check && $item->request_by == Auth::user()->id) {
                            // branch return items have been approve
//                            $show_item .= '<a class="' . $btn . ' btn_return" data-href = "' . route('get-request-stock-for-return', $item->id) . '">' . $text . '</a>';
                        }
                        if ($item->status === 3 && $item->request_to == Auth::user()->branch_id) {
                            $show_item .= '<a class="button_warning btn_return" data-href = "' . route('get-request-stock-for-return', $item->id) . '">' . __('administrator.return') . '</a>';
                        }
                        return $show_item;
                    })
                    ->addIndexColumn()
                    ->rawColumns(['action','status','confirm_status','delivery_status'])
                    ->make(true);
        }
        $warehouse = getWarehouse('item')->where('branch_id', Auth::user()->branch_id)->pluck('warehouse_name', 'id');
        $driver = DriverModel::where('branch_id', Auth::user()->id)->pluck('name', 'id');
        return view('stock-inventory.item-request.index', compact('warehouse', 'driver'));
    }

    public function create(Request $request)
    {
        $branch = BranchModel::where('id', '!=', Auth::user()->branch_id)->pluck('name', 'id');

        if ($request->ajax()) {
            $value = $request->value;
            $request_to = $request->request_to;
            $stock_item = StockModel::selectRaw('nso007_stocks.*,nso007_products.product_name,Sum(nso007_stocks.stock_qty) as total_stock')
                ->join('nso007_products', 'nso007_products.id', 'nso007_stocks.product_id')
                ->where(function ($q) use ($request_to) {
                    $wh = WarehouseModel::where('branch_id',$request_to)->pluck('id','id');
                    $q->whereIn('nso007_stocks.warehouse_id', $wh);
                })
                ->where('nso007_stocks.type','product')
                ->where('nso007_stocks.stock_qty', '>', 0)
                ->where(function ($q) use ($value) {
                    $q->where('nso007_stocks.barcode', 'LIKE', $value . '%');
                    $q->orwhere('nso007_products.product_name', 'LIKE', $value . '%');
                })
                ->groupBy('nso007_stocks.barcode')
                ->paginate(16);

            $html = view('stock-inventory.item-request.result-create', compact('stock_item'))->render();
            return response()->json(['html' => $html]);
        }
        return view('stock-inventory.item-request.create', compact('branch'));
    }

    public function edit($id)
    {
        $branch = BranchModel::where('id', '!=', Auth::user()->branch_id)->pluck('name', 'id');
        $master = ItemRequestModel::find($id);
        return view('stock-inventory.item-request.edit', compact('branch', 'master'));
    }

    public function store(Request $request)
    {

        return $this->update($request, null);
    }

    public function update(Request $request, $id)
    {
        $this->validate($request, [
            'qty.*' => 'required',
            'unit.*' => 'required',
            'size.*' => 'required',
            'barcode' => 'required',
            'barcode.*' => 'required',
            'product_id.*' => 'required',
            'request_to' => 'required',
            'date' => 'required',
        ]);
        $barcode = $request->barcode;

        $data = $request->all();
        $data['branch_id'] = Auth::user()->branch_id;
        $data['request_by'] = Auth::user()->id;
        $data['user_id'] = Auth::user()->id;
        $data['year'] = date('Y');
        $data['status'] = 0;
        $data['date'] = date('Y-m-d', strtotime($request->date));
        $data['invoice_number'] = generate_inv('nso007_item_request', 'STR');
        $item = ItemRequestModel::updateOrCreate(['id' => $id], $data);
        ItemRequestDetailModel::where('request_id', $item->id)->delete();
        foreach ($barcode as $key => $value) {
            $product_unit = ProductUnitModel::where(['barcode'=>$value,'product_id'=>$request->product_id[$key]])->first();
            $product = getProductById($product_unit->product_id);
            if ($product->type === "product") {
                $add_item = new ItemRequestDetailModel();
                $add_item->request_id = $item->id;
                $add_item->product_id = $product_unit->product_id;
                $add_item->unit_id = $product_unit->unit_id;
                $add_item->size_code = $product_unit->size_code;
                $add_item->color_code = $product_unit->color_code;
                $add_item->barcode = $product_unit->barcode;
                $add_item->qty = $request->qty[$key];
                $add_item->save();
            }
        }
        return response()->json(['status' => 'success', 'route' => route('request-stock.index').'?type=purchase_list']);
    }

    public function show($id)
    {
        $item = ItemRequestModel::find($id);
        $item_detail = ItemRequestDetailModel::where('request_id', $id)->get();
        $view = view('stock-inventory.item-request.show', compact('item', 'item_detail'))->render();
        return response()->json(['view' => $view, 'status' => $item->status]);
    }


    public function update_status(Request $request, $status)
    {
        $request_stock = ItemRequestModel::where(['id'=>$request->id,'status'=>0])->first();
        $wh_id = $request->warehouse;
        if ($request_stock != null) {
            if ($status == 1) { // approve
                $this->validate($request, [
                    'id' => 'required',
                    'warehouse' => 'required',
                ]);
                $request_stock_detail = ItemRequestDetailModel::where('request_id', $request->id)->get();
                $error = [];
                foreach ($request_stock_detail as $key => $row) {
                    // check if all product has enough stock
                    $stock = StockModel::where([
                        'warehouse_id' => $wh_id,
                        'barcode' => $row->barcode,
                        'product_id' => $row->product_id,
                    ])->first();
                    $size = findSize($row->size_code)->size ?? '';
                    $color = findColor($row->color_code)->name ?? '';
                    $pro_name = getProductById($row->product_id)->product_name ?? '';
                    if ($stock) {
                        if ($stock->stock_qty < $row->qty) {
                            $error[$key] = "$row->barcode | $pro_name($size,$color) មានចំនួនមិនគ្រប់គ្រាន់ ($stock->stock_qty ក្នុងស្តុក)";
                        }
                    } else {
                        $error[$key] = "$row->barcode | $pro_name($size,$color) មានចំនួនមិនគ្រប់គ្រាន់ (មិនមានក្នុងស្តុក)";
                    }
                }
                if(count($error)) throw_error($error);

                foreach ($request_stock_detail as $key => $row) {
                    $stock = StockModel::where([
                        'warehouse_id' => $wh_id,
                        'barcode' => $row->barcode,
                        'product_id' => $row->product_id,
                    ])->first();
                    if ($stock->stock_qty >= $row->qty) {
                        $stock->stock_qty -= $row->qty;
                        $stock->save();
                    }
                }
            }
            if ($status == 3) {// return
                $this->validate($request, [
                    'id' => 'required',
                    'return_qty.*' => 'required',
                ]);
                foreach ($request->detail_id as $key => $row) {
                    $detail = ItemRequestDetailModel::find($row);
                    $detail->return_qty = $request['return_qty'][$key];
                    $detail->save();
                }
            }
            if ($status === 4) {//confirm return
                $this->validate($request, [
                    'id' => 'required',
                ]);
                $arr = [];
                foreach ($request->detail_id as $key => $row) {
                    $detail = ItemRequestDetailModel::find($row);
                    $stock = StockModel::where(['barcode' => $detail->barcode, 'warehouse_id' => $request_stock->to_warehouse,'product_id' => $row->product_id,])->first();
                    $stock = $stock->stock_qty ?? 0;
                    if (!$stock) {
                        $arr[$detail->barcode] = $detail->barcode . ' dont have enough stock!!';
                    }
                }
                if (count($arr > 0)) {
                    throw ValidationException::withMessages(['field_name' => 'This value is incorrect']);
                }
                foreach ($request->detail_id as $key => $row) {
                    $detail = ItemRequestDetailModel::find($row);
                    $return_from = StockModel::where([
                        'warehouse_id' => $request_stock->warehouse_id,
                        'product_id' => $row->product_id,
                        'barcode' => $row->barcode])->first();
                    $return_from->stock_qty -= $detail->return_qty;
                    $return_from->update();

                    $return_to = StockModel::where([
                        'warehouse_id' => $request_stock->to_warehouse,
                        'product_id' => $row->product_id,
                        'barcode' => $row->barcode])
                        ->first();
                    $return_to->stock_qty += $detail->return_qty;
                    $return_to->update();
                }
            }

            $request_stock->status = $status;
            $request_stock->status_note = $request->note;
            if ($status !== 3 || $status !== 4) {
                $request_stock->warehouse_id = $wh_id;
            }
            $request_stock->delivery_fee = $request->delivery_fee;
            $request_stock->location = $request->location;
            $request_stock->delivery_status = $status;
            $request_stock->driver_id = $request->driver;
            $request_stock->approve_date = date('Y-m-d');
            $request_stock->update();
            return response()->json(['status' => 'success']);
        }
        return response()->json(['status' => 'fail']);
    }

    public function request_stock_update_confirm(Request $request, $status)
    {
        if($status == 1){
            $this->validate($request, [
                'id' => 'required',
                'warehouse_id' => 'required',
            ]);
        }

        $id = $request->id;
        $warehouse_id = $request->warehouse_id;
        $request_stock = ItemRequestModel::find($id);
        $request_stock->confirm_status = $status;
        $request_stock->to_warehouse = $warehouse_id;
        if ($status == 1) {
            $request_stock_detail = ItemRequestDetailModel:: where('request_id', $id)->get();
            foreach ($request_stock_detail as $key => $row) {
                $product_unit = ProductUnitModel:: where(['barcode' => $row->barcode])->first();
                $old_stock = StockModel::where(
                    [
                        'barcode' => $product_unit->barcode,
                        'warehouse_id' => $request_stock->to_warehouse,
                        'product_id' => $row->product_id,
                    ])->first()->stock_qty??0;
                StockModel::updateOrCreate(
                    [
                        'barcode' => $product_unit->barcode,
                        'warehouse_id' => $request_stock->to_warehouse,
                    ],
                    [
                        'warehouse_id' => $request_stock->to_warehouse,
                        'product_id' => $row->product_id,
                        'size_code' => $row->size_code,
                        'color_code' => $row->color_code,
                        'barcode' => $product_unit->barcode,
                        'type' => 'product',
                        'stock_qty' => ($old_stock+$row->qty),
                    ]
                );
            }
        }
        if ($status == 2) {
            $request_stock_detail = ItemRequestDetailModel:: where('request_id', $id)->get();
            foreach ($request_stock_detail as $key => $row) {
                $product_unit = ProductUnitModel:: where(['barcode' => $row->barcode,'product_id'=>$row->product_id])->first();
                $old_stock = StockModel::where(
                    [
                        'barcode' => $product_unit->barcode,
                        'product_id' => $row->product_id,
                        'warehouse_id' => $request_stock->warehouse_id,
                    ])->first();
                $old_stock->stock_qty+=$row->qty;
                $old_stock->save();
            }
        }
        $request_stock->update();
        session()->put('success', 'Item has been confirm !');
        return response()->json(['status' => 'success']);
    }

    public function return_stock($id)
    {
        $request_stock_detail = getSaleDetail($id);
        foreach ($request_stock_detail as $key => $row) {
            $stock = StockModel::where([
                'warehouse_id' => $row->warehouse_id,
                'barcode' => $row->barcode,
            ])->first();
            $cut_qty = generateSaleCutQty($row);
            if ($stock->stock_qty >= $cut_qty) {
                $stock->stock_qty += $cut_qty;
                $stock->save();
            }
        }
        return response()->json(['status' => 'success']);
    }

    public function request_stock_scan_code(Request $request)
    {
        $std = new \stdClass();
        $value = $request->barcode;
        $request_to = $request->request_to;
        if ($request_to) {

            $stock_item = StockModel::select('nso007_stocks.*','nso007_products.product_name')
                ->join('nso007_products', 'nso007_products.id', 'nso007_stocks.product_id')
                ->where(function ($q) use ($request_to,$value) {
                    $wh = WarehouseModel::where('branch_id',$request_to)->pluck('id','id');
                    $q->whereIn('nso007_stocks.warehouse_id', $wh);
                    $q->where('nso007_stocks.barcode', $value);
                })
                ->where('nso007_stocks.type','product')
                ->where('nso007_stocks.stock_qty', '>', 0)
                ->first();

            if ($stock_item) {
                $std->id = ProductUnitModel::where('barcode', $value)->first()->id;
                $std->name = $stock_item->product_name;
                $std->stock = $stock_item->stock_qty;
                $std->size = findSize($stock_item->size_code)->size??'';
                $std->color = findColor($stock_item->color_code)->name??'';
                $std->code = $stock_item->barcode;
            }
        }
        return response()->json(['data' => $std]);
    }

    public function get_return($id)
    {
        $item = ItemRequestModel::find($id);
        $item_detail = ItemRequestDetailModel::where('request_id', $id)->get();
        return view('stock-inventory.item-request.get-return', compact('item', 'item_detail'));

    }
}
