<?php

namespace App\Http\Controllers;

use App\Mail\SendOrderMail;
use App\Models\Deposit;
use App\Models\Gateway;
use App\Models\Order;
use App\Models\OrderDetail;
use App\Models\Store;
use App\Models\StoreCoupon;
use App\Models\StoreShipping;
use App\Models\UserGateway;
use App\Services\SendWhatsappMessageService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Mockery\Exception;
use Stevebauman\Purify\Facades\Purify;

class CheckoutController extends Controller
{
    protected $SendWhatsappMessageService;

    public function __construct(SendWhatsappMessageService $SendWhatsappMessageService)
    {
        $this->theme = template();
        $this->SendWhatsappMessageService = $SendWhatsappMessageService;
    }

    public function shipping(Request $request, $senderId, $link)
    {
        $data['link'] = $link;
        $store = Store::where('link', $link)->where('status', 1)->firstOrFail();
        if ($request->method() == 'GET') {
            $data['shippingAddress'] = StoreShipping::where('store_id', $store->id)->where('status', 1)->get();
            return view($this->theme . 'user.shop.shipping', $data, compact('senderId', 'store'));
        } elseif ($request->method() == 'POST') {
            $purifiedData = $request->all();
            $validator = Validator::make($purifiedData, [
                'name' => 'required|min:3|max:100|string',
                'email' => 'required|email|max:100',
                'phone' => 'required|min:5|max:32',
                'address' => 'required|min:5|max:250',
                'city' => 'required|numeric',
                'alt_phone' => 'nullable|min:5|max:32',
                'delivery_note' => 'nullable|string|max:5000',
            ]);
            if ($validator->fails()) {
                return back()->withErrors($validator)->withInput();
            }
            $purifiedData = (object)$purifiedData;
            $store = Store::where('status', 1)->where('link', $link)->firstOrFail();
            $shipping = StoreShipping::where('status', 1)->where('store_id', $store->id)->findOrFail($purifiedData->city);
            $shipping_charge = 0;
            if ($store->shipping_charge) {
                $shipping_charge = $shipping->charge;
            }

            $order = new Order();
            $order->order_number = 'O' . rand(100000, 999999);
            $order->store_id = $store->id;
            $order->user_id = $store->user_id;
            $order->full_name = $purifiedData->name;
            $order->email = $purifiedData->email;
            $order->phone = $purifiedData->phone;
            $order->detailed_address = $purifiedData->address;
            $order->shipping_id = $shipping->id;
            $order->shipping_charge = $shipping_charge;
            $order->alt_phone = $purifiedData->alt_phone;
            $order->delivery_note = $purifiedData->delivery_note ?? null;
            $order->sender_id = $senderId;
            $order->save();

            return redirect()->route('public.checkout', [$senderId, $link, $order->utr]);
        }
    }

    public function checkout($senderId, $link, $utr)
    {
        $order = Order::with(['shipping', 'store'])->where('status', 0)->where('utr', $utr)->firstOrFail();
        $gateways = UserGateway::where('user_id', $order->user_id)->where('status', 1)->orderBy('sort_by')->get();
        return view($this->theme . 'user.shop.checkout', compact('senderId', 'link', 'order', 'gateways', 'utr'));
    }

    public function promoApply(Request $request)
    {
        $store = Store::where('status', 1)->where('link', $request->link)->first();
        if (!$store) {
            return 0;
        }
        $coupon = StoreCoupon::where('code', $request->code)->where('store_id', $store->id)
            ->whereDate('start_date', '<=', Carbon::now())->whereDate('end_date', '>=', Carbon::now())
            ->where('status', 1)->first();
        if (!$coupon) {
            return 0;
        }

        $order = Order::where('status', 0)->where('utr', $request->orderUtr)->first();
        if (!$order) {
            return 0;
        }

        $totalAmount = 0;
        $discount = 0;

        $carts = $request->items;
        foreach ($carts as $cart) {
            $totalAmount += $cart['totalPrice'];
        }

        if ($totalAmount < $coupon->min_order) {
            $message = 'Minimum order amount is ' . $coupon->min_order . ' ' . basicControl()->base_currency;
            return response()->json([
                'status' => 'error',
                'message' => $message,
            ]);
        }

        if ($coupon->discount_type == 'percentage') {
            $discount = ($coupon->discount_amount * $totalAmount) / 100;
        } else {
            $discount = $coupon->discount_amount;
        }

        $order->discount_amount = $discount;
        $order->save();
        return response()->json([
            'status' => 'success',
            'discount' => $discount,
            'message' => 'You get ' . $discount . ' ' . basicControl()->base_currency . ' Discount',
            'item' => $carts,
        ]);
    }

