<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Mail\SendNotifications;
use App\Models\Bundle;
use App\Models\RewardAccounting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use App\Http\Controllers\Web\CartController;
use App\Models\Webinar;
use App\Models\Transaction;
use App\Models\Payout;
use App\Models\Accounting;
use App\Models\Purchase;
use App\Models\Sale;
use App\Models\OrderItem;
use App\Models\Order;
use App\Models\TicketUser;
use App\Models\Subscribe;
use App\Models\Discount;
use App\Models\ReserveMeeting;
use App\Services\EasyKashService;
use App\Services\PaymentTransactionLogger;
use App\Support\PaymentCurrency;
use App\Support\PaymentFailure;
use App\User;
use Auth;
use Session;

class PaymobController extends Controller
{
    private function paymentErrorRedirect(string $message, string $fallback = '/cart')
    {
        PaymentFailure::flash($message);

        return redirect($fallback)->with([
            'toast' => [
                'title' => trans('cart.failed_pay_title'),
                'msg' => $message,
                'status' => 'error',
            ],
        ]);
    }

    public function credit(Request $request) {
        if (!auth()->check()) {
            return redirect('/login?url=' . urlencode(url()->previous()));
        }

        $gateway = $request->input('gateway');
        $user = auth()->user();
        $order = resolveUserPaymentOrder($user->id, $request->input('order_id'));

        if (!$order) {
            $submittedId = $request->input('order_id');

            return $this->paymentErrorRedirect(
                'الطلب غير موجود أو انتهت صلاحيته.'
                . ($submittedId !== null && $submittedId !== '' ? ' (رقم المرسل: ' . $submittedId . ')' : '')
                . ' أعد الشراء من السلة ثم ادفع من جديد.',
                '/cart'
            );
        }

        normalizeMobileInRequest($request);

        $billingValidator = \Validator::make(
            $request->all(),
            billingInformationRules($user->id),
            array_merge(egyptianMobileValidationMessages(), [
                'full_name.required' => 'الاسم مطلوب.',
                'email.required' => 'البريد الإلكتروني مطلوب.',
                'email.email' => 'البريد الإلكتروني غير صحيح.',
                'billing_country.required' => 'البلد مطلوب.',
                'billing_city.required' => 'المدينة مطلوبة.',
                'address.required' => 'العنوان مطلوب.',
            ])
        );

        if ($billingValidator->fails()) {
            $data = app(CartController::class)->buildPaymentPageData($order, $user);

            return view(getTemplate() . '.cart.payment', $data)
                ->withErrors($billingValidator);
        }

        $billingData = $billingValidator->validated();
        saveUserBillingInformation($user, $billingData);
        $user->refresh();

        $order->update([
            'payment_data' => json_encode([
                'billing' => $billingData,
                'submitted_at' => time(),
            ]),
        ]);

        if ($gateway === 'offline'){
            if ($user->getAccountingCharge() < $order->amount) {
                $order->update(['status' => Order::$fail]);

                $data = [
                    'pageTitle' => trans('public.cart_page_title'),
                    'order' => $order,
                ];

                return view('web.default.cart.status_pay', $data);
            }

            $order->update([
                'payment_method' => Order::$credit
            ]);

            $this->setPaymentAccounting($order, 'credit');

            $order->update([
                'status' => Order::$paid
            ]);

            $data = [
                'pageTitle' => trans('public.cart_page_title'),
                'order' => $order,
                'success' => 'true',
            ];

            return view('web.default.cart.status_pay', compact('data'));
        }

        $orderItem = OrderItem::where('order_id', $order->id)->first();
        if ($orderItem && $orderItem->reserve_meeting_id) {
            ReserveMeeting::where('id', $orderItem->reserve_meeting_id)->update(['locked_at' => time()]);
        }

        if (empty($order->currency)) {
            $order->update(['currency' => PaymentCurrency::defaultItemCurrency()]);
            $order->refresh();
        }

        $order->update([
            'payment_method' => Order::$paymentChannel,
            'status' => Order::$paying,
            'payment_failure_reason' => null,
        ]);

        try {
            $paymentUrl = app(EasyKashService::class)->createDirectPayLink($order, $user);

            $charge = PaymentCurrency::forEasyKashGateway(
                (float) ($order->total_amount ?? $order->amount ?? 0),
                $order->currency
            );

            PaymentTransactionLogger::log([
                'order_id' => $order->id,
                'user_id' => $user->id,
                'event' => 'easykash_create_link',
                'status' => 'success',
                'currency' => $charge['currency'],
                'amount' => $charge['amount'],
                'request_payload' => [
                    'redirect' => $paymentUrl,
                    'order_currency' => $order->currency,
                    'order_amount' => $order->total_amount,
                    'charge' => $charge,
                ],
            ]);

            return \Redirect::away($paymentUrl);
        } catch (\Exception $exception) {
            $reason = $exception->getMessage();
            PaymentFailure::markOrderFailed($order, $reason);

            $httpStatus = $exception->getCode();
            $httpStatus = is_int($httpStatus) && $httpStatus >= 100 && $httpStatus < 600 ? $httpStatus : null;

            PaymentTransactionLogger::logEasyKashLinkFailed(
                $order,
                $user,
                $reason,
                $httpStatus,
                ['order_id' => $order->id, 'currency' => $order->currency, 'amount' => $order->total_amount],
                $httpStatus === 400 ? 'EasyKash HTTP 400 — see laravel.log easykash.pay.failed' : null
            );

            report($exception);

            return redirect('/payments/status/' . $order->id)->with([
                'toast' => [
                    'title' => trans('cart.failed_pay_title'),
                    'msg' => $reason,
                    'status' => 'error',
                ],
            ]);
        }
    }

