<?php

/**
 *
 * This Controller used to save, fetch or delete WooCommerce Products on various endpoints
 *
 * @category   Products
 * @package    WooCommerce API
 * @author     Original Author <tanmayap@riaxe.com>
 * @author     tanmayap@riaxe.com
 * @copyright  2019-2020 Riaxe Systems
 * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    Release: @1.0
 */

namespace ProductStoreSpace\Controllers;

use Illuminate\Database\Capsule\Manager as DB;
use ComponentStoreSpace\Controllers\StoreComponent;
use App\Dependencies\Zipper as Zipper;

class StoreProductsController extends StoreComponent
{
    public function __construct()
    {
        parent::__construct();
    }
    /**
     * Get list of product from the Shopify API
     *
     * @author     tanmayap@riaxe.com
     * @date       24 sep 2019
     * @parameter  Slim default params
     * @response   Array of list/one product(s)
     */
    public function getProducts($request, $response, $args)
    {
        $productId = trim($args['id']);
        if (!empty($productId)) {
            $jsonResponse = $this->getProductById($request, $response, $args);
            return $jsonResponse;
        }
        $storeResponse = [];
        $products = [];

        $searchstring = $request->getQueryParam('name');
        $categoryid = $request->getQueryParam('category');
        $limit = $request->getQueryParam('per_page');
        $page = $request->getQueryParam('page');
        $orderby = $request->getQueryParam('orderby');
        $order = $request->getQueryParam('order');
        $listCatalogue = (!empty($request->getQueryParam('is_catalog')) ? $request->getQueryParam('is_catalog') : 0);
        $fetchFilter = (!empty($request->getQueryParam('fetch')) ? $request->getQueryParam('fetch') : 'limited');
        $isCustomize = $request->getQueryParam('is_customize'); //For Predeco Product

        // Get all requested Query params
        $filters = [
            'limit' => $limit,
            'page' => $page,
            'orderby' => $orderby,
            'order' => $order,
            'published_status' => 'published',
            'isCatalogue' => $listCatalogue,
        ];
        if ($categoryid && $categoryid != '') {
            $filters['collection_id'] = $categoryid;
        }
        if ($searchstring && $searchstring != '') {
            $filters['title'] = $searchstring;
        }

        try {
            $getProductsData = $this->getAllProducts($filters, $isCustomize);
            $getProducts = $getProductsData;
            if (!empty($filters['title']) && empty($getProducts)) {
                $getTotalProductsCount = 0;
            } elseif (!empty($filters['title']) && !empty($getProducts)) {
                $getTotalProductsCount = count($getProducts);
            } else {
                $getTotalProductsCount = $this->getTotalProductsCount($filters, $isCustomize);
            }
            foreach ($getProducts as $key => $product) {

                $productImages = [];
                if (isset($product['node']['images']['edges']) && count($product['node']['images']['edges']) > 0) {
                    foreach ($product['node']['images']['edges'] as $prodImgKey => $prodImg) {
                        $productImages[$prodImgKey] = $prodImg['node']['url'];
                    }
                }
                //Choosing variant price as product price
                $productPrice = 10000000;
                $isSoldOut = true;

                foreach ($product['node']['variants']['edges'] as $pv) {
                    if (!empty($productId)) {
                        //For product details
                        if ($pv['node']['price'] < $productPrice) {
                            $productPrice = array(
                                'current' => $pv['node']['price'],
                                'regular_price' => $pv['node']['price'],
                                'sale_price' => $pv['node']['price'],
                            );
                            break;
                        }
                    } else {
                        if ($pv['node']['price'] < $productPrice) {
                            $productPrice = $pv['node']['price'];
                            break;
                        }
                        if ($pv['node']['inventory_policy'] == "continue" || $pv['node']['inventory_quantity'] > 0 || !empty($pv['node']['inventory_quantity'])) {
                            $isSoldOut = false;
                            break;
                        }
                    }
                }

                $productType = (strpos(strtolower($product['node']['variants']['edges'][0]['node']['title']), 'default title') !== false ? "simple" : "variable");
                $stock = 0;
                foreach ($product['node']['variants']['edges'] as $var) {
                    if ($var['node']['inventoryQuantity'] > 0) {
                        $stock = $var['node']['inventoryQuantity'];
                        break;
                    } elseif ($var['node']['inventoryPolicy'] == "CONTINUE") {
                        $stock = 10000;
                        break;
                    }
                }
                $products[$key] = [
                    'id' => $this->getNumericData($product['node']['id']),
                    'variation_id' => ($productType == 'simple') ? $this->getNumericData($product['node']['id']) : $this->getNumericData($product['node']['variants']['edges'][0]['node']['id']),
                    'name' => $product['node']['title'],
                    'stock' => $stock,
                    'type' => $productType,
                    'is_sold_out' => ($stock > 0 ? false : true),
                    'sku' => ($product['node']['variantsCount']['count'] > 0) ? $product['node']['variants']['edges'][0]['node']['sku'] : '',
                    'is_decoration_exists' => 0,
                    'print_profile' => [],
                    'price' => $productPrice,
                    'image' => $productImages,
                ];

                if ($fetchFilter == 'all') {
                    $preDecoMeta = $this->GetProductMeta($product['node']['id']);
                    if (!empty($preDecoMeta) && is_array($preDecoMeta)) {
                        $products[$key]['custom_design_id'] = $preDecoMeta['custom_design_id'];
                        $products[$key]['is_redesign'] = $preDecoMeta['is_redesign'];
                        $products[$key]['is_decorated_product'] = ($preDecoMeta['custom_design_id'] > 0 ? 1 : 0);
                    }
                }
            }

            if (isset($products) && is_array($products) && !empty($products)) {
                $storeResponse = [
                    'status' => 1,
                    'total_records' => $getTotalProductsCount,
                    'products' => $products,
                ];
            } else {
                $storeResponse = [
                    'status' => 0,
                    'total_records' => $getTotalProductsCount,
                    'message' => 'No products available',
                    'products' => [],
                ];
            }
        } catch (\Exception $e) {
            $storeResponse = [
                'status' => 0,
                'message' => 'Invalid request',
                'exception' => $e->getMessage(),
            ];
        }
        // Reset Total product Count
        $_SESSION['productsCount'] = 0;
        return $storeResponse;
    }

