<?php

namespace App\Http\Controllers\Frontend;

use App\Models\CsrRedemptionSetting;
use App\Models\Purchase;
use App\Models\User;
use App\Models\CSRNow\User as CsrNowUser;
use App\Models\UserTeamsiteLicense;
use App\Models\WalletLog;
use App\Services\BigNumber;
use Illuminate\Support\Facades\Http;
use PDF;
use App\Models\BV;
use Carbon\Carbon;
use App\Models\Cart;
use App\Models\Wallet;
use App\Models\GiftCode;
use App\Models\WalletList;
use App\Jobs\SendEmailJob;
use App\Models\LoginAttempt;
use Illuminate\Http\Request;
use App\Models\SiteConfiguration;
use App\Mail\GiftCodeRedeemed;
use App\Mail\GiftCodeRedeemedBy;
use App\Mail\GiftCodeSendBy;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use App\Models\ProductStaticOption;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\URL;
use App\Http\Controllers\Controller;
use App\Mail\GiftCodeSend;
use App\Models\Member;
use Illuminate\Support\Facades\Auth;
use Illuminate\Contracts\View\Factory;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Contracts\Foundation\Application;
use App\Models\ProductStaticOptionWallet;
use App\Models\Withdrawal;
use Illuminate\Support\Facades\Log;

class OrderController extends Controller
{
    /**
     * View product page
     *
     * @return Application|array|Factory|View
     */
    public function index(Request $request)
    {
        $product = ProductStaticOption::where('type',1)->orderBy('price','asc')->get();
        $csrSellingPrice = getCurrentTokenAndPrice(true) ?? 0;
        $licence = ProductStaticOption::where('type',2)->latest()->first();

        $walletBalance = getOCACurrentBalance();
        $bonusWalletBalance = getBonusWalletCurrentBalance();

        $guestMode = false;
        $guestCookie = $request->cookie('guest_mode');
        if (!empty($guestCookie) && $guestCookie == 'guest') {
            $guestMode = true;
        }

        $maintain = "member.loginSendToken";

        $isLogin = "Yes";
        $showMessage = "";
        $totalLockMinute = 60;
        $getAttempt = LoginAttempt::where('ip_address', getClientIp($request))->first();
        $loginDays = SiteConfiguration::where('key', 'remember_me')->value('value');
        if ($getAttempt) {
            $myAttempt = $getAttempt->attempt;
            $keys = SiteConfiguration::LOGIN_ATTEMPT;
            unset($keys['IDLE_TIME']);
            $settings = SiteConfiguration::whereIn('key', $keys)->get();
            $totalLockMinute = $settings[1]->value * 60;
            $showMessage = $settings[2]->value;
            if ($myAttempt >= $settings[0]->value) {
                if ($getAttempt->next_login_time >= Carbon::now()->toDateTimeString()) {
                    $carbonNow = Carbon::now();
                    $totalLockMinute = $carbonNow->diffInMinutes($getAttempt->next_login_time);
                    $isLogin = "No";
                } else {
                    $getAttempt->delete();
                }
            }
        }
        $settings = SiteConfiguration::where('key', 'login_idle_time')->first();

        $temp = 1;
        if ($settings) {
            $temp = (int) $settings->value;
        }
        $cartProductsCount = Cart::where('user_id', Auth::id())->count();
        Session::put('url.intended', route('member.shop.index'));
        return view('frontend.products.index', compact('csrSellingPrice','cartProductsCount','walletBalance', 'bonusWalletBalance', 'product', 'licence', 'guestMode', 'maintain', 'isLogin', 'showMessage', 'totalLockMinute', 'temp', 'loginDays'));
    }

    public function addToCart(Request $request)
    {
        if (readOnlyMode()) {
            return response()->json([
                'status' => false,
                'msg' => __('Feature disabled whilst in switched user mode.'),
            ], Response::HTTP_FORBIDDEN);
        }

        $product_id = null;
        if ($request->product_id) {
            $product_id = basicDecrypt($request->product_id);
            $product = ProductStaticOption::where('id',$product_id)->first();
            $price = $product->price;
            $cart = Cart::where('user_id', Auth::id())->where('product_static_option_id', $product_id)->first();

            /*---- START for check balance ----*/
            if ($product->type == 1){
                $productFound = 1;
            } else {
                $productFound = Cart::with('productStaticOption')->where('user_id',Auth::id())
                ->whereHas("productStaticOption", function ($q) {
                    $q->where('type', 1);
                })->count();
            }

            $OCAWalletBalance = getOCACurrentBalance();
            if($productFound > 0) {
                $walletBalance = $OCAWalletBalance;
            } else {
                $walletBalance = getBonusWalletCurrentBalance();
                if (empty($walletBalance) || $walletBalance <= 0 || $walletBalance < $OCAWalletBalance){
                    $walletBalance = $OCAWalletBalance;
                }
            }

            $tax = calculateTax($price)['total_tax'];
            $productTotalAmount = calculateCartTotalAmount() + $price + $tax;
            if ($productTotalAmount > $walletBalance) {
                return response()->json(['success' => false, 'message' => 'You have insufficient balance for purchase product.']);
            }
            /*---- END for check balance ----*/

            $csrSellingPrice = getCurrentTokenAndPrice(true) ?? 0;
            if ($cart) {
                $cart->price = $price;
                $cart->quantity = $cart->quantity + 1;
                $cart->save();
            } else {
                $input['user_id'] = Auth::id();
                $input['quantity'] = 1;
                $input['price'] = $input['static_frequency'] = $price;
                $input['csr'] = round($price / $csrSellingPrice);
                $input['amount'] = $input['csr'] / 10;
                $input['product_static_option_id'] = $product_id;
                Cart::create($input);
            }
            return response()->json(['success' => true, 'message' => 'Product added to cart successfully']);
        } else {
            return response()->json(['success' => true, 'message' => 'Please Select Product']);
        }
    }

