<?php

namespace Modules\Cart\Controllers;

use App\Helpers\ApiClient;
use App\Helpers\Common;
use Illuminate\Http\Request;
use Module;
use Modules\Cart\Models\TagRefer;
use Modules\Cart\Models\Product;
use App\Utils;
use App\Customer;
use Modules\Cart\Models\ErrorLog;
use Illuminate\Support\Facades\File;
use Config;
use Cache;
use View;

class IndexController extends Controller
{
    public function __construct() {
        parent::__construct();
    }
    
    public function index(Request $request)
    {
        $cartItems = $this->getCartItems($request);
        $user = \Auth::guard("customer")->user();
        $metaTitle = __('Giỏ hàng');
        view()->share('metaTitle', $metaTitle);
        view()->share('pageType', "add_to_cart");
        $strCodes = "";
        $totalValue = 0;
        $invalidPaypalName = [];
        $isValidPaypalByProduct = true;
        if (!empty($cartItems)) {
            view()->share('imagePreload', getImageCdn($cartItems[0]['image_url'], 540, 540, false));
        }
        foreach ($cartItems as $item) {
            $strCodes .= $item['sku'].',';
            $totalValue += $item['price'] * $item['quantity'];
            $containsKey = array_reduce($invalidPaypalName, function ($carry, $key) use ($item) {
                return $carry || strpos(strtolower($item['product_name']), strtolower($key)) !== false;
            }, false);
            if ($containsKey) {
                $isValidPaypalByProduct = false;
            }
        }
        view()->share('strCode', substr($strCodes, 0, -1));
        view()->share('totalValue', $totalValue);
        view()->share('metaTitle', __('Cart'));
        View::share('user', $user);
        View::share('isValidPaypalByProduct', $isValidPaypalByProduct);
        // paypal
        $account = getPaypalKey();
        $usePaypalByLimit = false;
        $paypalKey = config("cart::paypal.clientId");
        if (isset($account) && isset($account["name"])) {
            $usePaypalByLimit = true;
            $paypalKey = $account["clientId"];
        }
        if (isset($_GET['mode']) && $_GET['mode'] == 'test') {
            $paypalKey = config("cart::paypal.sandbox_clientId");
        }
        $cardForm = config('cart::sa.card_form', 'stripe');
        if ($cardForm == 'paypal') {
            $paypalKey = config("cart::paypal.clientId_card");
        }
        View::share('usePaypalByLimit', $usePaypalByLimit);
        View::share('paypalKey', $paypalKey);

        $this->onViewCartItem($cartItems);

        $view = 'cart.index';
        if (!empty($request->headers->get('tenancy_token'))) {
            view()->share('isTenancy', 1);
            $view = 'cart.tenancy-index';
        }

        return Module::view($view, compact(['cartItems']));
    }

    private function onViewCartItem($cartItems) {
        if (!$this->isPageRefresh($cartItems, 'cart')) {
            $items = $this->getUntrackItem($cartItems, 'cart');
            Module::action('viewCart', [
                'items' => $items,
            ]);
        }
    }

    public function updateCartItem(Request $request) {
        $id = $request->input("id", null);
        $quantity = $request->input("quantity", null);
        $data = [
            'cart_item_id' => $id,
            'quantity' => $quantity,
        ];
        Module::action('updateCartItem', [
            'items' => [
                $data
            ],
        ]);
        $data = [
            'id' => $id,
            'quantity' => $quantity,
        ];
        if ($request->has("configurations")) {
            $data['configurations'] = $request->input("configurations");
        }
        if (shouldUseNewInterface()) {
            $data["use_new_interface"] = true;
        }
        $response = ApiClient::buildCustomRequest("cart/update-cart-item", "POST", $data, []);
        return response()->json($response);
    }

    public function removeCartItems (Request $request) {
        $ids = $request->input("ids", null);
        Module::action('removeCartItem', [
            'cartItemIds' => $ids,
        ]);
        $response = ApiClient::buildCustomRequest("cart/empty-cart", "POST", [
            'ids' => $ids,
            'use_new_interface' => shouldUseNewInterface(),
        ], []);
        return response()->json($response);
    }