    /**
     * Get product details from the Shopify API
     *
     * @author     tanmayap@riaxe.com
     * @date       23 Dec 2019
     * @parameter  Slim default params
     * @response   Array of list/one product(s)
     */
    public function getProductById($request, $response, $args)
    {
        try {
            $args['id'] = !empty($args['id']) ? $args['id'] : $args['product_id'];
            $product = $this->getShopProductDetails($args['id']);
            $productData = $product['products'];
            // check if the product is stored at settings
            $productSettingsObj = new \App\Modules\Products\Models\ProductSetting();
            $productSetting = $productSettingsObj->where(['product_id' => $productData['id']])->get()->first();

            // custom_variant = 0 : means the images are manages at shopify, otherwise mangaged at ImprintNext
            if (!empty($productSetting) && $productSetting->custom_variant == 1) {

                $storeID = $productSetting->store_id;
                $variantImageIds = array_map(function ($eachImg) {
                    return $this->getNumericData($eachImg['id']);
                }, $productData['images']);

                $productImageObj = new \App\Modules\Products\Models\ProductImage();
                $productImages = $productImageObj->join('product_image_sides', 'product_images.xe_id', '=', 'product_image_sides.product_image_id')
                    ->where('product_images.xe_id', '=', $variantImageIds[0])
                    ->select([
                        'product_image_sides.xe_id as id',
                        'product_images.cloud_storage as cloud_storage',
                        'product_image_sides.file_name as src',
                        'product_image_sides.side_name as labels'
                    ])->orderBy('sort_order', "ASC");

                $product['products']['images'] = $productImages->get()->map(function ($productImage) use ($storeID) {
                    $fileName = basename($productImage->src);
                    if (SHOPIFY_VARIANTS_PLUGIN == 1) {
                        $productImage->src = $productImage->cloud_storage == 1 ?
                            $this->getS3URL($productImage->src, $storeID) : $productImage->src;
                        $productImage->thumbnail = $productImage->src;
                    } else {
                        $productImage->src = $productImage->cloud_storage == 1 ?
                            $this->getS3URL($productImage->src, $storeID) : path('read', 'product') . $productImage->src;
                             $productImage->thumbnail = str_replace($fileName, 'thumb_' . $fileName, $productImage->src);
                    }
                    return $productImage;
                })->toArray();
            }
        } catch (\Exception $e) {
            $storeResponse = [
                'status' => 0,
                'message' => 'Invalid request',
                'exception' => $e->getMessage(),
            ];
        }

        // Reset Total product Count
        $_SESSION['productsCount'] = 0;
        return $product;
    }

    /**
     * Get list of category/subcategory or a Single category/subcategory from the Shopify store
     *
     * @author     ramasankarm@riaxe.com
     * @date       14 dec 2019
     * @parameter  Slim default params
     * @response   Array of list/one categories/category
     */
    public function getCategories($request, $response, $args)
    {
        $categories = [];
        try {
            if (!empty($args['id'])) {
                $categories = $this->getCollectionsData($args['id']);
            } else {
                $categories = $this->getCollections();
            }
            if (!empty($categories)) {
                $storeResponse = $categories;
            }
        } catch (\Exception $e) {
            $storeResponse = [
                'status' => 0,
                'message' => 'Invalid request',
                'exception' => $e->getMessage(),
            ];
        }
        return $storeResponse;
    }

    /**
     * Get: Get minimal product details from the store end
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     *
     * @author tapasranjanp@riaxe.com
     * @date   28 feb 2020
     * @return Array of list/one product(s)
     */
    public function getProductShortDetails($request, $response, $args)
    {
        $storeResponse = [];

        $productId = to_int($args['product_id']);
        $variantId = to_int($args['variant_id']);

        if ($productId > 0 && $variantId > 0) {
            try {
                $productInfo = array(
                    'variantID' => $variantId,
                    'productID' => $productId
                );
                $storeResponse = $this->getVariantShortInfo($productInfo);
                if (SHOPIFY_VARIANTS_PLUGIN == 1) {
                    $getVarImagesFromDB = $this->getProductById($request, $response, $args);
                    $getVarImagesFromDB = $getVarImagesFromDB['products']['images'];
                    $storeResponse['images'] = $getVarImagesFromDB;
                }
                if (!empty($storeResponse['imp_image_id'])) {
                    $storeID = get_store_details($request);
                    $storeResponse['images'] = $this->getImpImages($storeResponse['imp_image_id'], $storeID);
                }
            } catch (\Exception $e) {
                $storeResponse['exception'] = show_exception() === true
                    ? $e->getMessage() : '';
            }
        }

        return $storeResponse;
    }

    /**
     * For custom variants(shopify) - the images are within imprintnext
     * get all the side images for the image_id
     */
    private function getImpImages($impImageId, $storeID = 1)
    {

        $productImageObj = new \App\Modules\Products\Models\ProductImage();
        $productImages = $productImageObj->join('product_image_sides', 'product_images.xe_id', '=', 'product_image_sides.product_image_id')
            ->whereIn('product_images.xe_id', [$impImageId])
            ->select([
                'product_image_sides.xe_id as id',
                'product_images.cloud_storage',
                'product_image_sides.file_name as src',
                'product_image_sides.side_name as labels'
            ])
            ->orderBy('product_image_sides.sort_order', 'ASC');

        return $productImages->get()->map(function ($productImage) use ($storeID) {

            $fileName = basename($productImage->src);
            if (SHOPIFY_VARIANTS_PLUGIN == 1) {
                $productImage->src = $productImage->cloud_storage == 1 ?
                $this->getS3URL($productImage->src, $storeID) : $productImage->src;
                $productImage->thumbnail = $productImage->src;
            } else {
                $productImage->src = $productImage->cloud_storage == 1 ?
                $this->getS3URL($productImage->src, $storeID) : path('read', 'product') . $productImage->src;
                $productImage->thumbnail = str_replace($fileName, 'thumb_' . $fileName, $productImage->src);
            }

            return $productImage;
        })->toArray();
    }