    public function payment(Request $request)
    {
        $basicControl = basicControl();

        if ($request['gateway'] != 0) {
            $method = UserGateway::where('status', 1)->find($request['gateway']);
            if (!$method) {
                return 0;
            }
        }

        if (isShopOpen($request->link) == 'close') {
            return 0;
        }

        $store = Store::where('status', 1)->where('link', $request->link)->first();
        if (!$store) {
            return 0;
        }
        $order = Order::where('status', 0)->where('utr', $request->utr)->where('store_id', $store->id)->first();
        if (!$order) {
            return 0;
        }
        $order->gateway_id = $request['gateway'];

        $orderCount = Order::where('store_id', $store->id)->where('status', 1)->count();

        if ($orderCount > optional(optional($order->user)->plan)->order_num || optional(optional($order->user)->plan)->expiry_date < Carbon::now()) {
            return 0;
        }

        $gateway = $request->gateway;
        $amount = $request->cvt_amount;
        $currency = $request->supported_currency;
        $cryptoCurrency = $request->supported_crypto_currency;

        $cartItems = $request->items;
        $payableAmount = 0;

        DB::beginTransaction();
        try {
            foreach ($cartItems as $key => $item) {
                $payableAmount += $item['totalPrice'];
                $orderDetails = new OrderDetail();
                $orderDetails->order_id = $order->id;
                $orderDetails->product_id = $item['productId'];
                $orderDetails->product_name = $item['productName'];
                $orderDetails->quantity = $item['quantity'];
                $orderDetails->price = $item['price'];
                $orderDetails->total_price = $item['totalPrice'];
                $orderDetails->variant_name = $item['variantName'];
                $orderDetails->variant_price = $item['variantPrice'];
                $orderDetails->extra_products = $item['extra_products'] ?? [];
                $orderDetails->save();
            }
            if ($gateway == 0) {
                $order->total_amount = $payableAmount;
                $order->order_note = $request['order_note'] ?? null;
                $order->payment_amount = ($payableAmount + $order->shipping_charge) - $order->discount_amount;

                if (Session::get('bot_type') == null) {
                    $order->bot_type = "Messenger Bot";
                } else {
                    $order->bot_type = "Telegram Bot";
                }

                $order->status = 1;
                $order->save();

                if ($basicControl->email_notification) {
                    @Mail::to($order->email)
                        ->queue(new SendOrderMail((object)$order));
                }

                if ($order->bot_type == 'Telegram Bot') {
                    $telegramObj = 'App\\Services\\TelegramServices';
                    $telegramObj::orderConfirm($store, $order->sender_id, $order);
                } else {
                    $facebookObj = 'App\\Services\\FacebookServices';
                    $facebookObj::orderConfirm($store, $order->sender_id, $order);
                }
                $this->SendWhatsappMessageService->sendOrderMessageWithPDF($order);
                DB::commit();
                Session::flash('success', 'Order has been placed');
                return response()->json([
                    'status' => 'success',
                    'msg' => 'Order has been placed',
                    'url' => route('public.view', [$order->sender_id, $store->link]),
                ]);
            } else {
                $checkAmountValidate = $this->validationCheck($amount, $gateway, $currency, $cryptoCurrency);

                if ($checkAmountValidate['status'] == 'error') {
                    return 0;
                }

                $deposit = Deposit::create([
                    'user_id' => $order->user_id,
                    'depositable_type' => Order::class,
                    'depositable_id' => $order->id,
                    'payment_method_id' => $checkAmountValidate['data']['gateway_id'],
                    'payment_method_currency' => $checkAmountValidate['data']['currency'],
                    'amount' => $amount,
                    'percentage_charge' => $checkAmountValidate['data']['percentage_charge'],
                    'fixed_charge' => $checkAmountValidate['data']['fixed_charge'],
                    'payable_amount' => $checkAmountValidate['data']['payable_amount'],
                    'base_currency_charge' => $checkAmountValidate['data']['base_currency_charge'],
                    'payable_amount_in_base_currency' => $checkAmountValidate['data']['payable_amount_base_in_currency'],
                    'status' => 0,
                ]);

                $order->deposit_id = $deposit->id;
                $order->total_amount = $deposit->payable_amount_in_base_currency;
                $order->order_note = $request['order_note'] ?? null;
                $order->payment_amount = ($deposit->payable_amount_in_base_currency + $order->shipping_charge) - $order->discount_amount;
                $order->save();
                DB::commit();
                return response()->json([
                    'status' => 'success',
                    'msg' => null,
                    'url' => route('payment.process', $deposit->trx_id),
                ]);
            }
        } catch (\Exception $e) {
            DB::rollBack();
            return 0;
        }
    }