    public function addToCart (Request $request) {
        $token = $request->input("token", null);
        $useCustomerId = $request->input("use_customer_id", 1);
        if (!$token) {
            $token = getFingerprint();
        }
        $user = \Auth::guard("customer")->user();
        $data = [
            "productId" => $request->input("productId", null),
            "productSkuId" => $request->input("productSkuId", null),
            "customerToken" => $token,
            "customerId" => isset($user->id) && $useCustomerId ? $user->id : null,
            "quantity" => $request->input("quantity", 1),
            "buynow" => $request->input("buynow", null),
            'configurations' => $request->input("configurations", null),
            'productVariantOptions' => $request->input("productVariantOptions", null),
            'data_insider' => $request->input("data_insider", null)
        ];

        if ($request->get('imageUrl')) {
            $data['imageUrl'] = $request->get('imageUrl');
        } else if ($request->hasFile('imageFile')) {
            $imageFile = $request->file('imageFile');
            
            $saveToFolder = 'customization-upload';
            if (!empty($data['configurations'])) {
                $fileName = md5($data['configurations']) . '_' . $imageFile->getClientOriginalName();
            } else {
                $fileName = generateRandomString(20) . '_' . $imageFile->getClientOriginalName();
            }
            //make folder
            if (!File::exists(public_path($saveToFolder))) {
                File::makeDirectory(public_path($saveToFolder), 0755, true, true);
            }
            if (File::exists(public_path($saveToFolder . '/' . $fileName))) {
                File::delete(public_path($saveToFolder . '/' . $fileName));
            }
            $imageFile->move(public_path($saveToFolder), $fileName);
            $finalPath = $saveToFolder . '/' . $fileName;
            $locale = env('APP_LOCALE');
            if (!empty($locale)) {
                $finalPath = $locale . '/' . $finalPath;
            }
            $data['imageUrl'] = asset($finalPath);
            if (!empty($data['configurations'])) {
                try {
                    $configurations = json_decode($data['configurations'], true);
                    $configurations['previewUrl'] = $data['imageUrl'];
                    $data['configurations'] = json_encode($configurations);
                } catch (\Exception $e) {}
            }
        }
        if ($request->has('note')) {
            $data['note'] = $request->input('note');
        }
        if (!empty($request->headers->get('tenancy_token'))) {
            $data['tenancy_token'] = $request->headers->get('tenancy_token');
        }
        $tokenUserQuery = $request->input('token_user_query');
        if (!isset($tokenUserQuery)) {
            if (isset($_COOKIE['token_user_query'])) {
                $tokenUserQuery = $_COOKIE['token_user_query'];
            }
        }
        if (isset($tokenUserQuery)) {
            $data['token_user_query'] = $tokenUserQuery;
        }
        if (shouldUseNewInterface()) {
            $data["use_new_interface"] = true;
        }
        $orderServiceUrl = config("cart::sa.order_service_url", "");
        if (empty($orderServiceUrl)) {
            $response = ApiClient::buildCustomRequest("cart/add-to-cart", "POST", $data , []);
            if(isset($response['cartItems']) && count($response['cartItems']) > 0) {
                foreach ($response['cartItems'] as $key => $item) {
                    if (isset(json_decode(urldecode($item['configurations']))->is_print_back) && Common::hasImageBack($item['product_id'])) {
                        $response['cartItems'][$key]['image_url'] = Common::convertUrlFrontsideToUrlBackside($item['image_url']);
                    }
                }
                priceChangeForceDecor($response['cartItems'], 'recommendation', ["pIdCol" => "product_id", "disableForceDecor" => true]);
            }
        } else {
            $url = $orderServiceUrl . "cart";
            $response = $this->triggerAsyncRequest($url, "POST", $data, ["headers" => "Content-Type: application/json"]);
            if(isset($response['result']) && count($response['result']) > 0) {
                $response['cartItems'] = $response['result'];
                unset($response['result']);
                foreach ($response['cartItems'] as $key => $item) {
                    if (isset(json_decode(urldecode($item['configurations']))->is_print_back) && Common::hasImageBack($item['product_id'])) {
                        $response['cartItems'][$key]['image_url'] = Common::convertUrlFrontsideToUrlBackside($item['image_url']);
                    }
                }
                priceChangeForceDecor($response['cartItems'], 'recommendation', ["pIdCol" => "product_id", "disableForceDecor" => true]);
            }
        }

        if (isset($response["message"])) {
            $response["message"] = __($response["message"]);
        }
        if ($request->has("with_related")) {
            $related = $this->getRelatedItems($request);
            $response["related"] = $related;
        }
        Module::action('addToCart', [
            'product_id' => $request->input('productId'),
            'product_sku_id' => $request->input('productSkuId'),
            'quantity' => $request->input('quantity'),
        ]);
        return response()->json($response);
    }

    public function addToCartFlow (Request $request) {
        $token = getFingerprint();
        $user = \Auth::guard("customer")->user();
        $data = [
            "productId" => $request->input("productId", null),
            "productSkuId" => $request->input("productSkuId", null),
            "customerToken" => $token,
            "customerId" => isset($user->id) ? $user->id : null,
            "quantity" => $request->input("quantity", 1),
            "buynow" => $request->input("buynow", null),
            'configurations' => $request->input("configurations", null),
            "use_new_interface" => shouldUseNewInterface(),
            'productVariantOptions' => $request->input("productVariantOptions", null),
        ];

        if ($request->has('designUrl')) {
            $data['designUrl'] = $request->designUrl;
        }
        Module::action('addToCart', [
            'product_id' => $data['productId'],
            'product_sku_id' => $data['productSkuId'],
            'quantity' => $data['quantity'],
        ]);
        $response = ApiClient::buildCustomRequest("cart/add-to-cart", "POST", $data, []);
        if ($request->input("buynow")) {
            return redirect('/checkout');
        }
        return redirect('/cart');
    }

    private function getCartItems(Request $request) {
        $cartItems = [];
        $query = ApiClient::buildClient("cart/get-cart-item");
        $token = getFingerprint();
        if ($request->has("token")) {
            $token = $request->input("token");
        }
        $user = \Auth::guard("customer")->user();
        $customerId = isset($user->id) ? $user->id : null;
        if ($request->has("customerId")) {
            $customerId = $request->input("customerId");
        }
        $query->addField("token", $token);
        $query->addField("customerId", $customerId);
        if (!empty($request) && !empty($request->headers->get('tenancy_token'))) {
            $query->addField("tenancy_token", $request->headers->get('tenancy_token'));
        }
        if (shouldUseNewInterface()) {
            $query->addField("use_new_interface", true);
        }
        if (!empty($_SERVER['SERVER_NAME']) && $_SERVER['SERVER_NAME'] == 'design4u.printerval.com') {
            \Log::info('get-cart-item-field', [
                'token' => $token,
                'customerId' => $customerId,
                'tenancy_token' => $request->headers->get('tenancy_token'),
            ]);
        }
        $orderServiceUrl = config("cart::sa.order_service_url", "");
        if (empty($orderServiceUrl)) {
            $result = $query->get();
            if (isset($result['status']) && $result['status'] == 'successful') {
                foreach ($result['items'] as $key => $item) {
                    if (isset(json_decode($item['configurations'])->is_print_back) && Common::hasImageBack($item['product_id'])) {
                        $result['items'][$key]['image_url'] = Common::convertUrlFrontsideToUrlBackside($item['image_url']);
                    }
                }
                $cartItems = $result['items'];
                priceChangeForceDecor($cartItems, 'recommendation', ["pIdCol" => "product_id", "disableForceDecor" => true]);
            }
        } else {
            $params = [
                "token" => $token,
                "customerId" => isset($user->id) ? $user->id : null,
                "use_new_interface" => shouldUseNewInterface(),
            ];
            if (!empty($request->headers->get('tenancy_token'))) {
                $params['tenancy_token'] = $request->headers->get('tenancy_token');
            }
            $url = $orderServiceUrl . "cart";
            if (count($params) > 0) {
                $url .= "?" . http_build_query($params);
            }
            $result = $this->triggerAsyncRequest($url, "GET", [], []);
            if (isset($result['status']) && $result['status'] == 'successful') {
                foreach ($result['result'] as $key => $item) {
                    if (isset(json_decode($item['configurations'])->is_print_back) && Common::hasImageBack($item['product_id'])) {
                        $result['result'][$key]['image_url'] = Common::convertUrlFrontsideToUrlBackside($item['image_url']);
                    }
                }
                $cartItems = $result['result'];
                priceChangeForceDecor($cartItems, 'recommendation', ["pIdCol" => "product_id", "disableForceDecor" => true]);
            }
        }
        return $cartItems;
    }