    /**
     * Get list of Color Variants from the WooCommerce API as per the product
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Arguments
     *
     * @author tanmayap@riaxe.com
     * @date   5 Oct 2019
     * @return Json
     */
    public function colorsByProduct($request, $response, $args)
    {
        $storeResponse = [
            'status' => 1,
            'records' => 0,
            'message' => 'No Color available',
            'data' => [],
        ];
        $isAdmin = to_int((!empty($request->getQueryParam('isadmin'))
            && $request->getQueryParam('isadmin') != "")
            ? $request->getQueryParam('isadmin') : 0);
        $filters = [
            'product_id' => $args['product_id'],
            'attribute' => $args['slug'],
            'is_admin' => $isAdmin,
        ];
        $options = [];
        foreach ($filters as $filterKey => $filterValue) {
            if (isset($filterValue) && $filterValue != "") {
                $options += [$filterKey => $filterValue];
            }
        }
        try {
            $storeResponse = $this->getColorOptions($options);
            $storeID = get_store_details($request);
            foreach ($storeResponse as  &$colorData) {
                if (!empty($colorData['imp_image_id'])) {
                    $impImages = $this->getImpImages($colorData['imp_image_id'], $storeID);
                    $colorData['sides'] = array_map(function ($impImage) {
                        return ['image' => $impImage];
                    }, $impImages);

                    unset($colorData['imp_image_id']);
                }
            }
        } catch (\Exception $e) {
            $storeResponse = [
                'status' => 0,
                'message' => message('Products', 'error'),
                'exception' => show_exception() === true ? $e->getMessage() : '',
            ];
        }

        return $storeResponse;
    }

    /**
     * Get: Get variation's attribute details by variant ID
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument
     *
     * @author tanmayap@riaxe.com
     * @date   13 Feb 2020
     * @return Array records and server status
     */
    public function storeVariantAttributeDetails($request, $response, $args)
    {
        $storeResponse = [
            'status' => 0,
            'message' => message('Quantity', 'error'),
        ];
        $filteredAttributes = $params = [];
        $params['productId'] = $args['pid'];
        $params['variantId'] = $args['vid'];
        $option['per_page'] = 100;
        $filteredAttributes = $this->getVariantInventory($params);
        if (!empty($filteredAttributes)) {
            $storeResponse = $filteredAttributes;
        }
        return $storeResponse;
    }

    /**
     * Get: Get all Attributes List from Magento store API
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     *
     * @author tapasranjanp@riaxe.com
     * @date   04 March 2020
     * @return Array list of Attributes
     */
    public function getOnlyAttribute($request, $response)
    {
        $storeResponse = [
            'status' => 0,
            'data' => message('Store Attributes', 'not_found'),
        ];
        $getAllAttributes = array(
            0 => array(
                'id' => 'color',
                'name' => 'color',
            ),
            1 => array(
                'id' => 'size',
                'name' => 'size',
            )
        );
        if (isset($getAllAttributes) && count($getAllAttributes) > 0) {
            $storeResponse = $getAllAttributes;
        }
        return $storeResponse;
    }

    public function getOriginalVarID($variantID)
    {
        $thisVariantId = $this->getParentVariantID($variantID);
        return $thisVariantId;
    }

    /**
     * Get: Product Attribute Pricing Details by Product Id from Shopify store
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Arguments
     *
     * @author debashisd@riaxe.com
     * @date   18 March 2020
     * @return All store attributes
     */
    public function storeProductAttrPrc($request, $response, $args)
    {
        $storeResponse = [];
        try {
            $productId = trim($args['id']);
            $result = $this->getAttributes($productId);
            if (!empty($result)) {
                $storeResponse = $result;
            }
        } catch (\Exception $e) {
            // Store exception in logs
            create_log(
                'store',
                'error',
                [
                    'message' => $e->getMessage(),
                    'extra' => [
                        'module' => 'Get products attribute price',
                    ],
                ]
            );
        }
        return $storeResponse;
    }

    /**
     * Get: Get all Attributes List from Store-end
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     *
     * @author debashisd@riaxe.com
     * @date   19 Mar 2019
     * @return Array list of Attributes
     */
    public function storeAttributeList($request, $response)
    {
        $storeResponse = [];
        $productId = $request->getQueryParam('product_id');
        // fetch raw to skip the cache data
        $fetchRaw = $request->getQueryParam('fetchRaw', false);
        if (!empty($productId)) {
            $attributeList = [];
            $getProductDetail = $this->getAttributes($productId, $fetchRaw);
            if (!empty($getProductDetail)) {
                foreach ($getProductDetail as $attribute) {
                    $attributeList[] = [
                        'id' => $attribute['id'],
                        'name' => $attribute['name'],
                        'option_id' => $attribute['option_id'],
                        'terms' => $attribute['options']
                    ];
                }
                $storeResponse = $attributeList;
            }
        } else {
            try {
                $getAllAttributes = $this->getAttributes(null, $fetchRaw);
                if (!empty($getAllAttributes)) {
                    $storeResponse = $getAllAttributes;
                }
            } catch (\Exception $e) {
                $storeResponse = [];
                create_log('store', 'error', [
                    'message' => $e->getMessage(),
                    'extra' => [
                        'module' => 'Create Variations'
                    ]
                ]);
            }
        }

        return $storeResponse;
    }
    /**
     * Get: Get all Attributes List from Store-end
     *
     * @author debashisd@riaxe.com
     * @return Shopify main product ID
     */
    public function getParentProductData($variantID)
    {
        $parentVarID = $this->getParentVariantID($variantID);
        $productID = $this->shopifyParentProductID($parentVarID);
        print_r($productID);
        exit();
    }


