<?php

namespace App\Http\Controllers\Stocks;

use App\Exports\Stocks\StockOutExportStatement;
use App\Http\Controllers\Controller;
use App\Models\Company;
use App\Models\CompanyAddress;
use App\Models\Product;
use App\Models\ProductPrice;
use App\Models\Stock;
use App\Models\Stocks\StockMomentType;
use App\Models\Stocks\StockOut;
use App\Models\Stocks\StockOutDetail;
use App\Models\VoucherMaster;
use App\Models\VoucherType;
use App\Traits\TransactionSummeryTrait;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Facades\Excel;

class StockOutController extends Controller
{
    use TransactionSummeryTrait;
    
    protected  $mainFolderName = 'stocks';

    public function index(Request $request)
    {
        \Session::forget('stock_out_products_cart');
        $data = StockOut::select(['id', 'invoice_date', 'main_invoice_no'])->with('getStockOutInvoiceBasicAmt');

        if ($request->ajax()) {
            $sort_by      = $request->get('sortby') ?? 10;
            $sort_type    = $request->get('sorttype');
            $search_query = $request->get('query');

            $data = $data->when(!empty($search_query), function ($query) use ($search_query) {

                $query->whereHas('getProduct', function ($product) use ($search_query) {
                    return $product->where('products.name', 'LIKE', '%' . $search_query . '%');
                });
                //$query->where('name', 'like', '%'.$search_query.'%');
            })
                ->orderBy('id', 'desc')
                ->paginate($sort_by);

            return view($this->mainFolderName . '.stock-out.table', compact('data'));
        } else {
            $data = $data
                ->orderBy('id', 'desc')
                ->paginate(10);
            return view($this->mainFolderName . '.stock-out.index', compact('data'));
        }
    }
    public  function create(Request $request)
    {
        $stockMomentTypes = StockMomentType::Active()->where('calculation_type','OUT')->get(['name','code']);
        $companyDateFormate = phpToJsDateFormat($this->companyDateFormate());
        $voucher_master = VoucherMaster::select('tax_calculation')->where('voucher_code', 'STOCK_OUT')->where(['status' => 1])->first();
        return view($this->mainFolderName . '.stock-out.create', compact('stockMomentTypes', 'companyDateFormate','voucher_master'));
    }


    public function searchProducts(Request $request)
    {
        $searchTerm = $request->search;
        $brand_id   = $request->brand_id ?? '';

        $results    = Product::select(
            'products.id',
            'products.name',
            'products.shortcode',
            'products.hsncode',
        )
            ->leftjoin('business_divisions', 'business_divisions.id', 'products.business_division_id')
            ->where(function ($query) use ($searchTerm) {
                $query->where('products.name', 'LIKE', "%" . $searchTerm . "%")
                    ->orWhere('products.product_code', 'LIKE', "%" . $searchTerm . "%")
                    ->orWhere('products.shortcode', 'LIKE', "%" . $searchTerm . "%");
            })
            ->when(!empty($brand_id), function ($query) use ($brand_id) {
                $query->where('products.brand_id', $brand_id);
            })
            ->where('products.status', 1)
            ->limit(15)
            ->get();

        return response()->json(['result' => $results, 'status' => true]);
    }