    public function getCart (Request $request) {
        $cartItems = $this->getCartItems($request);
        $subTotal = 0;
        $productIds = [];
        foreach ($cartItems as $item) {
            $subTotal = $subTotal + $item['quantity'] * $item['price'];
            $productIds[] = $item["product_id"];
        }
        $productCustom = \DB::table('product_custom')->whereIn('product_id', $productIds)->get()->keyBy('product_id');
        $invalidBuyDesignCate = getOption("invalid_buy_design_cate", []);
        $configIncludeDesignFeeCate = config("cart::sa.include_design_fee_cate", "");
        $includeDesignFeeCate = [];
        if ($configIncludeDesignFeeCate != "") {
            $includeDesignFeeCate = explode(",", $configIncludeDesignFeeCate);
        }

        $configGiftWrapCate = config("cart::sa.gift_wrap_cate", "");
        $giftWrapCate = [];
        if ($configGiftWrapCate != "") {
            $giftWrapCate = explode(",", $configGiftWrapCate);
        }

        $categories = \DB::table("product_n_category")->whereIn("product_id", $productIds)->pluck("category_id", "product_id");
        $listValidProducts = [];
        $listIncludeProducts = [];
        $listGiftWrapProducts = [];
        foreach ($categories as $productId => $categoryId) {
            $category = \DB::table("product_n_category")
                ->join("category", "category.id", "=", "product_n_category.category_id")
                ->where("product_id", $productId)
                ->where("is_parent", 0)
                ->select(["category.id", "category.slug", "is_parent", "is_valid_print_back", "sell_design"])
                ->first();
            if (isset($category->sell_design)) {
                if ($category->sell_design == 1) {
                    $listValidProducts[] = $productId;
                } else if ($category->sell_design == 2) {
                    $listValidProducts[] = $productId;
                    $listIncludeProducts[] = $productId;
                }
            }
            if (in_array($categoryId, $giftWrapCate) && !in_array($productId, $giftWrapCate)) {
                $listGiftWrapProducts[] = $productId;
            }
        }
        foreach ($cartItems as $key => $item) {
            $cartItems[$key]["is_custom_design"] = isset($productCustom[$item["product_id"]]) ? 1 : 0;
            $cartItems[$key]["is_valid_buy_design"] = in_array($item["product_id"], $listValidProducts) ? 1 : 0;
            $cartItems[$key]["is_include_design_fee"] = in_array($item["product_id"], $listIncludeProducts) ? 1 : 0;
            $cartItems[$key]["is_valid_gift_wrap"] = in_array($item["product_id"], $listGiftWrapProducts) ? 1 : 0;
        }
        $related = [];
        if ($request->has("with_related")) {
            $related = $this->getRelatedItems($request);
        }
        return response()->json([
            'status' => 'successful',
            'result' => $cartItems,
            'sub_total' => $subTotal,
            'related' => $related,
            'display_sub_total' => formatPrice($subTotal)
        ]);
    }

    public function indexTrackOrder(){
        $metaTitle = __('Track order');
        view()->share('metaTitle', $metaTitle);
        return Module::view('cart.track-order');
    }

    public function getShippingInfo(Request $request) {
        $productId = $request->input("id");
        $productSkuId = $request->input("productSkuId");
        $quantity = $request->input("quantity", 1);
        $countryByIp = config("app.locale_shipping");
        if (!$countryByIp || $countryByIp == "us") {
            $countryByIp = Utils::countryFromIp();
        }
        if ($request->has("country")) {
            $countryByIp = $request->input("country");
        }
        $url = "shipping-fee/info/v2?location_iso=" . $countryByIp . "&product_id=" . $productId . "&product_sku_id=" . $productSkuId . "&quantity=" . $quantity;
        if ($request->has("getCost")) {
            $url .= "&get_cost=" . $request->input("getCost");
        }
        if (shouldUseNewInterface()) {
            $url .= "&use_new_interface=true";
        }
        $response = ApiClient::buildCustomRequest($url, "GET", [], []);
        return response()->json($response);
    }

    public function getRelatedProducts(Request $request) {
        $response = [
            "status" => "fail",
        ];
        $response["result"] = $this->getRelatedItems($request);
        $response["status"] = "successful";
        return response()->json($response);
    }
    