    /**
     * Get: get variants of a product
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     *
     * @author debashisd@riaxe.com
     * @date   23 July 2020
     * @return Array records
     */
    public function productVariants($productId, $storeId = 1)
    {
        $result = [
            'status' => 0, 'variants' => []
        ];
        if (!empty($productId)) {
            $variants = $this->getStoreVariants($productId);
            if (!empty($variants)) {
                $result = [
                    'status' => 1, 'variants' => $variants
                ];
            }
        }
        return $result;
    }

    /**
     * Get: get tier Details of a product
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     *
     * @author debashisd@riaxe.com
     * @date   23 July 2020
     * @return Array records
     */
    public function productTierDiscounts($request, $response, $args)
    {
        $tierContent = [];
        if (!empty($args['productID'])) {
            $tierContent = $this->getTierDiscounts($args['productID']);
        }
        return $tierContent;
    }

    /**
     * Post: Save tier pricing
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     *
     * @author debashisd@riaxe.com
     * @date   23 July 2020
     * @return Boolean status
     */
    public function saveTierDiscount($request, $response, $args)
    {
        $tierData = $request->getParsedBody();
        $tierData['productID'] = $args['productID'];
        $tierData['price_rules'] = json_decode($tierData['price_rules'], true);
        $tierStatus = $this->saveProductTierPrice($tierData);
        return $tierStatus;
    }

    /**
     * Get: Get Attribute List for Variants with Multiple attribute
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument
     *
     * @author debashisd@riaxe.com
     * @date   10th June 2020
     * @return Array records and server status
     */
    public function storeMultiAttributeVariantDetails($request, $response, $args)
    {
        $storeResponse = [];
        $productId = to_int($args['pid']);
        $variationId = to_int($args['vid']);
        $attribute = $args['attribute'];
        $isPrice = (!empty($args['price'])) ? $args['price'] : (!empty($request->getQueryParam('price')) ? $request->getQueryParam('price') : 0);
        $option['per_page'] = 100;
        try {
            $storeData = array("productID" => $productId, "variantID" => $variationId, "option" => $attribute);
            $storeData['is_price'] = $isPrice;
            if (SHOPIFY_VARIANTS_PLUGIN == 1) {
                $finalArray = $this->getCustomVariantOption($storeData);
            } else {
                $finalArray = $this->getProductAttrOptions($storeData);
            }
            if (!empty($finalArray)) {
                $storeResponse = $finalArray;
            }
        } catch (\Exception $e) {
            // Store exception in logs
            create_log(
                'store',
                'error',
                [
                    'message' => $e->getMessage(),
                    'extra' => [
                        'module' => 'Store variant attribute details with quantity',
                    ],
                ]
            );
        }
        return $storeResponse;
    }

    public function getProductByType($request, $response, $args)
    {
        $storeResponse = [
            'status' => 0,
            'message' => message('Product', 'error'),
        ];
        $foundProduct = $this->storeProductByType($args);
        if (!empty($foundProduct)) {
            $storeResponse = $foundProduct;
        }
        return $storeResponse;
    }

    /**
     * Post: Save predecorated products into the store
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     *
     * @author debashisd@riaxe.com
     * @date   1 May 2019
     * @return Array records and server status
     */
    public function saveProduct($request, $response)
    {
        $storeResponse = $productImages = [];
        $getPostData = (isset($saveType) && $saveType == 'update')
            ? $this->parsePut() : $request->getParsedBody();

        if (!empty($getPostData['data'])) {
            $predecorData = json_clean_decode($getPostData['data'], true);
            $refId = $predecorData['ref_id'];
            $templateJsonPath = path('abs', 'design_state') . 'templates/' . $refId . '.json';
            if (file_exists($templateJsonPath)) {
                $tempData = file_get_contents($templateJsonPath);
                $tempData = json_clean_decode($tempData, true);
                $color_product_image_url = $tempData['color_product_image_url'];
            }

            if (
                is_array($predecorData['product_image_url'])
                && empty($predecorData['product_image_url'])
            ) {
                $uploadedFileNameList = do_upload(
                    'product_image_files',
                    path('abs', 'product'),
                    [],
                    'array'
                );
                foreach ($uploadedFileNameList as $uploadedImage) {
                    $productImages[] = path('read', 'product') . $uploadedImage;
                }
                $predecorData['product_image_url'] = $productImages;
            }
            foreach ($predecorData['attributes'] as $attrKey => $attributes) {
                foreach ($attributes['attribute_options'] as $optKey => $option) {
                    $predecorData['attributes'][$attrKey]['attribute_options'][$optKey] = addslashes($option);
                }
            }
            $predecorData['color_images'] = $color_product_image_url;
            $storeResponse = $this->createDecoratedProduct($predecorData);
        }
        return $storeResponse;
    }

    /**
     * POST: Product add to store
     *
     * @param $productData Product data
     * @param $catalog Catalog details
     *
     * @author radhanatham@riaxe.com
     * @date  05 June 2020
     * @return array json
     */
    public function addProductToStore($productData, $catalog, $priceData, $storeID)
    {
        $productArr = [];
        if (!empty($productData)) {
            foreach ($productData as $k => $v) {
                $price = $v['price'];
                $storeCategories = $v['categories'];
                $catalog_price = $v['catalog_price'] ? $v['catalog_price'] : $price;
                $params = array('style_id' => $v['style_id'], "catalog_code" => $catalog);
                $returnData = api_call_by_curl($params, 'product');
                $predecorData = $returnData['data'];
                $predecorData['old_product_id'] = $v['old_product_id'];
                $sideName = $predecorData['variations'][0]['side_name'];
                if (!empty($predecorData)) {
                    $productIds = $this->addCatalogProductToStore($priceData, $predecorData, $price, $catalog_price, $storeCategories);
                    if ($productIds) {
                        foreach ($productIds as $productId) {
                            if (SHOPIFY_VARIANTS_PLUGIN == 1) {
                                $this->saveProductAPIasCache($productId);
                            }
                            $productArr[$k][] = [
                                'product_id' => $productId,
                                'product_side' => $sideName,
                                'style_id' => $v['style_id'],
                                'decorData' => $predecorData
                            ];
                        }
                    }
                }
            }
        }
        return $productArr;
    }