    /**
     * cart
     *
     * @return view
     */
    public function cartDetail()
    {
        $cart = Cart::with('productStaticOption')->where('user_id', Auth::id())->get();
        $subTotal = $quantity = 0;
        foreach ($cart as $row){
            $subTotal += ($row->quantity * $row->price);
            $quantity += $row->quantity;
        }
        $taxArray = calculateTax($subTotal);
        $tax = $taxArray['total_tax'] ?? 0;
        $data = [
            'qty' => $quantity,
            'subtotal' => $subTotal,
            'tax' => $tax,
            'taxData' => $taxArray['tax_data']['details'] ?? null,
            'total' => $subTotal + $tax,
        ];
        return response()->json($data);
    }
    /**
     * cartAll
     *
     * @param Request $request
     * @return array
     */
    public function cartAll(Request $request)
    {
        $search = $request->filter;
        $filter = (array) json_decode($search);
        $sort   = $request->sort ?: 'created_at';
        $order  = $request->order ?: 'desc';
        $offset = $request->offset;
        $limit  = $request->limit;
        $sort   = $sort == "counter" ? "id" : $sort;
        $query  = Cart::with('productStaticOption')->where('user_id', Auth::id())
            ->when($search, function ($q) use ($filter) {
                foreach ($filter as $key => $item) {
                    if ($item) {
                        $q->where($key, 'like', $item . '%');
                    }
                }
            })->orderBy($sort, $order);

        $count = $query->count();
        $row = $query->when($offset, function ($q) use ($offset) {
            $q->offset($offset);
        })->when($limit, function ($q) use ($limit) {
            $q->limit($limit);
        })->get()->toArray();

        $index = $offset + 1;
        $totalSum = 0;
        $totalCartQuantity = 0;
        foreach ($row as $key => $item) {
            $encryptId = "'" . basicEncrypt($item['id']) . "'";
            $removeUser = "'" . route('member.shop.removeCartProduct') . "'";

            $row[$key]['counter']  = $index;
            $row[$key]['name']     = $item['product_static_option']['title'] ?? 'Plastic Neutrality Package - ' . $item['price'];
            if(isset($item['product_static_option']['type']) && $item['product_static_option']['type'] == 1){
                $kg = $item['amount'] ?? 0;
                $row[$key]['name'] .= "<br/><span class='package-detail'>".formatDisplayNumber($kg)." kg of Plastic Waste Removal Service</span>";
            }
            $row[$key]['quantity'] = '<div class="input-group my-2">
                <span class="input-group-text decrement quantityBtn cursor-pointer" data-cart-id="'. $encryptId .'" data-id="'. $item['id'] . '" data-old="' . ($item['quantity'] ?? 0) . '">'.renderIconHtml('minus','fs-3').'</span>
                <input class="form-control form-control-sm quantity cart-quantity-validation text-center" id="quantity'. $item['id'] . '" data-id="' . $encryptId . '" data-old="'. ($item['quantity'] ?? 0) .'" value="' . ($item['quantity'] ?? 0) . '" type="text">
                <span class="input-group-text increment quantityBtn cursor-pointer" data-cart-id="' . $encryptId . '" data-id="' . $item['id'] . '" data-old="' . ($item['quantity'] ?? 0) . '">'.renderIconHtml('add','fs-3').'</span>
            </div>';
            $row[$key]['price']    = "€".number_format(($item['quantity'] * $item['price']),2,'.',',');
            $row[$key]['action']   = '<a class="editBtn delete" href="javascript:void(0);" onclick="removeProduct(' . $encryptId . ',' . $removeUser . ')" data-toggle="tooltip" data-placement="top" title="Delete"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 6H5H21" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8 6V4C8 3.46957 8.21071 2.96086 8.58579 2.58579C8.96086 2.21071 9.46957 2 10 2H14C14.5304 2 15.0391 2.21071 15.4142 2.58579C15.7893 2.96086 16 3.46957 16 4V6M19 6V20C19 20.5304 18.7893 21.0391 18.4142 21.4142C18.0391 21.7893 17.5304 22 17 22H7C6.46957 22 5.96086 21.7893 5.58579 21.4142C5.21071 21.0391 5 20.5304 5 20V6H19Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 11V17" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14 11V17" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg></a>';

            $totalSum = $totalSum + $item['price'] * ($item['quantity'] ?? 0);
            $totalCartQuantity += ($item['quantity'] ?? 0);
            $index++;
        }
        if (count($row) == 0) {
            $count = 0;
        }

        $productFound = Cart::with('productStaticOption')->where('user_id',Auth::id())
            ->whereHas("productStaticOption", function ($q) {
                $q->where('type', 1);
            })->count();

        if($productFound > 0) {
            $walletsList = WalletList::where('id', 1)->get();
        } else {
            $productStaticOptionIds = Cart::where('user_id',Auth::id())->pluck('product_static_option_id');
            $walletListIds = ProductStaticOptionWallet::select('wallet_id')
                ->whereIn('product_static_option_id', $productStaticOptionIds)
                ->groupBy('wallet_id')
                ->havingRaw('COUNT(DISTINCT product_static_option_id) = ?', [$productStaticOptionIds->count()]);

            $walletsList = WalletList::whereHas('wallet', function ($q) use ($walletListIds) {
                $q->whereIn('wallet_list_id', $walletListIds)->where('user_id',Auth::id())->where('balance', '>', 0);
            })->get();
        }

        $taxArray = calculateTax($totalSum);
        $totalTax = $taxArray['total_tax'] ?? 0;
        return [
            'items' => $row,
            'count' => $count,
            'totalCartQuantity' => $totalCartQuantity,
            'totalSum' => $totalSum,
            'totalTax' => $totalTax,
            'taxData' => $taxArray['tax_data']['details'] ?? null,
            'finalSum' => $totalSum+$totalTax,
            'walletsList' => $walletsList,
        ];
    }
    /**
     * confirmYourOrder
     *
     * @return view
     */
    public function confirmYourOrder(Request $request)
    {
        return view('frontend.products.confirm-order');
    }
    /**
     * removeCartProduct
     *
     * @param Request $request
     * @return jsonResponse
     */
    public function removeCartProduct(Request $request)
    {
        if (readOnlyMode()) {
            return response()->json([
                'status' => false,
                'msg' => __('Feature disabled whilst in switched user mode.'),
            ], Response::HTTP_FORBIDDEN);
        }
        $cart = Cart::find(basicDecrypt($request->cartId));
        if($cart) {
            $cart->delete();
            return response()->json(['success' => true]);
        }
        return response()->json(['success' => false]);
    }
    /**
     * checkCashAmount
     *
     * @return jsonResponse
     */
    public function checkCashAmount()
    {
        if (readOnlyMode()) {
            return response()->json([
                'status' => false,
                'msg' => __('Feature disabled whilst in switched user mode.'),
            ], Response::HTTP_FORBIDDEN);
        }
        $wallet = Wallet::where(['user_id' => Auth::id(),'type' => Wallet::TYPE_CASH])->first();
        $cartProducts = Cart::where('user_id', Auth::id())->get();

        $productTotalAmount = 0;
        foreach ($cartProducts as $cart){
            $productTotalAmount += $cart->quantity * $cart->price;
        }

        if ($productTotalAmount == 0) {

            return response()->json(['success' => false, 'msg' => 'Please at-least one product in cart.']);
        }

        if ($wallet && $productTotalAmount < $wallet->balance) {
            return response()->json(['success' => true]);
        }
        return response()->json(['success' => false, 'msg' => 'You have insufficient amplivo cash amount.']);
    }
    /**
     * myGiftCode
     *
     * @return view
     */
    public function myGiftCode(Request $request)
    {
        $transactionId = $request->transaction_id ?? null;
        return view('frontend.products.my-gift-code', compact('transactionId'));
    }
    /**
     * myGiftCodeAll
     *
     * @param Request $request
     * @return array
     */
    public function myGiftCodeAll(Request $request)
    {
        $search = $request->filter;
        $filter = (array) json_decode($search);
        $sort   = $request->sort ?: 'created_at';
        $order  = $request->order ?: 'desc';
        $offset = $request->offset;
        $limit  = $request->limit;
        $sort   = $sort == "counter" ? "id" : $sort;

        $query = GiftCode::with(['purchaseProduct', 'purchaseProduct.ProductStaticOption', 'purchaseProduct.walletLog','transferredUser','user'])->with('redeemedBy');

        $query->where(function ($q) {
            $q->where('user_id', Auth::id())
              ->orWhere('transferred_user_id', Auth::id());
        });

        if ($request->transaction_id){
            $query->whereHas("purchaseProduct.walletLog", function ($q) use ($request) {
                $q->where("transaction_id", $request->transaction_id);
            });
        }

        $query->when($search, function ($q) use ($filter) {
            foreach ($filter as $key => $item) {
                if ($item) {
                    if ($key == 'name') {
                        if ($item == 'Plastic Neutrality Package'){
                            $q->whereHas("purchaseProduct", function ($q) use ($item) {
                                $q->whereNull('product_static_option_id');
                            });
                        } else {
                            $q->whereHas("purchaseProduct", function ($q) use ($item) {
                                $q->whereHas("ProductStaticOption", function ($q) use ($item) {
                                    $q->where('title', 'like', '%' . $item . '%');
                                });
                            });
                        }

                    } else if ($key == 'price') {
                        $q->whereHas("purchaseProduct", function ($q) use ($item) {
                            $q->where("price", [$item]);
                        });
                    } else if ($key == 'transaction_id') {
                        $q->whereHas("purchaseProduct.walletLog", function ($q) use ($item) {
                            $q->where("transaction_id", $item);
                        });
                    } else if ($key == 'package_date') {
                        $q->whereHas("purchaseProduct", function ($q) use ($item) {
                            $dates = explode(' - ', $item);
                            $startDate = createFromFormatCustom($dates[0]);
                            $endDate = createFromFormatCustom($dates[1]);
                            $q->whereDate('created_at', '>=', $startDate)->whereDate('created_at', '<=', $endDate);
                        });
                    } else if ($key == 'expiration_date') {
                        $dates = explode(' - ', $item);
                        $startDate = createFromFormatCustom($dates[0]);
                        $endDate = createFromFormatCustom($dates[1]);
                        $q->whereDate('expire_date', '>=', $startDate)->whereDate('expire_date', '<=', $endDate);
                    } else if ($key == 'redeemed_date') {
                        $dates = explode(' - ', $item);
                        $startDate = createFromFormatCustom($dates[0]);
                        $endDate = createFromFormatCustom($dates[1]);
                        $q->whereDate('redeemed_date', '>=', $startDate)->whereDate('redeemed_date', '<=', $endDate);
                    }   else if ($key == 'redeem_by') {
                        $externalId = CsrNowUser::where('username', 'LIKE', '%' . trim($item) . '%')->pluck('id');
                        $userId = User::whereIntegerInRaw('external_id',$externalId)->pluck('id');
                        $q->whereIntegerInRaw('redeem_by',$userId);
                    } else if ($key == 'transferred_by') {
                        $externalId = CsrNowUser::where(DB::raw("CONCAT(first_name,' ',last_name)"), 'LIKE', '%' . trim($item) . '%')->pluck('id');
                        $userId = User::whereIntegerInRaw('external_id',$externalId)->pluck('id');
                        $q->whereNotNull('transferred_user_id')->whereIntegerInRaw('user_id',$userId);
                    } else if ($key == 'transferred_to') {
                        $externalId = CsrNowUser::where(DB::raw("CONCAT(first_name,' ',last_name)"), 'LIKE', '%' . trim($item) . '%')->pluck('id');
                        $userId = User::whereIntegerInRaw('external_id',$externalId)->pluck('id');
                        $q->whereIntegerInRaw('transferred_user_id',$userId);
                    } else if ($key == 'status') {
                        if ($item === 'Pending') {
                            $q->where("status", 1);
                        } else if ($item === 'Redeemed') {
                            $q->where("status", 2);
                        } else if ($item === 'Rejected') {
                            $q->where("status", 4);
                        } else if ($item === 'Canceled') {
                            $q->where("status", 5);
                        } else if ($item === 'Expired') {
                            $q->where(function ($q) {
                                $q->where("status", 3);
                                $q->orWhereDate("expire_date", '<', date('Y-m-d'));
                            });
                        }
                    }  else {
                        $q->where($key, 'like', '%' . $item . '%');
                    }
                }
            }
        })->orderBy($sort, $order);

        $count = $query->count();
        $row = $query->when($offset, function ($q) use ($offset) {
            $q->offset($offset);
        })->when($limit, function ($q) use ($limit) {
            $q->limit($limit);
        })->get()->toArray();
        $index = $offset + 1;
        foreach ($row as $key => $item) {
            $redeemGiftCodeUrl = route('member.redeemGiftCode', basicEncrypt($item['id']));
            $transactionId = $item['purchase_product']['wallet_log'] ? basicEncrypt($item['purchase_product']['wallet_log']['transaction_id']) :'';
            $invoiceUrl = route('member.showInvoice',$transactionId);
            $price =  $item['purchase_product']['price'] ?? 0;
            $redeemBy = isset($item['redeemed_by']['details']) ? ($item['redeemed_by']['details']['username'] ?? ''): '-';
            $productName = $item['purchase_product']['product_static_option']['title'] ?? 'Plastic Neutrality Package';
            $row[$key]['counter']         = $index;
            $row[$key]['name']            = $item['purchase_product']['product_static_option']['title'] ?? 'Plastic Neutrality Package';
            $row[$key]['transaction_id']  = $item['purchase_product']['wallet_log'] && $item['purchase_product']['wallet_log']['transaction_id'] ? '<span class="text-monospace"><a class="text-primary" href="'. route('member.transactions.memberTransactions',['id' => $item['purchase_product']['wallet_log']['transaction_id']]) .'">'. $item['purchase_product']['wallet_log']['transaction_id'] .'</a><a target="_blank" href="' . $invoiceUrl . '" class="ms-1 text-primary"><i class="bi bi-filetype-pdf" title="Invoice"></i></a></span>' : '-';
            $row[$key]['price']           = formatDisplayNumber($price);
            $row[$key]['gift_code']       = '<span class="text-monospace">'. $item['gift_code'] . '</span> <span class="cursor-pointer gift_code" id="copyGiftCode" data-clipboard-text="'. $item['gift_code'] .'" data-toggle="tooltip" data-placement="top" title="Copy To Clipboard" ><i class="bi bi-copy"></i></span>';
            $row[$key]['package_date']    = getDateWithIcon($item['purchase_product']['created_at']);
            $row[$key]['expiration_date'] = getDateWithIcon($item['expire_date']);
            $row[$key]['redeemed_date'] = isset($item['redeemed_date']) ? getDateWithIcon($item['redeemed_date']) : '-';
            $row[$key]['redeem_by']       = $redeemBy;
            $row[$key]['transferred_to']  = isset($item['transferred_user']['details']) ? ($item['transferred_user']['details']['first_name'] ?? '')." ".($item['transferred_user']['details']['last_name'] ?? '') : '-';
            $row[$key]['transferred_by'] = '-';
            if(isset($item['transferred_user_id'])){
                $row[$key]['transferred_by']  = isset($item['user']['details']) ? ($item['user']['details']['first_name'] ?? '')." ".($item['user']['details']['last_name'] ?? '') : '-';
            }

            $action = '';
            if ($item['status'] == 3 || (strtotime(date('Y-m-d')) > strtotime($item['expire_date']))) {
                $row[$key]['status'] = 'Expired';
            } else if ($item['status'] == 2) {
                $row[$key]['status'] = 'Redeemed';
            } else if ($item['status'] == 1) {
                $row[$key]['status'] = 'Pending';
                if(!isset($item['transferred_user_id']) || $item['transferred_user_id'] == Auth::user()->id){
                    // ---- Redeem Button
                    if ((!empty(Auth::user()->setting->fa_setting) && in_array('redeem_gift_code', Auth::user()->setting->fa_setting)) || !empty(Auth::user()->setting->fa3_setting) && in_array('redeem_gift_code', Auth::user()->setting->fa3_setting)) {
                        $action .= '<a class="editBtn btn btn-sm btn-primary" target="__blank" href="' . $redeemGiftCodeUrl . '" data-toggle="tooltip" data-placement="top" title="' . __('Redeem Gift Code') . '">'.renderIconHtml('gift').''. __('Redeem Gift Code') . '</a>';
                    } else {
                        $action .= '<a class="btn btn-sm btn-primary opacity-75" href="javascript:void(0)" disabled>'.__('Redeem Gift Code').' <i class="bi bi-info-circle" data-toggle="tooltip" data-placement="top" title="'.__('Enable 2FA authenticator to redeem gift code.').'"></i></a>';
                    }
                 }

                if($item['transferred_user_id'] != Auth::user()->id){
                    // ---- Cancel Button
                    if ((!empty(Auth::user()->setting->fa_setting) && in_array('cancel_gift_code', Auth::user()->setting->fa_setting)) || !empty(Auth::user()->setting->fa3_setting) && in_array('cancel_gift_code', Auth::user()->setting->fa3_setting)){
                        $action .= '<button class="btn btn-sm btn-danger ms-1" onClick="cancelGiftCode($(this))" data-giftcode="'.$item['gift_code'].'" data-id="'.basicEncrypt($item['id']).'" data-toggle="tooltip" data-placement="top" title="'.__('Cancel Gift Code').'">'.renderIconHtml('cancel').''.__('Cancel').'</button>';
                    } else {
                        $action .= '<a class="btn btn-sm btn-danger ms-1 opacity-75" href="javascript:void(0)" disabled>'.renderIconHtml('cancel').''.__('Cancel').' <i class="bi bi-info-circle" data-toggle="tooltip" data-placement="left" title="'.__('Enable 2FA authenticator to cancel gift code.').'"></i></a>';
                    }
                }
                if(!isset($item['transferred_user_id'])){
                    // ---- Transfer Button
                    if ((!empty(Auth::user()->setting->fa_setting) && in_array('send_gift_code', Auth::user()->setting->fa_setting)) || !empty(Auth::user()->setting->fa3_setting) && in_array('send_gift_code', Auth::user()->setting->fa3_setting)){
                        $action .= '<button class="btn btn-sm btn-primary ms-1" onClick="transferGiftCode($(this))" data-giftcode="'.$item['gift_code'].'" data-id="'.basicEncrypt($item['id']).'"  data-product-name="'.$productName.'" data-toggle="tooltip" data-placement="top" title="'.__('Send Gift Code').'">'.renderIconHtml('send').''.__('Send').'</button>';
                    } else {
                        $action .= '<a class="btn btn-sm btn-primary ms-1 opacity-75" href="javascript:void(0)" disabled>'.renderIconHtml('send').''.__('Send').' <i class="bi bi-info-circle" data-toggle="tooltip" data-placement="left" title="'.__('Enable 2FA authenticator to send gift code.').'"></i></a>';
                    }
                }
            } else if ($item['status'] == 4) {
                $row[$key]['status'] = 'Rejected';
            } else if ($item['status'] == 5) {
                $row[$key]['status'] = 'Canceled';
            }

            $row[$key]['action'] = $action;

            $index++;
        }
        if (count($row) == 0) {
            $count = 0;
        }
        return [
            'items' => $row,
            'count' => $count,
        ];
    }