    private function getRelatedItems(Request $request) {
        $size = 20;
        if ($request->has('size')) {
            $size = $request->input("size");
        }
        $result = [];
        $token = getFingerprint();
        $resultRecommend = [];
        $notIds = [];
        $recommendationUrl = config("cart::sa.recommendation_url", "");
        if ($recommendationUrl) {
            $locale = env('APP_LOCALE');
            $data = $this->triggerAsyncRequest($recommendationUrl . "/recommendation?locale=" . $locale . "&uid=" . $token . "&size=" . $size);
            if (isset($data) && isset($data["status"]) && $data["status"] == "successful" && isset($data["result"])) {
                foreach ($data["result"] as $item) {
                    $notIds[] = $item["id"];
                    $resultRecommend[] = $item;
                }
            }
        }
        $limit = 20;
        if (count($resultRecommend) > 0) {
            $limit -= count($resultRecommend);
        }
        $cartItems = $this->getCartItems($request);
        $ids = [];
        foreach ($cartItems as $key => $value) {
            $ids[] = $value["product_id"];
        }
        $ids = array_unique (array_merge ($ids, $notIds));
        $relatedProducts = [];
        $tagIds = TagRefer::whereIn('refer_id', $ids)
            ->get(['tag_id'])
            ->pluck('tag_id')
            ->toArray();
        if (count($tagIds) > 0 && false) {
            $relatedProducts = Product::where("status", "ACTIVE")
                ->join("trending_tag_sale", function($query) use ($tagIds) {
                    $query->on("product_id", "=", "product.id");
                    $query->whereIn("tag_id", $tagIds);
                })
                ->whereNotIn("product.id", $ids)
                ->groupBy("product.id")
                ->orderBy("view_count", "DESC")
                ->orderBy("sold", "DESC")
                ->limit($limit)
                ->get(['product.id', 'product.sku', 'product.name', 'product.slug', 'product.image_url', 'product.price', 'product.high_price', 'product.created_at'])
                ->toArray();
        }
        $result = array_merge($resultRecommend, $relatedProducts);
        priceChangeForceDecor($result, 'recommendation');
        return $result;
    }

    public function getProductVariant(Request $request) {
        $response = [
            "status" => "fail",
        ];
        $id = $request->input('id');
        if ($id) {
            $result = ApiClient::buildCustomRequest('variant/' . $id, 'GET', [
                'has_options' => true
            ], []);
            $sortSize = getOption("size_sort_default");
            if (!$sortSize) {
                $sortSize = config("default.size_sort_default", []);
            }
            $data = $result["result"];
            if (isset($data['productVariants']) && $data['productVariants']) {
                $p = [
                    'id' => $id
                ];
                priceChangeDecorProduct($p, $data['productVariants']);
                $variantsStatistic = $this->statisticProductVariant($data);
                $data["variantsStatistic"] = $variantsStatistic;
            }
            if (!empty($data['variants'])) {
                foreach ($data['variants'] as $key => $variantGroup) {
                    if ($variantGroup["slug"] == "size" && count($sortSize) > 0) {
                        $newGroup = [];
                        foreach($variantGroup['values'] as $variant) {
                            $newGroup[$variant["slug"]] = $variant;
                        }

                        $newSortValues = array_merge(array_flip($sortSize), $newGroup);
                        $newVariantValues = [];
                        foreach ($newSortValues as $value) {
                            if (is_array($value)) {
                                $newVariantValues[] = $value;
                            }
                        }

                        $data['variants'][$key]["values"] = $newVariantValues;
                    }
                }
            }
            $response = [
                "status" => "successful",
                "result" => $data,
            ];
        }

        return response()->json($response);
    }

    private function statisticProductVariant($data) {
        $variantsStatistic = [];
        if (isset($data['productVariants'])) {
            foreach($data['productVariants'] as $key => $sku) {
                if (!isset($sku['variants'][0]['variant'])
                    || !isset($sku['variants'][1])
                    || !isset($sku['variants'][1]['variant'])) {
                    continue;
                }
                $vKey = $sku['variants'][0]['id'] . '-' . $sku['variants'][1]['id'];
                if (!isset($variantsStatistic[$vKey])) {
                    $variantsStatistic[$vKey]  = [
                        'count' => 0,
                        'price' => $sku['price'],
                        'display_price' => $sku['display_price'],
                    ];
                }
                $variantsStatistic[$vKey]['count']++;
                if ($variantsStatistic[$vKey]['price'] > $sku['price']) {
                    $variantsStatistic[$vKey]['price'] = $sku['price'];
                    $variantsStatistic[$vKey]['display_price'] = $sku['display_price'];
                }

            }
        }
        return $variantsStatistic;

    }