    public function createProductImportCSV($request, $response, $args)
    {
        $getStoreDetails = get_store_details($request);
        $predecoDetails = $request->getParsedBody();
        $productData = json_clean_decode($predecoDetails['product_data']);
        $catalog = $predecoDetails['catalog_code'];
        $assetsPath = ASSETS_PATH_W;
        $cataloAssetsPath = $assetsPath . 'catalog';
        if (!is_dir($cataloAssetsPath)) {
            mkdir($cataloAssetsPath, 0755);
        }
        $inventoryCSV = $this->createInventoryCSV($productData, $catalog, $cataloAssetsPath);
        $headerData = [
            "Handle","Title", "Body (HTML)", "Vendor",
			"Type", "Tags", "Published",
			"Option1 Name", "Option1 Value",
			"Option2 Name", "Option2 Value",
			"Option3 Name", "Option3 Value",
			"Variant SKU", "Variant Grams", "Variant Inventory Tracker", "Variant Inventory Qty", "Variant Inventory Policy", "Variant Fulfillment Service", "Variant Price", "Variant Compare At Price", "Variant Requires Shipping",
			"Variant Taxable", "Variant Barcode", "Image Src", "Image Position", "Gift Card", "Variant Image",
			"Variant Weight Unit", "Cost per item", "Included / India", "Included / International", "Status"
        ];
        $randNo = getRandom();
        $csvFilename = $randNo . '_pro.csv';
        if (!empty($productData)) {
            $productArray = [];
            $productArray[0] = $headerData;
            $i = 1;
            foreach ($productData as $k => $v) {
                $price = $v['price'];
                $catalog_price = $v['catalog_price'];
                $params = array("catalog_code" => $catalog, 'style_id' => $v['style_id']);
                $returnData = api_call_by_curl($params, 'product');
                $productData = $returnData['data'];
                $getVariations = $productData['variations'];
                $shopifyStoreLimits = $this->shopifyStoreResourceLimit();

                $getVariant = array_chunk($getVariations, $shopifyStoreLimits['maxProductVariants'], true);

                $category = $categories = '';
                foreach ($productData['category'] as $key => $cat) {
                    $category .= $cat . '>';
                }

                $categories = rtrim($category, ">");
                $arraySize = $productData['size_data'];
                $arrayColor = $productData['color_data'];
                $color = $colors = '';
                if (!empty($arrayColor)) {
                    foreach ($arrayColor as $cl) {
                        $color .= $cl . ', ';
                    }
                    $colors = rtrim($color, ', ');
                }

                $size = $sizes = '';
                if (!empty($arraySize)) {
                    foreach ($arraySize as $sz) {
                        $size .= $sz . ', ';
                    }
                    $sizes = rtrim($size, ', ');
                }
                $productImageUrl = $productData['images']['src'];
                $stock = $productData['total_qty'];
                $remainingVariantArray = [];
                $varCount = 0;
                foreach($getVariant as $varKey => $allVariant){
                    $productHandel = strtolower($productData['name']);
                    $productHandel = implode('-', explode(' ', $productHandel)).rand();
                    $getAttribute = $getVariant[$varKey];
                    $varIndex = array_keys($getVariant[$varKey]);
                    $getIndex = $varIndex[0];
                    $getOption1 = strtolower($productData['attributes'][0]['name']);
                    $getOption2 = strtolower($productData['attributes'][1]['name']);
                    $getOption3 =  strtolower($productData['attributes'][2]['name']);
                    $productArray[] = [
                        $productHandel,$productData['name'],$productData['description'],$productData['variations'][0]['brand_name'],
                        "",  "catalogue", "true",
                        $productData['attributes'][0]['name'],$getAttribute[$getIndex]['attributes'][$getOption1],
                        $productData['attributes'][1]['name'],$getAttribute[$getIndex][$getOption2],
                        $productData['attributes'][2]['name'],$getAttribute[$getIndex][$getOption3],
                        "'".$getAttribute[$getIndex]['sku'],$productData['variations'][0]['unit_weight'], "shopify", $stock, "deny",
                        "manual", $price, "", "true",
                        "true",  $productData['variations'][0]['gtin'], $allVariant[$varCount]['image_path'][0], 1, "false", $allVariant[$varCount]['image_path'][0], "gm", $productData['variations'][0]['piece_price'], "true", "true" ,"active"
                    ];
                    $productData['variations'] = $allVariant;
                    if (!empty($productData['variations'])) {
                        $j = 0;
                        if (count($productData['variations']) > 1) {
                            foreach ($productData['variations'] as $keys => $variations) {
                                $quantity = $variations['quantity'];
                                $varintPrice = 0;
                                if ($variations['piece_price'] > 0) {
                                    $diffPrice = $price - $catalog_price;
                                    $varintPrice = $variations['piece_price'] + $diffPrice;
                                } else {
                                    $varintPrice = $price;
                                }
                                $image_path = $variations['image_path'];
                                $image = $images = '';
                                if (!empty($image_path)) {
                                    foreach ($image_path as $img) {
                                        if ($img != '') {
                                            $image .= $img . ', ';
                                        }
                                    }
                                    $images = rtrim($image, ', ');
                                }
                                $randNos = getRandom();
                                $options = array_values($variations['attributes']);
                                $barcode = isset($variations['gtin']) ? $variations['gtin'] : '';

                                if (count($image_path) > 1) {
                                    for ($in = 1; $in < count($image_path); $in++) {
                                        $remainingVariantArray[] = [
                                            $productHandel,"", "", "",
                                        "", "", "",
                                        "", "",
                                        "", "",
                                        "", "",
                                        "", "", "", "", "", "", "", "", "",
                                        "", "", $image_path[$in], "", "", "",
                                        "", "", "", "", ""
                                        ];
                                    }
                                }
                                $productArray[] = [
                                    $productHandel, "", "", "",
                                    "",  "", "",
                                    "", $options[0],
                                    "", $options[1],
                                    "", $options[2],
                                    "'" . $productData['variations'][$keys]['sku'], $productData['variations'][$keys]['unit_weight'], "shopify", $quantity, "deny", "manual", $price, "", "true", "true", $barcode, $productData['variations'][$keys]['image_path'][0], "", "",
                                    $productData['variations'][$keys]['image_path'][0], "gm", $productData['variations'][$keys]['piece_price'], "", "", ""
                                ];
                                $j++;
                            }
                            $productArray = array_merge($productArray, $remainingVariantArray);
                        }
                    }
                    $varCount = $varCount + $shopifyStoreLimits['maxProductVariants'];
                }
                $productArray = array_unique($productArray, SORT_REGULAR);

                $uniqProductArr = array();
                $keys = array();
                foreach ($productArray as $prodArr) {
                    if ($prodArr[8] == "" && $prodArr[10] == "" && $prodArr[12] == "") {
                        $uniqProductArr[] = $prodArr;
                    }else{
                        $key = $prodArr[8] . '|' . $prodArr[10] . '|' . $prodArr[12];
                   if (!in_array($key, $keys)) {
                        $keys[] = $key;
                        $uniqProductArr[] = $prodArr;
                    }
                    }
                }
                $i++;
                $newArr = $uniqProductArr;

                if (!empty($newArr)) {
                    $cfilename = $cataloAssetsPath . '/' . $csvFilename;
                    if (is_dir($cataloAssetsPath)) {
                        $fp = fopen($cfilename, 'w');
                        foreach ($newArr as $fields) {
                            fputcsv($fp, $fields);
                        }
                    }
                    fclose($fp);
                }
            }
        }
        return  $this->createProductZIP($cataloAssetsPath, $inventoryCSV, $csvFilename);
    }
    /**
     * Create inventory CSV file
     *
     * @author sonali@imprintnext.com
     * @date   06 july 2022
     * @return Inventory csv
     */