    public function productAddToCart(Request $request)
    {
        $data = \Session::get('stock_out_products_cart') ?? [];

        if (!isset($data['moment_type']) || $data['moment_type'] == '') {
            $data['moment_type'] = $request->moment_type;
        }
        if ($request->date) {
            $data['date'] = $request->date;
        }

        if (!isset($data['amount'])) {
            $data['amount'] = 0;
        }

        if (!isset($data['special_discount'])) {
            $data['special_discount'] = 0;
        }

        if (!isset($data['amount_recieved'])) {
            $data['amount_recieved'] = 0;
        }

        if (!isset($data['due_balance_amount'])) {
            $data['due_balance_amount'] = $data['amount'];
        }

        if (!isset($data['discount_type'])) {
            $data['discount_type'] = 'FLAT';
        }

        if (!isset($data['sample_receive_time'])) {
            $data['sample_receive_time'] = date('H:i:s');
        }

        if ($request->date) {
            $data['invoice_date'] = $request->date;
        }

        if (!isset($data['sample_receive_date'])) {
            $data['sample_receive_date'] = date('Y-m-d');
        }

        $product = Product::select('products.id', 'products.name', 'products.hsncode', 'product_brands.name as brand', 'tax_masters.name as tax', 'product_prices.batch as batch')
            ->leftjoin('product_brands', 'product_brands.id', 'products.brand_id')
            ->leftjoin('tax_masters', 'tax_masters.id', 'products.tax_slab_id')
            ->leftjoin('product_prices', 'products.id', 'product_prices.product_id')
            ->where('products.id', $request->search_product)
            ->first();
        // Check if the product already exists in the cart
        if (isset($data['products'])) {
            foreach ($data['products'] as $cart_product) {
                if ($cart_product['price_id'] == $request->search_product) {
                    return response()->json(['success' => true, 'data' => $data]);
                }
            }
        }

        $product_price = $request->product_price;
        $main_qty      = $request->main_qty > 0 ? $request->main_qty : 1;
        $loose_qty     = $request->loose_qty > 0 ? $request->loose_qty : 1;
        $flat_discount = $request->flat_discount ?? '0';
        $per_discount  = $request->per_discount ?? '0';
        $amount = '0';

        if ($product_price > 0) {
            if ($flat_discount != '' && $flat_discount != 0) {
                $per_discount  = $flat_discount / ($product_price * $request->main_qty) * 100;

                $flat_discount = (($per_discount / 100) * $product_price) * $request->main_qty;
                $flat_per_discount = (($per_discount / 100) * $product_price);
                $per_discount  = $per_discount;
                $amount        = $product_price - $flat_per_discount;
            } else if ($per_discount != '' && $per_discount != 0) {
                $flat_discount = (($per_discount / 100) * $product_price) * $request->main_qty;
                $flat_per_discount = (($per_discount / 100) * $product_price);
                $per_discount  = $per_discount;
                $amount        = $product_price - $flat_per_discount;
            } else {
                $amount        = $product_price;
            }
        }



        $productMrp = 0;
        $product_price = $amount ?? $product_price;

        $main_qty_amount = $main_qty * $product_price;
        $product_price  = number_format($product_price, 2, '.', '');

        $ActualRateAfterTax = 0;
        $ActualRateBeforeTax = 0;
        $totalTax            = 0;

        $tax_per = $product->tax == 'Tax Free' ? 0 : preg_replace('/[^0-9]/', '', $product->tax);


        $voucher_master = VoucherMaster::select('tax_calculation')->where('voucher_code', 'STOCK_OUT')->where(['status' => 1])->first();

        if ($voucher_master && $voucher_master->tax_calculation == 'EXCLUSIVE') {
            $tax             = ($tax_per / 100) * $product_price; //(12/100)*1000;
            $productMrp      = ($product_price + $tax) * $main_qty;  // 1000+
            $basic_amount    = $request->product_price;  //1000
            $ActualRateAfterTax = $product_price + $tax;
            $ActualRateBeforeTax = $product_price * $main_qty;
            $totalTax = $tax * $main_qty;
        } else {
            $basic_amount    = $request->product_price / (($tax_per + 100) / 100);
            $basePrice       = $product_price / (1 + ($tax_per / 100));
            $tax             = $product_price - $basePrice;
            $productMrp      = $product_price * $main_qty;
            $ActualRateAfterTax = $product_price - $tax;
            $ActualRateBeforeTax = $ActualRateAfterTax * $main_qty;
            $totalTax = $tax * $main_qty;
        }



        $basic_amount      = number_format($basic_amount, 2, '.', '');
        $flat_discount     = number_format($flat_discount, 2, '.', '');
        $per_discount      = number_format($per_discount, 2, '.', '');
        $tax               = number_format($tax, 2, '.', '');
        $convertion_factor = !empty($product->convertion_factor) ? $product->convertion_factor : 1;

        $amount                     = $main_qty * $amount / $convertion_factor;
        $data_amount                = $data['amount'] ?? 0;
        $data['amount']             = $data_amount + $productMrp;
        $data['due_balance_amount'] = number_format($data['amount'], 2, '.', '');

        $data['products'][] = [
            'main_qty'       => $request->main_qty ?? 1,
            'loose_qty'      => $request->main_qty > 0  ? 0 : $request->loose_qty ?? 0.00,
            'free_qty'       => $request->free_qty ?? '',
            'product_detail' => $request->product_detail ?? '',
            'price_id'       => $request->price_id ?? '',
            'product_id'     => $request->search_product ?? '',
            'product'        => $product->name ?? '',
            'hsncode'        => $product->hsncode ?? '',
            'batch'          => $request->batch_name ?? '',
            'product_price'  => $basic_amount ?? '',
            'flat_discount'  => $flat_discount ?? '',
            'per_discount'   => $per_discount ?? '',
            'vial_code'      => '',
            'amount'         => $productMrp ?? '',
            'tax_per'        => $tax_per,
            'tax_flat'       => convertDecimelPoint($totalTax),
            'product_mrp'    => convertDecimelPoint($ActualRateAfterTax) ?? '',
            'product_basic'  => convertDecimelPoint($ActualRateBeforeTax) ?? '',
            'expiry_date'    => $request->expiry_date ? date('M-Y', strtotime($request->expiry_date)) : '',
        ];

        \Session::put('stock_out_products_cart', $data);

        return response()->json(['success' => true, 'data' => $data]);
    }