    public function checkAmountValidate($amount, $gateway, $currency, $cryptoCurrency = null)
    {
        try {
            $gateway = UserGateway::where('id', $gateway)->where('status', 1)->first();

            if (!$gateway) {
                return [
                    'status' => 'error',
                    'msg' => 'Payment method not available for this transaction'
                ];
            }

            if ($gateway->currency_type == 1) {
                $selectedCurrency = array_search($currency, $gateway->supported_currency);
                if ($selectedCurrency !== false) {
                    $selectedPayCurrency = $gateway->supported_currency[$selectedCurrency];
                } else {
                    return [
                        'status' => 'error',
                        'msg' => "Please choose the currency you'd like to use for payment"
                    ];
                }
            }

            if ($gateway->currency_type == 0) {
                $selectedCurrency = array_search($cryptoCurrency, $gateway->supported_currency);
                if ($selectedCurrency !== false) {
                    $selectedPayCurrency = $gateway->supported_currency[$selectedCurrency];
                } else {
                    return [
                        'status' => 'error',
                        'msg' => "Please choose the currency you'd like to use for payment"
                    ];
                }
            }

            if ($gateway) {
                $receivableCurrencies = $gateway->receivable_currencies;
                if (is_array($receivableCurrencies)) {
                    if ($gateway->id < 999) {
                        $currencyInfo = collect($receivableCurrencies)->where('name', $selectedPayCurrency)->first();
                    } else {
                        if ($gateway->currency_type == 1) {
                            $currencyInfo = collect($receivableCurrencies)->where('currency', $selectedPayCurrency)->first();
                        } else {
                            $currencyInfo = collect($receivableCurrencies)->where('currency', $selectedPayCurrency)->first();
                        }

                    }
                } else {
                    return null;
                }
            }

            if (!$currencyInfo) {
                return [
                    'status' => 'error',
                    'msg' => "Please choose the currency you'd like to use for payment"
                ];
            }

            if ($amount < $currencyInfo->min_limit || $amount > $currencyInfo->max_limit) {
                return [
                    'status' => 'error',
                    'msg' => "minimum payment $currencyInfo->min_limit and maximum payment limit $currencyInfo->max_limit"
                ];
            }

            $currencyType = $gateway->currency_type;
            $limit = $currencyType == 0 ? 8 : 2;

            if ($currencyInfo) {
                $percentage_charge = getAmount(($amount * $currencyInfo->percentage_charge) / 100, $limit);
                $fixed_charge = getAmount($currencyInfo->fixed_charge, $limit);
                $min_limit = getAmount($currencyInfo->min_limit, $limit);
                $max_limit = getAmount($currencyInfo->max_limit, $limit);
                $charge = getAmount($percentage_charge + $fixed_charge, $limit);
            }

            $basicControl = basicControl();
            $payable_amount = getAmount($amount + $charge, $limit);
            $amount_in_base_currency = getAmount($amount / $currencyInfo->conversion_rate, $limit);
            $base_currency_charge = getAmount($charge / $currencyInfo->conversion_rate ?? 1, $limit);

            $data['gateway_id'] = $gateway->id;
            $data['fixed_charge'] = $fixed_charge;
            $data['percentage_charge'] = $percentage_charge;
            $data['min_limit'] = $min_limit;
            $data['max_limit'] = $max_limit;
            $data['payable_amount'] = $payable_amount;
            $data['amount'] = $amount;
            $data['base_currency_charge'] = $base_currency_charge;
            $data['payable_amount_base_in_currency'] = $amount_in_base_currency;
            $data['currency'] = ($gateway->currency_type == 1) ? ($currencyInfo->name ?? $currencyInfo->currency) : "USD";
            $data['base_currency'] = $basicControl->base_currency;
            $data['currency_limit'] = $limit;

            return [
                'status' => 'success',
                'data' => $data
            ];
        } catch (Exception $e) {
            return [
                'status' => 'error',
                'msg' => $e->getMessage()
            ];
        }

    }

