<?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\Product\Services\ProductWarehouseService;
use Modules\User\Enums\AccountStatusEnum;
use Modules\User\Services\AccountService;

class OrderService
{

    public function __construct(
        private OrderRepositoryInterface $orderRepository,
        private CartService $cartService,
        private AccountService $accountService,
        private CouponService $couponService,
        private NotificationService $notificationService,
        private ProductWarehouseService $productWarehouseService
    ){}

    public function get(array $request = [])
    {
        $builder= $this->orderRepository->get($request);

        if (isset($request['user_id']))
        {
            $builder->where('user_id',$request['user_id']);
        }

        if (isset($request['search']))
        {
            $builder->whereHas('products.product.currentDescription',function ($query) use ($request){
                $query->where('title','LIKE', '%'.$request['search'].'%');
            })->orWhere('id',$request['search']);
        }

        if (isset($request['store_id']))
        {
            $builder->whereHas('products',function ($query) use ($request){
                $query->where('store_id',$request['store_id']);
            });
        }
        if (isset($request['product_id']))
        {
            $builder->whereHas('products',function ($query) use ($request){
                $query->where('product_id',$request['product_id']);
            });
        }
        if (isset($request['warehouse_id']))
        {
            $builder->where('warehouse_id',$request['warehouse_id']);
        }

        if (isset($request['showLatest']))
        {
            $date = date('Y-m-d',strtotime('- '.$request['showLatest'].' months'));
            $builder->whereDate('created_at','>=',$date);
        }

        if (isset($request['user_status']))
        {
            $builder->where('user_status',$request['user_status']);
        }

        if (isset($request['typeStatus']))
        {
            $builder->where('status',$request['typeStatus']);
        }

        if (isset($request['notTypeStatus']))
        {
            $builder->where('status','!=',$request['notTypeStatus']);
        }

        if (isset($request['status']))
        {
            if (@$request['status'] == 0)
            {
                $builder->onlyTrashed();
            }
        }

        if (isset($request['today']))
        {
            $builder->whereDate('created_at',$request['today']);
        }

        if (isset($request['date']))
        {
            $builder->whereDate('created_at','>=',$request['date']);
        }

        if (@$request['paginate']) {
            $orders = $builder->paginate(is_numeric($request['paginate'] ? $request['paginate'] : 50));
        }else{
            $orders = $builder->get();
        }
        return $orders;
    }

    public function totalProducts($request)
    {
        $total = 0;
        $orders = $this->get($request);
        foreach ($orders as $order)
        {
            $total += $order->productsStore($request['store_id'])->sum('total');
        }
        return $total;
    }


    public function getItem(int $id)
    {
        $order = $this->orderRepository->getItem($id);
        return $order;
    }
    public function getProduct(array $request)
    {
        $product = $this->orderRepository->getProduct($request['id']);
        if ($product)
        {
            if ($product->order->user_id != $request['user_id'])
            {
                $product = null;
            }
        }
        return $product;
    }
    public function tracks(int $id)
    {
        $order = $this->orderRepository->tracks($id);
        return $order;
    }
    public function productsStore(int $store_id,$order_id)
    {
        $products = $this->orderRepository->productsStore($store_id,$order_id);
        return $products;
    }
    public function getItemTrashed(int $id)
    {
        $order = $this->orderRepository->getItemTrashed($id);
        return $order;
    }

    public function createTrack(array $request)
    {
        $this->orderRepository->createTrack($request);
    }