    public function cartProductUpdate(Request $request)
    {
        $data = \Session::get('stock_out_products_cart') ?? [];

        if (isset($request->type) && $request->type == 'billing') {
            if (isset($request->date)) {
                $data['invoice_date'] = $request->date;
            }

            if (isset($request->payment_mode_id)) {
                $data['payment_mode_id'] = $request->payment_mode_id;
            }

            if (isset($request->payment_term_id)) {
                $data['payment_term_id'] = $request->payment_term_id;
            }

            if (isset($request->special_discount)) {
                $data['special_discount'] = $request->special_discount;
            }

            if (isset($request->discount_type)) {
                $data['discount_type'] = $request->discount_type;
            }

            if (isset($request->amount_recieved)) {
                $data['amount_recieved'] = $request->amount_recieved;
            }

            if (isset($request->date)) {
                $data['date'] = $request->date;
            }
            if (!isset($data['moment_type']) || $data['moment_type'] == '') {
                $data['moment_type'] = $request->moment_type;
            }

            if (isset($request->special_discount) || isset($request->discount_type) || isset($request->amount_recieved)) {
                if ($data['discount_type'] == 'FLAT') {
                    $due_balance_amount = $data['amount'] - $data['special_discount'];
                    $data['due_balance_amount'] = round($due_balance_amount - $data['amount_recieved']);
                } else {
                    $flat_discount = ($data['special_discount'] / 100) * $data['amount'];
                    $due_balance_amount = $data['amount'] - $flat_discount;
                    $data['due_balance_amount'] = round($due_balance_amount - $data['amount_recieved']);
                }
            }
        } else {
            if (isset($data['products'])) {
                $saleVoucher = VoucherType::select(['default_price_type'])->where(['code' => 'STOCK_OUT'])->first();
                if ($saleVoucher->default_price_type == 'MRP') {
                    $productPrice = 'product_prices.mrp as mrp';
                } elseif ($saleVoucher->default_price_type == 'Purchase Price') {
                    $productPrice = 'product_prices.purchase_price as mrp';
                } elseif ($saleVoucher->default_price_type == 'WholeSale Price') {
                    $productPrice = 'product_prices.wholesale_price as mrp';
                } elseif ($saleVoucher->default_price_type == 'Discounted/Sale Price(DP)') {
                    $productPrice = 'product_prices.sale_price as mrp';
                } elseif ($saleVoucher->default_price_type == 'Min. Sale Price') {
                    $productPrice = 'product_prices.min_sale_price as mrp';
                } elseif ($saleVoucher->default_price_type == 'Manufacturing Cost') {
                    $productPrice = 'product_prices.mfg_cost as mrp';
                }

                foreach ($data['products'] as $key => $value) {

                    $product = Product::select('products.id', 'products.name', 'products.hsncode', 'product_brands.name as brand', 'tax_masters.name as tax', 'product_prices.batch as batch', $productPrice)
                    ->leftjoin('product_brands', 'product_brands.id', 'products.brand_id')
                    ->leftjoin('tax_masters', 'tax_masters.id', 'products.tax_slab_id')
                    ->leftjoin('product_prices', 'products.id', 'product_prices.product_id')
                    ->where('product_prices.id', $value['price_id'])
                    ->where('products.id', $value['product_id'])
                    ->first();

                    $tax_per = $product->tax == 'Tax Free' ? 0 : preg_replace('/[^0-9]/', '', $product->tax);

                    $voucher_master = VoucherMaster::select('tax_calculation')
                        ->where('voucher_code', 'STOCK_OUT')
                        ->where(['status' => 1])
                        ->first();
    


                    if ($value['price_id'] == $request->id && isset($request->product_detail)) {
                        $data['products'][$key]['product_detail'] = $request->product_detail;
                    }

                    if ($value['price_id'] == $request->id) {
                        if (isset($request->main_qty) && $request->main_qty > 0) {
                           $data['products'][$key]['main_qty']  = $request->main_qty;
                            $data['products'][$key]['loose_qty'] = 0;

                            $main_qty_amount = $request->main_qty * $product->mrp;
                            $product_price   = number_format($main_qty_amount, 2, '.', '');
                            $per_discount    = $value['per_discount'];
                        } elseif (isset($request->loose_qty) && $request->loose_qty > 0) {
                            $data['products'][$key]['loose_qty'] = $request->loose_qty;
                            $data['products'][$key]['main_qty']  = 0;

                            $main_qty_amount = $request->loose_qty * $product->mrp;
                            $product_price    = number_format($main_qty_amount, 2, '.', '');
                            $per_discount     = $value['per_discount'];
                        } else if (isset($request->per_discount) && !empty($request->per_discount)) {
                            $main_qty_amount = $data['products'][$key]['main_qty'] * $product->mrp;
                            $product_price   = number_format($main_qty_amount, 2, '.', '');
                            $per_discount    = $request->per_discount;
                        } else {
                            $main_qty_amount = $data['products'][$key]['main_qty'] * $product->mrp;
                            $product_price   = number_format($main_qty_amount, 2, '.', '');
                            $per_discount    = $value['per_discount'];
                        }

                        $product_price = $product->mrp;
                        $flat_discount = $request->flat_discount ?? '0';
                        $per_discount  = $request->per_discount ?? $data['products'][$key]['per_discount'];

                        $productMrp = $basic_amount = 0;

                        if ($product_price > 0) {
                            if ($flat_discount != '' && $flat_discount != 0) {
                                $per_discount  = $flat_discount / ($product_price * $data['products'][$key]['main_qty']) * 100;

                                $flat_discount = (($per_discount / 100) * $product_price) * $data['products'][$key]['main_qty'];
                                $flat_per_discount = (($per_discount / 100) * $product_price);
                                $per_discount  = $per_discount;
                                $amount        = $product_price - $flat_per_discount;
                            } else if ($per_discount != '' && $per_discount != 0) {

                                $flat_discount = (($per_discount / 100) * $product_price) * $data['products'][$key]['main_qty'];
                                $flat_per_discount = (($per_discount / 100) * $product_price);
                                $per_discount  = $per_discount;
                                $amount        = $product_price - $flat_per_discount;
                            } else {
                                $amount        = $product_price;
                            }
                        }

                        $product_price = $amount ?? $product_price;

                        if ($voucher_master && $voucher_master->tax_calculation == 'EXCLUSIVE') {
                            $tax   =  $flat_tax        = ($tax_per / 100) * $product_price; //(12/100)*1000;
                            $productMrp      = ($product_price + $tax) * $data['products'][$key]['main_qty'];  // 1000+
                            $basic_amount    = $product->mrp;  //1000

                            $ActualRateAfterTax = $product_price + $tax;
                            $ActualRateBeforeTax = $product_price * $data['products'][$key]['main_qty'];
                            $totalTax = $tax * $data['products'][$key]['main_qty'];
                        } else {
                            $basic_amount    = $product->mrp / (($tax_per + 100) / 100);
                            $basePrice       = $product_price / (1 + ($tax_per / 100));
                            $tax  =    $flat_tax       = $product_price - $basePrice;
                            $productMrp      = $product_price * $data['products'][$key]['main_qty'];
                            $ActualRateAfterTax = $product_price - $tax;
                            $ActualRateBeforeTax = $ActualRateAfterTax * $data['products'][$key]['main_qty'];
                            $totalTax = $tax * $data['products'][$key]['main_qty'];
                        }


                        $amount = ($basic_amount - $flat_discount);
                        $amount = number_format($amount, 2, '.', '');

                        $convertion_factor = !empty($product->convertion_factor) ? $product->convertion_factor : 1;
                        $amount            = $main_qty_amount * $amount / $convertion_factor;
                        $flat_discount     = number_format($flat_discount, 2, '.', '');
                        $flat_tax          = number_format($totalTax, 2, '.', '');
                        $data['products'][$key]['flat_discount'] = $flat_discount;
                        $data['products'][$key]['per_discount']  = $per_discount;
                        $data['products'][$key]['tax_flat']      = $flat_tax;
                        $data['products'][$key]['amount']        = convertDecimelPoint($productMrp);
                        $data['products'][$key]['product_price'] = convertDecimelPoint($basic_amount);
                        $data['products'][$key]['product_mrp']   = convertDecimelPoint($ActualRateAfterTax) ?? '';
                        $data['products'][$key]['product_basic'] = convertDecimelPoint($ActualRateBeforeTax) ?? '';
                        $data['amount']                          = $data['amount'] + $productMrp;
                        $due_balance_amount                      = $data['amount'] - $flat_discount;
                        $data['due_balance_amount']              = number_format($due_balance_amount - $data['amount_recieved'], 2, '.', '');
                    }

                    if ($value['price_id'] == $request->id && isset($request->product_price)) {
                        $data['amount'] = $data['amount'] - $value['amount'];
                        $product_price = $request->product_price;
                        $flat_discount = $request->flat_discount ?? '0';
                        $per_discount  = $request->per_discount ?? $data['products'][$key]['per_discount'];

                        $productMrp = $basic_amount = 0;

                        if ($product_price > 0) {
                            if ($flat_discount != '' && $flat_discount != 0) {
                                $per_discount  = $flat_discount / ($product_price * $data['products'][$key]['main_qty']) * 100;

                                $flat_discount = (($per_discount / 100) * $product_price) * $data['products'][$key]['main_qty'];
                                $flat_per_discount = (($per_discount / 100) * $product_price);
                                $per_discount  = $per_discount;
                                $amount        = $product_price - $flat_per_discount;
                            } else if ($per_discount != '' && $per_discount != 0) {

                                $flat_discount = (($per_discount / 100) * $product_price) * $data['products'][$key]['main_qty'];
                                $flat_per_discount = (($per_discount / 100) * $product_price);
                                $per_discount  = $per_discount;
                                $amount        = $product_price - $flat_per_discount;
                            } else {
                                $amount        = $product_price;
                            }
                        }

                        $product_price = $amount ?? $product_price;

                        if ($voucher_master && $voucher_master->tax_calculation == 'EXCLUSIVE') {
                            $tax   =  $flat_tax        = ($tax_per / 100) * $product_price; //(12/100)*1000;
                            $productMrp      = ($product_price + $tax) * $data['products'][$key]['main_qty'];  // 1000+
                            $basic_amount    = $request->product_price;  //1000

                            $ActualRateAfterTax = $product_price + $tax;
                            $ActualRateBeforeTax = $product_price * $data['products'][$key]['main_qty'];
                            $totalTax = $tax * $data['products'][$key]['main_qty'];
                        } else {
                            $basic_amount    = $request->product_price / (($tax_per + 100) / 100);
                            $basePrice       = $product_price / (1 + ($tax_per / 100));
                            $tax  =    $flat_tax       = $product_price - $basePrice;
                            $productMrp      = $product_price * $data['products'][$key]['main_qty'];
                            $ActualRateAfterTax = $product_price - $tax;
                            $ActualRateBeforeTax = $ActualRateAfterTax * $data['products'][$key]['main_qty'];
                            $totalTax = $tax * $data['products'][$key]['main_qty'];
                        }


                        $amount = ($basic_amount - $flat_discount);
                        $amount = number_format($amount, 2, '.', '');

                        $convertion_factor = !empty($product->convertion_factor) ? $product->convertion_factor : 1;
                        $amount            = $main_qty_amount * $amount / $convertion_factor;
                        $flat_discount     = number_format($flat_discount, 2, '.', '');
                        $flat_tax          = number_format($totalTax, 2, '.', '');
                        $data['products'][$key]['flat_discount'] = $flat_discount;
                        $data['products'][$key]['per_discount']  = $per_discount;
                        $data['products'][$key]['tax_flat']      = $flat_tax;
                        $data['products'][$key]['amount']        = convertDecimelPoint($productMrp);
                        $data['products'][$key]['product_price'] = convertDecimelPoint($basic_amount);
                        $data['products'][$key]['product_mrp']   = convertDecimelPoint($ActualRateAfterTax) ?? '';
                        $data['products'][$key]['product_basic'] = convertDecimelPoint($ActualRateBeforeTax) ?? '';
                        $data['amount']                          = $data['amount'] + $productMrp;
                        $due_balance_amount                      = $data['amount'] - $flat_discount;
                        $data['due_balance_amount']              = number_format($due_balance_amount - $data['amount_recieved'], 2, '.', '');
                    }

                    if ($value['price_id'] == $request->id && (isset($request->flat_discount) || isset($request->per_discount) || isset($request->product_price) || isset($request->main_qty) || isset($request->loose_qty))) {
                        if ($data['discount_type'] == 'FLAT') {
                            $due_balance_amount = $data['amount'] - $data['special_discount'];
                            $data['due_balance_amount'] = round($due_balance_amount - $data['amount_recieved']);
                        } else {
                            $flat_discount = ($data['special_discount'] / 100) * $data['amount'];
                            $due_balance_amount = $data['amount'] - $flat_discount;
                            $data['due_balance_amount'] = round($due_balance_amount - $data['amount_recieved']);
                        }
                    }
                }
            }

            if (isset($request->moment_type)) {
                $data['moment_type'] = $request->moment_type;
            }

            if (isset($request->date)) {
                $data['date'] = $request->date;
            }
        }

        \Session::put('stock_out_products_cart', $data);

        return response()->json(['success' => true, 'data' => $data]);
    }