    public function cancelGiftCode(Request $request)
    {
        $request->validate([
            'gift_code_id' => 'required',
        ]);

        $giftCodeId = basicDecrypt($request->gift_code_id);
        $giftCode = GiftCode::find($giftCodeId);

        if ($giftCode->status == 1){
            $walletLog = $giftCode->purchaseProduct->walletLog ?? null;
            $walletId = $walletLog->wallet_id ?? null;
            if (!empty($walletId)){
                $wallet = Wallet::find($walletId);
                if ($wallet) {
                    $amount = $giftCode->purchaseProduct->price;
                    $updatedBalance = (double) $wallet->balance + (double) $amount;
                    $wallet->balance = $updatedBalance;
                    $wallet->save();

                    // ---- START for wallet Log
                    $action = WalletLog::ACTION_CREDIT;

                    $data['actionBy'] = '';
                    $data['user_id'] = Auth::id();
                    $data['external_comment'] = $request->external_comments;
                    $data['internal_comment'] = $request->internal_comment;
                    $data['canceled_gift_code'] = $giftCode->gift_code;

                    WalletLog::create([
                        'wallet_id' => $wallet->id,
                        'action' => $action,
                        'data' => json_encode($data),
                        'value' => $amount,
                        'balance' => $wallet->balance,
                    ]);

                    $log = 'Transaction of amount '. formatDisplayNumber($amount) . ' has been credited in '. $wallet->wallet_list->name .' against canceled gift code ('. $giftCode->gift_code . ')';
                    saveLog($log, Auth::user(), [], 'credited');
                    // --- Update status

                    $giftCode->status = 5;
                    $giftCode->save();

                    $logMessage = 'Gift code ' . $giftCode->gift_code . ' has been successfully canceled';
                    saveLog($logMessage, Auth::user(), ['logType' => 'gift_code'], 'GiftCode');

                    return response()->json(['success' => true, 'msg' => __("Gift code canceled successfully.")]);
                }
            }
            return response()->json(['success' => false,'msg' => __("Something went wrong try again.")]);
        } else {
            return response()->json(['success' => false,'msg' => __("You can't cancel this gift code.")]);
        }
    }