    protected function triggerAsyncRequest($url, $method = "GET", $params = [], $headers = []) {
        $channel = curl_init();
        curl_setopt($channel, CURLOPT_URL, $url);
        // curl_setopt($channel, CURLOPT_NOSIGNAL, 1);
        curl_setopt($channel, CURLOPT_TIMEOUT, 120);
        curl_setopt($channel, CURLOPT_RETURNTRANSFER, 1);
        if($method == "post" || $method == "POST") {
            curl_setopt($channel, CURLOPT_POST, true);
            curl_setopt($channel, CURLOPT_POSTFIELDS, json_encode($params));
        }
        if ($headers) {
            curl_setopt($channel, CURLOPT_HTTPHEADER, $headers);
        }
        curl_setopt($channel, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($channel, CURLOPT_SSL_VERIFYPEER, 0);
        $data = curl_exec($channel);
        curl_close($channel);
        return json_decode($data, true);
    }

    public function sendLogGoogleMap(Request $request) {
        $url = route('home') . '/checkout';
        $log = ErrorLog::insert([
            "project" => "printerval-site",
            "url" => $url,
            "data" => "[]",
            "message" => "Error Google Map",
            "created_at" => new \DateTime(),
            "updated_at" => new \DateTime(),
        ]);
        return response()->json(["status" => "successful"]);
    }

    public function getRelatedDropPrice(Request $request) {
        $query = ApiClient::buildClient("cart/get-cart-item");
        $token = getFingerprint();
        $query->addField("token", $token);
        if (shouldUseNewInterface()) {
            $query->addField("use_new_interface", true);
        }
        $resultItems = $query->get();
        $cartItems = [];
        if (isset($resultItems['status']) && $resultItems['status'] == 'successful') {
            $cartItems = $resultItems['items'];
        }
        $response = [
            "status" => "fail",
        ];
        if (count($cartItems) > 0) {
            $ids = [];
            foreach ($cartItems as $key => $value) {
                $ids[] = $value["product_id"];
            }
            $result = ApiClient::buildCustomRequest("/product/related-drop-price?ids=" . implode(",", $ids), 'GET', [], []);
            if (array_key_exists("result", $result)) {
                priceChangeDecor($result["result"]);
            }
            $response = $result;
        }
        return response()->json($response);
    }

    public function getCustomerToken(Request $request) {
        $token = getFingerprint();
        return response()->json(["status" => "successful", "result" => $token]);
    }

    public function sendLogFailCheckout(Request $request) {
        $data = $request->all();
        $url = route('home') . '/checkout';
        $log = ErrorLog::insert([
            "project" => "printerval-site",
            "url" => $url,
            "data" => json_encode($data),
            "file" => $data["image"],
            "message" => "Fail checkout",
            "created_at" => new \DateTime(),
            "updated_at" => new \DateTime(),
        ]);
        return response()->json(["status" => "successful"]);
    }

    public function saveCapturedImage(Request $request)
    {
        $retval = [
            'status' => 'fail'
        ];

        if (isset($request->base64Data)) {
            $data = explode('base64', $request->base64Data);
            $path = 'captured-images/' . \Carbon\Carbon::now()->format('d-m-Y');
            $imageDestination = base_path('public/' . $path);
            if (!\File::exists($imageDestination)) {
                \File::makeDirectory($imageDestination, 0777, true, true);
            }
            $fileName = '/captured_image_' . time() . '.jpg';
            $imageDestination = $imageDestination . $fileName;
            file_put_contents($imageDestination, base64_decode($data[1]));
            $retval['result'] = $path . $fileName;
            $retval['status'] = 'successful';
        }

        return $retval;
    }

    public function autocomplete (Request $request) {
        $retval = [
            'status' => 'fail',
            'msg' => 'Unknown error'
        ];

        if (!$request->has('input')) {
            $retval['msg'] = "Field input required";
            return $retval;
        }
        $keyword = $request->input('input');
        $country = $request->input('country');
        $keyword = rawurlencode($keyword);
        $key = Config::get('cart::sa.zillow_api_key');
        $url = "https://zillow-working-api.p.rapidapi.com/autocomplete?query=$keyword";
        if (Cache::get($url)) {
            $retval = Cache::get($url);
            return response()->json(json_decode($retval));
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            "X-RapidAPI-Key: " . $key,
            "x-rapidapi-host: zillow-working-api.p.rapidapi.com"
        ]);
        $output = curl_exec($ch);
        Cache::put($url, $output, 60 * 24);
        curl_close($ch);

       $retval =  $output;

       return response()->json(json_decode($retval));
    }

    public function details (Request $request) {
        $retval = [
            'status' => 'fail',
            'msg' => 'Unknown error'
        ];

        if (!$request->has('placeid')) {
            $retval['msg'] = "Field placeid required";
            return $retval;
        }
        $placeid = $request->input('placeid');
        $key = Config::get('cart::sa.google_api_key');

        $url = "https://maps.googleapis.com/maps/api/place/details/json?placeid=$placeid&key=$key";
        if (Cache::get($url)) {
            $retval = Cache::get($url);
            return response()->json(json_decode($retval));
        }
         $ch = curl_init();
         curl_setopt($ch, CURLOPT_URL, $url);
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
         $output = curl_exec($ch);
         curl_close($ch);

        $retval =  $output;
        Cache::put($url, $output, 60 * 24);
        return response()->json(json_decode($retval));
    }

    public function addAllToCart(Request $request) {
        $response = [
            "status" => "fail",
        ];
        $token = $request->has("token") ? $request->input("token") : getFingerprint();
        $user = \Auth::guard("customer")->user();

        $items = $request->input('items');
        if ($request->input('data')) {
            $items = $request->input('data');
        }

        $tenancyToken = $request->headers->get('tenancy_token', null);
        if (count($items) > 0) {

            $imageUrl = null;
            if ($request->hasFile('imageFile')) {

                $imageFile = $request->file('imageFile');
                
                $saveToFolder = 'customization-upload';
                $fileName = generateRandomString(20) . '_' . $imageFile->getClientOriginalName();

                //make folder
                if (!File::exists(public_path($saveToFolder))) {
                    File::makeDirectory(public_path($saveToFolder), 0755, true, true);
                }
                if (File::exists(public_path($saveToFolder . '/' . $fileName))) {
                    File::delete(public_path($saveToFolder . '/' . $fileName));
                }

                $imageFile->move(public_path($saveToFolder), $fileName);
                $finalPath = $saveToFolder . '/' . $fileName;
                $locale = env('APP_LOCALE');
                if (!empty($locale)) {
                    $finalPath = $locale . '/' . $finalPath;
                }

                $imageUrl = asset($finalPath);
            }

            $result = [];
            $notIds = [];
            foreach ($items as $key => $item) {
                $dataAddToCart = [
                    "productId" => $item["productId"],
                    "productSkuId" => $item["productSkuId"],
                    'productVariantOptions' => $request->input("productVariantOptions", null),
                    "customerToken" => $token,
                    "customerId" => isset($user->id) ? $user->id : null,
                    "quantity" => $item["quantity"],
                    "configurations" => $item["configurations"],
                    "source" => isset($item["source"]) ? $item["source"] : 'multiple-size',
                ];

                if (!empty($item['imageUrl'])) {
                    $dataAddToCart['imageUrl'] = $item['imageUrl'];
                }

                if ($imageUrl) {
                    $dataAddToCart['imageUrl'] = $imageUrl;
                    if (!empty($dataAddToCart['configurations'])) {
                        try {
                            $configurations = json_decode($item['configurations'], true);
                            $configurations['previewUrl'] = $dataAddToCart['imageUrl'];
                            $dataAddToCart['configurations'] = json_encode($configurations);
                        } catch (\Exception $e) {}
                    }
                }

                if (!empty($tenancyToken)) {
                    $dataAddToCart['tenancy_token'] = $tenancyToken;
                }
                
                if (shouldUseNewInterface()) {
                    $dataAddToCart['use_new_interface'] = true;
                }

                $notIds[] = $item["productId"];
                $data = ApiClient::buildCustomRequest("cart/add-to-cart", "POST", $dataAddToCart , []);
                if (isset($data["cartItems"])) {
                    foreach ($data["cartItems"] as $index => $value) {
                        if ($value["product_sku_id"] == $item["productSkuId"] && $value["product_id"] == $item["productId"]) {
                            $value["url"] = clroute($value["url"]);
                            $result[] = $value;
                        }
                    }
                }
            }
            $response = [
                "status" => "successful",
                "result" => $result,
            ];
        }
        return response()->json($response);

    }