    public function productCart(Request $request, $id = 0)
    {
        $page = $request->page ?? '';
        $data = \Session::get('stock_out_products_cart') ?? [];

        return view($this->mainFolderName . '.stock-out.product-cart', compact('data', 'page', 'id'));
    }

    public function cartProductRemove(Request $request)
    {
        $data = \Session::get('stock_out_products_cart') ?? [];
        $id   = $request->id;
        // dd($data);

        $amount = $data['amount'];

        $data['products'] = array_filter($data['products'], function ($product) use ($id, &$data, &$amount) {
            if ($product['price_id'] == $id) {
                $amount = $data['amount'] - $product['amount'];
            }

            return $product['price_id'] != $id;
        });

        if (count($data['products']) == 0) {
            $data['amount'] = 0;
        } else {
            $data['amount'] = $amount;
        }

        if ($data['discount_type'] == 'FLAT') {
            $due_balance_amount = $data['amount'] - $data['special_discount'];
            $data['due_balance_amount'] = round($due_balance_amount - $data['amount_recieved']);
        } else {
            $flat_discount = ($data['special_discount'] / 100) * $data['amount'];
            $due_balance_amount = $data['amount'] - $flat_discount;
            $data['due_balance_amount'] = round($due_balance_amount - $data['amount_recieved']);
        }

        \Session::put('stock_out_products_cart', $data);

        return response()->json(['success' => true]);
    }


