<?php

    namespace App\Http\Controllers\Administrator\product;

    use App\Exports\ProductExport;
    use App\Imports\ProductImport;
    use App\Model\pos\SaleDetailsModel;
    use App\Model\product\ProductUnitModel;
    use App\Model\stock_inventory\AdjustmentDetailModel;
    use App\Model\stock_inventory\ItemRequestDetailModel;
    use App\Model\stock_inventory\PurchaseDetailsModel;
    use App\Model\stock_inventory\TransferStockDetailModel;
    use Illuminate\Http\Request;
    use App\Http\Controllers\Controller;
    use App\Model\product\ProductModel;
    use DataTables;
    use Illuminate\Validation\ValidationException;
    use Image;
    use DB;
    use App\Model\product\ProductImageModel;
    use App\Fun\Fun;
    use App\Model\stock_inventory\StockModel;
    use Illuminate\Support\Facades\Gate;
    use Auth;
    use File;
    use Maatwebsite\Excel\Facades\Excel;

    class ProductController extends Controller

    {
        function __construct()
        {
            $this->middleware('permission:Products Create', ['only' => ['create', 'store']]);
            $this->middleware('permission:Products List', ['only' => ['index']]);
            $this->middleware('permission:Products Show', ['only' => ['show']]);
            $this->middleware('permission:Products Edit', ['only' => ['update', 'edit']]);
        }

        public function index(Request $request)
        {
            if ($request->ajax()) {
                Fun::lang();
                $search = $request->input('search.value');
                $data = ProductModel::where(['status' => 1, 'type' => 'product'])
                    ->where(function ($q) use ($search) {
                        if ($search) {
                            $q->where('barcode', 'like', "%$search%");
                            $q->orwhere('product_name', 'like',"%$search%");
                        }
                    })
                    ->latest();
                return Datatables::of($data)
                    ->addColumn('created_at', function ($product) {
                        return date('d-m-Y', strtotime($product->created_at));
                    })
                    ->addColumn('brand', function ($product) {
                        $brand = findBrand($product->brand);
                        return $brand ? $brand->brand : '';
                    })
                    ->addColumn('price_usd', function ($product) {
                        $product->p_unit = ProductUnitModel::where('product_id', $product->id)->where('qty_per_unit', 1)->first();
                        $price_usd = $product->p_unit ? $product->p_unit->price_usd : 0;
                        $price_riel = $product->p_unit ? $product->p_unit->price_riel : 0;
                        return '$' . number_format($price_usd, 2) . '<br>៛' . number_format($price_riel, 2);
                    })
                    ->addColumn('cost_usd', function ($product) {
                        if (Auth::user()->can('Show Purchase Item Price')) {
                            $cost_usd = $product->p_unit ? $product->p_unit->cost_usd : 0;
                            $cost_riel = $product->p_unit ? $product->p_unit->cost_riel : 0;
                            return '$' . number_format($cost_usd, 2) . '<br>៛' . number_format($cost_riel, 2);
                        }
                    })
                    ->addColumn('images', function ($product) {
                        $img = ProductImageModel::where('item_code', $product->barcode ?? '')->first();
                        return findImg($img->images ?? '');
                    })
                    ->addColumn('category_id', function ($product) {
                        $cat = findCategory($product->category_id);
                        return $cat ? $cat->category_name : '';
                    })
                    ->editColumn('unit_id', function ($data) {
                        $units = findParentProductUnit($data->id);
                        $u = $units ? $units->unit_id : '';
                        $unit = findUnit($u);
                        return $unit != null ? $unit->unit : '';
                    })
                    ->addColumn('action', function ($product) {
                        $btn = '';
                        if (Gate::check('Products Show')) {
                            $btn .= '<button title="' . __('administrator.show') . '" class="button_info show_productsinfo" data-url = "' . route("products.show", $product->id) . '"  >' . __('administrator.show') . '</button>';
                        }
                        if (Gate::check('Products Edit')) {
                            $btn .= '<button title="' . __('administrator.edit') . '" class="button_warning edit" data-url = "' . route("products.edit", $product->id) . '">' . __('administrator.edit') . '</button>';
                        }
                        $check_stock = StockModel::where('product_id', $product->id)->first();
                        if (!$check_stock && Gate::check('Products Delete')) {
                            $btn .= '<button title="' . __('administrator.delete') . '" class="button_danger delete" data-url = "' . route("material-destroy", $product->id) . '"><span class="fa fa-trash"></span></button>';
                        }
                        return $btn;
                    })
                    ->addIndexColumn()
                    ->rawColumns(['images', 'action', 'cost_usd', 'created_at', 'price_usd', 'price_usd'])
                    ->make(true);
            }
            return view('administrator.setup-item.products.index');
        }

        public function create(Request $request)
        {
            if ($request->ajax()) {
                $brand_code = findBrand($request->brand);
                return response()->json($brand_code->code ?? '');
            }
            $unit = getUnit('product')->pluck('unit', 'id');
            $category = getCategory('product')->pluck('category_name', 'id');
            $brand = getBrand()->pluck('brand', 'id');
            $size = getSize()->pluck('size', 'code');
            $color = getColor()->pluck('name', 'code');
            $code = ProductModel::where('type', 'product')->count() + 1;
            $code = sprintf('%04d', $code);
            return view('administrator.setup-item.products.create', compact('category', 'unit', 'brand', 'size', 'color', 'code'));
        }

        public function store(Request $request)
        {
            $unit = $request->unit_id;
            $color = $request->color_code;
            $size = $request->size_code;
            $cost_usd = $request->cost_usd;
            $cost_riel = $request->cost_riel;
            $this->validate($request, [
                'product_name' => 'required|max:50',
                'category_id' => 'required',
                'brand' => 'required',
                'unit_id' => 'required',
                'barcode' => 'required|max:15|unique:nso007_products,barcode',
                'barcode_child.*' => 'required|max:15|unique:nso007_product_unit,barcode',
                'color_code.*' => 'required',
                'size_code.*' => 'required',
            ]);
            $check_barcode = ProductModel::where('barcode', $request->barcode)->first();
            $check_name = ProductModel::where('product_name', $request->product_name1 . $request->product_name2 . $request->product_name3)->first();
            $check_child_code = ProductUnitModel::whereIn('barcode', $request->barcode_child)->first();
            if ($check_barcode || $check_name || $check_child_code) {
                if ($check_barcode) {
                    throw ValidationException::withMessages(['field_name' => 'Barcode ' . $check_barcode->barcode . ' already Existed']);
                }
                if ($check_child_code) {
                    throw ValidationException::withMessages(['field_name' => 'Barcode ' . $check_child_code->barcode . ' already Existed']);
                }
                if ($check_name) {
                    throw ValidationException::withMessages(['field_name' => 'Product ' . $check_name->product_name . ' already Existed']);
                }
            }
            $product = new ProductModel;
            $product->category_id = $request->category_id;
            $product->type = 'product';
            $product->unit_id = $unit;
            $product->brand = $request->brand;
            $product->product_name = $request->product_name;
            $product->barcode = $request->barcode;
            $product->alert_qty = $request->alert_qty;
            $product->status = 1;
            $product->save();
            foreach ($request->barcode_child as $key => $row) {
                $pro_unit = new ProductUnitModel();
                $pro_unit->unit_id = $unit;
                $pro_unit->color_code = @$color[$key];
                $pro_unit->size_code = @$size[$key];
                $pro_unit->cost_usd = @$cost_usd[$key];
                $pro_unit->cost_riel = @$cost_riel[$key];
                $pro_unit->qty_per_unit = 1;
                $pro_unit->product_id = $product->id;
                $pro_unit->barcode = $row;
                $pro_unit->type = ($key == 0 ? 'parent' : 'child');
                $pro_unit->save();
            }


            session()->put('success', 'Product created successfully');
            return response()->json(['status' => 'success', 'route' => route('products.index')]);
        }

        public function edit($id)

        {
            $product = ProductModel::find($id);
            $product_unit = ProductUnitModel::where('product_id', $id)->get();
            $unit = getUnit('product')->pluck('unit', 'id');
            $category = getCategory('product')->pluck('category_name', 'id');
            $brand = getBrand()->pluck('brand', 'id');
            $size = getSize()->pluck('size', 'code');
            $color = getColor()->pluck('name', 'code');

            return view('administrator.setup-item.products.edit', compact('category', 'product', 'unit', 'size', 'brand', 'color', 'product_unit'));
        }

        public function update(Request $request, $id)

        {
            $dup = $request->duplicate;
            $id = $dup ? 0 : $id;
            $this->validate($request, [
                'product_name' => 'required|max:50',
                'category_id' => 'required',
                'cost_usd' => 'required',
                'cost_riel' => 'required',
                'brand' => 'required',
                'unit_id' => 'required',
                'size_code.*' => 'required',
                'color_code.*' => 'required',
                'barcode_child.*' => 'required',
                'barcode' => 'required|max:15|unique:nso007_products,barcode,' . $id,
            ]);
            $id_product_unit = $request->id;
            $unit = $request->unit_id;
            $color = $request->color_code;
            $size = $request->size_code;
            $cost_usd = $request->cost_usd;
            $cost_riel = $request->cost_riel;
            $barcode_child = $request->barcode_child;
            $product = ProductModel::updateOrCreate(
                ['id' => $id]
            );
            if ($files = $request->file('gallery')) {
                $ProductImage = ProductImageModel::where('product_id', $id)->get();
                if (!$dup) {
                    foreach ($ProductImage as $file) {
                        if (file_exists(public_path() . '/' . $file->file)) {
                            unlink(public_path() . '/' . $file->images);
                        }
                        $file->delete();
                    }
                }
                $original_name = 'IMG' . date('ymdhis') . '.png';
                $destinationPath = 'images/upload';
                $files->move($destinationPath, $original_name);
                ProductImageModel::Insert([
                    'images' => $destinationPath . '/' . $original_name,
                    'product_id' => $product->id,
                ]);
            }
            // update product
            $product->category_id = $request->category_id;
            $product->product_name = $request->product_name;
            $product->barcode = $request->barcode;
            $product->brand = $request->brand;
            $product->alert_qty = $request->alert_qty;
            $product->unit_id = $unit;
            $product->type = 'product';
            $product->save();

            // update product unit
            foreach ($id_product_unit as $key => $row) {
                $productUnit = ProductUnitModel::updateOrCreate(['id' => $row]);
                $productUnit->unit_id = $unit;
                $size_code = $size[$key];
                $color_code = $color[$key];
                $code = $barcode_child[$key];

                $where = ['barcode'=>$productUnit->barcode,'product_id'=>$productUnit->product_id];
                $value = ['size_code'=>$size_code,'color_code'=>$color_code,'barcode'=>$code];
                StockModel::where($where)->update($value);
                SaleDetailsModel::where($where)->update($value);
                PurchaseDetailsModel::where($where)->update($value);
                AdjustmentDetailModel::where($where)->update($value);
                TransferStockDetailModel::where($where)->update($value);
                ItemRequestDetailModel::where($where)->update($value);

                $productUnit->size_code = $size_code;
                $productUnit->color_code = $color_code;
                $productUnit->cost_usd = $cost_usd[$key];
                $productUnit->cost_riel = $cost_riel[$key];
                $productUnit->qty_per_unit = 1;
                $productUnit->product_id = $product->id;
                $productUnit->barcode = $code;
                $productUnit->type = $key == 0 ? 'parent' : 'child';
                $productUnit->save();
            }
            session()->put('success', 'Product updated successfully');
            return response()->json(['status' => 'success', 'route' => route('products.index')]);
        }

        function show($id)
        {

            $product = ProductModel::find($id);

            $product_unit = ProductUnitModel::where('product_id', $product->id)->orderBy('type', 'DESC')->get();

            $data = [

                'currency' => optional($product->get_currency)->symbol,

                'product_id' => $product->id,

                'product_name' => $product->product_name,

                'barcode' => $product->barcode,

                'shelf' => $product->shelf,

                'qty_alert' => $product->qty_alert,

                'status' => $product->status,

                'category' => findCategory($product->category_id)->category_name,

                'brand' => findBrand($product->brand)->brand,

                'created_at' => date('d-m-Y', strtotime($product->created_at)),

            ];
            return view('administrator.setup-item.products.show', compact('data', 'product_unit'))->render();
        }

        public function destroy($id)

        {

            DB::table('nso007_products')->where('id', $id)->update(['status' => 0]);

            return response()->json([

                'success' => 'Record deleted successfully!'

            ]);
        }

        public function product_changeStatus(Request $request)

        {

            $products = ProductModel::find($request->id);

            $products->status = $request->status;

            $products->save();

            return response()->json(['success' => 'Status change successfully.']);
        }

//        public function getProductByCodename(Request $request)
//        {
//            $code = $request->code;
//
//            $product = ProductModel::where('status', 1)->where('type', 'product')
//                ->where(function ($q) use ($code) {
//                    if ($code) {
//                        $q->orwhere('product_name', 'LIKE', '%' . $code . '%');
//                        $q->orwhere('barcode', 'LIKE', '%' . $code . '%');
//                    }
//                })->pluck('barcode');
//            return response()->json($product);
//        }

        public function search_product(Request $request)

        {
            $key = $request->term['term'];
            $type = $request->type;
            $product_id = $request->product_id;

            $select = 'product_name';
            if($type==='product_code'){
                $type = 'product';
                $select = 'barcode';
            }

            $product = ProductModel::where('status', 1)->where('type', $type)
                ->where(function ($q) use ($product_id) {
                    if ($product_id) {
                        $q->where('product_id', $product_id);
                    }
                })
                ->where(function ($q) use ($key) {
                    if ($key) {
                        $q->where('product_name', 'LIKE', "%$key%");
                        $q->orwhere('barcode', 'LIKE', "%$key%");
                    }
                })->latest()->limit(30)->pluck("$select", 'id')->prepend('Please Select', '');
            $arr = [];
            foreach ($product as $key => $row) {
                $arr[] = ['id' => $key, 'text' => $row];
            }
            return \Response::json($arr);
        }

        public function getSizeCode(Request $request)
        {
            $size = findSize($request->size_id);
            return response()->json($size ? $size->code : '');
        }

        public function print_barcode(Request $request)
        {

            if ($request->ajax()) {
                $product_unit = [];
                if($request->product_id) {
                    $product_unit = ProductUnitModel::join('nso007_products', 'nso007_product_unit.product_id', 'nso007_products.id')
                        ->where(function ($q) use ($request) {
                            if ($request->product_id) {
                                if (count($request->product_id)) {
                                    $q->whereIn('nso007_product_unit.product_id', $request->product_id);
                                }
                            }
                            if ($request->size_code) {
                                $q->where('nso007_product_unit.size_code', $request->size_code);
                            }
                            if ($request->color_code) {
                                $q->where('nso007_product_unit.color_code', $request->color_code);
                            }
                            if ($request->brand_id) {
                                $q->where('nso007_products.brand', $request->brand_id);
                            }
                        })
                        ->select('nso007_product_unit.*', 'nso007_products.product_name')
                        ->get();
                }
                return view('administrator.setup-item.products.get-print-barcode', compact('product_unit'));
            }
            return view('administrator.setup-item.products.print-barcode');
        }

        public function import_exel(Request $request)
        {
            if ($request->export_sample) {
                return Excel::download(new ProductExport(), 'product.xlsx');
            }
            if ($request->method() === 'POST') {
                $this->validate($request, [
                    'file' => 'required|file|max:10000|mimes:xlsx,csv',
                ]);
                try {
                    if (request()->hasFile('file')) {
                        $path = $request->file('file');
                        Excel::import(new ProductImport(), $path);
                        return response()->json(['status' => 'success', 'reload' => 1]);
                    }
                } catch (\Exception $er) {
                    throw ValidationException::withMessages($er->getMessage());
                }
            }
            return view('component.import-exel', ['route' => 'products-import-exel']);
        }

        public function upload_image(Request $request)
        {
            if ($request->method() === 'POST') {
                $this->validate($request, [
                    'file' => 'required',
                    'file.*' => 'required',
//                    'file.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'
                ]);
                foreach ($request->file as $key => $item) {
                    $name = $item->getClientOriginalName();
                    $ext = '.' . $item->getClientOriginalExtension();
                    $destinationPath = 'images/product';
                    if (file_exists(public_path() . "/$destinationPath/$name")) {
                        unlink(public_path() . "/$destinationPath/$name");
                        ProductImageModel::where([
                            'images' => $destinationPath . '/' . $name,
                            'product_id' => 0,
                        ])->delete();
                    }
                    $item->move($destinationPath, $name);
                    ProductImageModel::create([
                        'images' => $destinationPath . '/' . $name,
                        'item_code' => str_replace($ext, '', $name),
                        'product_id' => 0,
                    ]);
                }
                return response()->json(['status' => 'success']);
            }
            return view('administrator.setup-item.products.image.upload-image', ['route' => 'products-upload-image']);
        }

        public function img_list(Request $request)
        {
            if (count($request->img_id ?? [])) {
                foreach ($request->img_id as $item) {
                    $img = ProductImageModel::find($item);
                    if (file_exists(public_path() . "/$img->images")) {
                        unlink(public_path() . "/$img->images");
                    }
                    $img->delete();
                }
                return 'ok';
            }
            if ($request->ajax()) {
                $img = ProductImageModel::where('product_id', 0)->latest()->paginate(36);
                return view('administrator.setup-item.products.image.table', compact('img'))->render();
            }
            return view('administrator.setup-item.products.image.index');
        }
    }