    public function orderSupportedCurrency(Request $request)
    {
        $gateway = UserGateway::where('id', $request->gateway)->first();
        $pmCurrency = $gateway->receivable_currencies[0]->name ?? $gateway->receivable_currencies[0]->currency;
        $isCrypto = $gateway->id < 1000 && checkTo($gateway->currencies, $pmCurrency) == 1;

        return response([
            'success' => true,
            'data' => $gateway->supported_currency,
            'currencyType' => $isCrypto ? 0 : 1,
        ]);
    }

    public function orderCheckConvertAmount(Request $request)
    {
        if ($request->ajax()) {
            $amount = $request->amount;
            $selectedCurrency = $request->selected_currency;
            $selectGateway = $request->select_gateway;
            $selectedCryptoCurrency = $request->selectedCryptoCurrency;
            $data = $this->checkConvertAmountValidate($amount, $selectedCurrency, $selectGateway, $selectedCryptoCurrency);
            return response()->json($data);
        }
        return response()->json(['error' => 'Invalid request'], 400);
    }

    public function checkConvertAmountValidate($amount, $selectedCurrency, $selectGateway, $selectedCryptoCurrency = null)
    {
        $selectGateway = UserGateway::where('id', $selectGateway)->where('status', 1)->first();
        if (!$selectGateway) {
            return ['status' => false, 'message' => "Payment method not available for this transaction"];
        }

        if ($selectGateway->currency_type == 1) {
            $selectedCurrency = array_search($selectedCurrency, $selectGateway->supported_currency);
            if ($selectedCurrency !== false) {
                $selectedPayCurrency = $selectGateway->supported_currency[$selectedCurrency];
            } else {
                return ['status' => false, 'message' => "Please choose the currency you'd like to use for payment"];
            }
        }

        if ($selectGateway->currency_type == 0) {
            $selectedCurrency = array_search($selectedCryptoCurrency, $selectGateway->supported_currency);
            if ($selectedCurrency !== false) {
                $selectedPayCurrency = $selectGateway->supported_currency[$selectedCurrency];
            } else {
                return ['status' => false, 'message' => "Please choose the currency you'd like to use for payment"];
            }
        }

        if ($selectGateway) {
            $receivableCurrencies = $selectGateway->receivable_currencies;
            if (is_array($receivableCurrencies)) {
                if ($selectGateway->id < 999) {
                    $currencyInfo = collect($receivableCurrencies)->where('name', $selectedPayCurrency)->first();
                } else {
                    if ($selectGateway->currency_type == 1) {
                        $currencyInfo = collect($receivableCurrencies)->where('currency', $selectedPayCurrency)->first();
                    } else {
                        $currencyInfo = collect($receivableCurrencies)->where('currency', $selectedCryptoCurrency)->first();
                    }
                }
            } else {
                return null;
            }
        }

        $currencyType = $selectGateway->currency_type;
        $limit = $currencyType == 0 ? 8 : 2;
        $amount = getAmount($amount * $currencyInfo->conversion_rate, $limit);
        $status = false;

        if ($currencyInfo) {
            $percentage = getAmount($currencyInfo->percentage_charge, $limit);
            $percentage_charge = getAmount(($amount * $percentage) / 100, $limit);
            $fixed_charge = getAmount($currencyInfo->fixed_charge, $limit);
            $min_limit = getAmount($currencyInfo->min_limit, $limit);
            $max_limit = getAmount($currencyInfo->max_limit, $limit);
            $charge = getAmount($percentage_charge + $fixed_charge, $limit);
        }

        $basicControl = basicControl();
        $payable_amount = getAmount($amount + $charge, $limit);
        $amount_in_base_currency = getAmount($payable_amount / $currencyInfo->conversion_rate ?? 1, $limit);

        if ($amount < $min_limit || $amount > $max_limit) {
            $message = "minimum payment $min_limit and maximum payment limit $max_limit";
        } else {
            $status = true;
            $message = "Amount : $amount" . " " . $selectedPayCurrency;
        }

        $data['status'] = $status;
        $data['message'] = $message;
        $data['fixed_charge'] = $fixed_charge;
        $data['percentage'] = $percentage;
        $data['percentage_charge'] = $percentage_charge;
        $data['min_limit'] = $min_limit;
        $data['max_limit'] = $max_limit;
        $data['payable_amount'] = $payable_amount;
        $data['charge'] = $charge;
        $data['amount'] = $amount;
        $data['conversion_rate'] = $currencyInfo->conversion_rate ?? 1;
        $data['amount_in_base_currency'] = number_format($amount_in_base_currency, 2);
        $data['currency'] = ($selectGateway->currency_type == 1) ? ($currencyInfo->name ?? $currencyInfo->currency) : "USD";
        $data['base_currency'] = $basicControl->base_currency;
        $data['currency_limit'] = $limit;
        return $data;
    }