    public function store(Request $request){

        $data = \Session::get('stock_out_products_cart') ?? [];
        if (empty($data)) {
            return redirect()->back()->with('error', 'Empty cart!');
        }
        $company_id     = Auth::user()->company_id ?? '';

        $voucher_master = VoucherMaster::with('voucherSeries')
            ->where('voucher_code', 'STOCK_OUT')
            ->first();

        $voucher_type   = VoucherType::with('voucherSeries')->where('code', 'STOCK_OUT')->where(['status' => 1])->first();

        # last voucher count for main voucher type invoice number
        $voucher_type_last_count = StockOut::select('last_voucher_type_count')->where('voucher_type_code', 'STOCK_OUT')->orderBy('created_at', 'DESC')->first();
        $voucher_type_count      = isset($voucher_type_last_count) && isset($voucher_type_last_count->last_voucher_type_count) ? $voucher_type_last_count->last_voucher_type_count + 1 : ($voucher_type->voucherSeries->start_from + 1 ?? 1);
        $voucher_type_invoice_no = $this->generateCode(
            $voucher_type_count,
            ($voucher_type->voucherSeries->prefix ?? 'STI'),
            ($voucher_type->voucherSeries->postfix ?? ''),
            ($voucher_type->voucherSeries->separator ?? '-'),
            ($voucher_type->voucherSeries->length ?? 5)
        );

        $invoice_date        = $data['date'] != '' ? date('Y-m-d H:i:s', strtotime($data['date'] . ' ' . date('H:i:s'))) : '';
        $stock_invoice  = [
            'payment_term_id'         => $request->payment_term_id,
            'invoice_date'            => $invoice_date,
            'patient_id'              => $data['customer_id'] ?? '',
            'doctor_id'               => $data['doctor_id'] ?? '',
            'reff_no'                 => $request->reff_no,

            'sale_delivery_status'    => 'PENDING',
            'company_id'              => $company_id,
            'status'                  => 'NEWSTOCK',
            'special_case_id'         => $request->special_case,
            'discount_amount'         => $request->special_discount,

            'financial_year_id'       => $this->financialyear(),
            'industry_type_id'        => 2,
            'operator_id'             => Auth::ID(),
            'payment_mode_id'         => $request->payment_mode_id ?? '',
            'transaction_mode_id'     => $request->transaction_mode_id ?? '',
            'bussiness_source_id'     => $request->bussiness_source ?? '',
            'voucher_type_invoice_no' => $voucher_type_invoice_no,
            'last_voucher_type_count' => $voucher_type_count,
            'ship_to_id'              => $request->ship_to,
            'dispatch_from_id'        => $request->ship_from,
            'bill_to_account_id'      => $request->bill_to_account_id,
            'tpa_corporate_id'        => $request->tpa_corporate_id,

        ];

        $stock_invoice = StockOut::create($stock_invoice);


            foreach ($data['products'] as $key => $value) {
            $product = Product::where('id', $value['product_id'])
                ->with('getProductPrice')
                ->first();

            $item = [
                'invoice_id'                => $stock_invoice->id,
                'batch_id'                  => '',
                'product_id'                => $value['product_id'],
                'product_price_id'          => $value['price_id'],
                'price'                     => $value['product_price'],
                'basic_amount'              => $value['product_basic'],
                'discount_percentage'       => $value['per_discount'],
                'discount_amount'           => $value['flat_discount'],
                'total_amount'              => $value['amount'],
                'item_details'              => $value['product_detail'],
                'main_qty'                  => $value['main_qty'],
                'alt_qty'                   => $value['loose_qty'],
                'free_qty'                  => $value['free_qty'],
                'item_batch'                => $value['batch'] ?? '',
                'tax_slab_id'               => $product->tax_slab_id ?? '',
                'tpa_amount'                => 0,
                'customer_amount'           => $value['amount'] ?? 0,
                'tax_calculation_type'      => $voucher_master->tax_calculation ?? '',
            ];

              StockOutDetail::create($item);

            /**************Stock OUT Function ********************/
            stockOut($stock_invoice->id, 'STOCK_OUT', $value['product_id'], $value['main_qty'], $value['product_price'], $invoice_batch_id='',$value['price_id'], $data['moment_type']);
            }

            \Session::forget('stock_out_products_cart');

            return redirect()->route('stock-out.index')->with('success', "Stock Out Successfully");
    }