    private function createInventoryCSV($productData, $catalog, $cataloAssetsPath)
    {

        $headerData = [
            "Handle",
            "Title",
            "Option1 Name",
            "Option1 Value",
            "Option2 Name",
            "Option2 Value",
            "Option3 Name",
            "Option3 Value",
            "SKU",
            "HS Code",
            "COO"
        ];
        $getLocationInventory = $this->getloation();
        $allLocation = array_column($getLocationInventory, 'name');
        foreach ($allLocation as $location) {
            $headerData[] = $location;
        }
        $randNo = getRandom();
        $csvFilename = $randNo . '_inv.csv';

        if (!empty($productData)) {
            $productArray = [];
            $productArray[0] = $headerData;
            $i = 1;
            foreach ($productData as $v) {

                $params = array("catalog_code" => $catalog, 'style_id' => $v['style_id']);
                $returnData = api_call_by_curl($params, 'product');
                $productData = $returnData['data'];


                //get the product name excatly what shopify need.
                // $stock = $productData['total_qty'];
                $handle = strtolower($productData['name']);
                $handle1 = str_replace(array('+'), ' ', $handle);
                $handle1 = str_replace(array('+', ".", "'"), '', $handle1);
                $handle1 = explode(" ", $handle1);
                $handle2 = implode("-", $handle1);


                if (!empty($productData['variations'])) {
                    $j = 0;
                    if (count($productData['variations']) > 1) {
                        foreach ($productData['variations'] as $keys => $variations) {

                            if ($keys >= 0) {
                                $attrs = [];
                                $keys = [];

                                foreach ($variations['attributes'] as $attrKey => $attr) {
                                    $keys[] = ucfirst($attrKey);
                                    $attrs[] = $attr;
                                }

                                $productArray[] = [
                                    $handle2,
                                    $variations['style_name'],
                                    $keys[0],
                                    $attrs[0],
                                    $keys[1],
                                    $attrs[1],
                                    "",
                                    "",
                                    $variations['sku'],
                                    "",
                                    "",
                                    100,
                                    "not stocked"

                                ];

                                $j++;
                            }
                        }
                    }
                }
                $i++;

                $newArr = $productArray;
                if (!empty($newArr)) {
                    $cfilename = $cataloAssetsPath . '/' . $csvFilename;

                    if (is_dir($cataloAssetsPath)) {
                        $fp = fopen($cfilename, 'w');
                        foreach ($newArr as $fields) {
                            fputcsv($fp, $fields);
                        }
                    }
                    fclose($fp);
                }
            }
        }
        return  $csvFilename;
    }

    /**
     * Create zip file
     *
     * @author sonali@imprintnext.com
     * @date   06 july 2022
     * @return zip name
     */

    private function createProductZIP($cataloAssetsPath, $inventoryCSV, $productCSV)
    {

        $zip = new Zipper();
        $randNo = getRandom();
        $zipFilename = $randNo . '.zip';
        $inventoryFileName = $cataloAssetsPath . '/' . $inventoryCSV;
        $productFileName = $cataloAssetsPath . '/' . $productCSV;
        // print_r($inventoryFileName);exit;
        $zipStatus = $zip->make($cataloAssetsPath . '/' . $zipFilename);
        if ($zipStatus) {
            $zip->add($inventoryFileName, $inventoryCSV);
            $zip->add($productFileName, $productCSV);
        }
        $zip->close();
        return $zipFilename;
    }

    /**
     * Get total product count from the WooCommerce API
     *
     * @author debashisd@riaxe.com
     * @date   23 August 2020
     * @return count
     */
    public function totalProductCount()
    {
        try {
            $getCountDetails = $this->getTotalProductsCount(array(), "");
            $totalCountDetails = array("total" => $getCountDetails);
        } catch (\Exception $e) {
            // Store exception in logs
            create_log(
                'store',
                'error',
                [
                    'message' => $e->getMessage(),
                    'extra' => [
                        'module' => 'Get product count',
                    ],
                ]
            );
        }

        return $totalCountDetails;
    }

