<?php

namespace Modules\Order\Services;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Session;
use Modules\Coupon\Services\CouponService;
use Modules\Notification\Enums\ManagementNotificationStatusEnum;
use Modules\Notification\Services\ManagementNotificationService;
use Modules\Notification\Services\NotificationService;
use Modules\Order\Enums\OrderPaymentStatusEnum;
use Modules\Order\Enums\OrderStatusEnum;
use Modules\Order\Services\PaymentService;
use Modules\Order\Interfaces\OrderRepositoryInterface;
use Modules\Order\Models\Order;
use Modules\Order\Repositories\Payment\MyFatoorahPayment;
use Modules\Product\Models\ProductAttribute;
use Modules\User\Enums\AccountStatusEnum;
use Modules\User\Services\AccountService;

class OrderService
{
    private OrderRepositoryInterface $orderRepository ;
    private CartService $cartService ;
    private CouponService $couponService ;
    private AccountService $accountService ;
    private NotificationService $notificationService ;
    private ManagementNotificationService $managementNotificationService ;

    public function __construct(OrderRepositoryInterface $orderRepository,CartService $cartService,AccountService $accountService,CouponService $couponService,NotificationService $notificationService,ManagementNotificationService $managementNotificationService)
    {
        $this->orderRepository = $orderRepository;
        $this->cartService = $cartService;
        $this->accountService = $accountService;
        $this->couponService = $couponService;
        $this->notificationService = $notificationService;
        $this->managementNotificationService = $managementNotificationService;
    }

    public function get(Request $request)
    {
        $orders= $this->orderRepository->get($request);
        return $orders;
    }
    public function getItem(Order $order)
    {
        $order = $this->orderRepository->getItem($order);
        return $order;
    }
    public function create(Request $request)
    {
        $account = $this->accountService->getAccount();
        if ($request->coupon)
        {
            $coupon = $this->couponService->getItemByCode($request->coupon);
            if ($coupon)
            {
                $request->merge(['coupon_id'=>$coupon->id]);
            }

        }
        $way_id = Session::get('way_id');
        if ($way_id)
        {
            $request->merge(['way_id'=>$way_id]);
        }
        $shipping_id = Session::get('shipping_id');
        if ($shipping_id)
        {
            $request->merge(['shipping_id'=>$shipping_id]);
        }
        $address_id = Session::get('address_id');
        if ($address_id)
        {
            $request->merge(['address_id'=>$address_id]);
        }
        $calculate = $this->cartService->calculate($request);
        foreach ($calculate as $key=>$row)
        {
            $request->merge([$key=>$row]);
        }

        if ($way_id == 1)
        {
            $token = str_replace(str_split('%\\/:*?"<>|.'), '', bcrypt(rand(11111, 99999) . time()));
            $request->merge(['token'=>$token,'user_status'=>$account['status'],'user_id'=>$account['user']->id,'status'=>OrderStatusEnum::NEW->value,'payment_status'=>OrderPaymentStatusEnum::PAID->value]);
            $order = $this->orderRepository->create($request);
            $order->delete();
            $content = [
                'token'=>$token,
                'total'=>$calculate['total']
            ];
            if ($order->total == 0)
            {
                $this->orderRepository->restore($request,$order->id);
                $this->orderRepository->orderProductCount($order);
                $this->cartService->destroyAll($request);
                $qr_code = QrCodeService::generate($order->updated_at, $order->total, $order->total_tax);
                $order->update(['qr_image' => $qr_code['image_path']]);
                if ($order->coupon_id)
                {
                    $this->couponService->decrease($order->coupon_id);
                }

                $request->merge(['status'=>ManagementNotificationStatusEnum::NEW_ORDER->value,'order_id'=>$order->id]);
                $this->managementNotificationService->create($request);
                foreach($order->products as $row)
                {
                    if ($row->sub_attribute_id)
                    {
                        $attr = ProductAttribute::where('product_id',$row->product_id)->where('main_attribute_id','!=',null)->where('attribute_id',$row->sub_attribute_id)->first();
                        if ($attr)
                        {
                            $product_count = $attr->count;
                        }
                        else
                        {
                            $product_count = 0;
                        }
                    }
                    else
                    {
                        $product_count = $row->product->count;
                    }
                    if($product_count <= settings('notify_alert'))
                    {
                        $request->merge(['status'=>ManagementNotificationStatusEnum::PRODUCT_EMPTY->value,'product_id'=>$row->product_id]);
                        $this->managementNotificationService->create($request);
                    }
                }

                $url = ($account['status'] == AccountStatusEnum::USER->value) ? route('web.profile') : route('web.home');
            }
            else
            {
                $url = (new PaymentService(new MyFatoorahPayment()))->payment($content);
            }
        }
        else
        {
            $request->merge(['status'=>OrderStatusEnum::NEW->value,'payment_status'=>OrderPaymentStatusEnum::UNPAID->value,'user_status'=>$account['status'],'user_id'=>$account['user']->id]);
            $order = $this->orderRepository->create($request);
            $qr_code = QrCodeService::generate($order->updated_at, $order->total, $order->total_tax);
            $order->update(['qr_image' => $qr_code['image_path']]);
            $url = $account['status'] == AccountStatusEnum::VISITOR->value ? route('web.home') : route('web.profile');
            $request->merge(['status'=>$account['status'],'user_id'=>$account['user']->id]);
            $this->orderRepository->restore($request,$order->id);
            $this->orderRepository->orderProductCount($order);
            $this->cartService->destroyAll($request);
            if ($order->coupon_id)
            {
                $this->couponService->decrease($order->coupon_id);
            }

            $request->merge(['status'=>ManagementNotificationStatusEnum::NEW_ORDER->value,'order_id'=>$order->id]);
            $this->managementNotificationService->create($request);
            foreach($order->products as $row)
            {
                if ($row->sub_attribute_id)
                {
                    $attr = ProductAttribute::where('product_id',$row->product_id)->where('main_attribute_id','!=',null)->where('attribute_id',$row->sub_attribute_id)->first();
                    if ($attr)
                    {
                        $product_count = $attr->count;
                    }
                    else
                    {
                        $product_count = 0;
                    }
                }
                else
                {
                    $product_count = $row->product->count;
                }
                if($product_count <= settings('notify_alert'))
                {
                    $request->merge(['status'=>ManagementNotificationStatusEnum::PRODUCT_EMPTY->value,'product_id'=>$row->product_id]);
                    $this->managementNotificationService->create($request);
                }
            }
        }


        return $url;
    }
    public function update(Request $request , $order) :Order
    {
        $order = $this->orderRepository->update($request, $order);
        if ($order->user_status == AccountStatusEnum::USER->value)
        {
            $requestData = [
                'status' => $order->status,
                'user_id' => $order->user_id,
                'order_id' => $order->id,
            ];
            $this->notificationService->orderChangeStatus($request, $requestData);
        }
        return $order;
    }
    public function paymentStatus(Request $request)
    {
        $order = null;
        if (isset($_GET['paymentId'])) {
            $username = Config::get('app.username');
            $password = Config::get('app.password');
            $tokenApi = Config::get('app.tokenApi');
            $transaction = Config::get('app.transaction');

            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $tokenApi);
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query(array('grant_type' => 'password', 'username' => $username, 'password' => $password)));
            $result = curl_exec($curl);
            $error = curl_error($curl);
            $info = curl_getinfo($curl);
            curl_close($curl);
            $json = json_decode($result, true);