    public function convertAmountByCurrency($amount, $currency, $data = []) {
        $currencyRatio = (array) getOption("currency_ratio_parse");
        if (isset($currencyRatio[$currency])) {
            $currencyConfig = (array) $currencyRatio[$currency];
            $decimal = 2;
            if ($currency == 'JPY' || $currency == 'KRW' || $currency == 'VND') {
                $decimal = 0;
            }
            $amountConvert = $this->roundUp($amount * $currencyConfig["ratio"], $decimal);
            if (isset($data["orderId"])) {
                \DB::table("order_meta")->insert([
                    "order_id" => $data["orderId"],
                    "key" => "amount_convert",
                    "value" => json_encode(["amount" => $amountConvert, "currency" => $currency, "ratio" => $currencyConfig["ratio"]]),
                ]);
            }
            return $amountConvert;
        } else {
            return false;
        }
    }

    function roundUp($value, $precision = 0) {
        $offset = 0.5;
        if ($precision !== 0) $offset /= pow(10, $precision);
       return round($value + $offset, $precision, PHP_ROUND_HALF_DOWN);
   }

   public function getShippingInfoCart(Request $request) {
        $token = getFingerprint();
        $countryByIp = $request->input("country", null);
        if (!$countryByIp) {
            $countryByIp = config("app.locale_shipping");
            if (!$countryByIp || $countryByIp == "us") {
                $countryByIp = Utils::countryFromIp();
            }
        }
        $user = \Auth::guard("customer")->user();
        $url = "/shipping-fee/item/info?token=" . $token . "&location_iso=" . $countryByIp;
        if (isset($user->id)) {
            $url .= "&customer_id=" . $user->id;
        }
        $response = ApiClient::buildCustomRequest($url, "GET", [], []);
        return response()->json($response);
   }

   public function getSameItemInCart(Request $request) {
        $ids = $request->input("ids");
        $url = "/same-item-in-cart?ids=" . $ids;
        $response = ApiClient::buildCustomRequest($url, "GET", [], []);
        return response()->json($response);
   }

    public function getCustomerRewards(Request $request) {
        $response = [
            "status" => "fail",
            "result" => [],
        ];
        $user = \Auth::guard('customer')->user();
        if (!empty($request->get('zdebug'))) {
            // debug
            echo '<pre>';
            print_r($user);
            echo '</pre>';die;
        }
        if ($user && $user->id) {
            $url = "/order/get-customer-rewards?customer_id=" . $user->id;
            $response = ApiClient::buildCustomRequest($url, "GET", [], []);
        }
        return response()->json($response);
    }
    public function getCustomerPoint(Request $request) {
        $response = [
            "status" => "fail",
            "result" => [],
        ];
        $user = \Auth::guard('customer')->user();
        if ($user && $user->id) {
            $url = "/customer-point?customer_id=" . $user->id;
            $response = ApiClient::buildCustomRequest($url, "GET", [], []);
        }
        return response()->json($response);
    }

    public function getDiscountByRefer() {
        $response = [
            "status" => "fail",
            "result" => [],
        ];
        $user = \Auth::guard('customer')->user();
        if ($user && $user->id) {
            $url = "/discount-by-refer?customer_id=" . $user->id;
            $response = ApiClient::buildCustomRequest($url, "GET", [], []);
        }
        return response()->json($response);
    }

    public function getConfigRangeByMarket()
    {
        $url = "/config-range-by-market";
        $response = ApiClient::buildCustomRequest($url, "GET", [], []);
        return response()->json($response);
    }