    /**
     * Post: Create product catagories/subcategories.
     *
     * @param $request       Slim's Request object
     * @param $response      Slim's Response object
     *
     * @author devon@imprintnext.com
     * @date   17 Mar 2021
     * @return Array records and server status
     */
    public function createProductCatagories($request, $response)
    {
        $storeResponse = [];
        $getPostData = $request->getParsedBody();
        $catName = $getPostData['name'];
        $storeResponse = $this->addCollection($catName);
        return $storeResponse;
    }

    /**
     * Internal: Saves product API data in cache files
     * for Shopify API call limitation.
     *
     * @param $productID       Product ID
     * @param $storeID         Store ID - default = 1
     * @author devon@imprintnext.com
     * @date   24 AUG 2021
     * @return Array records and server status
     */
    public function saveProductAPIasCache($productID, $storeID = 1)
    {
        if (!is_dir(SHOPIFY_CACHE_FOLDER)) {
            mkdir(SHOPIFY_CACHE_FOLDER);
        }
        $variantsDIR = SHOPIFY_CACHE_FOLDER . "variants/";
        if (!is_dir($variantsDIR)) {
            mkdir($variantsDIR);
        }

        $productData = $this->getShopifyProductInfo($productID);

        // custom options: managed by ImprintNext
        $customOptions = $this->getCustomOptions($productID);

        if (!empty($customOptions['images'])) {
            //$productData['options'] = $customOptions['options'];
            //$productData['variants'] = $customOptions['variants'];
            // $productData['images'] = $customOptions['images'];
            // $productData['image'] = $customOptions['image'];
            $productData['data']['product']['options'] = $customOptions['options'];
            $productData['data']['product']['variants'] = $customOptions['variants'];
            $productData['data']['product']['images'] = $customOptions['images'];
            //$productData['image'] = $customOptions['image'];

        }


        if (!empty($productData)) {
            $thisProdCacheFile = SHOPIFY_CACHE_FOLDER . $productID . ".json";
            file_put_contents($thisProdCacheFile, json_encode($productData));
            foreach ($productData['data']['product']['variants']['nodes'] as $variant) {
                $varId = $this->getNumericData($variant['id']);
                $thisVarCacheFile = $variantsDIR . $varId . ".json";
                file_put_contents($thisVarCacheFile, json_encode($variant));
            }
        }
    }

    /**
     * Get: Get Product Description Id
     *
     * @param $productId  Product Id
     *
     * @author debashisd@riaxe.com
     * @date  19 October 2021
     * @return string
     */
    public function getProductDescription($variantID)
    {
        $description = '';
        $productData = $this->shopifyParentProductID($variantID);
        $IDs = json_decode($productData, true);
        $productData = $this->getShopifyProductInfo($IDs['pid']);
        $description = $productData['data']['product']['descriptionHtml'];
        return $description;
    }

    /**
     * Update selected variant id inventory to out of stock
     *
     * @param $variantStocks  Array (productId, variantId, stock)
     *
     * @author divya@imprintnext.com
     * @date  27 April 2022
     * @return true/false
     */
    public function stockPriceUpdate($variantStocks = [])
    {
        return $this->variantStockUpdate($variantStocks);
    }

    public function priceUpdate($productData)
    {
        $productJsonData = json_encode($productData, true);
        $result = $this->variantStockUpdate($productJsonData);
        $data = json_decode($result, true);
        return $data['price_update_count'];
    }

    /**
     * prepare the product options, variants, image for custom variant
     */
    private function getCustomOptions($productID)
    {
        $result = ['variants' => [], 'options' => [], 'images' => []];

        // inventory policy  = product_settings:dnt_inventory=1 then "continue" else "deny"
        $productSettingsObj = new \App\Modules\Products\Models\ProductSetting();
        $productSetting = $productSettingsObj->where(['product_id' => $productID])->get()->first();
        // custom_variant = 0 : means the options are manages at shopify, otherwise mangaged at ImprintNext
        if (empty($productSetting) || !$productSetting->custom_variant) {
            return false;
        }

        $productOptionObj = new \App\Modules\Products\Models\ProductOptionRel();
        $getProductOptions = $productOptionObj->getAllOptions($productID)->orderBy('position', 'ASC');

        // get all options
        $result['options'] = $getProductOptions->get()->map(function ($option) use (&$optionNames) {
            // the calulation needs the postion start with 1 (not 0)
            $option->position += 1;
            $optionNames[$option->position - 1] = $option->name;
            $option->optionValues = array_map(function ($value) use ($option) {
                return [
                    'id' => $option->id,
                    'name' => $value
                ];
            }, $option->values);

            // Remove product_id
            unset($option->product_id);
            return $option;
        })->toArray();

        $inventoryPolicy = !empty($productSetting->dnt_inventory) ? "continue" : "deny";

        // get the store from settings
        $storeID = !empty($productSetting->store_id) ? $productSetting->store_id : 1;

        $productVariantObj = new \App\Modules\Products\Models\ProductVariantRel();
        $productID_gid = "gid://shopify/Product/" . $productID;

        $result['variants']['nodes'] = $productVariantObj->getAllVariants($productID)->orderBy('xe_id', 'ASC')
            ->get()->map(function ($variant) use ($inventoryPolicy, $productID_gid, $optionNames) {
                //list($option1, $option2, $option3) = explode('/', $variant->title, 3);
                $options = explode('/', $variant->title, 3);
                $selectedOptions = [];
                foreach ($options as $key => $value) {
                    $selectedOptions[] = [
                        'name' => $optionNames[$key] ?? 'Option ' . ($key + 1),
                        'value' => $value,
                        'optionValue' => [
                            'id' => $variant->xe_id + $key,
                            'name' => $value
                        ]
                    ];
                }
                $variant->id = $variant->xe_id;
                $variant->inventoryPolicy =  $inventoryPolicy;
                $variant->position = $key + 1;
                $variant->inventoryItem = ['tracked' => $variant->inventory];
                $variant->image = ['id' => $variant->image_id];
                $variant->selectedOptions = $selectedOptions;
                $variant->product = ['id' => $productID_gid];
                unset($variant->xe_id);
                return $variant;
            })->toArray();

        // get all images
        $variantImageIds = array_unique(array_column($result['variants'], 'image_id'));
        if (!empty($variantImageIds)) {
            $productImageObj = new \App\Modules\Products\Models\ProductImage();
            $productImages = $productImageObj->join('product_image_sides', 'product_images.xe_id', '=', 'product_image_sides.product_image_id')
                ->whereIn('product_images.xe_id', $variantImageIds)
                ->where('product_image_sides.sort_order', '=', 1)
                ->select([
                    'product_images.xe_id as id',
                    'product_images.cloud_storage',
                    'product_image_sides.file_name as src',
                    'product_image_sides.sort_order as sort_order'
                ]);

            $variantImageArr = array_column($result['variants']['nodes'], 'image_id', 'id');

            $result['images']['nodes'] = $productImages->get()->map(function ($productImage) use ($storeID, $variantImageArr) {
                if (SHOPIFY_VARIANTS_PLUGIN == 1) {
                    $productImage->url = $productImage->cloud_storage == 1 ?
                    $this->getS3URL($productImage->src, $storeID) : $productImage->src;
                } else {
                    $productImage->url = $productImage->cloud_storage == 1 ?
                    $this->getS3URL($productImage->src, $storeID) : path('read', 'product') . $productImage->src;
                }
                $productImage->url = ASSETS_PATH_R . 'products/' . $productImage->url;
                // find the variants having the image, and put it in the image
                // $matchedVariants = array_keys($variantImageArr, $productImage->id);
                // $productImage->variant_ids = $matchedVariants;
                unset($productImage->cloud_storage);
                unset($productImage->sort_order);
                unset($productImage->src);
                return $productImage;
            })->toArray();
            $result['image'] = !empty($result['images']) ?  $result['images'][0] : [];
        }

        return $result;
    }