    public function edit($id)
    {

        $company_id      = Auth::user()->company_id ?? '';
        $company_address = CompanyAddress::getCompanyAddress(['companies_addresses.company_id' => $company_id]);
        $countryCode     = $company_address->country_code ?? 'us';

        $stockData = Stock::select(['stock_type'])->where(['voucher_type' => 'STOCK_OUT', 'voucher_id' => $id])->first();
        $stocks    = StockOut::find($id);
        $data            = [];
        $customer        =  '';
        $doctor          = '';
        $amount = 0;

        if ($stocks) {
            $data['moment_type']            = $stockData->stock_type ?? '';
            $data['date']                   = $stocks->invoice_date;
            $data['amount_recieved']        = $stocks->received_amount;
            $data['due_balance_amount']     = $stocks->due_amount;
            $data['discount_type']          = 'FLAT';
            $data['invoice_date']           = $stocks->invoice_date;
            $data['payment_mode_id']        = $stocks->payment_mode_id;
            $data['special_discount']       = 0;

            $stockVoucher = VoucherType::select(['default_price_type'])->where(['code' => 'STOCK_OUT'])->first();
            if ($stockVoucher->default_price_type == 'MRP') {
                $productPrice = 'product_prices.mrp as mrp';
            } elseif ($stockVoucher->default_price_type == 'Purchase Price') {
                $productPrice = 'product_prices.purchase_price as mrp';
            } elseif ($stockVoucher->default_price_type == 'WholeSale Price') {
                $productPrice = 'product_prices.wholesale_price as mrp';
            } elseif ($stockVoucher->default_price_type == 'Discounted/Sale Price(DP)') {
                $productPrice = 'product_prices.sale_price as mrp';
            } elseif ($stockVoucher->default_price_type == 'Min. Sale Price') {
                $productPrice = 'product_prices.min_sale_price as mrp';
            } elseif ($stockVoucher->default_price_type == 'Manufacturing Cost') {
                $productPrice = 'product_prices.mfg_cost as mrp';
            }

            $productMrp    = 0;
            $ActualRateAfterTax = 0;
            $ActualRateBeforeTax = 0;
            $totalAmount = 0;

            foreach ($stocks->getStockOutInvoiceDetail as $key => $value) {

                $productPriceData = ProductPrice::select('exp_date',$productPrice)->find($value->product_price_id);
                $product_price = $productPriceData->mrp;
                $flat_discount = 0;
                $per_discount = $value->discount_percentage;

                if ($product_price > 0) {
                    if ($flat_discount != '' && $flat_discount != 0) {
                        $per_discount  = ($flat_discount / $product_price) * 100;
                        $amount        = $product_price - $flat_discount;
                        $flat_discount = $flat_discount;
                    } else if ($per_discount != '' && $per_discount != 0) {
                        $flat_discount = ($per_discount / 100) * $product_price;
                        $per_discount  = $per_discount;
                        $amount        = $product_price - $flat_discount;
                    } else {
                        $amount        = $product_price;
                    }
                }

                $product_price = $amount ?? $product_price;


                $totalAmount += $value->total_amount;
                $main_qty = $value->main_qty > 0 ? $value->main_qty : ($value->alt_qty > 0 ? $value->alt_qty : 1);
                $main_qty_amount = $main_qty * $productPriceData->mrp;

                $tax_per = $value->getProduct->getTaxMaster->name != 'Tax Free' ? preg_replace('/[^0-9]/', '', $value->getProduct->getTaxMaster->name ?? 0,) : 0;

                $tax  = (($tax_per ?? 0) / 100) * $main_qty_amount;

                /*************** Tax Calculation ***************** **/
                if ($value && $value->tax_calculation_type == 'EXCLUSIVE') {
                    $tax             = ($tax_per / 100) * $product_price; //(12/100)*1000;
                    $productMrp      = ($product_price + $tax) * $main_qty;  // 1000+
                    $basic_amount    = $value->price;  //1000

                    $ActualRateAfterTax = $product_price + $tax;
                    $ActualRateBeforeTax = $product_price * $main_qty;
                    $totalTax = $tax * $main_qty;
                } else {
                    $basic_amount    = $productPriceData->mrp / (($tax_per + 100) / 100);
                    $basePrice       = $product_price / (1 + ($tax_per / 100));
                    $tax             = $product_price - $basePrice;
                    $productMrp      = $product_price * $main_qty;
                    $ActualRateAfterTax = $product_price - $tax;
                    $ActualRateBeforeTax = $ActualRateAfterTax * $main_qty;
                    $totalTax = $tax * $main_qty;
                }

                $data['products'][] = array(
                    'batch'          => $value->item_batch ?? '',
                    'price_id'       => $value->product_price_id ?? '',
                    'product_id'     => $value->product_id ?? '',
                    'product'        => $value->getProduct->name ?? '',
                    'hsncode'        => $value->getProduct->hsncode ?? '',
                    'product_price'  => convertDecimelPoint($basic_amount) ?? '0',
                    'flat_discount'  => $value->discount_amount ?? '0',
                    'per_discount'   => $value->discount_percentage ?? '0',
                    'product_detail' => $value->item_details ?? '',
                    'amount'         => convertDecimelPoint($productMrp) ?? '0',
                    'main_qty'       => $value->main_qty ?? '0',
                    'loose_qty'      => $value->alt_qty ?? '0',
                    'free_qty'       => $value->free_qty ?? '0',
                    'tax_per'        => $tax_per,
                    'tax_flat'       => convertDecimelPoint($totalTax) ?? 0,
                    'product_mrp'    => convertDecimelPoint($ActualRateAfterTax) ?? '',
                    'product_basic'  => convertDecimelPoint($ActualRateBeforeTax) ?? '',
                    'expiry_date'    => $productPriceData->exp_date ? date('M-Y', strtotime($productPriceData->exp_date)) : '',
                );
            }

            $data['amount']                 =  $totalAmount;
        }


        \Session::put('stock_out_products_cart', $data);

        $stockMomentTypes = StockMomentType::Active()->where('calculation_type','OUT')->get(['name', 'code']);
        $companyDateFormate = phpToJsDateFormat($this->companyDateFormate());
        $voucher_master = VoucherMaster::select('tax_calculation')->where('voucher_code', 'STOCK_OUT')->where(['status' => 1])->first();
        return view($this->mainFolderName . '.stock-out.edit', compact(
            'id',
            'stockMomentTypes',
            'companyDateFormate',
            'stocks',
            'stockData',
            'voucher_master'
        ));
    }