    public function findProduct(Request $request) {
        $response = [
            "status" => "fail",
        ];
        $productId = $request->input('product_id');
        if ($productId) {
            if ($productId == 'null' && $request->has("sku")) {
                $productBySku = \DB::table("product")->where("sku", "=", $request->input("sku"))->first();
                if ($productBySku) {
                    $productId = $productBySku->id;
                }
            }
            $result = ApiClient::buildCustomRequest('product/' . $productId, 'GET', [], []);
            $items = [$result["result"]];
            priceChangeForceDecor($items, 'recommendation');
            $data = isset($items[0]) ? $items[0] : $result["result"];
            $isShirt = false;
            $category = [];
            $categories = \DB::table("product_n_category")
                ->join("category", "category.id", "=", "product_n_category.category_id")
                ->where("product_id", $productId)
                ->select(["category.id", "category.slug", "is_parent", "is_valid_print_back", "sell_design"])
                ->get();
            foreach ($categories as $cate) {
                if ($cate->id == 6) {
                    $isShirt = true;
                }
                if (isset($cate->is_parent) && $cate->is_parent == 0) {
                    $category = (array) $cate;
                }
            }
            $validPrintBack = false;
            if (isset($category["is_valid_print_back"]) && $category["is_valid_print_back"] == 1) {
                $validPrintBack = true;
            }
            $isMultipleDesign = false;
            $isCustomDesign = \DB::table('product_custom')->where('product_id', $productId)->exists();
            $isDoubleSided = false;
            if (!isset($data["attributes"])) {
                $data["attributes"] = [];
            }
            foreach ($data["attributes"] as $key => $item) {
                if ($key == "multiple_design" && $item == 1) {
                    $isMultipleDesign = true;
                }
                if ($key == "is_double_sided" && $item == 1) {
                    $isDoubleSided = true;
                }
                if ($key == "double_sided" && $item == 1) {
                    $isDoubleSided = true;
                }
            }
            if (!$isShirt || $isMultipleDesign || $isCustomDesign || $isDoubleSided) {
                $validPrintBack = false;
            }
            $data["is_valid_print_back"] = $validPrintBack;
            if (isset( $data['variant_default'])) {
                $variantDefault = $data['variant_default'];
                priceChangeDecor($variantDefault, [
                    'pIdCol' => 'product_id'
                ]);
                $data['variant_default'] = $variantDefault;
            }
            $data["is_custom"] = $data["attributes"] && isset($data["attributes"]["is_custom"]) ? 1 : 0;
            if ($request->has("sku")) {
                $splitSku = explode("-", $request->input("sku"));
                $newSku = [];
                foreach ($splitSku as $key => $sk) {
                    if ($key != 0) {
                        $newSku[] = $sk;
                    }
                }
                $sku = null;
                $template = \DB::table("product_n_template")->where("product_id", $productId)->first();
                if ($template) {
                    $sku = \DB::table("product_template_sku")->where("template_id", $template->template_id)->where("sku", "-" . implode("-", $newSku))->first();
                }
                if (!$sku) {
                    $sku = \DB::table("product_sku")->where("sku", $request->input("sku"))->where("product_id", $productId)->first();
                }
                if ($sku) {
                    $data["product_sku"] = $sku;
                }
            }
            $response = [
                "status" => "successful",
                "result" => $data,
            ];
        }
        return response()->json($response);
    }

    public function getFreeshipPackageProduct() {
        $url = "/product?filters=slug=freeship-package&simple_paginate=1";
        $response = ApiClient::buildCustomRequest($url, "GET", [], []);
        return response()->json($response);
    }

    public function getCustomerInfo(Request $request) {
        $email = $request->input('email');
        $response = [
            "status" => "fail",
        ];
        if ($email) {
            $customer = Customer::where("email", $email)->orderBy("id", "DESC")->first();
            $response = [
                "status" => "successful",
                "result" => $customer,
            ];
        }
        return response()->json($response);
    }