            $access_token = $json['access_token'];
            $token_type = $json['token_type'];
            if (isset($_GET['paymentId'])) {
                $id = $_GET['paymentId'];
            }
            $url = $transaction . $id;
            $soap_do1 = curl_init();
            curl_setopt($soap_do1, CURLOPT_URL, $url);
            curl_setopt($soap_do1, CURLOPT_CONNECTTIMEOUT, 10);
            curl_setopt($soap_do1, CURLOPT_TIMEOUT, 10);
            curl_setopt($soap_do1, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($soap_do1, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($soap_do1, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($soap_do1, CURLOPT_POST, false);
            curl_setopt($soap_do1, CURLOPT_POST, 0);
            curl_setopt($soap_do1, CURLOPT_HTTPGET, 1);
            curl_setopt($soap_do1, CURLOPT_HTTPHEADER, array('Content-Type: application/json; charset=utf-8', 'Accept: application/json', 'Authorization: Bearer ' . $access_token));
            $result_in = curl_exec($soap_do1);

            $err_in = curl_error($soap_do1);
            $file_contents = htmlspecialchars(curl_exec($soap_do1));
            curl_close($soap_do1);
            $getRecorById = json_decode($result_in, true);

            $customFiles = explode('&', $getRecorById['ApiCustomFileds']);
            foreach ($customFiles as $value) {
                $field = explode('=', $value);
                $fields[$field[0]] = $field[1];
            }

            $token = $fields['token'];

            $order = $this->orderRepository->getItemByToken($token);

            if (in_array($getRecorById['TransactionStatus'], array(1, 2)) && $order) {

                $account = $this->accountService->getAccount();
                $this->orderRepository->restore($request,$order->id);
                $qr_code = QrCodeService::generate($order->updated_at, $order->total, $order->total_tax);
                $request->merge(['payment_log' => $result_in, 'payment_id' => $getRecorById['InvoiceId'],'token'=>null,'qr_image' => $qr_code['image_path']]);
                $this->orderRepository->update($request,$order);
                $this->orderRepository->orderProductCount($order);
                $request->merge(['status'=>$account['status'],'user_id'=>$account['user']->id]);
                $this->cartService->destroyAll($request);
                if ($order->coupon_id) {
                    $this->couponService->decrease($order->coupon_id);
                }
                $request->merge(['status'=>ManagementNotificationStatusEnum::NEW_ORDER->value,'order_id'=>$order->id]);
                $this->managementNotificationService->create($request);
                foreach($order->products as $row)
                {
                    if ($row->sub_attribute_id)
                    {
                        $attr = ProductAttribute::where('product_id',$row->product_id)->where('main_attribute_id','!=',null)->where('attribute_id',$row->sub_attribute_id)->first();
                        if ($attr)
                        {
                            $product_count = $attr->count;
                        }
                        else
                        {
                            $product_count = 0;
                        }
                    }
                    else
                    {
                        $product_count = $row->product->count;
                    }
                    if($product_count <= settings('notify_alert'))
                    {
                        $request->merge(['status'=>ManagementNotificationStatusEnum::PRODUCT_EMPTY->value,'product_id'=>$row->product_id]);
                        $this->managementNotificationService->create($request);
                    }
                }
            }
        }
        return $order;
    }

    public function destroy(Request $request, int $id): array
    {
        $response = $this->orderRepository->destroy($request,$id);
        return $response;
    }
    public function destroyAll(Request $request): array
    {
        $response = $this->orderRepository->destroyAll($request);
        return $response;
    }
    public function restore(Request $request, int $id): array
    {
        $response = $this->orderRepository->restore($request,$id);
        return $response;
    }
    public function restoreAll(Request $request): array
    {
        $response = $this->orderRepository->restoreAll($request);
        return $response;
    }
}