    public function validationCheck($amount, $gateway, $currency, $cryptoCurrency = null)
    {
        try {
            $gateway = UserGateway::where('id', $gateway)->where('status', 1)->first();

            if (!$gateway) {
                return [
                    'status' => 'error',
                    'msg' => 'Payment method not available for this transaction'
                ];
            }

            if ($gateway->currency_type == 1) {
                $selectedCurrency = array_search($currency, $gateway->supported_currency);
                if ($selectedCurrency !== false) {
                    $selectedPayCurrency = $gateway->supported_currency[$selectedCurrency];
                } else {
                    return [
                        'status' => 'error',
                        'msg' => "Please choose the currency you'd like to use for payment"
                    ];
                }
            }

            if ($gateway->currency_type == 0) {
                $selectedCurrency = array_search($cryptoCurrency, $gateway->supported_currency);
                if ($selectedCurrency !== false) {
                    $selectedPayCurrency = $gateway->supported_currency[$selectedCurrency];
                } else {
                    return [
                        'status' => 'error',
                        'msg' => "Please choose the currency you'd like to use for payment"
                    ];
                }
            }

            if ($gateway) {
                $receivableCurrencies = $gateway->receivable_currencies;
                if (is_array($receivableCurrencies)) {
                    if ($gateway->id < 999) {
                        $currencyInfo = collect($receivableCurrencies)->where('name', $selectedPayCurrency)->first();
                    } else {
                        if ($gateway->currency_type == 1) {
                            $currencyInfo = collect($receivableCurrencies)->where('currency', $selectedPayCurrency)->first();
                        } else {
                            $currencyInfo = collect($receivableCurrencies)->where('currency', $selectedPayCurrency)->first();
                        }

                    }
                } else {
                    return null;
                }
            }

            if (!$currencyInfo) {
                return [
                    'status' => 'error',
                    'msg' => "Please choose the currency you'd like to use for payment"
                ];
            }

            if ($amount < $currencyInfo->min_limit || $amount > $currencyInfo->max_limit) {
                return [
                    'status' => 'error',
                    'msg' => "minimum payment $currencyInfo->min_limit and maximum payment limit $currencyInfo->max_limit"
                ];
            }

            $currencyType = $gateway->currency_type;
            $limit = $currencyType == 0 ? 8 : 2;

            if ($currencyInfo) {
                $percentage_charge = getAmount(($amount * $currencyInfo->percentage_charge) / 100, $limit);
                $fixed_charge = getAmount($currencyInfo->fixed_charge, $limit);
                $min_limit = getAmount($currencyInfo->min_limit, $limit);
                $max_limit = getAmount($currencyInfo->max_limit, $limit);
                $charge = getAmount($percentage_charge + $fixed_charge, $limit);
            }

            $basicControl = basicControl();
            $payable_amount = getAmount($amount + $charge, $limit);
            $amount_in_base_currency = getAmount($amount / $currencyInfo->conversion_rate, $limit);
            $base_currency_charge = getAmount($charge / $currencyInfo->conversion_rate ?? 1, $limit);

            $data['gateway_id'] = $gateway->id;
            $data['fixed_charge'] = $fixed_charge;
            $data['percentage_charge'] = $percentage_charge;
            $data['min_limit'] = $min_limit;
            $data['max_limit'] = $max_limit;
            $data['payable_amount'] = $payable_amount;
            $data['amount'] = $amount;
            $data['base_currency_charge'] = $base_currency_charge;
            $data['payable_amount_base_in_currency'] = $amount_in_base_currency;
            $data['currency'] = ($gateway->currency_type == 1) ? ($currencyInfo->name ?? $currencyInfo->currency) : "USD";
            $data['base_currency'] = $basicControl->base_currency;
            $data['currency_limit'] = $limit;

            return [
                'status' => 'success',
                'data' => $data
            ];
        } catch (Exception $e) {
            return [
                'status' => 'error',
                'msg' => $e->getMessage()
            ];
        }

    }

}