    public function getToken() {
        $response = Http::post('https://accept.paymob.com/api/auth/tokens', [
            'api_key' => env('PAYMOB_API_KEY')
        ]);
        return $response->object()->token;
    }

    public function createOrder($token,$item,$discountId = null) {

        $course = [];
        foreach ($item as $it){

            if (!isset($it->webinar_id)){
                $name = "subscribe";
//                $orderItem = OrderItem::where('order_id', $it->id)->first();
                $orderItem = Bundle::where('id',$it->bundle_id)->first();

                $price = $orderItem->price * 100;

                $reserveMeeting = null;
                if ($orderItem && $orderItem->reserve_meeting_id) {
                    $reserveMeeting = ReserveMeeting::where('id', $orderItem->reserve_meeting_id)->first();
                }

//                if ($it->status == Order::$paying) {
//                    $this->setPaymentAccounting($it);
//
//                    $it->update(['status' => Order::$paid]);
//                } else {
//                    if ($it->type === Order::$meeting) {
//                        $reserveMeeting->update(['locked_at' => null]);
//                    }
//                }

                $temp = [
                    "name"=>$name,
                    "amount_cents"=> $price,
                    "description"=> 'subscribe',
                    "quantity"=> "1"
                ];


            }else{
                $cr = Webinar::where('id',$it->webinar_id)->first();
                $name = "course";

                if ($cr->bestTicket() < $cr->price){
                    $price = $cr->bestTicket() * 100;
                }else{
                    $price = $cr->price * 100;
                }


                $title = $cr->title;


                $temp = [
                    "name"=>$name,
                    "amount_cents"=> $price,
                    "description"=> $title,
                    "quantity"=> "1"
                ];
            }
            array_push($course, $temp);

        }

        if ($discountId){

            $discountCoupon = Discount::where('code', $discountId)
                ->where('expired_at', '>', time())
                ->first();

            $couponAmount = $price * $discountCoupon->percent / 100;

            if (!empty($discountCoupon->amount) and $couponAmount > $discountCoupon->amount) {
                $price -= $discountCoupon->amount * 100;
            } else {
                $price -= $couponAmount * 100;
            }

        }

        $data = [
            "auth_token" =>   $token,
            "delivery_needed" =>"false",
            "amount_cents"=> $price,
            "currency"=> "EGP",
            "items"=> $course,

        ];

        $response = Http::post('https://accept.paymob.com/api/ecommerce/orders', $data);
        return $response->object();
    }