    private function getCustomVariantOption($storeData)
    {
        $productID = $storeData['productID'];
        $variantID = $storeData['variantID'];
        $attribute = strtolower($storeData['option']);
        // print_r($attribute);
        // exit;
        $productSettingsObj = new \App\Modules\Products\Models\ProductSetting();
        $productSetting = $productSettingsObj->where(['product_id' => $productID])->first();

        if (empty($productSetting) || !$productSetting->custom_variant) {
            return false;
        }

        $productOptionObj = new \App\Modules\Products\Models\ProductOptionRel();
        $options = $productOptionObj->getAllOptions($productID)->orderBy('position', 'ASC')->get();

        $sizeValues = [];
        $optionNames = [];

        foreach ($options as $option) {
            $optionNames[$option->position] = strtolower($option->name);
            if (strtolower($option->name) === $attribute) {
                $sizeValues = $option->values;
            }
        }

        if (empty($sizeValues)) {
            return [];
        }

        $productVariantObj = new \App\Modules\Products\Models\ProductVariantRel();
        $variants = $productVariantObj->getVariant($variantID)->orderBy('xe_id', 'ASC')->get();

        if ($variants->isEmpty()) {
            return [];
        }

        foreach ($variants as $variant) {
            $selectedVar = explode('/', $variant->title, 3);
            $notPresent = !empty($sizeValues) ? array_diff($selectedVar, $sizeValues) : [];
            $notPresentValue = reset($notPresent);

            if (!empty($notPresent)) {
                $finalVariants = $productVariantObj->getVarCombination($productID, reset($notPresent))->get();
            }
        }

        if (empty($finalVariants)) {
            return [];
        }

        $result = ['size' => []];
        $addedSizes = []; // To track added sizes and prevent duplicates

        foreach ($finalVariants as $eachVariant) {
            $selected = explode('/', $eachVariant->title, 3);
            $size = $selected[0] ?? ''; // Extract the size from the variant title

            // Skip if this size has already been added
            if (isset($addedSizes[$size])) {
                continue;
            }

            $attributes = [
                'color' => ucfirst($notPresentValue),
                'color_id' => $notPresentValue,
                'size' => $size,
                'size_id' => strtolower($size)
            ];

            $result['size'][] = [
                'id' => $attributes['size'] ?? '',
                'name' => $attributes['size'] ?? '',
                'variant_id' => $eachVariant->xe_id, // Assign the correct variant ID
                'inventory' => [
                    'stock' => $eachVariant->inventory,
                    'min_quantity' => 1,
                    'max_quantity' => $eachVariant->inventory > 0 ? $eachVariant->inventory : 100,
                    'quantity_increments' => 1
                ],
                'price' => number_format(floatval($eachVariant->price), 2),
                'tier_prices' => [],
                'attributes' => $attributes
            ];

            $addedSizes[$size] = true; // Mark this size as added
        }

        // print_r($result);
        // exit;
        return $result;
    }










    public function deleteStoreDuplicateProducts($request)
    {
        $filter['status'] = $request->getQueryParam('status');
        $filter['days'] = $request->getQueryParam('days');
        return $this->deleteDuplicateProducts($filter);
    }

    public function saveShopifyCartSetting($cartSettingsData) {
        return $this->saveMetafieldsToShop($cartSettingsData);
    }

    /**
     * update the shopify store discount cache
     *
     * @author pansy@imprintnext.com
     * @date  27 Dec 2024
     * @return true/false
     */

    public function updateShopifyDiscount($request)
    {
        $discountId = $request->getQueryParam('discount_id');
        if (!empty($discountId)) {
            return $this->updateDiscountCache($discountId);
        }
    }

    public function saveVariantOptionData($request, $response, $args)
    {
        $productId = $args['product_id'];
        $optionStatus = $this->optionStatus($productId);
        return $optionStatus;
    }
}