    public function create(array $request)
    {
        $account = $this->accountService->getAccount();
        $request['address_id'] = $account['user']->address_id;
        $request['user'] = $account['user'];
        $request['status'] = $account['status'];
        $request['user_id'] = $account['user']->id;
        if (isset($request['coupon']))
        {
            $coupon = $this->couponService->getItemByCode($request['coupon']);
            if ($coupon)
            {
                $request['coupon_id'] = $coupon->id;
            }

        }

        $calculate = $this->cartService->calculate($request);

        foreach ($calculate as $key=>$row)
        {
            $request[$key] = $row;
        }
        $request['warehouse_id'] = $account['user']->address->city->warehouses->first()->warehouse_id ?? null;
        if ($request['payment_way_id'] == 3 && !isset($request['pay_mobile']))
        {
            $token = str_replace(str_split('%\\/:*?"<>|.'), '', bcrypt(rand(11111, 99999) . time()));
            $request['token'] = $token;
            $request['user_status'] = $account['status'];
            $request['user_id'] = $account['user']->id;
            $request['status'] = OrderStatusEnum::NEW->value;
            $order = $this->orderRepository->create($request);
            $this->orderCart([
                'user_status'=>$account['status'],
                'user_id'=>$account['user']->id,
                'order_id'=>$order->id
            ]);
            $order->delete();
            $content = [
                'token'=>$token,
                'total'=>$calculate['total'],
                'user'=>$account['user']
            ];
            if ($order->total == 0)
            {
                $this->orderRepository->restore($order);
                $this->createTrack([
                    'order_id'=>$order->id,
                    'status'=>$order->status
                ]);
                $this->cartService->emptyCart($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);
                }

                $this->decreaseProductCount($order->id);

                $url = ($account['status'] == AccountStatusEnum::USER->value) ? route('web.profile') : route('web.order.details',$order->id);
            }
            else
            {
                $url = (new PaymentService(new MyFatoorahPayment()))->payment($content);
            }
        }
        else
        {
            $request['user_status'] = $account['status'];
            $request['user_id'] = $account['user']->id;
            $request['status'] = OrderStatusEnum::NEW->value;
            $order = $this->orderRepository->create($request);
            $this->orderCart([
                'user_status'=>$account['status'],
                'user_id'=>$account['user']->id,
                'order_id'=>$order->id
            ]);
            $qr_code = QrCodeService::generate($order->updated_at, $order->total, $order->total_tax);
            $this->update(['qr_image' => $qr_code['image_path']],$order->id);

            $this->orderRepository->restore($order);

            $this->createTrack([
                'order_id'=>$order->id,
                'status'=>$order->status
            ]);
            $this->cartService->emptyCart($request);

            if ($order->coupon_id)
            {
                $this->couponService->decrease($order->coupon_id);
            }
            $this->decreaseProductCount($order->id);
            $url = $account['status'] == AccountStatusEnum::VISITOR->value ? route('web.home') : route('web.order.details',$order->id);

        }


        return $url;
    }

    public function orderCart(array $request)
    {
        $carts = $this->cartService->get($request);
        foreach ($carts as $row)
        {
            $cost = $row->product->price['cost'];
            $data =
            [
                'count'=> $row->count,
                'product_cost'=> $cost,
                'total' => $cost * $row->count,
                'product_id' => $row->product_id,
                'store_id' => $row->product->store_id ,
                'option_id' => $row->option_id,
                'order_id' => $request['order_id'],
            ];
            $this->orderRepository->saveData($data);
        }
    }

    public function update(array $request , int $id) :Order
    {
        $order = $this->getItemTrashed($id);
        $order = $this->orderRepository->update($request, $order);
        if(isset($request['status']))
        {
            $this->createTrack([
                'order_id'=>$id,
                'status'=>$order->status
            ]);
        }
        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();
                $request['user_status'] = $account['status'];
                $request['user_id'] = $account['user']->id;

                $qr_code = QrCodeService::generate($order->updated_at, $order->total, $order->total_tax);

                $this->update(['qr_image' => $qr_code['image_path']],$order->id);

                $this->orderRepository->restore($order);

                $this->createTrack([
                    'order_id'=>$order->id,
                    'status'=>$order->status
                ]);

                $this->cartService->emptyCart([
                    'user_status'=>$account['status'],
                    'user_id'=>$account['user']->id
                ]);
                $this->decreaseProductCount($order->id);

                if ($order->coupon_id)
                {
                    $this->couponService->decrease($order->coupon_id);
                }
            }
        }
        return $order;
    }

    public function decreaseProductCount($order_id)
    {
        $order = $this->getItem($order_id);
        foreach ($order->products as $row)
        {
            $this->productWarehouseService->decreaseProductCount($row);
        }
    }

    public function destroy(int $id): array
    {
        $order = $this->getItem($id);
        $response = $this->orderRepository->destroy($order);
        return $response;
    }
    public function destroyAll(array $ids): array
    {
        $response = $this->orderRepository->destroyAll($ids);
        return $response;
    }
    public function restore(int $id): array
    {
        $order = $this->getItem($id);
        $response = $this->orderRepository->restore($order);
        return $response;
    }
    public function restoreAll(array $ids): array
    {
        $response = $this->orderRepository->restoreAll($ids);
        return $response;
    }
}