    public function update(Request $request, $id)
    {

        $stock_out_invoice   = StockOut::find($id);
        $data = \Session::get('stock_out_products_cart') ?? [];
        if (!$stock_out_invoice || !$data) {
            $data = [];
            \Session::put('stock_out_products_cart', $data);

            return redirect()->route('stock-out.index')->with('error', 'Stock Out invoice not found!');
        }
        $special_discount = 0;

        if ($data['discount_type'] == 'FLAT') {
            $special_discount = $request->special_discount;
        } else {
            $special_discount = ($request->special_discount / 100) * 0;
        }

        $data               = \Session::get('stock_out_products_cart') ?? [];
        $received_amount    = 0;
        $due_balance_amount = 0 - $received_amount - $special_discount;

        if (empty($data)) {
            return redirect()->back()->with('error', 'Empty cart!');
        }

        $invoice_date        = $data['date'] != '' ? date('Y-m-d H:i:s', strtotime($data['date'] . ' ' . date('H:i:s'))) : '';

        $stock_out_update  = [
            'payment_term_id'         => $request->payment_term_id,
            'supplier_invoice_number' => $request->supplier_invoice_no ?? '',
            'invoice_date'            => $invoice_date,
            'patient_id'              => $data['customer_id'] ?? '',
            'doctor_id'               => $data['doctor_id'] ?? '',
            'reff_no'                 => $request->reff_no,
            'received_amount'         => $received_amount,
            'due_amount'              => $due_balance_amount,
            'remarks'                 => $request->sale_remarks,
            'special_case_id'         => $request->special_case,
            'discount_amount'         => $special_discount,
            'adjustment_type'         => $request->discount_type,
            'payment_mode_id'         => $request->payment_mode_id ?? '',
            'bussiness_source_id'     => $request->bussiness_source ?? '',
            'bill_to_account_id'      => $request->bill_to_account_id,
            'tpa_corporate_id'        => $request->tpa_corporate_id,
            'updated_by'              => Auth::user()->id
        ];

        $stock_out_invoice->update($stock_out_update);
        
        $product_ids = $price_ids =  [];
        $voucher_master = VoucherMaster::select('tax_calculation')->where('voucher_code', 'STOCK_OUT')->where(['status' => 1])->first();
        foreach ($data['products'] as $key => $value) {
            $product = Product::where('id', $value['product_id'])
                ->with('getProductPrice')
                ->first();


            $item = [
                'batch_id'            => '',
                'price'               => $value['product_price'],
                'basic_amount'        => $value['product_basic'],
                'discount_percentage' => $value['per_discount'],
                'discount_amount'     => $value['flat_discount'],
                'total_amount'        => $value['amount'],
                'item_details'        => $value['product_detail'],
                'main_qty'            => $value['main_qty'],
                'alt_qty'             => $value['loose_qty'],
                'free_qty'            => $value['free_qty'],
                'item_batch'          => $value['batch'] ?? '',
                'tax_slab_id'         => $product->tax_slab_id ?? '',
                'tpa_amount'          => 0,
                'customer_amount'     => $value['amount'] ?? 0,
                'tax_calculation_type'=> $voucher_master->tax_calculation??'',
            ];

            $stock_out_invoice_details = StockOutDetail::updateOrCreate([
                'product_id'                => $value['product_id'],
                'invoice_id'                => $stock_out_invoice->id,
                'product_price_id'          => $value['price_id']
            ], $item);

            $stock_in_invoice_detail_ids[] = $stock_out_invoice_details->id;
            $product_ids[]             = $value['product_id'];
            $price_ids[]               = $value['price_id'];

            /**************Stock Out Function ********************/
            stockOut($stock_out_invoice->id, 'STOCK_OUT', $value['product_id'], $value['main_qty'], $value['product_price'], $invoice_batch_id='',$value['price_id'], $data['moment_type']);
        }

        StockOutDetail::whereNotIn('id', $stock_in_invoice_detail_ids)
        ->where(['invoice_id' => $stock_out_invoice->id])
        ->delete();
        Stock::whereNotIN('product_id', $product_ids)
        ->whereNotIN('batch_id', $price_ids)
        ->where(['voucher_id' => $stock_out_invoice->id, 'voucher_type' => 'STOCK_OUT'])
        ->delete();


        \Session::forget('stock_out_products_cart');

        return redirect()->route('stock-out.index')->with('success', "New Bill Created Successfully");
    }