    public function getSearchedMembers(Request $request)
    {
        $query = $request->term;
        $data = [];
        $loginUserCountry = Auth::user()->details->address->country_id;
        $loginUserRegion = Auth::user()->details->address->state_id;
        $loggedInUserId = Auth::user()->id;

        if ($query) {
            $externalIds = CsrNowUser::with('hasRole','address')
                        ->whereHas('hasRole', function ($q){
                            $q->whereHas('role',function ($q){
                                $q->where('name','member');
                            });
                        })
                        ->whereHas('address', function ($query) use ($loginUserCountry, $loginUserRegion) {
                            $query->where('country_id', $loginUserCountry);
                            if (!empty($loginUserRegion)) {
                                $query->where('state_id', $loginUserRegion);
                            }
                        })
                        ->where(function ($q) use ($query) {
                            $q->where('username', 'LIKE', '%' . trim($query) . '%')
                                        ->orWhere('email', 'LIKE', '%' . trim($query) . '%');
                        })
                        ->pluck('id');

            $allowedUserIds = User::whereIn('external_id',$externalIds)->whereNot('id',Auth::user()->id)->pluck('id')->toArray();

            $member = Member::where('user_id', Auth::user()->id)->first();
            $downlines = $member->allDownlines($member)->get();
            $this->addMembersToData($downlines, $data, $loggedInUserId, $query, 'downline',$allowedUserIds);
        }

        return response()->json(['items' => $data]);
    }

    public function checkDownlineUser($selectedUserId)
    {
        $selectedUser = Member::with('user')->where('user_id', $selectedUserId)->first();

        $level = $selectedUser->level ?? '-';
        return response()->json(['success' => true,'msg' => "This member is positioned on level $level in your downline.",'data' => $selectedUser]);
    }

    public function addMembersToData($members, &$data, $loggedInUserId, $filter, $direction, $allowedUserIds = [])
    {
        foreach ($members as $item) {
            $user = $item->user;

            // Recurse first to go deep into the tree regardless of current user match
            if ($direction === 'upline') {
                $nestedMembers = $item->allUplines()->get();
            } else {
                $nestedMembers = $item->allDownlines()->get();
            }

            $this->addMembersToData($nestedMembers, $data, $loggedInUserId, $filter, $direction, $allowedUserIds);

            // Only process and add if user is in allowed list
            if (
                $user &&
                $user->id !== $loggedInUserId &&
                in_array($user->id, $allowedUserIds)
            ) {
                $username = strtolower($user->details->username ?? '');
                $email = strtolower($user->details->email ?? '');
                $filter = strtolower($filter);

                if (
                    str_contains($username, $filter) ||
                    str_contains($email, $filter)
                ) {
                    $data[] = [
                        'id' => $user->id,
                        'text' => $user->details->username . ' ( ' . $user->details->email . ' )'
                    ];
                }
            }
        }
    }

    public function transferGiftCode(Request $request)
    {
        if(in_array('send_gift_code', Auth::user()->setting->fa_setting) || in_array('send_gift_code', Auth::user()->setting->fa3_setting)) {
            if(!Session::has('transferGiftCode2faVerification') || (Session::has('transferGiftCode2faVerification') && Session::get('transferGiftCode2faVerification') !== true)) {
                return response()->json(['status' => false, 'msg' => 'Can`t submit form without authentication code '], Response::HTTP_UNPROCESSABLE_ENTITY);
            } else {
                Session::forget('transferGiftCode2faVerification');
            }
        }

        $request->validate([
            'gift_code_id' => 'required',
            'transferred_user_id' => 'required',
        ],[
            'transferred_user_id.required' => 'The user field is required.',
        ]);
        $giftCode = GiftCode::with('user','purchaseProduct','transferredUser')->findOrFail(basicDecrypt($request->gift_code_id));
        $giftCode->transferred_user_id = $request->transferred_user_id;
        $giftCode->update();
        $transferredUser = User::with('details')->find($request->transferred_user_id);

        $logMessage = "Gift code ".$giftCode->gift_code." has successfully sent from ".(Auth::user()->details->first_name ?? '')." ".(Auth::user()->details->last_name ?? '')." to ".($transferredUser->details->first_name ?? '')." ".($transferredUser->details->last_name ?? '');
        saveLog($logMessage, Auth::user(), ['logType' => 'gift_code'], 'GiftCode', $transferredUser);
        $log = "Gift code ".$giftCode->gift_code." has successfully received by ".($transferredUser->details->first_name ?? '')." ".($transferredUser->details->last_name ?? '');
        saveLog($log, Auth::user(), ['logType' => 'gift_code'], 'GiftCode');

        // Notification for sender
         $senderDetails = [
            'sender_name' => (Auth::user()->details->first_name ?? '')." ".(Auth::user()->details->last_name ?? ''),
            'receiver_name' => ($transferredUser->details->first_name ?? '')." ".($transferredUser->details->last_name ?? ''),
            'gift_code' => $giftCode->gift_code,
            'subject' => "Gift Code Sent",
        ];
        $emailSwitch = getEmailSettings('send_gift_code');
        if($emailSwitch == 'on'){
            $emailClassRef = new GiftCodeSend($senderDetails);
            SendEmailJob::dispatch($giftCode->user->details->email, $emailClassRef);
        }
        $message = 'You have successfully sent a gift code '. $giftCode->gift_code .' to ' . $transferredUser->details->first_name . ' ' . $transferredUser->details->last_name;
        createNotification(
            'Gift Code Sent',
            $message,
            $giftCode->user_id);

        $receiverDetails = [
            'name' => ($transferredUser->details->first_name ?? '')." ".($transferredUser->details->last_name ?? ''),
            'gift_code' => $giftCode->gift_code,
            'subject' => "Gift Code Received",
        ];
        // Notification for receiver
        $emailSwitch = getEmailSettings('send_gift_code');
        if($emailSwitch == 'on'){
            $emailClassRef = new GiftCodeSendBy($receiverDetails);
            SendEmailJob::dispatch($transferredUser->details->email, $emailClassRef);
        }
        $message = 'You have received a gift code '.$giftCode->gift_code.' from ' . $giftCode->user->details->first_name . ' ' . $giftCode->user->details->last_name;
        createNotification(
            'Gift Code Received',
            $message,
            $request->transferred_user_id);

        return response()->json(['success' => true, 'msg' => __("Gift code send successfully.")]);
    }