    public function validateAppleMerchant(Request $request) {
        $validationUrl = $request->input("validationUrl");
        $configCertPath = config("cart::sa.apple_cert_path", "/printerval_apple_pay_prod/apple_pay_crt.pem");
        $configKeyPath = config("cart::sa.apple_kay_path", "/printerval_apple_pay_prod/apple_pay.rsa.key.pem");
        $domainName = config("cart::sa.domain_name", "printerval.com");
        $clientCertificatePath = storage_path($configCertPath);
        $clientKeyPath = storage_path($configKeyPath);
        $merchantItentifier = openssl_x509_parse(file_get_contents($clientCertificatePath))['subject']['UID'];
        
        $channel = curl_init();
        curl_setopt($channel, CURLOPT_URL, $validationUrl);
        // curl_setopt($channel, CURLOPT_NOSIGNAL, 1);
        curl_setopt($channel, CURLOPT_TIMEOUT, 120);
        curl_setopt($channel, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($channel, CURLOPT_POST, true);
        curl_setopt($channel, CURLOPT_POSTFIELDS, json_encode([
            "merchantIdentifier" => $merchantItentifier,
            "displayName" => "Printerval",
            "domainName" => $domainName
        ]));
        curl_setopt($channel, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        curl_setopt($channel, CURLOPT_SSLCERT, $clientCertificatePath);
        curl_setopt($channel, CURLOPT_SSLKEY, $clientKeyPath);     

        $data = curl_exec($channel);
        if (curl_errno($channel)) {
            $error_msg = curl_error($channel);
            return $error_msg;
        }
        curl_close($channel);

        $response = [
            "status" => "successful",
            "result" => json_decode($data, true),
        ];
        return response()->json($response);

    }

    public function getCountryByIp(Request $request) {
        $response = [
            "status" => "successful",
            "result" => Utils::countryFromIp(),
        ];
        return response()->json($response);
    }

    public function checkTrademarksPaypal(Request $request) {
        $cartItems = $this->getCartItems($request);
        $isValidPaypalByProduct = true;
        $invalidPaypalName = getOption("invalid_paypal_keywords", "");
        $invalidPaypalName = explode(",", $invalidPaypalName);
        $invalidPaypalTrademarks = \DB::table('product_trademarks')->where("type", "keyword")->where("site", "PAYPAL")->where("status", "ACTIVE")->pluck("keyword")->toArray();
        $result = [];
        $foundKey = null;
        $foundKeyTrademarks = null;
        foreach ($cartItems as $item) {
            foreach ($invalidPaypalName as $key) {
                if ($key != "") {
                    $escapedKey = preg_quote(strtolower($key), '/');
                    $escapedKey = $escapedKey . "s?";
                    $escapedKey = preg_replace('/\s+/', '\W+', $escapedKey);
                    if (preg_match("/\b$escapedKey\b|^$escapedKey\b|\b$escapedKey$/", strtolower($item['product_name']))) {
                        $foundKey = true;
                        $result[] = $key;
                        break;
                    }
                }
            }
            if (!$foundKey) {
                foreach ($invalidPaypalTrademarks as $key) {
                    if ($key != "") {
                        $escapedKey = preg_quote(strtolower($key), '/');
                        $escapedKey = $escapedKey . "s?";
                        $escapedKey = preg_replace('/\s+/', '\W+', $escapedKey);
                        if (preg_match("/\b$escapedKey\b|^$escapedKey\b|\b$escapedKey$/", strtolower($item['product_name']))) {
                            $foundKeyTrademarks = true;
                            $result[] = $key;
                            break;
                        }
                    }
                }
            }
            if ($foundKey || $foundKeyTrademarks) {
                $isValidPaypalByProduct = false;
            }
        }
        $response = [
            "status" => "successful",
            "result" => $isValidPaypalByProduct,
            "data" => $result,
        ];
        return response()->json($response);
    }

    public function getEvent(Request $request) {
        $response = [
            "status" => "fail",
        ];
        if ($request->has("product_id")) {
            $nextTwentyDays = date('Y-m-d', strtotime('+20 days'));
            $nextThreeDays = date('Y-m-d', strtotime('+3 days'));
            $event = \DB::table("season_event_n_product")
                ->join("season_event", "season_event.id", "=", "season_event_n_product.season_event_id")
                ->where("status", "ACTIVE")
                ->where("end_at", "<", $nextTwentyDays)
                ->where("end_at", ">", $nextThreeDays)
                ->where("product_id", $request->input("product_id"))
                ->first();
            $response = [
                "status" => "successful",
                "result" => $event,
            ];
        }
        return response()->json($response);
    }

    public function getProductPersonalizeUrl(Request $request) {
        $response = [
            'status' => 'fail'
        ];
        $id = $request->input('id');
        $product = \DB::table("product_meta")->where('product_id', $id)->where('key', 'personalize_url')->first(['value']);
        if (!empty($product)) {
            $response['status'] = 'successful';
            $response['url'] = $product->value;
        }
        return response()->json($response);
    }

    public function cancelOrder(Request $request) {
        $result = [
            "status" => "fail",
            "message" => "Invalid order"
        ];
        $id = $request->input("id");
        $email = $request->input("email");
        $data = [
            "id" => $id,
            "email" => $email,
            "service_token" => "megaads@123",
            "cancel_data" => $request->input("cancel_data", null),
        ];
        if ($id && $email) {
            $result = ApiClient::buildCustomRequest("/order/cancel", 'POST', $data, []);
        }
        return $result;
    }

    public function checkTaxUs(Request $request) {
        $response = [
            "status" => "successful",
            "result" => false,
        ];
        $country = $request->input("country");
        if ($country != 226) {
            return response()->json($response);
        }
        if ($request->has("product_id") || $request->has("product_sku_id")) {
            $productId = $request->input("product_id");
            $productSkuId = $request->input("product_sku_id");
            if (!$productSkuId) {
                $resultCost = getProductCost($productId, "product_id", $country);
            } else {
                $resultCost = getProductCost($productSkuId, "product_sku_id", $country);
            }
            if (isset($resultCost["warehouse"]) && isset($resultCost["warehouse"]["location"]) && $resultCost["warehouse"]["location"] == "China") {
                $response["result"] = true;
                $response["data"] = $resultCost;
            }
        } else {
            $cartItems = $this->getCartItems($request);
            foreach ($cartItems as $item) {
                if ($item["product_sku_id"]) {
                    $resultCost = getProductCost($item["product_sku_id"], "product_sku_id", $country);
                    if (isset($resultCost["warehouse"]) && isset($resultCost["warehouse"]["location"]) && $resultCost["warehouse"]["location"] == "China") {
                        $response["result"] = true;
                        $response["data"] = $resultCost;
                        break;
                    }
                }
            }
        }
        return response()->json($response);
        $categories = [];
        if ($request->has("product_id")) {
            $categories = \DB::table("product_n_category")->where("product_id", $request->input("product_id"))->get(["category_id", "product_id"]);
        } else {
            $cartItems = $this->getCartItems($request);
            $productIds = [];
            foreach ($cartItems as $item) {
                $productIds[] = $item["product_id"];
            }
            $categories = \DB::table("product_n_category")->whereIn("product_id", $productIds)->get(["category_id", "product_id"]);
        }
        $categoryIds = [];
        foreach ($categories as $category) {
            $categoryIds[] = $category->category_id;
        }
        $listValidCategories = config("sa.category_tax_us", []);
        foreach ($categoryIds as $key => $value) {
            if (in_array($value, $listValidCategories)) {
                $response = [
                    "status" => "successful",
                    "result" => true,
                ];
                break;
            }
        }
        return response()->json($response);
    }

    public function continueLogin(Request $request) {
        $email = $request->input("email");
        $customer = Customer::where("email", $email)->wherenotNull("password")->first(["full_name", "email", "id"]);
        return response()->json([
            "status" => "successful",
            "result" => $customer,
        ]);
    }

    public function getDesignFee(Request $request) {
        $defaultDesignFee = config('cart::sa.design_fee');
        $productIds = $request->input("ids");
        $productIds = explode(",", $productIds);
        $designFees = \DB::table("product")
            ->leftJoin("product_n_user", "product_n_user.product_id", "=", "product.id")
            ->leftJoin("users", "users.id", "=", "product_n_user.user_id")
            ->join("product_n_design", "product_n_design.product_id", "=", "product.id")
            ->join("design_price", function($join) {
                $join->on("design_price.design_id", "=", "product_n_design.design_id");
            })
            ->whereIn("product.id", $productIds)
            ->where("users.role", "=", "SELLER")
            ->whereNotNull("users.seller_token")
            ->get(["product.id", "product.name", "design_price.price", "users.id as seller_id", "design_price.is_sell"]);
        $result = [];
        foreach ($productIds as $productId) {
            $result[$productId] = floatval($defaultDesignFee);
        }
        foreach ($designFees as $designFee) {
            if ($designFee->is_sell == 1) {
                $result[$designFee->id] = floatval($designFee->price);
            } else if ($designFee->is_sell == 0) {
                $result[$designFee->id] = 0;
            }
        }
        $response = [
            "status" => "successful",
            "result" => $result,
        ];
        return response()->json($response);
    }
}