    public function destroy(Request $request)
    {
        $data = StockOut::find($request->id);
        StockOutDetail::where('invoice_id',$request->id)->delete();
        Stock::where(['voucher_id'=>$request->id,'voucher_type'=>'STOCK_OUT'])->delete();
        $data->update(['deleted_by'=>Auth::user()->id]);
        $data->delete();

        return response()->json([
            'success' => true,
            'message' => ['Deleted successfully'],
            'data'    => [
            ]
        ]);
    }

    public function invoice($id)
    {
        $invoice = StockOut::with('getInvoiceDetails')
            ->with('getPaymentTerm')
            ->with('getCompany')
            ->find($id);
        if (!$invoice) {
            return redirect()->route('stock-out.index')->with('error', 'Stock In Invoice not found');
        }

        $transactionSummery = $this->StockTransactionSummery($id,'STOCK_OUT');
        $transactionHistory = $this->transactionHistory($id,'STOCK_OUT');

        $voucher_type   = VoucherType::with('voucherSeries')->where('code', 'STOCK_OUT')->first();
        return view($this->mainFolderName . '.stock-out.invoice',compact('invoice','voucher_type','transactionSummery','transactionHistory'));
    }

    public function statement(Request $request)
    {
        $companyDateFormate = phpToJsDateFormat($this->companyDateFormate());
        if ($request->ajax()) {
            $from_date         = $request->from_date ? date('Y-m-d', strtotime($request->from_date)) : date('Y-m-d');
            $to_date           = $request->to_date ? date('Y-m-d', strtotime($request->to_date)) : date('Y-m-d');

            $voucher_type_code = $request->voucher_type_code ?? '';
            $invoices = $this->query($request);

            return view('invoice-formats.stocks.stock-out.statement-table', compact([
                'voucher_type_code',
                'invoices',
                'from_date',
                'to_date',
            ]));
        }


        $company       = Company::find(Auth::user()->company_id);
        $companies     = Company::get();
        $voucher_type  = VoucherType::where('code', 'STOCK_OUT')->where(['status' => 1])->first();
        $voucher_types = VoucherType::select('name', 'code')->where(['status' => 1])->get();

        return view('invoice-formats.stocks.stock-out.statement', compact(
            'voucher_types',
            'companies',
            'company',
            'companyDateFormate',
            'voucher_type'
        ));
    }

    public function query($request)
    {
        $from_date         = $request->from_date ? date('Y-m-d', strtotime($request->from_date)) : date('Y-m-d');
        $to_date           = $request->to_date ? date('Y-m-d', strtotime($request->to_date)) : date('Y-m-d');
        $company           = $request->company ?? '';
        $created_by        = $request->created_by ?? '';

        $voucher_type_code = $request->voucher_type_code ?? '';

        $columns = [
            'stock_outs.id',
            'stock_outs.invoice_date',
            'stock_outs.main_invoice_no',
            'stock_outs.patient_id',
            'stock_outs.voucher_type_code',
            'stock_outs.payment_mode_id',
            'tax_masters.total_percentage as tax_percentage',
            'payment_terms.payment_term_name',
            \DB::raw('SUM(stock_out_details.customer_amount) as billing_amount'),
        ];
        $invoices = StockOut::with(
                'getPaymentTerm',
                'getInvoiceDetails',
            )
            ->leftJoin('payment_terms','payment_terms.id','stock_outs.transaction_mode_id')
            ->leftJoin('stock_out_details','stock_out_details.invoice_id','stock_outs.id')
            ->leftJoin('tax_masters','stock_out_details.tax_slab_id','tax_masters.id')
           
            
            ->when(!empty($voucher_type_code), function($invoices) use($voucher_type_code) {
                $invoices->where('stock_outs.voucher_type_code', '=', $voucher_type_code);
            })
            ->when(!empty($created_by), function($invoices) use($created_by) {
                $invoices->where('stock_outs.operator_id', '=', $created_by);
            })
            ->when(!empty($company), function($invoices) use($company) {
                $invoices->where('stock_outs.company_id', '=', $company);
            })
            ->when(!empty($from_date) && !empty($to_date), function($query) use ($from_date, $to_date) {
                $query->whereDate('stock_outs.invoice_date', '>=', $from_date)
                      ->whereDate('stock_outs.invoice_date', '<=', $to_date);
            })
            ->select($columns)
            ->groupBy('main_invoice_no')
            ->get();
            
            return $invoices;
    }

    public function statementExport(Request $request)
    {

        $from_date         = $request->from_date ? date('Y-m-d', strtotime($request->from_date)) : date('Y-m-d');
        $to_date           = $request->to_date ? date('Y-m-d', strtotime($request->to_date)) : date('Y-m-d');

        $invoices = $this->query($request);
        $invoices = $invoices->toArray();

        $fileName = 'Stock-out-Statements'.' From '.$from_date.' To '.$to_date.'.xlsx';

        return Excel::download(new StockOutExportStatement($invoices), $fileName);
    }
}