    /**
     * redeemGiftCode
     *
     * @return view
     */
    public function redeemGiftCode($id)
    {
        $giftCard = GiftCode::with('user','purchaseProduct')->findOrFail(basicDecrypt($id));
        return view('frontend.products.redeem-code', compact('giftCard'));
    }
    public function redeemedGiftCode()
    {
        return view('frontend.products.redeemed-gift-code');
    }
    public function redeemedGiftCodeAll(Request $request)
    {
        $search = $request->filter;
        $filter = (array) json_decode($search);
        $sort   = $request->sort ?: 'created_at';
        $order  = $request->order ?: 'desc';
        $offset = $request->offset;
        $limit  = $request->limit;
        $sort   = $sort == "counter" ? "id" : $sort;

        $query = GiftCode::with('purchaseProduct','purchaseProduct.walletLog','purchaseProduct.ProductStaticOption')->with('redeemedBy')->where(function($q) {
            $q->where('redeem_by', Auth::id());
        })->whereNotNull('redeem_by')
            ->when($search, function ($q) use ($filter) {
                foreach ($filter as $key => $item) {
                    if ($item) {
                        if ($key == 'name') {
                            if ($item == 'Plastic Neutrality Package'){
                                $q->whereHas("purchaseProduct", function ($q) use ($item) {
                                    $q->whereNull('product_static_option_id');
                                });
                            } else {
                                $q->whereHas("purchaseProduct", function ($q) use ($item) {
                                    $q->whereHas("ProductStaticOption", function ($q) use ($item) {
                                        $q->where('title', 'like', '%' . $item . '%');
                                    });
                                });
                            }
                        } else if ($key == 'transaction_id') {
                            $q->whereHas("purchaseProduct", function ($q) use ($item) {
                                $q->whereHas("walletLog", function ($q) use ($item) {
                                    $q->where('transaction_id', 'like', '%' . $item . '%');
                                });
                            });
                        }else if ($key == 'kgs_removed') {
                            $q->whereRaw('(COALESCE(principal_kgs, 0) + COALESCE(bonus_kgs, 0) + COALESCE(discount_kgs, 0)) = ?', [$item]);
                        }else if ($key == 'created_at') {
                            $dates = explode(' - ', $item);
                            $startDate = createFromFormatCustom($dates[0]);
                            $endDate = createFromFormatCustom($dates[1]);
                            $q->whereDate('redeemed_date', '>=', $startDate)->whereDate('redeemed_date', '<=', $endDate);
                         }
                        else if ($key == 'amount') {
                            $q->whereHas("purchaseProduct", function ($q) use ($item) {
                                $q->where('price', 'like', '%' . $item . '%');
                            });
                        }
                         else if ($key == 'type') {
                            $q->whereHas("purchaseProduct", function ($q) use ($item) {
                                $q->where('product_type', $item);
                            });
                        } else {
                            $q->where($key, 'like', '%' . $item . '%');
                        }
                    }
                }
            })->orderBy($sort, $order);

        $count = $query->count();
        $row = $query->when($offset, function ($q) use ($offset) {
            $q->offset($offset);
        })->when($limit, function ($q) use ($limit) {
            $q->limit($limit);
        })->get()->toArray();

        $index = $offset + 1;
        foreach ($row as $key => $item) {
            $transaction_id = $item['purchase_product']['wallet_log']['transaction_id'] ?? null;
            $row[$key]['counter']         = $index;
            $row[$key]['status']          = ($item['status'] == 4) ? 'Rejected' : 'Completed';
            $row[$key]['name']            = $item['purchase_product']['product_static_option']['title'] ?? 'Plastic Neutrality Package';
            $row[$key]['amount']          = formatDisplayNumber($item['purchase_product']['price']);
            $totalRemovedKgs              = $item['principal_kgs'] + $item['bonus_kgs'] + $item['discount_kgs'];
            $row[$key]['kgs_removed']     = formatDisplayNumber($totalRemovedKgs);
            $row[$key]['created_at']      = getDateWithIcon($item['redeemed_date']);
            $row[$key]['reference_no']    = '<span class="text-monospace">'.$item['reference_no'].'</span>';
            $row[$key]['type'] = $item['purchase_product']['product_type_name'] ?? '';

            $index++;
        }
        if (count($row) == 0) {
            $count = 0;
        }
        return [
            'items' => $row,
            'count' => $count,
        ];
    }
    /**
     * redeemGiftVoucher
     *
     * @param Request $request
     * @return jsonResponse
     */
    public function redeemGiftVoucher(Request $request)
    {
        if(in_array('redeem_gift_code', Auth::user()->setting->fa_setting) || in_array('redeem_gift_code', Auth::user()->setting->fa3_setting)) {
            if(!Session::has('redeemGiftCode2faVerification') || (Session::has('redeemGiftCode2faVerification') && Session::get('redeemGiftCode2faVerification') !== true)) {
                return response()->json(['status' => false, 'msg' => 'Can`t submit form without authentication code '], Response::HTTP_UNPROCESSABLE_ENTITY);
            } else {
                Session::forget('redeemGiftCode2faVerification');
            }
        }
        $giftCode = GiftCode::with('purchaseProduct')->find(basicDecrypt($request->gift_code_id));
        if($giftCode->transferred_user_id != Auth::user()->id && $giftCode->user_id != Auth::user()->id ){
            $message = "You can't redeem this gift code.";
            return response()->json(['status' => false, 'msg' => $message], Response::HTTP_UNPROCESSABLE_ENTITY);
        }
        if (readOnlyMode()) {
            return response()->json([
                'status' => false,
                'msg' => __('Feature disabled whilst in switched user mode.'),
            ], Response::HTTP_FORBIDDEN);
        }
        $validator = Validator::make($request->all(), [
            'gift_code' => 'required|exists:gift_codes',
        ], [
            'gift_code.exists' => 'The gift code is wrong.',
        ]);
        if ($validator->fails()) {
            $validatorFailed = $validator->failed();
            $logMessage = '';
            if ($validatorFailed['gift_code'] && isset($validatorFailed['gift_code']['Required'])) {
                $logMessage = (Auth::user()->details->first_name ?? '')." ".(Auth::user()->details->last_name ?? '') . ' has enter wrong gift code. ';
            } else if ($validatorFailed['gift_code'] && isset($validatorFailed['gift_code']['Exists'])) {
                $logMessage = (Auth::user()->details->first_name ?? '')." ".(Auth::user()->details->last_name ?? '') . ' has enter wrong gift code. ';
            }
            saveLog($logMessage, Auth::user(), ['logType' => 'gift_code'], 'GiftCode');
            return response()->json(['status' => false, 'errors' => $validator->messages(), 'msg' => $validator->messages()->all()], 422);
        }

        $exists = GiftCode::where('gift_code', $request->gift_code)->where('status', 2)->count();
        if ($exists > 0) {
            $logMessage = (Auth::user()->details->first_name ?? '')." ".(Auth::user()->details->last_name ?? '') . ' has enter used gift code. ';
            saveLog($logMessage, Auth::user(), ['logType' => 'gift_code'], 'GiftCode');
            return response()->json(['status' => false, 'msg' => 'The gift code is wrong.'], Response::HTTP_UNPROCESSABLE_ENTITY);
        }
        if ($giftCode->status == 5) {
            $logMessage = (Auth::user()->details->first_name ?? '')." ".(Auth::user()->details->last_name ?? '') . ' has enter canceled gift code. ';
            saveLog($logMessage, Auth::user(), ['logType' => 'gift_code'], 'GiftCode');
            return response()->json(['status' => false, 'msg' => 'The gift code has been cancelled and cannot be redeemed.'], Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        if ($giftCode) {
            if ((strtotime(date('Y-m-d')) > strtotime($giftCode->expire_date)) || $giftCode->status === 3){
                $logMessage = (Auth::user()->details->first_name ?? '')." ".(Auth::user()->details->last_name ?? '') . ' has enter expired gift code. ';
                saveLog($logMessage, Auth::user(), ['logType' => 'gift_code'], 'GiftCode');
                return response()->json(['status' => false, 'msg' => 'The gift code is expired.'], Response::HTTP_UNPROCESSABLE_ENTITY);
            } else if ($giftCode->status === 4){
                $logMessage = (Auth::user()->details->first_name ?? '')." ".(Auth::user()->details->last_name ?? '') . ' has enter rejected gift code. ';
                saveLog($logMessage, Auth::user(), ['logType' => 'gift_code'], 'GiftCode');
                return response()->json(['status' => false, 'msg' => 'The gift code is rejected.'], Response::HTTP_UNPROCESSABLE_ENTITY);
            }
            $giftCode->redeem_by = Auth::id();
            $giftCode->status = 2;
            $giftCode->redeemed_date = Carbon::now();
            // $giftCode->save();

            /** Add BV **/
            if ($giftCode->purchaseProduct->product_type == 1) { //---- product type is product
                $bvInput['user_id'] = Auth::id();
                $refBV = 0;
                for ($i = 1; $i <= 2; $i++) {
                    $bvInput['value'] = $giftCode->purchaseProduct->bv / 2;
                    $bvInput['origin'] = $i;
                    $dataArray = [];
                    if ($i == 2) {
                        $dataArray['reference_bv_id'] = $refBV;
                    }
                    $dataArray['gift_code_id'] = $giftCode->gift_code;
                    $bvInput['data'] = json_encode($dataArray);
                    $bvInput['source'] = BV::SOURCE_COUPON_REDEEM;
                    $bvInput['created_at'] = Carbon::now();
                    $data = BV::create($bvInput);
                    if ($i == 1) {
                        $refBV = $data->id;
                    }
                    saveLog("BV (value : " . $bvInput['value'] . ") created for gift code $giftCode->gift_code.", Auth::user(), ['logType' => 'BV'], 'BV');

                    calculateUserPerformance(Auth::id()); // ---- Calculate user performance runtime
                }
            } else { //---- product type is License
                $oldLicenseEndDate = UserTeamsiteLicense::where(['user_id' => Auth::id()])->orderBy('end','DESC')->value('end');
                if (empty($oldLicenseEndDate) || (!empty($oldLicenseEndDate) && date('Y',strtotime($oldLicenseEndDate)) < date('Y'))){
                    $oldLicenseEndDate = date('Y-m-d H:i:s');
                }
                $start = date('Y-m-d H:i:s',strtotime($oldLicenseEndDate));
                $end = date('Y-m-d 23:59:59', strtotime("$oldLicenseEndDate + 12 months"));
                UserTeamsiteLicense::create([
                    'user_id' => Auth::id(),
                    'gift_code_id' => $giftCode->id,
                    'type' => UserTeamsiteLicense::TYPE_12_MONTHS,
                    'start' => $start,
                    'end' => $end,
                ]);
                saveLog("Business License (Start Date:  $start , End Date: $end ) created for gift code $giftCode->gift_code.", Auth::user(), ['logType' => 'business_license'], 'BusinessLicense');

                calculateUserPerformance(Auth::id()); // ---- Calculate user performance runtime
            }

            $redeemed = [
                'name' => (Auth::user()->details->first_name ?? '')." ".(Auth::user()->details->last_name ?? ''),
                'price' => $giftCode->purchaseProduct->price,
                'redeemed_date' => Carbon::now(),
                'subject' => "Redeemed gift code",
            ];
            $emailClassRef = new GiftCodeRedeemed($redeemed);

            /*---- START for redemption ----*/
            if ($giftCode->purchaseProduct->product_type == 1) { //---- product type is product
                $csrAmount = $giftCode->purchaseProduct->csr;
                $randomRefNo = wordwrap(generateRandomCode(12), 4, "-", true);
                $referenceNo = "PNP-$randomRefNo";

                /*---- redemption ----*/
                $weekNumber = date('W');
                $CsrRedemptionSetting = CsrRedemptionSetting::whereDate('date',date('Y-m-d'))->first();

                $giftCode->reference_no = $referenceNo;
                $giftCode->principal_kgs = round(($csrAmount / 10)); //---- convert into kg
                $giftCode->save();

                $insertData = [
                    'gift_code' => $giftCode->gift_code,
                    'reference_no' => $referenceNo,
                    'csr_amount' => $csrAmount,
                    'source' => 'Purchase',
                    'redemption_date' => now(),
                    'pool_ref' => "PNP -" . date('Y') . "-" . $weekNumber,
                    'csr_redemption_setting' => null,
                ];
                if (!empty($CsrRedemptionSetting)) {
                    $weekWiseData = [];
                    if (strtolower($CsrRedemptionSetting->is_week_wise_advance) == strtolower('yes')){
                        $advance_week_percentage = explode(',',$CsrRedemptionSetting->primary_advance_week_percentage) ?? '';
                        foreach(explode(',',$CsrRedemptionSetting->primary_advance_week_number ?? '') as $key => $value){
                            $weekWiseData[] = [
                                'week_number' => $value,
                                'percentage' => $advance_week_percentage[$key] ?? 0,
                            ];
                        }
                    }

                    $insertData['csr_redemption_setting'] = [
                        'csr_segmentation' => $CsrRedemptionSetting->primary_csr_segmentation,
                        'no_of_deliveries' => $CsrRedemptionSetting->primary_no_of_deliveries,
                        'delivery_interval' => $CsrRedemptionSetting->primary_delivery_interval,
                        'delivery_start_week' => $CsrRedemptionSetting->primary_delivery_start_week,
                        'week_wise_advance_data' => $weekWiseData
                    ];
                }
                Http::withToken('Bearer ' . Session::get('api_login_token'))->withHeaders(getCsrNowApiHeader())->post(config('csrnow.api.live_endpoint') . 'auth/csr-redemption/store', $insertData);

                /*---- Bonus / Discount ----*/
                $promotionType = $CsrRedemptionSetting->promotion_type ?? null;
                $promotionValue = $CsrRedemptionSetting->promotion_value ?? null;
                $initialEuroAmount = $giftCode->purchaseProduct->price ?? null;
                if ($CsrRedemptionSetting && !empty($promotionType) && !empty($promotionValue)) {
                    if ($promotionType === 'Bonus') {
                        $bonusPercentage = BigNumber::create($promotionValue)->div(100)->value;
                        $csrRedemptionValue = BigNumber::create($csrAmount)->mul($bonusPercentage)->value;
                        $poolRefPrefix = 'BNS';

                        $giftCode->bonus_kgs = round(($csrRedemptionValue / 10)); //---- convert into kg
                        $giftCode->save();
                    } else {
                        $csrPriceAtPurchaseTime = BigNumber::create($giftCode->purchaseProduct->price)->div($giftCode->purchaseProduct->csr)->value;
                        $baseCsrPercentage = BigNumber::create($csrPriceAtPurchaseTime)->mul($promotionValue)->div(100)->value;
                        $discountCsrPercentage = BigNumber::create($csrPriceAtPurchaseTime)->sub($baseCsrPercentage)->value;
                        $discount = BigNumber::create($giftCode->purchaseProduct->price)->div($discountCsrPercentage)->value;
                        // ---- Final Bonus
                        $csrRedemptionValue = round(BigNumber::create($discount)->sub($csrAmount)->value);
                        $poolRefPrefix = 'DIS';

                        $giftCode->discount_kgs = round(($csrRedemptionValue / 10)); //---- convert into kg
                        $giftCode->save();
                    }

                    $insertData = [
                        'gift_code' => $giftCode->gift_code,
                        'reference_no' => "$poolRefPrefix-$randomRefNo",
                        'pool_ref' => $poolRefPrefix . "-" . date('Y') . "-" . $weekNumber,
                        'csr_amount' => $csrRedemptionValue,
                        'base_csr_amount' => $csrAmount,
                        'base_euro_amount' => $initialEuroAmount,
                        'csr_redemption_setting' => null,
                        'gift_code_reference_no' => $referenceNo = "PNP-$randomRefNo"
                    ];

                    $weekWiseData = [];
                    if (strtolower($CsrRedemptionSetting->is_week_wise_advance) == strtolower('yes')){
                        $advance_week_percentage = explode(',',$CsrRedemptionSetting->promotion_advance_week_percentage) ?? '';
                        foreach(explode(',',$CsrRedemptionSetting->promotion_advance_week_number ?? '') as $key => $value){
                            $weekWiseData[] = [
                                'week_number' => $value,
                                'percentage' => $advance_week_percentage[$key] ?? 0,
                            ];
                        }
                    }

                    $insertData['csr_redemption_setting'] = [
                        'type' => $CsrRedemptionSetting->promotion_type,
                        'csr_segmentation' => $CsrRedemptionSetting->promotion_csr_segmentation,
                        'no_of_deliveries' => $CsrRedemptionSetting->promotion_no_of_deliveries,
                        'delivery_interval' => $CsrRedemptionSetting->promotion_delivery_interval,
                        'delivery_start_week' => $CsrRedemptionSetting->promotion_delivery_start_week,
                        'promotion_value' => $promotionValue,
                        'week_wise_advance_data' => $weekWiseData,
                    ];

                    Http::withToken('Bearer ' . Session::get('api_login_token'))->withHeaders(getCsrNowApiHeader())->post(config('csrnow.api.live_endpoint') . 'auth/csr-award/store', $insertData);
                }
            } else {
                $randomRefNo = wordwrap(generateRandomCode(12), 4, "-", true);
                $referenceNo = "LIC-$randomRefNo";
                $giftCode->reference_no = $referenceNo;
                $giftCode->save();
            }
            /*---- END for redemption ----*/
            $emailSwitch = getEmailSettings('redeem_gift_code');
            if($emailSwitch == 'on'){
                SendEmailJob::dispatch(Auth::user()->details->email, $emailClassRef);
            }

            if($giftCode->user_id == $giftCode->redeem_by){
                $logMessage = 'Gift code '. $giftCode->gift_code .' has been successfully redeemed';
                saveLog($logMessage, Auth::user(), ['logType' => 'gift_code'], 'GiftCode');
            } else{
                $redeemedBy = [
                    'name' => ($giftCode->user->details->first_name ?? '')." ".($giftCode->user->details->last_name ?? ''),
                    'redeemedBy' => (Auth::user()->details->first_name ?? '')." ".(Auth::user()->details->last_name ?? ''),
                    'subject' => "Redeemed gift code",
                ];
                $emailSwitch = getEmailSettings('redeem_gift_code');
                if($emailSwitch == 'on'){
                    $emailClassRef = new GiftCodeRedeemedBy($redeemedBy);
                    SendEmailJob::dispatch($giftCode->user->details->email, $emailClassRef);
                }

                $logMessage = "Gift code $giftCode->gift_code has been redeemed by ". (Auth::user()->details->first_name ?? '')." ".(Auth::user()->details->last_name ?? '');
                saveLog($logMessage, Auth::user(), ['logType' => 'gift_code'], 'GiftCode', $giftCode->user);
                $log = 'Gift code '. $giftCode->gift_code .' has been successfully redeemed.';
                saveLog($log, Auth::user(), ['logType' => 'gift_code'], 'GiftCode');
            }
            return response()->json(['success' => true, 'msg' => 'Gift code redeemed successfully.', 'url' => route('member.GiftCodes')]);
        }
        return response()->json(['success' => false, 'msg' => 'Something is wrong.']);
    }
    public function redeemCode()
    {
        return view('frontend.products.redeem-code');
    }
    public function checkRedeemCode(Request $request)
    {
        $validated = $request->validate([
            'gift_code' => 'required'],
            [
                'gift_code.required' => 'The Gift Code field is required.',
            ]);

        $checkRedeemCode = GiftCode::with('purchaseProduct')->where('gift_code', $validated['gift_code'])->first();

        /*---- START to check gift code in v1 or not ----*/
        $checkAndGetGiftCodeFromV1 = getSiteSettings('check_and_get_giftcode_from_v1');
        if ($checkAndGetGiftCodeFromV1 == 'yes'){
            $apiCall = Http::get(config('datascraping.api.endpoint')."get-giftcode-data/".$validated['gift_code']);
            $response = $apiCall->object();
            if (isset($response->status) && $response->status === 'success'){
                $responseData = $response->data;
                $type = 1;
                if ($responseData->type != 'package'){
                    $type = 2;
                }
                $price = $responseData->price * 100;
                $product = ProductStaticOption::where(['price' => $price,'type' => $type])->first();
                if (!empty($product)) {
                    $purchase = Purchase::where(['product_static_option_id' => $product->id,'user_id' => $responseData->user_id])->orderBY('id','desc')->first();
                    if (!empty($purchase)){
                        $giftCode = GiftCode::where('purchase_id',$purchase->id)->first();
                        if ($giftCode->user_id != Auth::id()){
                            $giftCode->transferred_user_id = Auth::id();
                        }
                        $giftCode->gift_code = $validated['gift_code'];
                        $giftCode->save();

                        $checkRedeemCode = GiftCode::with('purchaseProduct')->where('gift_code', $validated['gift_code'])->first();
                    }
                }
            }
        }
        /*---- END to check gift code in v1 or not ----*/

        if ($checkRedeemCode) {
            $html = view('frontend.products.redeem-code-details', ['giftCard' => $checkRedeemCode])->render();
            $message = '';
            $success = false;
            if ($checkRedeemCode->status === 2) {
                $message = 'The gift code is redeemed.';
            } else if ($checkRedeemCode->status === 4) {
                $message = 'The gift code is rejected.';
            } else if ($checkRedeemCode->status === 3 || (strtotime(date('Y-m-d')) > strtotime($checkRedeemCode->expire_date))) {
                $message = 'The gift code is expired.';
            } else if($checkRedeemCode->transferred_user_id != Auth::user()->id && $checkRedeemCode->user_id != Auth::user()->id ){
                $message = "You can't redeem this gift code.";
                throw ValidationException::withMessages(['gift_code' => $message]);
            } else if ($checkRedeemCode->status === 1) {
                $success = true;
                $message = '';
            }
            return response()->json(['success' => $success, 'message' => $message, 'html' => $html,'checkRedeemCode' => $checkRedeemCode]);
        }
        throw ValidationException::withMessages(['gift_code' => 'The gift code is incorrect.']);
    }
    /**
     * placeOrder
     *
     * @return redirect
     */
    public function placeOrder(Request $request)
    {
        if (readOnlyMode()) {
            return response()->json([
                'status' => false,
                'msg' => __('Feature disabled whilst in switched user mode.'),
            ], Response::HTTP_FORBIDDEN);
        }

        if (!isMyProfileCompleted()){
            return response()->json([
                'status' => false,
                'msg' => __('Complete your profile to finalize your purchase.'),
            ]);
        }

        $request->validate([
            'wallet_id' => 'required',
        ]);

        /*---- START for check balance ----*/
        $wallet = Wallet::where(['user_id' => Auth::id(),'wallet_list_id' => $request->wallet_id])->first();
        if(!$wallet) {
            return response()->json(['success' => false, 'msg' => 'You have insufficient balance for purchase product.']);
        }
        $productTotalAmount = calculateCartTotalAmount();
        //withdrawal amount which is not approve or reject
        $withdrawalAmount = Withdrawal::where('user_id', Auth::id())
                            ->whereNotIn('status', [1,2])
                            ->sum('amount');
        if($request->wallet_id == 1 && $withdrawalAmount) {
            $currentBalance = getOCACurrentBalance();
            if ($productTotalAmount > $currentBalance) {
                return response()->json(['success' => false, 'msg' => 'You have insufficient balance for purchase product.']);
            }
        }
        if ($productTotalAmount == 0) {
            return response()->json(['success' => false, 'msg' => 'Please at-least one product in cart.']);
        } else {
            if ($wallet && $productTotalAmount > $wallet->balance) {
                return response()->json(['success' => false, 'msg' => 'You have insufficient balance for purchase product.']);
            }
        }
        /*---- END for check balance ----*/
        $isRedeemGiftCodeAutomatic = $request->is_redeem_gift_code_automatic ?? false;

        $auth = checkAuthenticationProcess(Auth::user()->setting,Auth::user()->details->email,'order',false);
        if ($auth !== false){
            return response()->json(['success' => true, 'msg' => '','validate2fa' => true,'walletId' => basicEncrypt($wallet->id),'is_redeem_gift_code_automatic' => $isRedeemGiftCodeAutomatic]);
        } else {
            $orderData = createOrder($wallet->id);
            $transactionId = $orderData['transaction_id'];

            /*---- START for auto redeem gift code ----*/
            if ($isRedeemGiftCodeAutomatic == 'true'){
                if (isset($orderData['product_data']) && !empty($orderData['product_data'])){
                    foreach ($orderData['product_data'] as $productData){
                        redeemGiftCode($productData['gift_code']);
                    }
                }
            }
            /*---- END for auto redeem gift code ----*/
        }

        $redirectTo = URL::temporarySignedRoute('member.shop.orderSuccess',Carbon::now()->addMinutes(30),
            [
                'transactionId' => isset($transactionId) ? basicEncrypt($transactionId) : null,
                'status' => 'success',
                'message' => 'Congratulations!',
            ]
        );
        return response()->json(['success' => true, 'msg' => '','redirectTo' => $redirectTo]);
    }
    /**
     * orderSuccess
     *
     * @return view
     */
    public function orderSuccess(Request $request)
    {
        $giftCode = [];
        if ($request->transactionId){
            $data = WalletLog::with('purchase','purchase.giftCard')->where('transaction_id',basicDecrypt($request->transactionId))->first();
            if ($data && isset($data->purchase)){
                foreach ($data->purchase as $row){
                    if (isset($row->giftCard->gift_code)) {
                        $giftCode[] = $row->giftCard->gift_code;
                    }
                }
            }
        }
        return view('frontend.products.order-success',compact('giftCode'));
    }

    public function updateProductQuantity(Request $request)
    {
        if (readOnlyMode()) {
            return response()->json([
                'status' => false,
                'msg' => __('Feature disabled whilst in switched user mode.'),
            ], Response::HTTP_FORBIDDEN);
        }
        $cart = Cart::find(basicDecrypt($request->id));
        if (empty($cart)){
            return response()->json(['success' => false]);
        }

        /*---- START for check balance ----*/
        if ($cart->quantity < $request->quantity) {
            $qtyDiff = ($cart->quantity - $cart->quantity) ?? 1;
            $qtyDiff = ($qtyDiff === 0) ? 1 : $qtyDiff;

            $price = $cart->price * $qtyDiff;
            $productFound = Cart::with('productStaticOption')->where('user_id', Auth::id())
                ->whereHas("productStaticOption", function ($q) {
                    $q->where('type', 1);
                })->count();

            $OCAWalletBalance = getOCACurrentBalance();
            if ($productFound > 0) {
                $walletBalance = $OCAWalletBalance;
            } else {
                $walletBalance = getBonusWalletCurrentBalance();
                if (empty($walletBalance) || $walletBalance <= 0 || $walletBalance < $OCAWalletBalance){
                    $walletBalance = $OCAWalletBalance;
                }
            }

            $tax = calculateTax($price)['total_tax'];
            $productTotalAmount = calculateCartTotalAmount() + $price + $tax;
            if ($productTotalAmount > $walletBalance) {
                return response()->json(['success' => false, 'msg' => 'You have insufficient balance for purchase product.']);
            }
        }
        /*---- END for check balance ----*/

        if ($request->quantity >= 1) {
            $cart->quantity = $request->quantity;
            $cart->save();
        } else {
            $cart->delete();
        }
        return response()->json(['success' => true]);
    }

    public function invoicesIndex(Request $request)
    {
        return view('frontend.invoices.index');
    }
    /**
     * myGiftCodeAll
     *
     * @param Request $request
     * @return array
     */
    public function invoicesListAll(Request $request)
    {
        $search = $request->filter;
        $filter = (array) json_decode($search);
        $sort   = $request->sort ?: 'created_at';
        $order  = $request->order ?: 'desc';
        $offset = $request->offset;
        $limit  = $request->limit;
        $sort   = $sort == "counter" ? "id" : $sort;

        $query = WalletLog::with(['purchase','purchase.ProductStaticOption']);
        $query->whereHas("purchase", function ($q) {
            $q->where('user_id', Auth::id());
        });
        $query->where('action',6);

        if ($request->transaction_id){
            $query->where("id", $request->transaction_id);
        }

        $query->when($search, function ($q) use ($filter) {
            foreach ($filter as $key => $item) {
                if ($item) {
                    if ($key == 'price') {
                        $q->whereRaw(
                            'ROUND(ABS(value) - ROUND(CAST(IFNULL(JSON_UNQUOTE(JSON_EXTRACT(data, "$.tax_data.total_amount")), 0) AS DECIMAL(20,10)), 2), 2) = ?',
                            [round((float)trim($item), 2)]
                        );
                    }else if ($key == 'tax') {
                        $q->whereRaw('ROUND(CAST(IFNULL(JSON_UNQUOTE(JSON_EXTRACT(data, "$.tax_data.total_amount")), 0) AS DECIMAL(20,10)), 2) = ?', [ round((float)trim($item), 2) ]);

                    }  else if ($key == 'package_date') {
                        $dates = explode(' - ', $item);
                        $startDate = createFromFormatCustom($dates[0]);
                        $endDate = createFromFormatCustom($dates[1]);
                        $q->whereDate('created_at', '>=', $startDate)->whereDate('created_at', '<=', $endDate);
                    }  else if ($key == 'value') {
                        $formatted = number_format((float) $item, 2, '.', '');
                        $q->whereRaw("FORMAT(value, 2) = ?", [$formatted]);
                    }else if ($key == 'name') {
                        $names = explode(',', trim($item));
                        $q->whereHas('purchase.ProductStaticOption', function ($q) use ($names) {
                            $q->whereIn('title', array_map('trim', $names));
                        });
                    }  else if ($key == 'value') {
                        $q->whereRaw(
                            'ROUND(CAST(IFNULL(value, 0) AS DECIMAL(20,10)), 2) = ?',
                            [round((float)trim($item), 2)]
                        );
                    }else {
                        $q->where($key, 'like', '%' . $item . '%');
                    }
                }
            }
        })->orderBy($sort, $order);

        $count = $query->count();
        $row = $query->when($offset, function ($q) use ($offset) {
            $q->offset($offset);
        })->when($limit, function ($q) use ($limit) {
            $q->limit($limit);
        })->get()->toArray();
        $index = $offset + 1;

        foreach ($row as $key => $item) {

            $transactionId = $item['transaction_id'] ? basicEncrypt($item['transaction_id']) :'';
            $invoiceUrl = route('member.showInvoice',$transactionId);

            $name = [];
            if (isset($item['purchase']) && !empty($item['purchase'])){
                foreach ($item['purchase'] as $purchaseRow){
                    $name[] = $purchaseRow['product_static_option']['title'] ?? 'Plastic Neutrality Package';
                }
            }
            $name = implode(',', $name ?? '');
            $price = number_format(abs($item['value']) ?? 0,2,'.','');
            $row[$key]['counter']         = $index;
            $row[$key]['name']            = '<span class="w-100 text-wrap">'.$name.'</span>';
            $row[$key]['transaction_id']  = '<span class="text-monospace">'.$item['transaction_id'].'</span>';
            $row[$key]['tax']            = formatDisplayNumber($item['tax']);
            $row[$key]['price']          = formatDisplayNumber($price - ($item['tax'] ?? 0));
            $row[$key]['value']          = formatDisplayNumber($item['value'] ?? 0);
            $row[$key]['package_date']    = getDateWithIcon($item['created_at']);
            $row[$key]['action']          = '<a class="editBtn btn btn-sm btn-primary " target="__blank" href="' . $invoiceUrl . '" data-toggle="tooltip" data-placement="top" title="Invoice PDF">'.renderIconHtml('invoice').'View Invoice</a>';

            $index++;
        }
        if (count($row) == 0) {
            $count = 0;
        }
        return [
            'items' => $row,
            'count' => $count,
        ];
    }
}