    public function getPaymentToken($order, $token,$discountId = null)
    {
        $price = 0;
        $quantity = 0;

        foreach ($order->items as $item) {
            $price += $item->amount_cents;
            $quantity += $item->quantity;
        }

        if ($discountId){

            $discountCoupon = Discount::where('code', $discountId)
                ->where('expired_at', '>', time())
                ->first();

            $couponAmount = $price * $discountCoupon->percent / 100;

            if (!empty($discountCoupon->amount) and $couponAmount > $discountCoupon->amount) {
                $price -= $discountCoupon->amount * 100;
            } else {
                $price -= $couponAmount;
            }

        }

        $user = Auth::User();

        $name = explode(' ', Auth::user()->full_name);

        if ($user === null){
            $email = "N/A";
            $first_name = "N/A";
            $last_name = "N/A";
            $mobile = "N/A";
        }else{
            $email = Auth::User()->email;
            $first_name = $name['0'];
            $last_name = $name['1'];
            $mobile = Auth::User()->mobile;
        }

        $billingData = [
            "apartment" => "N/A",
            "email" => $email,
            "floor" => "N/A",
            "first_name" => $first_name,
            "street" => "N/A",
            "building" => "N/A",
            "phone_number" => $mobile,
            "shipping_method" => "N/A",
            "postal_code" => "N/A",
            "city" => "N/A",
            "country" => "N/A",
            "last_name" => $last_name,
            "state" => "N/A"
        ];

        $data = [
            "auth_token" => $token,
            "amount_cents" => $price,
            "expiration" => 3600,
            "order_id" => $order->id,
            "billing_data" => $billingData,
            "currency" => "EGP",
            "integration_id" => env('PAYMOB_INTEGRATION_ID'),
        ];

        $response = Http::post('https://accept.paymob.com/api/acceptance/payment_keys', $data);

        return $response->object()->token;
    }
    public function callback(Request $request)
    {

        $data = $request->all();
        ksort($data);
        $hmac = $data['hmac'];
        $array = [
            'amount_cents',
            'created_at',
            'currency',
            'error_occured',
            'has_parent_transaction',
            'id',
            'integration_id',
            'is_3d_secure',
            'is_auth',
            'is_capture',
            'is_refunded',
            'is_standalone_payment',
            'is_voided',
            'order',
            'owner',
            'pending',
            'source_data_pan',
            'source_data_sub_type',
            'source_data_type',
            'success',
        ];
        $connectedString = '';
        foreach ($data as $key => $element) {
            if(in_array($key, $array)) {
                $connectedString .= $element;
            }
        }
        $secret = env('PAYMOB_HMAC');
        $hased = hash_hmac('sha512', $connectedString, $secret);

        if ( $hased == $hmac) {

            $transaction = Transaction::where('invoice_id',$data['order'])->first();
            $order = Order::where('id', $transaction->course_id)->first();
            $orderItem = OrderItem::where('order_id', $order->id)->first();


            $course_id = $transaction->course_id;
            $user_id = $transaction->user_id;
//            $course = Webinar::where('id',$course_id)->first();
            $carts = Cart::where('creator_id',$user_id)->first();
            $user = User::where('id',$user_id)->first();
//            $gsettings = Setting::first();
//            $current_date = Carbon::now();
//            $currency = Currency::first();
            $getUserPayout = $data['amount_cents'] / 100;

            if ($data['success'] === "true"){

                if (isset($orderItem->subscribe_id)){

                    $sale = Sale::create([
                        'buyer_id' => $user->id,
                        'order_id' => $order->id,
                        'subscribe_id' => $orderItem->subscribe_id,
                        'meeting_id' => !empty($orderItem->reserve_meeting_id) ? $orderItem->reserveMeeting->meeting_id : null,
                        'type' => 'subscribe',
                        'payment_method' => 'credit',
                        'amount' => $getUserPayout,
                        'total_amount' => $getUserPayout,
                        'created_at' => time(),
                    ]);

                    $subscribe = Subscribe::where('id', $orderItem->subscribe_id)->first();

                    Accounting::createAccountingForSubscribe($orderItem, 'addiction');



                }elseif (isset($orderItem->bundle_id)){

                    $bundle = Bundle::where('id', $orderItem->bundle_id)
                        ->where('status', 'active')
                        ->first();

                    Sale::create([
                        'buyer_id' => $user->id,
                        'seller_id' => $bundle->creator_id,
                        'bundle_id' => $bundle->id,
                        'type' => Sale::$bundle,
                        'payment_method' => Sale::$credit,
                        'amount' => 0,
                        'total_amount' => 0,
                        'created_at' => time(),
                    ]);
                    RewardAccounting::makeRewardAccounting($user->id, $bundle->points, 'withdraw', null, false, RewardAccounting::DEDUCTION);

                }else{
                    $orderItems = OrderItem::where('order_id', $order->id)->get();

                    $webinar = Webinar::where('id', $carts->webinar_id)->first();

                    if ($webinar->bestTicket() < $webinar->price){
                        $price = $webinar->bestTicket();
                    }else{
                        $price = $webinar->price;
                    }

                    foreach ($orderItems as $orderItem) {
                        $removeOlds = Sale::where('webinar_id', $webinar->id)->where('buyer_id', $user->id)->delete();

                        $sale = Sale::create([
                            'buyer_id' => $user->id,
                            'seller_id' => $webinar->creator_id,
                            'order_id' => $order->id,
                            'webinar_id' => $webinar->id,
                            'meeting_id' => !empty($orderItem->reserve_meeting_id) ? $orderItem->reserveMeeting->meeting_id : null,
                            'type' => 'webinar',
                            'payment_method' => 'credit',
                            'amount' => $price,
                            'total_amount' => $price,
                            'created_at' => time(),
                        ]);


                        if (!empty($orderItem->reserve_meeting_id)) {
                            $reserveMeeting = ReserveMeeting::where('id', $orderItem->reserve_meeting_id)->first();
                            $reserveMeeting->update([
                                'sale_id' => $sale->id,
                                'reserved_at' => time()
                            ]);
                        }


                        Accounting::create([
                            'user_id' => $webinar->creator_id,
                            'amount' => $price,
                            'webinar_id' => $webinar->id,
                            'type' => Accounting::$deduction,
                            'type_account' => Accounting::$income,
                            'description' => 'Paid from Credit',
                            'created_at' => time()
                        ]);




                    }

//                Sale::create([
//                    'buyer_id' => $user->id,
//                    'seller_id' => $webinar->creator_id,
//                    'webinar_id' => $webinar->id,
//                    'type' => Sale::$webinar,
//                    'payment_method' => Sale::$credit,
//                    'amount' => $price,
//                    'total_amount' => $price,
//                    'created_at' => time(),
//                ]);
//
//
//                Accounting::create([
//                    'system' => true,
//                    'user_id' => $webinar->creator_id,
//                    'amount' => $price,
//                    'webinar_id' => $webinar->id,
//                    'type' => Accounting::$deduction,
//                    'type_account' => Accounting::$asset,
//                    'description' => 'Paid from Credit',
//                    'created_at' => time()
//                ]);


                    Cart::emptyCart($order->user_id);

                }

                Payout::create([
                    'user_id' => $user->id,
                    'amount' => $getUserPayout,
                    'account_name' => $user->full_name,
                    'account_number' => 0,
                    'account_bank_name' => 'Online',
                    'status' => Payout::$done,
                    'created_at' => time(),
                ]);


                $order->update([
                    'payment_method' => Order::$credit
                ]);

                $order->update([
                    'status' => Order::$paid
                ]);





                $notifyOptions = [
                    '[payout.amount]' => $getUserPayout,
                    '[u.name]' => $user->full_name
                ];


//            sendNotification('payout_proceed', $notifyOptions, $user->id);
//            sendNotification('payout_request_admin', $notifyOptions, 1); // for admin

                if (!empty($user->email) and env('APP_ENV') == 'production') {
                    \Mail::to($user->email)->send(new SendNotifications(['title' => "عملية شراء تمت", 'message' => " تم دفع مبلغ ".$getUserPayout. " جنيه " ]));
                }

            }



            return view('web.default.cart.status_pay',compact('data','order'));

        }

        echo 'not secure'; exit;
    }

    public function setPaymentAccounting($order, $type = null)
    {
        if ($order->is_charge_account) {
            Accounting::charge($order);
        } else {
            foreach ($order->orderItems as $orderItem) {
                $sale = Sale::createSales($orderItem, $order->payment_method);

                if (!empty($orderItem->reserve_meeting_id)) {
                    $reserveMeeting = ReserveMeeting::where('id', $orderItem->reserve_meeting_id)->first();
                    $reserveMeeting->update([
                        'sale_id' => $sale->id,
                        'reserved_at' => time()
                    ]);
                }

                if (!empty($orderItem->subscribe_id)) {
                    Accounting::createAccountingForSubscribe($orderItem, $type);
                } elseif (!empty($orderItem->promotion_id)) {
                    Accounting::createAccountingForPromotion($orderItem, $type);
                } else {
                    // webinar and meeting

                    Accounting::createAccounting($orderItem, $type);
                    TicketUser::useTicket($orderItem);
                }
            }
        }

        Cart::emptyCart($order->user_id);
    }

}
