<?php

/**
 * Manage Product Decorations - Single and Multiple Variation
 *
 * PHP version 7.2
 *
 * @category  Product_Decorations
 * @package   Decoration_Settings
 * @author    Tanmaya Patra <tanmayap@riaxe.com>
 * @copyright 2019-2020 Riaxe Systems
 * @license   http://www.php.net/license/3_0.txt  PHP License 3.0
 * @link      http://inkxe-v10.inkxe.io/xetool/admin
 */

namespace App\Modules\Products\Controllers;

use App\Modules\DecorationAreas\Models\PrintArea;
use App\Modules\PrintProfiles\Models as PrintProfileModels;
use App\Modules\Products\Models\AppUnit;
use App\Modules\Products\Models\AttributePriceRule;
use App\Modules\Products\Models\DecorationObjects;
use App\Modules\Products\Models\PrintProfileDecorationSettingRel;
use App\Modules\Products\Models\PrintProfileProductSettingRel;
use App\Modules\Products\Models\ProductCategorySettingsRel;
use App\Modules\Products\Models\ProductDecorationSetting;
use App\Modules\Products\Models\ProductImageSettingsRel;
use App\Modules\Products\Models\ProductImageSides;
use App\Modules\Products\Models\ProductImage;
use App\Modules\Products\Models\ProductSection;
use App\Modules\Products\Models\ProductSectionImage;
use App\Modules\Products\Models\ProductSetting;
use App\Modules\Products\Models\ProductSettingsRel;
use App\Modules\Products\Models\ProductSide;
use Illuminate\Database\Capsule\Manager as DB;
use ProductStoreSpace\Controllers\StoreProductsController;
use App\Modules\Products\Controllers\ProductConfiguratorController;
use App\Components\Controllers\Component as ParentController;
use App\Modules\Products\Models\productOptionSettingRel;

/**
 * Product Decoration Controller
 *
 * @category                Product_Decoration
 * @package                 Product
 * @author                  Tanmaya Patra <tanmayap@riaxe.com>
 * @license                 http://www.gnu.org/copyleft/gpl.html GNU General Public License
 * @link                    http://inkxe-v10.inkxe.io/xetool/admin
 * @SuppressWarnings(PHPMD)
 */
class ProductDecorationsController extends ParentController {
    private $storeController = null;
    /**
     * Get the instance of the store product controller
     */
    public function getStore() {
        if (!$this->storeController) {
            $this->storeController = new StoreProductsController();
        }
        return $this->storeController;
    }
    /**
     * Delete: Delete Decoration Settings
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     *
     * @author tanmayap@riaxe.com
     * @date   5 Oct 2019
     * @return All Print Profile List
     */
    public function deleteDecoration($request, $response, $args)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [];
        $productKey = to_int($args['product_id']);

        $productSettingObj = new ProductSetting();
        $productSettingGet = $productSettingObj->where('product_id', $productKey)->first();

        if (!empty($productSettingGet->xe_id)) {
            $productSettingDeleteId = $productSettingGet->xe_id;

            $prodImgSettRelObj = new ProductImageSettingsRel();
            $prodImgSettRelObj->where('product_setting_id', $productSettingDeleteId)->delete();

            $productSideObj = new ProductSide();
            $productSideObj->where('product_setting_id', $productSettingDeleteId)->delete();

            // Delete Print Profile Product Setting Relation Table Records
            $profProdSettRelObj = new PrintProfileProductSettingRel();
            $profProdSettRelObj->where('product_setting_id', $productSettingDeleteId)->delete();

            // Delete Product Decoration Setting Table Records
            $productDecoSettObj = new ProductDecorationSetting();
            $productDecoSettIds = $productDecoSettObj->where('product_setting_id', $productSettingDeleteId)->get()
                ->pluck('xe_id')->toArray();

            // Delete Product Setting Table Records
            $productSettDelObj = new ProductSetting();
            $productSettDelObj->where('xe_id', $productSettingDeleteId)->delete();

            // Delete Print Profile Decoration Setting Relation Table Records
            if (!empty($productDecoSettIds)) {
                $proflDecoSettRelObj = new PrintProfileDecorationSettingRel();
                $proflDecoSettRelObj->whereIn('decoration_setting_id', $productDecoSettIds)->delete();
                // Delete Product Decoration Settings Table Records
                $prodDecoSettDelObj = new ProductDecorationSetting();
                $prodDecoSettDelObj->whereIn('xe_id', $productDecoSettIds)->delete();
            }

            $jsonResponse = [
                'status' => 1,
                'message' => message('Decoration Setting', 'deleted')
            ];
        }

        return response($response, [
            'data' => $jsonResponse, 'status' => $serverStatusCode
        ]);
    }

    /**
     * Post: Save Product Decoration Settings
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     *
     * @author tanmayap@riaxe.com
     * @date   5 Oct 2019
     * @return Json
     */
    public function saveProductDecorations($request, $response)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [
            'status' => 0,
            'message' => message('Decoration Setting', 'error')
        ];

        $isProductImage = $is3dPreviewAll = 0;
        $allPostPutVars = $request->getParsedBody();
        $getProdDecoInfo = !empty($allPostPutVars['decorations'])
            ? json_clean_decode($allPostPutVars['decorations'], true) : null;
        $replaceExisting = (int)!empty($allPostPutVars['replace'])
            ? $allPostPutVars['replace'] : 0;
        $storeId = $allPostPutVars['store_id'] ? $allPostPutVars['store_id'] : 1;
        $isVariableDecoration = !empty($getProdDecoInfo['is_variable_decoration'])
            ? $getProdDecoInfo['is_variable_decoration'] : 0;
        $uploadedFiles = $request->getUploadedFiles();
        $isOptionPrintArea = !empty($allPostPutVars['is_option_print_area']) ? $allPostPutVars['is_option_print_area'] : 0;
        if ($isVariableDecoration === 1) {
            // Process for variable decoration area
            $variableDecoResp = $this->saveVariableProductDecoration(
                $getProdDecoInfo,
                $uploadedFiles,
                $storeId,
                $replaceExisting,
                false
            );
            return response($response, [
                'data' => $variableDecoResp['response'],
                'status' => $variableDecoResp['server_status_code']
            ]);
        }
        $prodSettInit = new ProductSetting();
        // Clear old records if replace is set to 1
        $checkRecord = $prodSettInit->where([
            'product_id' => $getProdDecoInfo['product_id'], 'store_id' => $storeId
        ]);

        $pid = $getProdDecoInfo['product_id'];
        $optionSettingRelObj = new productOptionSettingRel();

        if($isOptionPrintArea){
            $jsonResponse = $this->saveOptionBasedProductDecorations($request, $response);

            return response($response, [
                'data' => $jsonResponse, 'status' => $serverStatusCode
            ]);

        }else{
            $optionSettingRelObj->where('product_id', $pid)->delete();
        }

        if ($checkRecord->count() > 0) {
            if ($replaceExisting != 1) {
                $jsonResponse = [
                    'status' => 0,
                    'message' => message('Variable Decoration', 'exist')
                ];
                return response($response, [
                    'data' => $jsonResponse, 'status' => OPERATION_OKAY
                ]);
            }
            $checkRecord->delete();
        }

        // Save Product Decorations
        $prodSettInsId = $this->saveProductSetting($getProdDecoInfo, $storeId);

        /**
         * Processing for Table: print_profile_product_setting_rel
         * - For saving the outer Print profile Ids
         */

        if (!empty($prodSettInsId) && !empty($getProdDecoInfo['print_profile_ids'])) {
            $this->setProductPrintProfileRel($prodSettInsId, $getProdDecoInfo['print_profile_ids']);
        }

        if (!empty($getProdDecoInfo['is_product_image_all'])) {
            $isProductImage = 1;
        }
        if (!empty($getProdDecoInfo['is_3d_preview_all'])) {
            $is3dPreviewAll = 1;
        }
        if (!empty($prodSettInsId)) {
            if (!empty($getProdDecoInfo['product_setting'])) {
                $this->svaeProductSettingsRel(
                    $getProdDecoInfo['product_setting'],
                    $prodSettInsId,
                    $isProductImage,
                    $is3dPreviewAll,
                    $getProdDecoInfo['product_id']
                );
            }
            $jsonResponse = [
                'status' => 1,
                'product_settings_insert_id' => $prodSettInsId,
                'message' => message('Product Decoration Setting', 'saved')
            ];
        }
        if (strtolower(STORE_NAME) == "shopify") {
            $this->getStore()->saveProductAPIasCache($getProdDecoInfo['product_id']);
        }


        //Flush product memcached
		$this->memcache('deleteMulti', '', '', 'product');

        return response($response, [
            'data' => $jsonResponse, 'status' => $serverStatusCode
        ]);
    }
    /**
     * Post: save product setting
     *
     * @param $request         Slim's Request object
     * @param $response        Slim's Response object
     * @param $getProdDecoInfo Decoration data from f/end
     * @param $storeId         Store id
     *
     * @author tanmayap@riaxe.com
     * @date   19 mar 2020
     * @return integer
     */
    protected function saveProductSetting($getProdDecoInfo, $storeId)
    {
        $productSettingId = 0;
        // If any file exist then upload
        $objectFileName = do_upload('3d_object_file', path('abs', '3d_object'), [150], 'string');
        // Processing for Table: product_settings
        if (!empty($getProdDecoInfo['product_id'])) {
            $productSettData = [
                'store_id' => $storeId,
                'product_id' => $getProdDecoInfo['product_id'],
                'is_crop_mark' => $getProdDecoInfo['is_crop_mark'],
                'is_ruler' => !empty($getProdDecoInfo['is_ruler']) ? $getProdDecoInfo['is_ruler'] : 0,
                'is_safe_zone' => $getProdDecoInfo['is_safe_zone'],
                'crop_value' => $getProdDecoInfo['crop_value'],
                'safe_value' => $getProdDecoInfo['safe_value'],
                'is_3d_preview' => $getProdDecoInfo['is_3d_preview'],
                '3d_object_file' => !empty($objectFileName) ? $objectFileName : null,
                '3d_object' => !empty($getProdDecoInfo['3d_object']) ? $getProdDecoInfo['3d_object'] : null,
                'scale_unit_id' => $getProdDecoInfo['scale_unit_id'],
                'is_increment' => $getProdDecoInfo['is_incremental_qty'] ? $getProdDecoInfo['is_incremental_qty'] : 0,
                'increment_values' => ($getProdDecoInfo['is_incremental_qty'] == 1) ? json_encode($getProdDecoInfo['incremental_qty_values']) : "{}",
                'is_prod_desc' => !empty($getProdDecoInfo['is_prod_desc']) ? $getProdDecoInfo['is_prod_desc'] : null,
                'is_prod_rotate' => !empty($getProdDecoInfo['is_prod_rotate']) ? $getProdDecoInfo['is_prod_rotate'] : 0,
                'is_use_full_width' => $getProdDecoInfo['is_use_full_width'] ? $getProdDecoInfo['is_use_full_width'] : 0
            ];
            if (isset($getProdDecoInfo['is_configurator'])) {
                $productSettData['is_configurator'] = $getProdDecoInfo['is_configurator'];
            }
            $productSetting = new ProductSetting($productSettData);
            $productSetting->save();
            $productSettingId = $productSetting->xe_id;
        }
        // Processing for Table: product_image_settings_rel
        if (!empty($productSettingId) && !empty($getProdDecoInfo['product_image_id'])) {
            $this->updateImageSettingsRel($productSettingId, $getProdDecoInfo['product_image_id']);
        }
        // Save Decoration Sides
        $this->saveDecorationSides($getProdDecoInfo, $productSettingId);
        return $productSettingId;
    }
    /**
     * Post: save decoration sides
     *
     * @param $decoration Decoration data from f/end
     * @param $settingsId Settings save id
     *
     * @author tanmayap@riaxe.com
     * @date   19 mar 2020
     * @return boolean
     */
    public function saveDecorationSides($decoration, $settingsId)
    {
        // Processing for Table: product_sides, product_decoration_settings
        $imageSides = $decoration['sides'];
        if (!empty($settingsId) && !empty($imageSides)) {
            foreach ($imageSides as $sideKey => $productSideData) {
                $overlayImgUpload = do_upload('overlay_' . $sideKey, path('abs', 'overlay'), [], 'string');
                $productSide = new ProductSide([
                    'product_setting_id' => $settingsId,
                    'side_name' => $productSideData['name'],
                    'product_image_dimension' => $productSideData['image_dimension'],
                    'is_visible' => $productSideData['is_visible'],
                    'product_image_side_id' => $productSideData['product_image_side_id'],
                    'image_overlay' => $productSideData['is_image_overlay'] ? $productSideData['is_image_overlay'] : 0,
                    'multiply_overlay' => $productSideData['multiply_overlay'] ? $productSideData['multiply_overlay'] : 0,
                    'overlay_file_name' => $overlayImgUpload,
                ]);
                $productSide->save();
                // Product Side Insert Id
                $prodSideInsId = $productSide->xe_id;
                $prodDecoSettRecord = [];

                foreach ($productSideData['product_decoration'] as $productDecoSetting) {
                    $prodDecoSettRecord = $productDecoSetting;
                    $prodDecoSettRecord['product_side_id'] = $prodSideInsId;
                    $prodDecoSettRecord['dimension'] = isset($productDecoSetting['dimension'])
                        ? json_encode($productDecoSetting['dimension'], true) : "{}";
                    $prodDecoSettRecord['locations'] = isset($productDecoSetting['locations'])
                        ? json_encode($productDecoSetting['locations'], true) : "{}";
                    $prodDecoSettRecord['bleed_mark_data'] = isset($productDecoSetting['bleed_mark_data'])
                        ? json_encode($productDecoSetting['bleed_mark_data'], true) : "{}";
                    $prodDecoSettRecord['shape_mark_data'] = isset($productDecoSetting['shape_mark_data'])
                        ? json_encode($productDecoSetting['shape_mark_data'], true) : "{}";

                    $prodDecoSettRecord['is_disable_design'] = isset($productDecoSetting['is_disable_design']) ? $productDecoSetting['is_disable_design'] : 0;
                    $prodDecoSettRecord['product_setting_id'] = $settingsId;
                    $prodDecoSettRecord['default_pp_id'] = $productDecoSetting['default_print_profile'] ? $productDecoSetting['default_print_profile'] : 0;

                    $prodDecoSettInit = new ProductDecorationSetting($prodDecoSettRecord);

                    $prodDecoSettInit->save();
                    $prodDecoSettInsId = $prodDecoSettInit->xe_id;

                    if (!empty($prodDecoSettInsId)) {
                        // Processing for Table: print_profile_decoration_setting_rel
                        $this->setProdDecoSettingsRel($prodDecoSettInsId, $productDecoSetting['print_profile_ids']);
                    }
                }
            }
            return true;
        }
        return false;
    }

    /**
     * Put: Update Product Decoration Settings
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     *
     * @author tanmayap@riaxe.com
     * @date   5 Oct 2019
     * @return Json
     */
    public function updateProductDecorations($request, $response, $args)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [
            'status' => 0,
            'message' => message('Decoration Setting', 'error')
        ];
        try {
            $isProductImage = $is3dPreviewAll = 0;
            $storeDetails = get_store_details($request);
            $storeId = $storeDetails['store_id'];
            $allPostPutVars = $request->getParsedBody();
            $productUpdateId = $args['product_id'];
            $getProductDecorationData = json_clean_decode($allPostPutVars['decorations'], true);
            $uploadedFiles = $request->getUploadedFiles();
            // get the file keys fields
            $uploadedFileKeys = array_keys($uploadedFiles);

            $isOptionPrintArea = !empty($allPostPutVars['is_option_print_area']) ? $allPostPutVars['is_option_print_area'] : 0;

            // get product settings details
            $prodSettGtInit = new ProductSetting();
            $productSettingsGet = $prodSettGtInit->where(['product_id' => $productUpdateId])
                ->orderBy('xe_id', 'desc')->first();
            // create product decoration
            if (empty($productSettingsGet)) {
                return $this->saveProductDecorations($request, $response);
            }

            //Check option based print area
            $pid = $productUpdateId;
            $optionSettingRelObj = new productOptionSettingRel();

            if($isOptionPrintArea){
                $jsonResponse = $this->updateOptionProductDecorations($request, $response, $args);

                return response($response, [
                    'data' => $jsonResponse,
                    'status' => $serverStatusCode
                ]);
            }else{
                // Delete Option setting relation if its not an option based product setting.
                $optionSettingRelObj->where('product_id', $pid)->delete();
            }

            $productSettingInsertId = $productSettingsGet->xe_id;

            // Delete Option based setting
            if(!$isOptionPrintArea){
                $deleteProdSettGtInit = new ProductSetting();
                $deleteProdSettGtInit->where(['product_id' => $productUpdateId])
                ->where('xe_id','<>', $productSettingInsertId )
                ->delete();
            }

            $isVariableDecoration = $getProductDecorationData['is_variable_decoration'];

            if (!empty($isVariableDecoration) && $isVariableDecoration === 1) {
                // Process for variable decoration area
                $getVariableProductDecoration = $this->saveVariableProductDecoration(
                    $getProductDecorationData,
                    $uploadedFiles,
                    $storeId,
                    0,
                    true
                );
                return response($response, [
                    'data' => $getVariableProductDecoration['response'],
                    'status' => $getVariableProductDecoration['server_status_code']
                ]);
            }

            // update product settings
            $this->updateProductSettings($getProductDecorationData, $productSettingInsertId, $productUpdateId);

            // Processing for Table: product_image_settings_rel
            if (empty($getProductDecorationData['product_image_id'])) {
                (new ProductImageSettingsRel())->where(['product_setting_id' => $productSettingInsertId])->delete();
            } else {
                $this->updateImageSettingsRel($productSettingInsertId, $getProductDecorationData['product_image_id']);
            }

            // Processing for Table: product_sides, product_decoration_settings
            $this->updateProductSides($getProductDecorationData, $productSettingInsertId, $uploadedFileKeys);

            // Processing for Table: print_profile_product_setting_rel
            $this->setProductPrintProfileRel($productSettingInsertId, $getProductDecorationData['print_profile_ids']);

            // update product setting rel
            if (!empty($getProductDecorationData['product_setting'])) {
                if (!empty($getProductDecorationData['is_product_image_all'])) {
                    $isProductImage = 1;
                }
                if (!empty($getProductDecorationData['is_3d_preview_all'])) {
                    $is3dPreviewAll = 1;
                }
                $this->svaeProductSettingsRel($getProductDecorationData['product_setting'], $productSettingInsertId, $isProductImage, $is3dPreviewAll, $productUpdateId);
            }

            if (strtolower(STORE_NAME) == "shopify") {
                $this->getStore()->saveProductAPIasCache($args['product_id']);
            }

            $jsonResponse = [
                'status' => 1,
                'product_settings_insert_id' => $productSettingInsertId,
                'message' => message('Product Decoration Setting', 'updated')
            ];
        } catch (\Exception $e) {
            $jsonResponse['message'] = $e->getMessage();
        }

        //Flush product memcached
		$this->memcache('deleteMulti', '', '', 'product');

        return response($response, [
            'data' => $jsonResponse, 'status' => $serverStatusCode
        ]);
    }

    /**
     * Update product setting
     */
    private function updateProductSettings($getProductDecorationData, $productSettingId, $productUpdateId)
    {
        // upload 3d object file
        $updateObjectFile = do_upload('3d_object_file', path('abs', '3d_object'), [], 'string');

        // Processing for Table: product_settings
        if (!empty($productUpdateId)) {
            $productDecorationDataSet = [
                'is_variable_decoration' => $getProductDecorationData['is_variable_decoration'],
                'is_ruler' => $getProductDecorationData['is_ruler'],
                'is_crop_mark' => $getProductDecorationData['is_crop_mark'],
                'is_safe_zone' => $getProductDecorationData['is_safe_zone'],
                'crop_value' => $getProductDecorationData['crop_value'],
                'safe_value' => $getProductDecorationData['safe_value'],
                'is_3d_preview' => $getProductDecorationData['is_3d_preview'],
                '3d_object' => !empty($getProductDecorationData['3d_object']) ? $getProductDecorationData['3d_object'] : "{}",
                'scale_unit_id' => $getProductDecorationData['scale_unit_id'],
                'is_increment' => $getProductDecorationData['is_incremental_qty'],
                'increment_values' => (!empty($getProductDecorationData['is_incremental_qty']) && $getProductDecorationData['is_incremental_qty'] == 1) ? json_encode($getProductDecorationData['incremental_qty_values']) : "{}",
                'decoration_type' => null,
                'is_prod_desc' => !empty($getProductDecorationData['is_prod_desc']) ? $getProductDecorationData['is_prod_desc'] : null,
                'is_prod_rotate' => !empty($getProductDecorationData['is_prod_rotate']) ? $getProductDecorationData['is_prod_rotate'] : 0,
                'is_use_full_width' => $getProductDecorationData['is_use_full_width'] ? $getProductDecorationData['is_use_full_width'] : 0
            ];
            if (!empty($updateObjectFile)) {
                $productDecorationDataSet['3d_object_file'] =  $updateObjectFile;
            }
            if ($getProductDecorationData['is_configurator']) {
                $productDecorationDataSet['is_configurator'] = $getProductDecorationData['is_configurator'];
            }
            if ((isset($getProductDecorationData['decoration_type']) && $getProductDecorationData['decoration_type'] != '')) {
                $productDecorationDataSet['decoration_type'] = $getProductDecorationData['decoration_type'];
            }

            $prodSettGtInit = new ProductSetting();
            $productSettingsUpdateInit = $prodSettGtInit->where(['xe_id' => $productSettingId]);
            return $productSettingsUpdateInit->update($productDecorationDataSet);
        }
    }

    /**
     * Internal: update product image settings relation
     */
    private function updateImageSettingsRel($productSettingId, $productImageId = null)
    {
        $prodImgSettRelData = [
            'product_setting_id' => $productSettingId,
            'product_image_id' => $productImageId
        ];
        $prodImgSettRelGtInit = new ProductImageSettingsRel();
        // get the image setting rel
        $imageSettingRelQuery = $prodImgSettRelGtInit->where(['product_setting_id' => $productSettingId]);
        if ($imageSettingRelQuery->count() > 0) {
            // update the relation
            $imageSettingRelQuery->update($prodImgSettRelData);
        } else {
            // add new record
            $prodImgSettRelGtInit->insert($prodImgSettRelData);
        }
        return true;
    }

    /**
     * Internal: update product side data
     */
    private function updateProductSides($getProductDecorationData, $productSettingId, $uploadedFileKeys)
    {
        $imageSides = $getProductDecorationData['sides'];
        $dbOldOverlayFiles = $keepOverlayFiles = [];
        // Clearing the old records
        $productSideObj = new ProductSide();
        $oldProductSidesQuery = $productSideObj->where(['product_setting_id' => $productSettingId]);
        if ($oldProductSidesQuery->count() > 0) {
            $oldProductSides = $oldProductSidesQuery->get();
            $dbOldOverlayFiles = $oldProductSides->pluck('overlay_file_name')->toArray();
            // Delete Product Decoration Setting Table Records
            $productDecoSettObj = new ProductDecorationSetting();
            $productDecoSettIds = $productDecoSettObj->where('product_setting_id', $productSettingId)
                ->get()->pluck('xe_id')->toArray();

            // Delete Print Profile Decoration Setting Relation Table Records
            if (!empty($productDecoSettIds)) {
                $proflDecoSettRelObj = new PrintProfileDecorationSettingRel();
                $proflDecoSettRelObj->whereIn('decoration_setting_id', $productDecoSettIds)->delete();
                // Delete Product Decoration Settings Table Records
                $prodDecoSettDelObj = new ProductDecorationSetting();
                $prodDecoSettDelObj->whereIn('xe_id', $productDecoSettIds)->delete();
            }

            // delete the product sides
            $oldProductSidesQuery->delete();
        }
        foreach ($imageSides as $sideKey => $productSideData) {
            $overlayImgUpload = '';
            if (!empty($productSideData['is_image_overlay'])) {
                if (in_array('overlay_' . $sideKey, $uploadedFileKeys)) {
                    $overlayImgUpload = do_upload('overlay_' . $sideKey, path('abs', 'overlay'), [], 'string');
                } else {
                    $overlayImgUpload = substr($productSideData['overlay_image'], strrpos($productSideData['overlay_image'], '/') + 1);
                    $keepOverlayFiles[] = $overlayImgUpload;
                }
            }
            $productSide = new ProductSide([
                'product_setting_id' => $productSettingId,
                'side_name' => $productSideData['name'],
                'product_image_dimension' => $productSideData['image_dimension'],
                'is_visible' => $productSideData['is_visible'],
                'product_image_side_id' => $productSideData['product_image_side_id'],
                'image_overlay' => $productSideData['is_image_overlay'] ? $productSideData['is_image_overlay'] : 0,
                'multiply_overlay' => $productSideData['multiply_overlay'] ? $productSideData['multiply_overlay'] : 0,
                'overlay_file_name' => $overlayImgUpload,
            ]);

            $productSide->save();
            $productSideInsertId = $productSide->xe_id;
            $this->createProductDecorationSettings($productSideData['product_decoration'], $productSideInsertId, $productSettingId);
        }
        if (!empty($dbOldOverlayFiles)) {
            $deletableFiles = array_diff($dbOldOverlayFiles, $keepOverlayFiles);
            foreach ($deletableFiles as $deletableFile) {
                delete_file(path('abs', 'overlay') . $deletableFile);
            }
        }
    }

    private function createProductDecorationSettings($productDecoSettings, $productSideInsertId, $productSettingId)
    {
        foreach ($productDecoSettings as $productDecoSetting) {
            $prodDecoSettData = $productDecoSetting;
            // convert fields to JSON
            $prodDecoSettData['product_side_id'] = $productSideInsertId;
            $prodDecoSettData['dimension'] = isset($productDecoSetting['dimension'])
                ? json_encode($productDecoSetting['dimension'], true) : "{}";
            $prodDecoSettData['locations'] = isset($productDecoSetting['locations'])
                ? json_encode($productDecoSetting['locations'], true) : "{}";
            $prodDecoSettData['is_disable_design'] = intval($productDecoSetting['is_disable_design']);
            $prodDecoSettData['bleed_mark_data'] = isset($productDecoSetting['bleed_mark_data'])
                ? json_encode($productDecoSetting['bleed_mark_data'], true) : "{}";
            $prodDecoSettData['shape_mark_data'] = isset($productDecoSetting['shape_mark_data'])
                ? json_encode($productDecoSetting['shape_mark_data'], true) : "{}";
            $prodDecoSettData['product_setting_id'] = $productSettingId;
            $prodDecoSettData['default_pp_id'] = intval($productDecoSetting['default_print_profile']);

            $productDecorationSettingInit = new ProductDecorationSetting($prodDecoSettData);
            $productDecorationSettingInit->save();
            $prodDecoSettInsId = $productDecorationSettingInit->xe_id;

            // Processing for Table: print_profile_decoration_setting_rel
            if (!empty($prodDecoSettInsId) && !empty($productDecoSetting['print_profile_ids'])) {
                $this->setProdDecoSettingsRel($prodDecoSettInsId, $productDecoSetting['print_profile_ids']);
            }
        }
    }
    /**
     * Internal: create product print profile
     */
    private function setProductPrintProfileRel($productSettingId, $printProfileIds)
    {
        // Processing for Table: print_profile_product_setting_rel
        if (!empty($productSettingId) && !empty($printProfileIds)) {
            // Clearing the old records
            $ppProdSettRelDataInit = new PrintProfileProductSettingRel();
            $ppProdSettRelDataInit->where(['product_setting_id' => $productSettingId])->delete();
            // add new relations
            $ppProdSettRelData = array_map(function ($printProfile) use ($productSettingId) {
                return [
                    'print_profile_id' => $printProfile,
                    'product_setting_id' => $productSettingId
                ];
            }, $printProfileIds);
            $ppProdSettRelDataInit->insert($ppProdSettRelData);
        }
    }

    /**
     * Internal: Update and Save Variable Product Decoration Module
     * (ProductSetting ProductSide ProductDecorationSetting)
     *
     * @param $prodVarDecoData Product Variable Decoration Data
     * @param $uploadedFiles   Array of files
     * @param $storeId         Store ID
     * @param $doReplace       Flag to whearher replace/not
     * @param $updateRecord    Flag = 1 for update, 0=create
     *
     * @author tanmayap@riaxe.com
     * @date   5 Oct 2019
     * @return Json
     */
    private function saveVariableProductDecoration(
        $prodVarDecoData,
        $uploadedFiles,
        $storeId,
        $doReplace,
        $updateRecord
    ) {
        $serverStatusCode = OPERATION_OKAY;

        $settingsExists = 0;
        $productSettingsObj = $prodSettInit = new ProductSetting();
        $checkProductSettingRecord = $prodSettInit->where('product_id', $prodVarDecoData['product_id']);
        if ($checkProductSettingRecord->count() > 0) {
            $productSettingsObj = $checkProductSettingRecord->first();
            $settingsExists = 1;
        }

        // Processing Product Settings
        if ($settingsExists && !$updateRecord && !$doReplace) {
            // do not allow to create duplicate settings, should be replaced/updated only
            $jsonResponse['message'] = message('Variable Decoration', 'exist');
            // Stop and return the error message from here
            return [
                'response' => $jsonResponse,
                'server_status_code' => $serverStatusCode
            ];
        }

        $prodSettingData = [
            'store_id' => $storeId,
            'product_id' => $prodVarDecoData['product_id'],
            'is_variable_decoration' => $prodVarDecoData['is_variable_decoration'],
            'is_custom_size' => $prodVarDecoData['is_custom_size'],
            'is_crop_mark' => $prodVarDecoData['is_crop_mark'],
            'is_ruler' => $prodVarDecoData['is_ruler'],
            'is_safe_zone' => $prodVarDecoData['is_safe_zone'],
            'crop_value' => $prodVarDecoData['crop_value'],
            'safe_value' => $prodVarDecoData['safe_value'],
            'is_3d_preview' => $prodVarDecoData['is_3d_preview'],
            '3d_object_file' => "",
            '3d_object' => $prodVarDecoData['3d_object'],
            'scale_unit_id' => $prodVarDecoData['scale_unit_id'],
            'decoration_type' => $prodVarDecoData['decoration_type'],
            'custom_size_unit_price' => $prodVarDecoData['custom_size_unit_price'],
            'is_increment' => $prodVarDecoData['is_incremental_qty'] ? $prodVarDecoData['is_incremental_qty'] : 0,
            'increment_values' => ($prodVarDecoData['is_incremental_qty'] == 1) ? json_encode($prodVarDecoData['incremental_qty_values']) : "{}",
            'is_prod_desc' => !empty($prodVarDecoData['is_prod_desc']) ? $prodVarDecoData['is_prod_desc'] : null,
            'is_prod_rotate' => !empty($prodVarDecoData['is_prod_rotate']) ? $prodVarDecoData['is_prod_rotate'] : 0,
            'is_use_full_width' => $prodVarDecoData['is_use_full_width'] ? $prodVarDecoData['is_use_full_width'] : 0
        ];
        if (isset($prodVarDecoData['decoration_dimensions']) && $prodVarDecoData['decoration_dimensions'] != "") {
            $prodSettingData['decoration_dimensions'] = json_clean_encode($prodVarDecoData['decoration_dimensions']);
        }
        if (isset($prodVarDecoData['is_configurator']) && $prodVarDecoData['is_configurator'] != "") {
            $prodSettingData['is_configurator'] = $prodVarDecoData['is_configurator'];
        }

        // If any file exist then upload
        $objectFileUpload = $prodVarDecoData['3d_object_file_upload'];
        if (!empty($objectFileUpload) && !empty($uploadedFiles[$objectFileUpload]->file)) {
            $objectFileName = do_upload($objectFileUpload, path('abs', '3d_object'), [150], 'string');
            $prodSettingData['3d_object_file'] = $objectFileName;
        }
        // save or update
        $productSettingsObj->fill($prodSettingData);
        $productSettingsObj->save();
        $productSettingId = $productSettingsObj->xe_id;
        if ($updateRecord) {
            // Delete old records from Print_Profile_Product_Setting_Rel
            (new PrintProfileProductSettingRel())->where('product_setting_id', $productSettingId)->delete();
            // Delete old records from Product_Image_Settings_Rel
            ProductImageSettingsRel::where('product_setting_id', $productSettingId)->delete();
        }

        // For Variable Decoration Ares, delete Sides if Any sides are available
        $prodSideGtInit = new ProductSide();
        $initProductSides = $prodSideGtInit->where('product_setting_id', $productSettingId);
        if ($initProductSides->count() > 0) {
            $initProductSides->delete();
        }

        // create print print profile relation
        if (!empty($prodVarDecoData['print_profile_ids'])) {
            $this->setProductPrintProfileRel($productSettingId, $prodVarDecoData['print_profile_ids']);
        }

        // Processing Product Image Settings Rel
        if (!empty($prodVarDecoData['product_image_id'])) {
            $productImageSettings = new ProductImageSettingsRel([
                'product_setting_id' => $productSettingId,
                'product_image_id' => $prodVarDecoData['product_image_id']
            ]);
            $productImageSettings->save();
        }

        // Processing Product Decoration Settings Record
        $productDecorationData = $prodVarDecoData['product_decoration'];


        // for overlay image section (Note: for static boundary this is saved side wise)
        if (array_key_exists('overlay_0', $uploadedFiles)) {
            $overlayImgUpload = do_upload('overlay_0', path('abs', 'overlay'), [], 'string');
        } else {
            $overlayImgUpload = substr($productDecorationData['overlay_image'], strrpos($productDecorationData['overlay_image'], '/') + 1);
        }

        // Setup decoration settings array
        $prodDecoSettDataNw = [
            'product_setting_id' => $productSettingId,
            'dimension' => isset($productDecorationData['dimension'])
                ? json_encode($productDecorationData['dimension'], true) : "{}",
            'locations' => isset($productDecorationData['locations'])
                ? json_encode($productDecorationData['locations'], true) : "{}",
            'is_disable_design' => isset($productDecorationData['is_disable_design']) ? $productDecorationData['is_disable_design'] : 0,
            'is_border_enable' => $productDecorationData['is_border_enable'],
            'is_sides_allow' => $productDecorationData['is_sides_allow'],
            'no_of_sides' => $productDecorationData['no_of_sides'],
            'bleed_mark_data' => isset($productDecorationData['bleed_mark_data'])
                ? json_encode($productDecorationData['bleed_mark_data'], true) : "{}",
            'shape_mark_data' => isset($productDecorationData['shape_mark_data'])
                ? json_encode($productDecorationData['shape_mark_data'], true) : "{}",
            'image_overlay' => $productDecorationData['is_image_overlay'] ? $productDecorationData['is_image_overlay'] : 0,
            'multiply_overlay' => $productDecorationData['multiply_overlay'] ? $productDecorationData['multiply_overlay'] : 0,
            'overlay_file_name' => $overlayImgUpload,
            'pre_defined_dimensions' => null,
            'user_defined_dimensions' => null
        ];

        // Choose dimension according to the flag
        if (isset($productDecorationData['is_pre_defined']) && $productDecorationData['is_pre_defined'] == 1) {
            $prodDecoSettDataNw['pre_defined_dimensions'] = json_encode($productDecorationData['pre_defined_dimensions']);
        } else {
            $prodDecoSettDataNw['user_defined_dimensions'] = json_encode($productDecorationData['user_defined_dimensions']);
        }

        if (!empty($productDecorationData['print_area_id'])) {
            $prodDecoSettDataNw['print_area_id'] = $productDecorationData['print_area_id'];
        }

        $prodDecoSettObj = $prodDecoSettInit = new ProductDecorationSetting();
        $prodDecoSettUpdateQuery = $prodDecoSettInit->where(['product_setting_id' => $productSettingId]);
        if ($prodDecoSettUpdateQuery->count()) {
            $prodDecoSettObj = $prodDecoSettUpdateQuery->get()->first();
        }
        $prodDecoSettObj->fill($prodDecoSettDataNw);
        $prodDecoSettObj->save();
        $prodDecoSettInsId = $prodDecoSettObj->xe_id;

        // Processing Print Profile Decoration Setting Rel
        $this->setProdDecoSettingsRel($prodDecoSettInsId, $productDecorationData['print_profile_ids'], $updateRecord);

        //Flush product memcached
		$this->memcache('deleteMulti', '', '', 'product');
        $jsonResponse = [
            'status' => 1,
            'product_settings_insert_id' => $productSettingId,
            'message' => message('Variable Product Decoration Setting', ($updateRecord ? 'updated' : 'saved'))
        ];

        return [
            'response' => $jsonResponse,
            'server_status_code' => $serverStatusCode
        ];
    }
    /**
     * Internal: create predeco settings relation
     */
    private function setProdDecoSettingsRel($prodDecoSettInsId, $printProfileIds, $iSupdateRecord = false)
    {
        if (!empty($prodDecoSettInsId) && !empty($printProfileIds)) {
            $ppDecoSettRelSvInit = new PrintProfileDecorationSettingRel();
            // Delete old records from "print_profile_decoration_setting_rel
            if ($iSupdateRecord) {
                $ppDecoSettRelSvInit->where('decoration_setting_id', $prodDecoSettInsId)->delete();
            }
            // Processing for Table: print_profile_decoration_setting_rel
            $ppDecoSettRelData = array_map(function ($printProfile) use ($prodDecoSettInsId) {
                return [
                    'print_profile_id' => $printProfile,
                    'decoration_setting_id' => $prodDecoSettInsId
                ];
            }, $printProfileIds);

            $ppDecoSettRelSvInit->insert($ppDecoSettRelData);
        }
    }

    /**
     * Get: Get product settings details along with other related records
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     *
     * @author tanmayap@riaxe.com
     * @date   03 Feb 2020
     * @return Array
     */
    public function productSettingDetails($request, $response, $args)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [
            'status' => 0,
            'data' => [],
            'message' => message('Settings Details', 'error')
        ];

        $settingsDetail = [];
        $getStoreDetails = get_store_details($request);
        $storeId = $getStoreDetails['store_id'];
        $productId = $args['product_id'];
        $returnType = !empty($args['return_type']) ? $args['return_type'] : 'json';

        $prodSettingObj = new ProductSetting();
        $settingsAssocRecords = $prodSettingObj->with('sides');
        $settingsAssocRecords->with('sides.product_decoration_setting');
        $settingsAssocRecords->with('sides.product_decoration_setting.print_profile_decoration_settings');
        $settingsAssocRecords->with('sides.product_decoration_setting.print_profile_decoration_settings.print_profile');
        $settingsAssocRecords->with('sides.product_decoration_setting.print_area');
        $settingsAssocRecords->with('print_profiles', 'print_profiles.profile');

        if(isset($args['option_setting_id']) and $args['option_setting_id'] > 0){
            $settingsAssocRecords->where('xe_id', $args['option_setting_id']);
        }

        $settingsAssocRecords->where([
            ['product_id', '=', $productId],
            ['store_id', '=', $storeId]
        ]);

        if ($settingsAssocRecords->count() > 0) {
            $settingsDetail = $settingsAssocRecords->orderBy('xe_id', 'desc')->first()->toArray();
            $jsonResponse = [
                'status' => 1,
                'data' => $settingsDetail
            ];
        }
        if ($returnType == 'json') {
            return response($response, [
                'data' => $jsonResponse, 'status' => $serverStatusCode
            ]);
        }
        return $settingsDetail;
    }
    /**
     * Get: Return AppUnit's default record if no ID available
     * or else return the associated data with the supplied ID
     *
     * @param $id     App Unit Primary Key
     * @param $column Which column to retun
     *
     * @author tanmayap@riaxe.com
     * @date   03 Mar 2020
     * @return string
     */
    protected function getAppUnit($id = 0, $column = 'label')
    {
        $data = 1;
        $appUnitObj = new AppUnit();
        if (!empty($id)) {
            $appUnitDetail = $appUnitObj->where('xe_id', $id);
        } else {
            $appUnitDetail = $appUnitObj->where('is_default', 1);
        }

        if ($appUnitDetail->count() > 0) {
            $scaleUnit = $appUnitDetail->first()->toArray();
            $data = $scaleUnit[$column];
        }

        return $data;
    }
    /**
     * Get: Fetch all Product Decoration Settings
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     * @param $returnType     response return type
     *
     * @author tanmayap@riaxe.com
     * @date   5 Oct 2019
     * @return Json
     */
    public function getProductDecorations($request, $response, $args, $returnType = 0)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [];
        $productDecorationSettingData = [];
        $productSideImages = [];
        $getFinalArray = [];
        $getScaleUnit = 0;
        $productId = !empty($args['product_id']) ? $args['product_id'] : null;
        $storeId = $request->getQueryParam('store_id');
        $is3dPreviewAll = $isProductImage = $isDecoration = 0;
        $productImgId = 0;
        $importedProductId = '';
        /**
         * (#001) Get Product Image Sides from Respective Stores If the
         * store has no product images then, create a blank array with
         * exception error
         */
        $getStoreProduct = $this->getStore()->getProducts($request, $response, [
            'id' => $productId
        ]);
        // do not proceed if product not found
        if (empty($getStoreProduct) || empty($getStoreProduct['products'])) {
            return response($response, [
                'data' => $jsonResponse, 'status' => $serverStatusCode
            ]);
        }
        /**
         * Relational Tables by their function names from Model size_variant_id
         */
        $getSettingsAssociatedRecords = $this->productSettingDetails($request, $response, [
            'product_id' => $productId,
            'return_type' => 'array'
        ]);

        $optionSettingRelObj = new productOptionSettingRel();
        $optionsSettingData = $optionSettingRelObj->where('product_id', $productId);
        $isOptionsBased = 0;
        if($optionsSettingData->count() > 0) {
            $isOptionsBased = 1;
        }

        if (empty($getSettingsAssociatedRecords)) {
            $settingData = $this->getSettingsIdByProductId($productId, $getStoreProduct['products']['categories']);
            if (!empty($settingData)) {
                $is3dPreviewAll = $settingData->is_3d_preview;
                $isProductImage = $settingData->is_product_image;
                $isDecoration = 1;
                $importedProductId = $settingData->product_id;
                $getSettingsAssociatedRecords = $this->productSettingDetails($request, $response, [
                    'product_id' => $settingData->product_id,
                    'return_type' => 'array'
                ]);
            }
        }

        // product details
        $getProductDetails = $getStoreProduct['products'];
        // product images
        $productSideImages = $getProductDetails['images'];
        // product variant id
        $productVariantId = $getProductDetails['variant_id'];

        $productDecorationSettingData = [
            'product_id' => $productId,
            'variant_id' => !empty($productVariantId) ? $productVariantId : 0,
            'product_name' => !empty($getProductDetails['name']) ? $getProductDetails['name'] : '',
            'type' => $getProductDetails['type'],
            'sku' => $getProductDetails['sku'],
            'price' => $getProductDetails['price'],
            'is_variable_decoration' => 0,
            'is_custom_size' => 0,
            'decoration_type' => "",
            'custom_size_unit_price' => "",
            'decoration_dimensions' => "",
            'is_ruler' => 0,
            'is_crop_mark' => 0,
            'is_safe_zone' => 0,
            'crop_value' => 0,
            'safe_value' => 0,
            'is_3d_preview' => 0,
            '3d_object_file' => "",
            '3d_object' => "",
            'scale_unit_id' => $getScaleUnit,
            'is_configurator' => 0,
            'is_product_image' => 0,
            'product_image_id' => 0,
            'is_decoration_exists' => 0,
            'is_svg_configurator' => 0,
            'is_applied_color' => 0,
            'is_applied_pattern' => 0,
            'is_incremental_qty' => 0,
            'incremental_qty_values' => "{}",
            'is_use_full_width' => 0,
            'store_images' => $productSideImages,
            'sides' => [],
            'print_profiles' => [],
            'configurator_image' => [],
            'imported_product_id' => $importedProductId,
            'is_option_print_area' => $isOptionsBased,
        ];
        // get the store attributes
        $getSizeData = $this->getProductAttributeOption($getProductDetails['attributes'], 'size');
        if (!empty($getSizeData)) {
            $productDecorationSettingData['size'] = $getSizeData;
        }
        // Check if any record(s) exist
        if (!empty($getSettingsAssociatedRecords)) {
            $getFinalArray = $getSettingsAssociatedRecords;
            /**
             * If the DB has it's own image product ID, send product_image_id, or
             * send 0
             */
            if ($isProductImage || !$isDecoration) {
                $prodImgSettRelObj = new ProductImageSettingsRel();
                $checkForProductImage = $prodImgSettRelObj->where('product_setting_id', $getFinalArray['xe_id'])->first();
                $productImgId = to_int($checkForProductImage['product_image_id']);
            }

            if (!empty($getFinalArray['decoration_dimensions'])) {
                $productDecorationSettingData['decoration_dimensions'] = json_clean_decode($getFinalArray['decoration_dimensions'], true);
            }

            if ($getFinalArray['is_configurator'] == 1) {
                $configuratorImage = $this->getConfiguratorImages($productId);
                $productDecorationSettingData['configurator_image'] = $configuratorImage;
            }
            if ($is3dPreviewAll || !$isDecoration) {
                $decorationObjInit = new DecorationObjects();
                $objFileDetails = $decorationObjInit->where('product_id', $getFinalArray['product_id'])->select('3d_object_file', 'cloud_storage')->first();
                $objFile = $objFileDetails['3d_object_file'];
                if ($objFileDetails['cloud_storage'] == 1) {
                    $objFile = $this->getS3URL($objFile, $storeId);
                }
                $productDecorationSettingData['3d_object_file'] = !empty($objFile) ? $objFile : "";
            }

            $productDecorationSettingData['is_product_image'] = $productImgId > 0 ? 1 : 0;
            $productDecorationSettingData['product_image_id'] = $productImgId;
            $productDecorationSettingData['is_variable_decoration'] = $getFinalArray['is_variable_decoration'];
            $productDecorationSettingData['is_custom_size'] = $getFinalArray['is_custom_size'];
            $productDecorationSettingData['decoration_type'] = $getFinalArray['decoration_type'];
            $productDecorationSettingData['custom_size_unit_price'] = $getFinalArray['custom_size_unit_price'];
            $productDecorationSettingData['is_ruler'] = $getFinalArray['is_ruler'];
            $productDecorationSettingData['is_crop_mark'] = $getFinalArray['is_crop_mark'];
            $productDecorationSettingData['is_safe_zone'] = $getFinalArray['is_safe_zone'];
            $productDecorationSettingData['crop_value'] = (float) $getFinalArray['crop_value'];
            $productDecorationSettingData['safe_value'] = (float) $getFinalArray['safe_value'];
            $productDecorationSettingData['is_3d_preview'] = $getFinalArray['is_3d_preview'];
            // $productDecorationSettingData['3d_object_file'] = $getFinalArray['3d_object_file'];
            $productDecorationSettingData['3d_object'] = $getFinalArray['3d_object'];
            $productDecorationSettingData['scale_unit_id'] = $getFinalArray['scale_unit_id'];
            $productDecorationSettingData['is_configurator'] = (isset($getFinalArray['is_configurator'])) ? $getFinalArray['is_configurator'] : 0;
            $productDecorationSettingData['is_decoration_exists'] = 1;
            $productDecorationSettingData['is_svg_configurator'] = $getFinalArray['is_svg_configurator'];
            $productDecorationSettingData['is_incremental_qty'] = $getFinalArray['is_increment'];
            $productDecorationSettingData['incremental_qty_values'] = (!empty($getFinalArray['increment_values'])) ? json_clean_decode($getFinalArray['increment_values'], true) : "{}";
            $productDecorationSettingData['is_prod_desc'] = !empty($getFinalArray['is_prod_desc']) ? $getFinalArray['is_prod_desc'] : null;
            $productDecorationSettingData['is_prod_rotate'] = !empty($getFinalArray['is_prod_rotate']) ? $getFinalArray['is_prod_rotate'] : 0;

            $productDecorationSettingData['is_applied_pattern'] = $getFinalArray['is_applied_pattern'];
            $productDecorationSettingData['is_applied_color'] = $getFinalArray['is_applied_color'];
            $productDecorationSettingData['is_use_full_width'] = $getFinalArray['is_use_full_width'];
            // Check if requested array is for Decoration or for variable Decoration
            if (!empty($getFinalArray['sides'])) {
                $productDecorationSides = $this->getProductSideData($getFinalArray['sides'], $productSideImages, $productImgId, $storeId);
                $productDecorationSettingData['sides'] = $productDecorationSides;
            } else {
                // Get variable decoration settings data
                $varProdDecoData = $this->getVaiableDecoData($getFinalArray['xe_id']);
                $productDecorationSettingData += $varProdDecoData;
            }
            // Processing Print Profiles
            if (!empty($getFinalArray['print_profiles'])) {
                foreach ($getFinalArray['print_profiles'] as $printProfile) {
                    if (!empty($printProfile['profile']['xe_id']) && !empty($printProfile['profile']['name'])) {
                        $productDecorationSettingData['print_profiles'][] = [
                            'id' => $printProfile['profile']['xe_id'],
                            'name' => $printProfile['profile']['name'],
                        ];
                    }
                }
            }
        }
        $jsonResponse = [
            'status' => 1, 'data' => $productDecorationSettingData
        ];

        if ($returnType == 1) {
            return $jsonResponse;
        }

        return response($response, [
            'data' => $jsonResponse, 'status' => $serverStatusCode
        ]);
    }
    /**
     * Internal: get the product side data
     */
    private function getProductSideData($productSides, $productSideImages = [], $productImgId = 0, $storeId = 1)
    {
        // default empty deco sides
        $productDecorationSettingSides = [];
        // get all the side images for the product
        $prodImageSideObj = new ProductImageSides();
        $getProductImageSides = $prodImageSideObj->where('product_image_id', $productImgId)->orderBy('sort_order', 'ASC')->get();

        // Get side image accordoing to the side index of the side array
        // Check if product_image_id exist in ProductImageSettingsRel
        $prodImgSettRelGtInit = new ProductImageSettingsRel();
        $doExistProdImgSetts = $prodImgSettRelGtInit->where('product_image_id', $productImgId)->count();

        $productStoreImageSide = count($productSideImages);
        if (count($productSides) > $productStoreImageSide) {
            $imageSide = count($productSides);
        } else {
            $imageSide = (!$productImgId) ? $productStoreImageSide : count($productSides);
        }

        $i = 1;
        foreach ($productSides as $sideKey => $side) {
            // Build Product Side Array
            if ($imageSide >= $i) {
                $productDecorationSides['id'] = $side['xe_id'];
                $productDecorationSides['name'] = $side['side_name'];
                $productDecorationSides['index'] = $side['side_index'];
                $productDecorationSides['dimension'] = $side['dimension'];
                $productDecorationSides['is_visible'] = $side['is_visible'];
                $productDecorationSides['crop_value'] = $side['crop_value'];
                $productDecorationSides['safe_value'] = $side['safe_value'];
                $productDecorationSides['locations'] = $side['locations'];
                $productDecorationSides['is_disable_design'] = $side['is_disable_design'];
                $productDecorationSides['is_image_overlay'] = $side['image_overlay'];
                $productDecorationSides['multiply_overlay'] = $side['multiply_overlay'];
                $productDecorationSides['overlay_image'] = !empty($side['overlay_file_name']) ? path('read', 'overlay') . $side['overlay_file_name'] : "";

                if ($doExistProdImgSetts == 0) {
                    // Get Product Image Sides from Respective Stores
                    /**
                     * In the section #001, we got all images from Store
                     * end. There may be multiple images. Each image belongs
                     * to one side Programatically, we get each side by the
                     * foreach loop key's index
                     */
                    if (!empty($productSideImages[$sideKey])) {
                        $productDecorationSides['image'] = $productSideImages[$sideKey];
                    }
                } else {
                    $productImageObj = new ProductImage();
                    $imageDetails = $productImageObj->where('xe_id', $productImgId)->select('cloud_storage')->first()->toArray();
                    // Get Product Image Sides from DB
                    if (!empty($getProductImageSides[$sideKey])) {
                        $getProductImageSideData = $getProductImageSides[$sideKey];
                        if (!empty($getProductImageSideData)) {
                            $productDecorationSides['image'] = [
                                'id' => $getProductImageSideData->xe_id,
                                'src' => ($imageDetails['cloud_storage'] == 1) ? $this->getS3URL($getProductImageSideData->file_name, $storeId) : $getProductImageSideData->file_name,
                                'thumbnail' => ($imageDetails['cloud_storage'] == 1) ? $this->getS3URL($getProductImageSideData->thumbnail, $storeId) : $getProductImageSideData->thumbnail,
                            ];
                        }
                    }
                }

                // format the deco side settings data
                $productDecorationSides['decoration_settings'] = $this->formatDecoData($side['product_decoration_setting']);
                $productDecorationSettingSides[$sideKey] = $productDecorationSides;
                $i++;
            }
        }
        return $productDecorationSettingSides;
    }
    /**
     * Internal: format the decoration data
     */
    private function formatDecoData($sideDecoSettings = [])
    {
        $productDecorationSidesSettings = [];
        foreach ($sideDecoSettings as $decorationSetting) {
            $decoSettingsPprofile = [];
            // Loop through, Print Profile Decoration Setting
            if (!empty($decorationSetting['print_profile_decoration_settings'])) {
                foreach ($decorationSetting['print_profile_decoration_settings'] as $ppDecoSetting) {
                    if (
                        !empty($ppDecoSetting['print_profile'][0]['xe_id']) && !empty($ppDecoSetting['print_profile'][0]['name'])
                    ) {
                        $decoSettingsPprofile[] = [
                            'id' => $ppDecoSetting['print_profile'][0]['xe_id'],
                            'name' => $ppDecoSetting['print_profile'][0]['name'],
                        ];
                    }
                }
            }
            $productDecorationSidesSettings[] = [
                'id' => $decorationSetting['xe_id'],
                'name' => $decorationSetting['name'],
                'dimension' => $decorationSetting['dimension'],
                'locations' => $decorationSetting['locations'],
                'is_disable_design' => $decorationSetting['is_disable_design'],
                'bleed_mark_data' => $decorationSetting['bleed_mark_data'],
                'shape_mark_data' => $decorationSetting['shape_mark_data'],
                'sub_print_area_type' => $decorationSetting['sub_print_area_type'],
                'min_height' => $decorationSetting['min_height'],
                'max_height' => $decorationSetting['max_height'],
                'min_width' => $decorationSetting['min_width'],
                'max_width' => $decorationSetting['max_width'],
                'is_border_enable' => $decorationSetting['is_border_enable'],
                'is_sides_allow' => $decorationSetting['is_sides_allow'],
                'print_area_id' => $decorationSetting['print_area_id'],
                'default_print_profile' => $decorationSetting['default_pp_id'] ? $decorationSetting['default_pp_id'] : 0,
                'print_profiles' => $decoSettingsPprofile,
                // this field 'decoration_size_variants' will be implemented in future
                'decoration_size_variants' => []
            ];
        }
        return $productDecorationSidesSettings;
    }
    /**
     * Internal: get the attributes based on option-name
     */
    private function getProductAttributeOption($attrbutes = [], $optionName = '')
    {
        $storeAttributes = $this->getAttributeName();
        if (empty($storeAttributes[$optionName]) && empty($attrbutes)) {
            return [];
        }
        $attributeName = clean($storeAttributes[$optionName]);
        foreach ($attrbutes as $attribute) {
            if ($attributeName === strtolower(clean($attribute['name']))) {
                return $attribute['options'];
            }
        }
        return [];
    }
    /**
     * Get: Product Decoration details with minimal store data
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     *
     * @author tanmayap@riaxe.com
     * @date   27 feb 2020
     * @return Json
     */
    public function productDetailsWithDecoration($request, $response, $args)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [];
        $getStoreProduct = [];
        $productDecorationSettingData = [];
        $productSideImages = [];
        $getStoreDetails = get_store_details($request);
        $storeId = $getStoreDetails['store_id'];
        $productId = $args['product_id'];
        $type = $request->getQueryParam('type', '');
        $source = $request->getQueryParam('source', '');
        $variantId = $request->getQueryParam('variant_id');
        $importedDecoration = false; //bydefault we think its not imported from elsewhere
        // For Opencart store
        $optionId = $request->getQueryParam('option_id', '');
        $currentStoreUrl = '';

        if (!empty($args['product_id'])) {

            // check if cache available
            //MEMCACHED KEY
            $thisCacheKey = "productdetails_pid". $productId."_vid".$variantId."_s".$storeId;
            //Register MEMCACHED KEY in Local Cache
            $this->createUpdateMemCacheGroup('product', $thisCacheKey, 'SET');
            $cacheData = $this->memcache("get", $thisCacheKey);

            if (!empty($cacheData) && is_array($cacheData)) {
                $jsonResponse = $cacheData;
                return response($response, [
                    'data' => $jsonResponse, 'status' => $serverStatusCode
                ]);
            }

			$optionSettingRelObj = new productOptionSettingRel();
            $optionsSettingData = $optionSettingRelObj->where('product_id', $productId);
            $isOptionsBased = 0;
            $optionSettingId = 0;

            /**
             * (#001) Get Product Image Sides from Respective Stores If the
             * store has no product images then, create a blank array with
             * exception error
             */

            // Get product short details from the store method
            $getStoreProduct =$this->getStore()->getProductShortDetails($request, $response, [
                'product_id' => $args['product_id'],
                'variant_id' => $variantId,
                'option_id' => $optionId,
                'details' => 1
            ]);
            // Get Setting Id from Option setting relation table
            if($optionsSettingData->count() > 0) {
                $isOptionsBased = 1;
                $optionsSettingData = $optionsSettingData->get()->toArray();
                $printAreaOptionId = $optionsSettingData[0]['option_id'];
                $converted_array = array_values($getStoreProduct['attributes']);
                $optionListArray = array_column($converted_array, 'option_id');
                $optionsearchIndex = array_search($printAreaOptionId,$optionListArray);

                $variantOptionValue = $converted_array[$optionsearchIndex]['name'];
                $optionValueArray = array_column($optionsSettingData, 'option_value');
                $optionValueIndex = array_search(strtolower($variantOptionValue),$optionValueArray);
                $finalOptionSettingArray = $optionsSettingData[$optionValueIndex];
                $optionSettingId = $finalOptionSettingArray['product_setting_id'];
            }
            /**
             * Relational Tables by their function names from Model size_variant_id
             */
            $getSettingsAssociatedRecords = $this->productSettingDetails($request, $response, [
                'product_id' => $args['product_id'],
                'return_type' => 'array',
                'option_setting_id' => $optionSettingId,
            ]);
            /**
             * (#001) Get Product Image Sides from Respective Stores If the
             * store has no product images then, create a blank array with
             * exception error
             */
            // Get product short details from the store method
            $getStoreProduct = $this->getStore()->getProductShortDetails($request, $response, [
                'product_id' => $args['product_id'],
                'variant_id' => $variantId,
                'option_id' => $optionId,
                'details' => 1
            ]);
            // Check if print area for this product was set in bulk or against it's category
            if (empty($getSettingsAssociatedRecords)) {
                $settingData = $this->getSettingsIdByProductId($args['product_id'], $getStoreProduct['categories']);
                if (!empty($settingData)) {
                    $import3DPreview = $settingData->is_3d_preview;
                    $importProductImage = $settingData->is_product_image;
                    $importedDecoration = true;
                    $importedProductId = $settingData->product_id;
                    $getSettingsAssociatedRecords = $this->productSettingDetails($request, $response, [
                        'product_id' => $importedProductId,
                        'return_type' => 'array'
                    ]);
                }
            }
        }

        // do not proceed if product short details not found
        if (empty($getStoreProduct)) {
            return response($response, [
                'data' => $jsonResponse, 'status' => $serverStatusCode
            ]);
        }

        if ($storeId > 1 && $type == 'tool') {
            $databaseStoreInfo = DB::table('stores')->where('xe_id', '=', $storeId);
            if ($databaseStoreInfo->count() > 0) {
                $currentStoreUrl = $databaseStoreInfo->first()->store_url;
            }
        }

        if ($storeId > 1 && $type == 'tool' && IS_HOSTED == 0) {
            $getStoreProduct['images'] = array_map(function ($productImage) use ($currentStoreUrl) {
                $hostname = parse_url($productImage['src'], PHP_URL_HOST); //hostname
                return [
                    'src' => str_replace($hostname, $currentStoreUrl, $productImage['src']),
                    'thumbnail' => str_replace($hostname, $currentStoreUrl, $productImage['thumbnail'])
                ];
            }, $getStoreProduct['images']);
        }
        // $productSideImages = !empty($productSideImages) ? $productSideImages : $getStoreProduct['images'];

        $productSideImages = $getStoreProduct['images'];
        $attributeName = $this->getAttributeName();
        $colorAttrName = $attributeName['color'];
        if (!empty($getStoreProduct['attributes'][$colorAttrName])) {
            $colorData = $getStoreProduct['attributes'][$colorAttrName];
            $variantData = $this->getColorSwatchData([
                ['id' => $colorData['id'], 'name' => $colorData['name']]
            ]);
            $getStoreProduct['attributes'][$colorAttrName] = $variantData[0];
        }

        // Check if any record(s) exist
        if (!empty($getSettingsAssociatedRecords)) {
            $settingKeyArray['getSettingsAssociatedRecords'] = $getSettingsAssociatedRecords;
            $settingKeyArray['import3DPreview'] = $import3DPreview;
            $settingKeyArray['importedDecoration'] = $importedDecoration;
            $settingKeyArray['storeId'] = $storeId;
            $settingKeyArray['importProductImage'] = $importProductImage;
            $settingKeyArray['productId'] = $productId;
            $settingKeyArray['getStoreProduct'] = $getStoreProduct;
            $settingKeyArray['importedProductId'] = $importedProductId;
            $settingKeyArray['productSideImages'] = $productSideImages;
            $settingKeyArray['currentStoreUrl'] = $currentStoreUrl;
            $settingKeyArray['type'] = $type;
            $settingKeyArray['source'] = $source;

            $productDecorationSettingData = $this->getSettingsAssociatedRecords($request, $response, $settingKeyArray);
        } else {
            $productDecorationSettingData = $this->getDefaultDecorationeData($productSideImages, $storeId, $getStoreProduct, $args);
        }
        $productDecorationSettingData['is_option_print_area'] = $isOptionsBased;
        $jsonResponse = [
            'status' => 1,
            'data' => $productDecorationSettingData
        ];
        $this->memcache("set", $thisCacheKey, $jsonResponse);
        return response($response, [
            'data' => $jsonResponse, 'status' => $serverStatusCode
        ]);
    }
    /**
     * Post: Save & Get Decoration Object File
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     *
     * @author satyabratap@riaxe.com
     * @date   3 Feb 2019
     * @return A JSON Response
     */
    public function objDetailsOperation($request, $response)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [
            'status' => 0,
            'message' => message('Object Details', 'error')
        ];
        try {
            $allPostPutVars = $request->getParsedBody();
            $getStoreDetails = get_store_details($request);
            $storeId = $getStoreDetails['store_id'];
            $isS3Enabled = $this->checkS3Settings($storeId);
            // product id required
            if (!empty($allPostPutVars['product_id'])) {
                $cloudStorage = 0;
                $productId = $allPostPutVars['product_id'];
                $decoObject = $objInit = new DecorationObjects();
                $getDetailsQuery = $objInit->where('product_id', $productId);
                if ($getDetailsQuery->count()) {
                    $decoObject = $getDetailsQuery->first();
                }
                // check new file
                $uploadedFiles = $request->getUploadedFiles();
                if (empty($uploadedFiles['3d_object_file'])) {
                    throw new \Exception('3d object file not found');
                }
                // delete 3d oject file
                if (!empty($decoObject['3d_object_file'])) {
                    if ($decoObject['cloud_storage'] == 1) {
                        $this->deleteS3File($decoObject['3d_object_file'], $storeId);
                    }
                    $this->deleteOldFile('decoration_objects', '3d_object_file', ['product_id' => $productId], path('abs', '3d_object'));
                }
                // upload new file
                $fileName = do_upload('3d_object_file', path('abs', '3d_object'), [], 'string');
                $fileUrl =  path('read', '3d_object') . $fileName;
                if ($isS3Enabled) {
                    $cloudStorage = 1;
                    $fileToUpload = path('abs', '3d_object') . $fileName;
                    $s3Response = $this->uploadFileToS3("3d_object", $fileToUpload, $storeId);
                    $fileUrl = $s3Response['S3URL'];
                }
                $objData = [
                    '3d_object_file' => $fileName, 'cloud_storage' => $cloudStorage, 'product_id' => $productId
                ];
                $decoObject->fill($objData);
                if ($decoObject->save()) {
                    $jsonResponse = [
                        'status' => 1,
                        'message' => "3d Object file uploaded successfully",
                        '3d_object_file' => $fileUrl
                    ];
                }
            }
        } catch (\Exception $e) {
            $jsonResponse['message'] = $e->getMessage();
        }
        return response($response, [
            'data' => $jsonResponse, 'status' => $serverStatusCode
        ]);
    }

    /**
     * Post: Save & Get UV File
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     *
     * @author satyabratap@riaxe.com
     * @date   11 Jun 2019
     * @return A JSON Response
     */
    public function uvFilesOperation($request, $response)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [
            'status' => 0,
            'message' => message('Object Details', 'error')
        ];
        try {
            $allPostPutVars = $request->getParsedBody();
            $getStoreDetails = get_store_details($request);
            $storeId = $getStoreDetails['store_id'];
            $isS3Enabled = $this->checkS3Settings($storeId);
            // product id required
            if (!empty($allPostPutVars['product_id'])) {
                $cloudStorage = 0;
                $productId = $allPostPutVars['product_id'];
                $decoObject = $objInit = new DecorationObjects();
                $getDetailsQuery = $objInit->where('product_id', $productId);
                if ($getDetailsQuery->count()) {
                    $decoObject = $getDetailsQuery->first();
                }
                // check new file
                $uploadedFiles = $request->getUploadedFiles();
                if (empty($uploadedFiles['uv_file'])) {
                    throw new \Exception('uv file not found');
                }
                // delete 3d oject file
                if (!empty($decoObject['uv_file'])) {
                    if ($decoObject['cloud_storage'] == 1) {
                        $this->deleteS3File($decoObject['uv_file'], $storeId);
                    }
                    $this->deleteOldFile('decoration_objects', 'uv_file', ['product_id' => $productId], path('abs', '3d_object'));
                }
                // upload new file
                $fileName = do_upload('uv_file', path('abs', '3d_object'), [], 'string');
                $fileUrl =  path('read', '3d_object') . $fileName;
                if ($isS3Enabled) {
                    $cloudStorage = 1;
                    $fileToUpload = path('abs', '3d_object') . $fileName;
                    $s3Response = $this->uploadFileToS3("3d_object", $fileToUpload, $storeId);
                    $fileUrl = !empty($s3Response['S3URL']) ? $this->getS3URL($fileToUpload, $storeId) : $fileUrl;
                }
                $objData = [
                    'uv_file' => $fileName, 'cloud_storage' => $cloudStorage, 'product_id' => $productId
                ];
                $decoObject->fill($objData);
                if ($decoObject->save()) {
                    $jsonResponse = [
                        'status' => 1,
                        'message' => "uv file uploaded successfully",
                        'uv_file' => $fileUrl
                    ];
                }
            }
        } catch (\Exception $e) {
            $jsonResponse['message'] = $e->getMessage();
        }
        return response($response, [
            'data' => $jsonResponse, 'status' => $serverStatusCode
        ]);
    }

    /**
     * Delete: Delete Decoration Settings From Relation Table
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     *
     * @author radhanatham@riaxe.com
     * @date   10 Sept 2019
     * @return Nothing
     */
    public function deleteProductDecorationRel($productId)
    {
        // remove all the related table based on the settings id, then delete the product settings
        // the product will share the setting of the parent product which settings is applied as bulk
        $productSettingObj = new ProductSetting();
        $productSettingGet = $productSettingObj->where('product_id', $productId)->first();

        if (!empty($productSettingGet->xe_id)) {
            $productSettingDeleteId = $productSettingGet->xe_id;
            // remove the "product category settings rel" based on the deletable product setting id
            $productCatSettingsRelInit = new ProductCategorySettingsRel();
            $productCatSettingsRelInit->where('product_setting_id', $productSettingDeleteId)->delete();
            // remove product image settings rel
            $prodImgSettRelObj = new ProductImageSettingsRel();
            $prodImgSettRelObj->where('product_setting_id', $productSettingDeleteId)->delete();

            // remove all product sides based on the deletable product setting id
            $productSideObj = new ProductSide();
            $productSideObj->where('product_setting_id', $productSettingDeleteId)->delete();

            // Delete Print Profile Product Setting Relation Table Records
            $profProdSettRelObj = new PrintProfileProductSettingRel();
            $profProdSettRelObj->where('product_setting_id', $productSettingDeleteId)->delete();

            // Delete Product Decoration Setting Table Records
            $productDecoSettObj = new ProductDecorationSetting();
            $productDecoSettIds = $productDecoSettObj->where('product_setting_id', $productSettingDeleteId)
                ->get()->pluck('xe_id')->toArray();

            // Delete Print Profile Decoration Setting Relation Table Records
            if (!empty($productDecoSettIds)) {
                $proflDecoSettRelObj = new PrintProfileDecorationSettingRel();
                $proflDecoSettRelObj->whereIn('decoration_setting_id', $productDecoSettIds)->delete();
                // Delete Product Decoration Settings Table Records
                $prodDecoSettDelObj = new ProductDecorationSetting();
                $prodDecoSettDelObj->whereIn('xe_id', $productDecoSettIds)->delete();
            }

            // Delete Product Setting Table Records
            $productSettDelObj = new ProductSetting();
            $productSettDelObj->where('xe_id', $productSettingDeleteId)->delete();
        }
    }

    /**
     * Internal: Save Product Setting Relation Table
     *
     * @param $productDetails  Product or product categoies id
     * @param $productSettingId Setting id
     * @param $isProductImage    Flag check product image enbaled or not
     * @param $is3dPreviewAll    Flaf check 3d enabled or not
     *
     * @author radhanatham@riaxe.com
     * @date   10 Sept 2019
     * @return Nothing
     */
    private function svaeProductSettingsRel($productDetails, $productSettingId, $isProductImage, $is3dPreviewAll, $parentProductId)
    {
        foreach ($productDetails as $productD) {
            $ppProdSettRelData = $deletablePids = [];
            if (!empty($productD['product_ids'])) {
                $deletablePids =  array_diff((array) $productD['product_ids'], (array) $productD['skip_product_ids']);
            }
            foreach ($deletablePids as $productId) {
                $this->removeProductSettingsRel($productId);
                // the parent product settings, decoration shared among other product
                if ($parentProductId != $productId) {
                    $this->deleteProductDecorationRel($productId);
                    $ppProdSettRelData[] = [
                        'product_setting_id' => $productSettingId,
                        'product_id' => $productId,
                        'is_3d_preview' => $is3dPreviewAll,
                        'is_product_image' => $isProductImage
                    ];
                }
            }
            // create product settings relation
            if ($ppProdSettRelData) {
                $productSettingsRelInit = new ProductSettingsRel();
                $productSettingsRelInit->insert($ppProdSettRelData);
            }
            // create product category settings relation
            if (!empty($productD['category_id'])) {
                $this->removeProductCategorySettingsRel($productD['category_id']);
                $ppProdCatSettRelData = [
                    'product_setting_id' => $productSettingId,
                    'product_category_id' => $productD['category_id'],
                    'is_3d_preview' => $is3dPreviewAll,
                    'is_product_image' => $isProductImage
                ];
                $productCategorySettingsRelInit = new ProductCategorySettingsRel();
                $productCategorySettingsRelInit->insert($ppProdCatSettRelData);
            }
        }
    }

    /**
     * Get: Delete Product Setting Relation Table
     *
     * @param $productId  Product Id
     *
     * @author radhanatham@riaxe.com
     * @date   10 Sept 2019
     * @return Nothing
     */
    private function removeProductSettingsRel($productId)
    {
        // check if product settings rel exists
        $productSettingsRelInit = new ProductSettingsRel();
        $getproductSettings = $productSettingsRelInit->where('product_id', $productId);
        $totalCounts = $getproductSettings->count();
        if ($totalCounts > 0) {
            // delete product settings relation
            $getproductSettings->delete();
        }
    }

    /**
     * Get: Delete Product Category Setting Relation Table
     *
     * @param $categoryId  Product category id
     *
     * @author radhanatham@riaxe.com
     * @date   10 Sept 2019
     * @return Nothing
     */
    private function removeProductCategorySettingsRel($categoryId)
    {
        // check if product cat settings rel exists
        $productCatSettingsRelInit = new ProductCategorySettingsRel();
        $getproductCatSettings = $productCatSettingsRelInit->where('product_category_id', $categoryId);
        $totalCounts = $getproductCatSettings->count();
        if ($totalCounts > 0) {
            // delete product cat settings rel exists
            $getproductCatSettings->delete();
        }
    }

    /**
     * Get: Get Product Setting
     *
     * @param $productId  Product id
     * @param $productCategory  Product categories id
     *
     * @author radhanatham@riaxe.com
     * @date   10 Sept 2019
     * @return Setting Object
     */
    public function getSettingsIdByProductId($productId, $productCategory)
    {
        // get the settings data from product settings rel
        $settingData = DB::table('product_settings_rel')
            ->join('product_settings', 'product_settings.xe_id', '=', 'product_settings_rel.product_setting_id')
            ->where('product_settings_rel.product_id', '=', $productId)
            ->select([
                'product_settings.product_id', 'product_settings_rel.product_setting_id',
                'product_settings_rel.is_3d_preview', 'product_settings_rel.is_product_image'
            ])->first();
        // if not found - get settings data from product category setting rel
        if (empty($settingData)) {
            $productCategoryIds = array_column($productCategory, 'id');
            $settingData = DB::table('product_category_settings_rel')
                ->join('product_settings', 'product_settings.xe_id', '=', 'product_category_settings_rel.product_setting_id')
                ->whereIn('product_category_settings_rel.product_category_id', $productCategoryIds)
                ->select([
                    'product_settings.product_id', 'product_category_settings_rel.product_setting_id',
                    'product_category_settings_rel.is_3d_preview', 'product_category_settings_rel.is_product_image'
                ])->first();
        }
        return $settingData;
    }

    /**
     * Get: Get Product Configurator Images
     *
     * @param $productId  Product id
     *
     * @author satyabratap@riaxe.com
     * @date   05 Oct 2020
     * @return Setting Object
     */
    private function getConfiguratorImages($productId, $storeID = 1)
    {
        $configuratorImage = [];
        $sectionInit = new ProductSection();
        $sectionImageInit = new ProductSectionImage();
        $isSection = $sectionInit->where('product_id', $productId)->count();

        $sectionImages = [];
        if ($isSection > 0) {
            $sections = $sectionInit->select('xe_id')
                ->where('product_id', $productId)
                ->where('parent_id', 0)
                ->where('is_disable', 0)
                ->get()
                ->toArray();
            if (!empty($sections)) {
                foreach ($sections as $section) {
                    $isSubsection = $sectionInit
                        ->where('parent_id', $section['xe_id'])
                        ->where('is_disable', 0)
                        ->count();
                    $parentImage = $sectionImageInit
                        ->where('section_id', $section['xe_id'])
                        ->where('is_disable', 0)
                        ->count();
                    if ($isSubsection === 0 && $parentImage > 0) {
                        $sectionImages = $sectionImageInit
                            ->where('section_id', $section['xe_id'])
                            ->where('is_disable', 0)
                            ->first();
                    } elseif ($isSubsection > 0 && $parentImage === 0) {
                        $subSectionId = $sectionInit
                            ->where('parent_id', $section['xe_id'])
                            ->where('is_disable', 0)
                            ->first()->xe_id;
                        $countSectionImages = $sectionImageInit
                            ->where('section_id', $subSectionId)
                            ->where('is_disable', 0)
                            ->count();
                        if ($countSectionImages > 0) {
                            $sectionImages = $sectionImageInit
                                ->where('section_id', $subSectionId)
                                ->where('is_disable', 0)
                                ->first();
                        }
                    }
                    if (!empty($sectionImages)) {
                        break;
                    }
                }
            }
        }
        if (!empty($sectionImages)) {
            $sectionImageArr = $sectionImages->get()->toArray();
            foreach ($sectionImageArr as $image) {
                if ($image['cloud_storage'] == 1) {
                    $configuratorImage = [
                        'src' => $this->getS3URL($image['file_name'], $storeID),
                        'thumbnail' => $this->getS3URL($image['thumbnail'], $storeID),
                        'thumb_value' => $sectionImages->thumb_value,
                    ];
                } else {
                    $configuratorImage = [
                        'src' => $sectionImages->file_name,
                        'thumbnail' => $sectionImages->thumbnail,
                        'thumb_value' => $sectionImages->thumb_value,
                    ];
                }
            }
        }
        return $configuratorImage;
    }


    /**
     * Get: Fetch all Product Decoration Detail for Quotation details
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     * @param $returnType     response return type
     *
     * @author malay@riaxe.com
     * @date   29 Dec 2020
     * @return Json
     */
    public function getDecorationDetail($request, $response, $args, $returnType = 0)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [
            'status' => 0,
            'message' => 'Some error occurred while getting product decoration'
        ];
        $getStoreDetails = get_store_details($request);
        $storeId = $getStoreDetails['store_id'];
        $productDecorationSettingData = [];
        $productSideImages = [];
        $getFinalArray = [];
        $getScaleUnit = 0;
        $productId = !empty($args['product_id']) ? $args['product_id'] : null;
        $getSizeData = [];
        /**
         * (#001) Get Product Image Sides from Respective Stores If the
         * store has no product images then, create a blank array with
         * exception error
         */
        $getStoreProduct = $this->getStore()->getProducts($request, $response, [
            'id' => $productId, 'store_id' => $storeId
        ]);
        // do not proceed if product not found
        if (empty($getStoreProduct) || empty($getStoreProduct['products'])) {
            return response($response, [
                'data' => $jsonResponse, 'status' => $serverStatusCode
            ]);
        }
        $getProductDetails = $getStoreProduct['products'];

        $attributeName = $this->getAttributeName();
        if (!empty($getProductDetails['attributes'])) {
            $attrKey = array_search($attributeName['size'], array_column($getProductDetails['attributes'], 'name'));
            if ($attrKey !== false) {
                $getSizeData = $getProductDetails['attributes'][$attrKey]['options'];
            }
        }
        if (!empty($getProductDetails['images'])) {
            $productSideImages = $getProductDetails['images'];
        }
        $productVariantId = $getProductDetails['variant_id'];

        $productDecorationSettingData = [
            'product_id' => $productId,
            'variant_id' => !empty($productVariantId) ? $productVariantId : 0,
            'product_name' => !empty($getProductDetails['name']) ? $getProductDetails['name'] : '',
            'product_description' => $getProductDetails['description'],
            'type' => $getProductDetails['type'],
            'sku' => $getProductDetails['sku'],
            'price' => $getProductDetails['price'],
            'is_variable_decoration' => 0,
            'is_custom_size' => 0,
            'decoration_type' => "",
            'custom_size_unit_price' => "",
            'decoration_dimensions' => "",
            'is_ruler' => 0,
            'is_crop_mark' => 0,
            'is_safe_zone' => 0,
            'crop_value' => 0,
            'safe_value' => 0,
            'is_3d_preview' => 0,
            '3d_object_file' => "",
            '3d_object' => "",
            'scale_unit_id' => $getScaleUnit,
            'is_configurator' => 0,
            'is_product_image' => 0,
            'product_image_id' => 0,
            'is_decoration_exists' => 0,
            'store_images' => $productSideImages,
            'sides' => [],
            'print_profiles' => [],
            'configurator_image' => []
        ];

        if (!empty($getSizeData)) {
            $productDecorationSettingData['size'] = $getSizeData;
        }
        /**
         * Relational Tables by their function names from Model size_variant_id
         */
        $getSettingsAssociatedRecords = $this->productSettingDetails($request, $response, [
            'product_id' => $productId,
            'return_type' => 'array'
        ]);
        if (empty($getSettingsAssociatedRecords)) {
            $defaultDecoData = $this->getDefaultDecoData($productSideImages, $storeId);
            $productDecorationSettingData = array_merge($productDecorationSettingData, $defaultDecoData);
        } else {
            $getFinalArray = $getSettingsAssociatedRecords;
            $productDecorationSettingData['is_variable_decoration'] = $getFinalArray['is_variable_decoration'];
            $productDecorationSettingData['is_custom_size'] = $getFinalArray['is_custom_size'];
            $productDecorationSettingData['decoration_type'] = $getFinalArray['decoration_type'];
            $productDecorationSettingData['custom_size_unit_price'] = $getFinalArray['custom_size_unit_price'];
            $productDecorationSettingData['is_ruler'] = $getFinalArray['is_ruler'];
            $productDecorationSettingData['is_crop_mark'] = $getFinalArray['is_crop_mark'];
            $productDecorationSettingData['is_safe_zone'] = $getFinalArray['is_safe_zone'];
            $productDecorationSettingData['crop_value'] = (float) $getFinalArray['crop_value'];
            $productDecorationSettingData['safe_value'] = (float) $getFinalArray['safe_value'];
            $productDecorationSettingData['is_3d_preview'] = $getFinalArray['is_3d_preview'];
            $productDecorationSettingData['3d_object'] = $getFinalArray['3d_object'];
            $productDecorationSettingData['scale_unit_id'] = $getFinalArray['scale_unit_id'];
            $productDecorationSettingData['is_configurator'] = (isset($getFinalArray['is_configurator'])) ? $getFinalArray['is_configurator'] : 0;
            $productDecorationSettingData['is_decoration_exists'] = 1;
            /**
             * If the DB has it's own image product ID, send product_image_id, or
             * send 0
             */

            $prodImgSettRelObj = new ProductImageSettingsRel();
            $checkForProductImage = $prodImgSettRelObj->where('product_setting_id', $getFinalArray['xe_id'])->first();
            $productImageId = to_int($checkForProductImage['product_image_id']);
            $productDecorationSettingData['product_image_id'] = $productImageId;
            $productDecorationSettingData['is_product_image'] = $productImageId > 0 ? 1 : 0;

            if (!empty($getFinalArray['decoration_dimensions'])) {
                $productDecorationSettingData['decoration_dimensions'] = json_clean_decode($getFinalArray['decoration_dimensions'], true);
            }
            if ($getFinalArray['is_configurator'] == 1) {
                $configuratorImage = $this->getConfiguratorImages($productId);
                $productDecorationSettingData['configurator_image'] = $configuratorImage;
            }

            $decorationObjInit = new DecorationObjects();
            $objFileDetails = $decorationObjInit->select('3d_object_file')->where('product_id', $getFinalArray['product_id'])->first();
            $productDecorationSettingData['3d_object_file'] = !empty($objFileDetails['3d_object_file']) ? $objFileDetails['3d_object_file'] : '';

            // Check if requested array is for Decoration or for variable Decoration
            if (!empty($getFinalArray['sides'])) {
                $productDecorationSettingData['sides'] = $this->getSideImages(
                    $getFinalArray['sides'],
                    $productSideImages,
                    $productDecorationSettingData['product_image_id']
                );
            } else {
                // Get variable decoration settings data
                $varProdDecoData = $this->getVaiableDecoData($getFinalArray['xe_id']);
                $productDecorationSettingData += $varProdDecoData;
            }

            // Processing Print Profiles
            if (!empty($getFinalArray['print_profiles'])) {
                $productDecorationSettingData['print_profiles'] = array_reduce($getFinalArray['print_profiles'], function ($accumulator, $printProfile) {
                    if (!empty($printProfile['profile']['xe_id']) && !empty($printProfile['profile']['name'])) {
                        $accumulator[] = [
                            'id' => $printProfile['profile']['xe_id'],
                            'name' => $printProfile['profile']['name'],
                        ];
                    }
                    return $accumulator;
                });
            }
        }

        $jsonResponse = [
            'status' => 1, 'data' => $productDecorationSettingData
        ];

        if ($returnType == 1) {
            return $jsonResponse;
        }
        return response($response, [
            'data' => $jsonResponse, 'status' => $serverStatusCode
        ]);
    }

    /**
     * Internal: get dafault deco data
     */
    public function getDefaultDecoData($productSideImages, $storeId = 1)
    {
        $decoData = [
            'is_decoration_exists' => 1,
            'scale_unit_id' => 1,
            'configurator_image' => [],
            'print_profiles' => []
        ];
        if (!empty($productSideImages)) {
            $sides = [];
            $printProfiles = [];
            // Check if print profile exist in this ID
            $printProfileInit = new PrintProfileModels\PrintProfile();
            $getPrintProfileInfo = $printProfileInit->where([
                'is_disabled' => 0,
                'store_id' => $storeId
            ])->first();

            $imageSideCount =  count($productSideImages);
            $dimension = '{"x":206,"y":212,"width":175.35,"height":124.05,"type":"rect","path":"","rotate":false,"cx":0,"cy":0,"cw":0,"ch":0,"sx":0,"sy":0,"sw":0,"sh":0}';
            $locations = '{"x_location":0,"y_location":0}';
            //Get print area id
            $defaultPrintArea = DB::table('print_areas')->where([
                'name' => 'A4',
                'store_id' => $storeId
            ]);
            $getDefaultPrintArea = $defaultPrintArea->first();
            $prinAreaId = $getDefaultPrintArea->xe_id;

            if (!empty($getPrintProfileInfo->xe_id)) {
                $printProfile = [
                    'xe_id' => $getPrintProfileInfo->xe_id,
                    'name' => $getPrintProfileInfo->name
                ];
                $decoData['print_profiles'] = [$printProfile];
                for ($j = 1; $j <= $imageSideCount; $j++) {
                    $printProfiles[] = $printProfile;
                }
            }
            for ($i = 0; $i < $imageSideCount; $i++) {
                $sides[] = [
                    "xe_id" => $i + 1,
                    "side_name" => "Side " . ($i + 1),
                    "side_index" => null,
                    "dimension" => "",
                    "locations" => null,
                    "is_disable_design" => 0,
                    "is_visible" => 1,
                    "crop_value" => null,
                    "safe_value" => null,
                    "image" => [
                        "id" => 1,
                        "src" => $productSideImages[$i]['src'],
                        "thumbnail" => $productSideImages[$i]['thumbnail']
                    ],
                    "product_decoration_setting" => [[
                        'xe_id' => 1,
                        'name' => "Front",
                        "dimension" => $dimension,
                        "locations" => $locations,
                        "is_disable_design" => 0,
                        "sub_print_area_type" => "normal_size",
                        "min_height" => null,
                        "max_height" => null,
                        "min_width" => null,
                        "max_width" => null,
                        "is_border_enable" => 0,
                        "is_sides_allow" => 0,
                        "print_area_id" => $prinAreaId,
                        "print_profile_decoration_settings" => [
                            ["print_profile" => $printProfiles]
                        ]
                    ]]
                ];
            }
            $decoData['sides'] = $sides;
        }

        return $decoData;
    }

    /**
     * Internal: get side images
     */
    private function getSideImages($productSides, $productSideImages, $productImageId = 0)
    {
        $doExistProdImgSetts = 0;
        if ($productImageId) {
            $prodImgSettRelGtInit = new ProductImageSettingsRel();
            $doExistProdImgSetts = $prodImgSettRelGtInit->where('product_image_id', $productImageId)->count();
        }

        foreach ($productSides as $sideKey => $side) {
            if ($doExistProdImgSetts == 0 && !empty($productSideImages[$sideKey])) {
                // Get Product Image Sides from Respective Stores
                /**
                 * In the section #001, we got all images from Store
                 * end. There may be multiple images. Each image belongs
                 * to one side Programatically, we get each side by the
                 * foreach loop key's index
                 */
                $productSides[$sideKey]['image'] = $productSideImages[$sideKey];
                continue;
            }
            $prodImageSideObj = new ProductImageSides();
            $getProductImageSides = $prodImageSideObj->where('product_image_id', $productImageId)->get();
            // Get Product Image Sides from DB
            if (!empty($getProductImageSides[$sideKey])) {
                $getProductImageSideData = $getProductImageSides[$sideKey];
                $productSides[$sideKey]['image'] = [
                    'id' => $getProductImageSideData->xe_id,
                    'src' => $getProductImageSideData->file_name,
                    'thumbnail' => $getProductImageSideData->thumbnail,
                ];
            }
        }
        return $productSides;
    }
    /**
     * Internal: get variable deco data
     */
    private function getVaiableDecoData($productSettingId)
    {
        $varProdDecoData = [];
        // get the decoration setting details
        $getProductDecorationSetting = ProductDecorationSetting::where('product_setting_id', $productSettingId)->first();
        if (!empty($getProductDecorationSetting)) {
            // Get print area and print area type
            $printAreaObj = new PrintArea();
            $getPrintAreaDetails = $printAreaObj->where(
                'xe_id',
                $getProductDecorationSetting['print_area_id']
            )
                ->with('print_area_type')
                ->get();

            $printAreaDetails = $getPrintAreaDetails->toArray();
            $printArea = [];
            if (!empty($printAreaDetails)) {
                $path = "";
                $typeName = "";
                if (!empty($printAreaDetails[0]['print_area_type'])) {
                    $typeName = $printAreaDetails[0]['print_area_type']['name'];
                }
                $path = $printAreaDetails[0]['file_name'];
                $printArea = array(
                    'id' => $printAreaDetails[0]['xe_id'],
                    'name' => $printAreaDetails[0]['name'],
                    'type' => $typeName,
                    'height' => $printAreaDetails[0]['height'],
                    'width' => $printAreaDetails[0]['width'],
                    'path' => $path,
                );
            }
            // End
            // format the decoration data
            $varProdDecoData = [
                'product_decoration' => [
                    'dimension' => json_clean_decode($getProductDecorationSetting['dimension'], true),
                    'locations' => json_clean_decode($getProductDecorationSetting['locations'], true),
                    'bleed_mark_data' => json_clean_decode($getProductDecorationSetting['bleed_mark_data'], true),
                    'shape_mark_data' => json_clean_decode($getProductDecorationSetting['shape_mark_data'], true),
                    'is_disable_design' => $getProductDecorationSetting['is_disable_design'],
                    'bound_price' => $getProductDecorationSetting['custom_bound_price'],
                    'is_border_enable' => $getProductDecorationSetting['is_border_enable'],
                    'is_sides_allow' => $getProductDecorationSetting['is_sides_allow'],
                    'no_of_sides' => $getProductDecorationSetting['no_of_sides'],
                    'print_area_id' => $getProductDecorationSetting['print_area_id'],
                    'is_image_overlay' => $getProductDecorationSetting['image_overlay'],
                    'overlay_image' => !empty($getProductDecorationSetting['overlay_file_name']) ? path('read', 'overlay') . $getProductDecorationSetting['overlay_file_name'] : "",
                    'print_area' => $printArea
                ]
            ];

            if (!empty($getProductDecorationSetting['pre_defined_dimensions'])) {
                $varProdDecoData['product_decoration']['is_pre_defined'] = 1;
                $varProdDecoData['product_decoration']['pre_defined_dimensions'] = json_clean_decode($getProductDecorationSetting['pre_defined_dimensions'], true);
            } elseif (!empty($getProductDecorationSetting['user_defined_dimensions'])) {
                $varProdDecoData['product_decoration']['is_pre_defined'] = 0;
                $varProdDecoData['product_decoration']['user_defined_dimensions'] = json_clean_decode($getProductDecorationSetting['user_defined_dimensions'], true);
            }
        }
        return $varProdDecoData;
    }
    /**
     * GET: Banner product custom size
     * @param $productId
     * @author soumyas@riaxe.com
     * @date   28 September 2022
     * @return Array
     */
    private function getTierCustomSize($productId)
    {
        $customSizeData = [];
        $productSettingInit = new ProductSetting();
        $getProductSetting = $productSettingInit->select('custom_size')->where(['product_id' => $productId])->first();
        if ($getProductSetting->count() > 0) {
            $getProductData =  $getProductSetting->toArray();
            $customSizeData = json_clean_decode($getProductData['custom_size'], true);
        }
        return $customSizeData;
    }
    /**
     * Update the bigcommerce cache file for webhook call
     * @param $productId
     * @author pansy@imprintnext.com
     * @date   13 Jan 2023
     */

    public function updateBigCommerceCacheFile($request, $response, $args)
    {
        $pdetails = $this->getStore()->saveProductAPIasCache($args['pid']);
        $product = json_decode($pdetails, true);
        $resourceId = $args['pid'] . '_' . '_' . $product['data']['date_modified'];
        $resourceType = "store/product/updated";
        $conn = new mysqli(API_DB_HOST, API_DB_USER, API_DB_PASS, API_DB_NAME);
        if (!$conn) {
            error_log("Connection failed: " . $conn->connect_error);
            return 0;
        }
        $id_count = "SELECT `resource_id` FROM `big_webhook_data` WHERE `resource_id` = '$resourceId' LIMIT 1";
        $result = mysqli_query($conn, $id_count);
        if (($result->num_rows <= 0)) {
            $sql = "INSERT INTO `big_webhook_data` (`xe_id`,`resource_type`, `resource_id`) VALUES (NULL,'$resourceType','$resourceId')";
            mysqli_query($conn, $sql);
        }

        return  $this->getStore()->saveProductAPIasCache($args['pid']);
    }

    /**
     * gte setting data
     * @param $request
     * @param $response
     * @param $settingKeyArray
     *
     * @author steve@imprintnext.com
     * @date   17th june 2023
     */

    private function getSettingsAssociatedRecords($request, $response, $settingKeyArray)
    {
        $getSettingsAssociatedRecords = $settingKeyArray['getSettingsAssociatedRecords'];
        $import3DPreview = $settingKeyArray['import3DPreview'];
        $importedDecoration = $settingKeyArray['importedDecoration'];
        $storeId = $settingKeyArray['storeId'];
        $importProductImage = $settingKeyArray['importProductImage'];
        $productId =  $settingKeyArray['productId'];
        $getStoreProduct = $settingKeyArray['getStoreProduct'];
        $importedProductId = $settingKeyArray['importedProductId'];
        $productSideImages = $settingKeyArray['productSideImages'];
        $currentStoreUrl = $settingKeyArray['currentStoreUrl'];
        $type = $settingKeyArray['type'];
        $source = $settingKeyArray['source'];

        $getFinalArray = $getSettingsAssociatedRecords;

        if ($import3DPreview == 1 || !$importedDecoration) {
            $decorationObjInit = new DecorationObjects();
            $objFileDetails = $decorationObjInit->where('product_id', $getFinalArray['product_id'])->select('3d_object_file', 'cloud_storage')->first();
            $objFile = $objFileDetails['3d_object_file'];
            if ($objFileDetails['cloud_storage'] == 1) {
                $objFile = $this->getS3URL($objFile, $storeId);
            }
        }

        /**
         * If the DB has it's own image product ID, send product_image_id, or send 0
         */
        if ($importProductImage == 1 || !$importedDecoration) {
            $prodImgSettRelObj = new ProductImageSettingsRel();
            $checkForProductImage = $prodImgSettRelObj->where('product_setting_id', $getFinalArray['xe_id'])->first();
            $hasProdImgId = to_int($checkForProductImage['product_image_id']);
        }

        // Get App unit name
        $getScaleUnit = $this->getAppUnit($getFinalArray['scale_unit_id'], 'label');
        $getScaleUnitName = $this->getAppUnit($getFinalArray['scale_unit_id'], 'name');
        // Build Product Settings Array product_image_id
        $productDecorationSettingData = [
            'id' => $getFinalArray['xe_id'],
            'product_id' => $productId,
            'is_variable_decoration' => $getFinalArray['is_variable_decoration'],
            'is_custom_size' => $getFinalArray['is_custom_size'],
            'decoration_type' => $getFinalArray['decoration_type'],
            'custom_size_unit_price' => $getFinalArray['custom_size_unit_price'],
            'product_name' => $getStoreProduct['name'],
            'price' => (float) $getStoreProduct['price'],
            'tax' => $getStoreProduct['tax'] ? $getStoreProduct['tax'] : 0,
            'is_ruler' => $getFinalArray['is_ruler'],
            'is_crop_mark' => $getFinalArray['is_crop_mark'],
            'is_safe_zone' => $getFinalArray['is_safe_zone'],
            'crop_value' => (float) $getFinalArray['crop_value'],
            'safe_value' => (float) $getFinalArray['safe_value'],
            'is_3d_preview' => $getFinalArray['is_3d_preview'],
            '3d_object_file' => !empty($objFile) ? $objFile : $getFinalArray['3d_object_file'],
            '3d_object' => $getFinalArray['3d_object'],
            'scale_unit_id' => $getScaleUnit,
            'print_unit' => $getScaleUnitName,
            'is_configurator' => (isset($getFinalArray['is_configurator'])) ? $getFinalArray['is_configurator'] : 0,
            'is_product_image' => $hasProdImgId > 0 ? 1 : 0,
            'attributes' => $getStoreProduct['attributes'],
            'tier_prices' => isset($getStoreProduct['tier_prices']) ? $getStoreProduct['tier_prices'] : [],
            'is_svg_configurator' => $getFinalArray['is_svg_configurator'],
            'is_increment' => $getFinalArray['is_increment'],
            'increment_values' => json_clean_decode($getFinalArray['increment_values'], true),
            'print_profiles' => [],
            'imported_product_id' => $importedProductId,
            'is_price_rule' => 0,
            'is_prod_desc' => !empty($getFinalArray['is_prod_desc']) ? $getFinalArray['is_prod_desc'] : null,
            'is_applied_color' => $getFinalArray['is_applied_color'],
            'is_applied_pattern' => $getFinalArray['is_applied_pattern'],
            'is_prod_rotate' => $getFinalArray['is_prod_rotate'],
            'is_use_full_width' => $getFinalArray['is_use_full_width'] ? $getFinalArray['is_use_full_width'] : 0,
        ];
        // Process Price Data
        $priceInit = new AttributePriceRule();
        $getPriceData = $priceInit->where(['product_id' => $productId])->first();
        if (!empty($getPriceData)) {
            $productDecorationSettingData['is_price_rule'] = 1;
        }
        if (!empty($getFinalArray['decoration_dimensions'])) {
            $productDecorationSettingData['decoration_dimensions'] = json_clean_decode($getFinalArray['decoration_dimensions'], true);
        }
        /*get custom size*/
        if ($getFinalArray['decoration_type'] == "banner" && $getFinalArray['is_variable_decoration'] == 1) {
            $productDecorationSettingData['custom_size_tier_prices'] = $this->getTierCustomSize($getFinalArray['product_id']);
        }
        $configuratorImage = [];
        if ($getFinalArray['is_configurator'] == 1) {
            if ($importedDecoration) {
                // Get Product Configurator Image
                $configuratorImage = $this->getConfiguratorImages($importedProductId);
            } else {
                // Get Product Configurator Image
                $configuratorImage = $this->getConfiguratorImages($productId);
            }
        }
        if ($productDecorationSettingData['is_svg_configurator'] == 1) {
            $configuratorInit = new ProductConfiguratorController();
            if ($importedDecoration) {
                $configuratorData = $configuratorInit->getSVGProductConfigurator($request, $response, [
                    'product_id' => $importedProductId, 'isReturn' => true
                ]);
            } else {
                $configuratorData = $configuratorInit->getSVGProductConfigurator($request, $response, [
                    'product_id' => $productId, 'isReturn' => true
                ]);
            }
            if (!empty($configuratorData) && !empty($configuratorData[0]['side_list'])) {
                $configuratorImage = $configuratorData[0]['side_list'];
            }
        }
        $productDecorationSettingData['configurator_image'] = $configuratorImage;
        $decorationObjInit = new DecorationObjects();
        if ($getFinalArray['is_3d_preview']) {
            $objFileDetails = $decorationObjInit->where('product_id', $getFinalArray['product_id'])->select(['3d_object_file', 'cloud_storage'])->first();
            if (!empty($objFileDetails->{'3d_object_file'})) {
                $objFile = $objFileDetails->{'3d_object_file'};
                if ($objFileDetails['cloud_storage'] == 1) {
                    $objFile = $this->getS3URL($objFile, $storeId);
                }
                $productDecorationSettingData['3d_object_file'] = $objFile;
            }
        }

        $prodImgSideObj = new ProductImageSides();
        $getProductImageSides = $prodImgSideObj->where('product_image_id', $checkForProductImage['product_image_id'])->with('product_image')->get();

        // Check if requested array is for Decoration or for variable Decoration
        if (!empty($getFinalArray['sides'])) {
            $storeImageCount = count($productSideImages);
            // default = setting's side count
            $imageSideCount = count($getFinalArray['sides']);
            // For SVG configurator section sides is coming from only databse.
            // 1st priority is configuration side
            if (!empty($configuratorImage)) {
                $imageSideCount = count($configuratorImage);
            } else {
                if (!$hasProdImgId) {
                    $imageSideCount = $storeImageCount;
                }
            }
            $settingKeyDataArray['getFinalArray'] = $getFinalArray;
            $settingKeyDataArray['imageSideCount'] = $imageSideCount;
            $settingKeyDataArray['hasProdImgId'] = $hasProdImgId;
            $settingKeyDataArray['productDecorationSettingData'] = $productDecorationSettingData;
            $settingKeyDataArray['productSideImages'] = $productSideImages;
            $settingKeyDataArray['storeId'] = $storeId;
            $settingKeyDataArray['getProductImageSides'] = $getProductImageSides;
            $productDecorationSettingData = $this->getproductSettingData($settingKeyDataArray);
        } else {
            // Get variable decoration settings data
            $varProdDecoData = $this->getVaiableDecoData($getFinalArray['xe_id']);
            $productDecorationSettingData += $varProdDecoData;
        }
        if ($storeId > 1 && $type == 'tool' && $source != 'admin' && IS_HOSTED == 0) {
            foreach ($productDecorationSettingData['sides'] as $key => $value) {
                $hostname = parse_url($value['image']['src'], PHP_URL_HOST); //hostname
                $productDecorationSettingData['sides'][$key]['image']['src'] = str_replace($hostname, $currentStoreUrl, $value['image']['src']);
                $productDecorationSettingData['sides'][$key]['image']['thumbnail'] = str_replace($hostname, $currentStoreUrl, $value['image']['thumbnail']);
            }
        }
        // Processing Print Profiles
        if (!empty($getFinalArray['print_profiles'])) {
            // get the print profile array
            $productDecorationSettingData['print_profiles'] = array_reduce($getFinalArray['print_profiles'], function ($accumulator, $printProfile) use ($storeId) {
                $printProfileThumb = $printProfile['profile']['thumbnail'];
                // add to result if id, name exists
                if (!empty($printProfile['profile']['xe_id']) && !empty($printProfile['profile']['name'])) {
                    $accumulator[] = [
                        'id' => $printProfile['profile']['xe_id'],
                        'name' => $printProfile['profile']['name'],
                        'thumbnail' => ($printProfile['profile']['cloud_storage'] == 1)
                            ? $this->getS3URL($printProfileThumb, $storeId) : $printProfileThumb,
                        'description' => !empty($printProfile['profile']['description'])
                            ? $printProfile['profile']['description'] : "",
                    ];
                }
                return $accumulator;
            });
        }
        //$settingData = $productDecorationSettingData;
        return $productDecorationSettingData;
    }

    /**
     * gte setting data
     * @param $settingKeyDataArray
     *
     * @author steve@imprintnext.com
     * @date   17th june 2023
     */

    private function getproductSettingData($settingKeyDataArray)
    {
        $productDecorationSides = [];
        $getFinalArray = $settingKeyDataArray['getFinalArray'];
        $imageSideCount = $settingKeyDataArray['imageSideCount'];
        $hasProdImgId = $settingKeyDataArray['hasProdImgId'];
        $productDecorationSettingData = $settingKeyDataArray['productDecorationSettingData'];
        $productSideImages = $settingKeyDataArray['productSideImages'];
        $storeId = $settingKeyDataArray['storeId'];
        $getProductImageSides = $settingKeyDataArray['getProductImageSides'];

        $i = 1;
        foreach ($getFinalArray['sides'] as $sideKey => $side) {
            // Build Product Side Array
            if ($i <= $imageSideCount) {
                $productDecorationSides = [
                    'name' => $side['side_name'],
                    'is_visible' => $side['is_visible'],
                    'is_image_overlay' => $side['image_overlay'],
                    'overlay_image' => !empty($side['overlay_file_name']) ? path('read', 'overlay') . $side['overlay_file_name'] : "",
                    'image' => [],
                    'decoration_settings' => []
                ];

                if (!$hasProdImgId && !empty($productSideImages[$sideKey])) {
                    // Get Product Image Sides from Respective Stores
                    /**
                     * In the section #001, we got all images from Store
                     * end. There may be multiple images. Each image belongs
                     * to one side Programatically, we get each side by the
                     * foreach loop key's index
                     */
                    $productDecorationSides['image'] = $productSideImages[$sideKey];
                } else {
                    // Get Product Image Sides from DB
                    if (!empty($getProductImageSides[$sideKey])) {
                        $getProductImageSideData = $getProductImageSides[$sideKey];
                        $fileName = $getProductImageSideData->file_name;
                        $thumbnail = $getProductImageSideData->thumbnail;
                        if ($getProductImageSideData->product_image->cloud_storage == 1) {
                            $fileName = $this->getS3URL($fileName, $storeId);
                            $thumbnail = $this->getS3URL($thumbnail, $storeId);
                        }
                        $productDecorationSides['image'] = [
                            'id' => $getProductImageSideData->xe_id,
                            'src' => $fileName,
                            'thumbnail' => $thumbnail
                        ];
                    }
                }
                // Loop through, Product Decoration Settings
                if (!empty($side['product_decoration_setting'])) {
                    foreach ($side['product_decoration_setting'] as $decorationSetting) {
                        $decorationPrintProfiles = $printArea = [];

                        // Get print area and print area type
                        $printAreaObj = new PrintArea();
                        $printAreaDetails = $printAreaObj->where('xe_id', $decorationSetting['print_area_id'])
                            ->with('print_area_type')
                            ->first();
                        if (!empty($printAreaDetails)) {
                            $printArea = [
                                'id' => $printAreaDetails->xe_id,
                                'name' => $printAreaDetails->name,
                                'type' => !empty($printAreaDetails->print_area_type) ? $printAreaDetails->print_area_type->name : '',
                                'height' => $printAreaDetails->height,
                                'width' => $printAreaDetails->width,
                                'path' => $printAreaDetails->file_name
                            ];
                        }
                        // Loop through, Print Profile Decoration Setting
                        array_walk($decorationSetting['print_profile_decoration_settings'], function ($ppDecoSetting) use (&$decorationPrintProfiles) {
                            if (!empty($ppDecoSetting['print_profile'][0]['xe_id']) && !empty($ppDecoSetting['print_profile'][0]['name'])) {
                                $decorationPrintProfiles[] = [
                                    'id' => $ppDecoSetting['print_profile'][0]['xe_id'],
                                    'name' => $ppDecoSetting['print_profile'][0]['name'],
                                ];
                            }
                        });

                        $sidesDecorationSetting = [
                            'name' => $decorationSetting['name'],
                            'dimension' => $decorationSetting['dimension'],
                            'locations' => $decorationSetting['locations'],
                            'is_disable_design' => $decorationSetting['is_disable_design'],
                            'bleed_mark_data' => $decorationSetting['bleed_mark_data'],
                            'shape_mark_data' => $decorationSetting['shape_mark_data'],
                            'print_area' => $printArea,
                            'print_profiles' => $decorationPrintProfiles,
                            'default_print_profile' => $decorationSetting['default_pp_id'] ? $decorationSetting['default_pp_id'] : 0
                        ];
                        if ($getFinalArray['is_variable_decoration'] == 1) {
                            $sidesDecorationSetting += [
                                'min_height' => $decorationSetting['min_height'],
                                'max_height' => $decorationSetting['max_height'],
                                'min_width' => $decorationSetting['min_width'],
                                'max_width' => $decorationSetting['max_width'],
                                'is_border_enable' => $decorationSetting['is_border_enable'],
                                'is_sides_allow' => $decorationSetting['is_sides_allow']
                            ];
                        }
                        $productDecorationSides['decoration_settings'][] = $sidesDecorationSetting;
                    }
                }
                $productDecorationSettingData['sides'][] = $productDecorationSides;
                $i++;
            }
        } // End of foreach print_area_id

        return $productDecorationSettingData;
    }

    /**
     * gte setting data
     * @param $productSideImages
     * @param $storeId
     * @param $getStoreProduct
     * @param $args
     *
     * @author steve@imprintnext.com
     * @date   17th june 2023
     */

    private function getDefaultDecorationeData($productSideImages, $storeId, $getStoreProduct, $args)
    {
        $sides = [];
        if (!empty($productSideImages)) {
            $dimension = '{"x":206,"y":212,"width":175.35,"height":124.05,"type":"rect","path":"","rotate":false,"cx":0,"cy":0,"cw":0,"ch":0,"sx":0,"sy":0,"sw":0,"sh":0}';
            $locations = '{"x_location":0,"y_location":0}';
            $printProfile = $printArea = [];
            // get the print profile
            $printProfileInit = new PrintProfileModels\PrintProfile();
            $getPrintProfileInfo = $printProfileInit->where(['is_disabled' => 0, 'store_id' => $storeId])->first();
            if (!empty($getPrintProfileInfo->xe_id)) {
                $printProfile[] = [
                    'id' => $getPrintProfileInfo->xe_id,
                    'name' => $getPrintProfileInfo->name
                ];
            }
            // Get print area and print area type
            $defaultPrintAreaId = 4;
            $printAreaObj = new PrintArea();
            $printAreaDetails = $printAreaObj->where('xe_id', $defaultPrintAreaId)->with('print_area_type')->first();
            if (!empty($printAreaDetails)) {
                $printArea = [
                    'id' => $printAreaDetails->xe_id,
                    'name' => $printAreaDetails->name,
                    'type' => !empty($printAreaDetails->print_area_type) ? $printAreaDetails->print_area_type->name : '',
                    'height' => $printAreaDetails->height,
                    'width' => $printAreaDetails->width,
                    'path' => $printAreaDetails->file_name
                ];
            }
            $imageSide = count($productSideImages);
            for ($i = 0; $i < $imageSide; $i++) {
                $sides[] = [
                    'name' => 'Side ' . $i + 1,
                    'is_visible' => 1,
                    'is_image_overlay' => 0,
                    'overlay_image' => '',
                    'image' => [
                        'src' => $productSideImages[$i]['src'],
                        'thumbnail' => $productSideImages[$i]['thumbnail']
                    ],
                    'decoration_settings' => [[
                        'name' => 'Front',
                        'dimension' => $dimension,
                        'locations' => $locations,
                        'is_disable_design' => 0,
                        'print_area' => $printArea,
                        'print_profiles' => $printProfile
                    ]]
                ];
            }
        }
        $printProfiles = [];
        if (!empty($getPrintProfileInfo->xe_id)) {
            $printProfiles[] = [
                'id' => $getPrintProfileInfo->xe_id,
                'name' => $getPrintProfileInfo->name,
                'thumbnail' => $getPrintProfileInfo->thumbnail,
                'description' => !empty($getPrintProfileInfo->description) ? $getPrintProfileInfo->description : '',
            ];
        }
        // Get App unit name
        $getScaleUnit = $this->getAppUnit(0, 'label');
        $getScaleUnitName = $this->getAppUnit(0, 'name');
        // Build Product Settings Array product_image_id
        $productDecorationSettingData = [
            'id' => 1,
            'product_id' => $args['product_id'],
            'is_variable_decoration' => 0,
            'is_custom_size' => 0,
            'decoration_type' => null,
            'custom_size_unit_price' => 0,
            'product_name' => $getStoreProduct['name'],
            'price' => (float)$getStoreProduct['price'],
            'tax' => $getStoreProduct['tax'] ? $getStoreProduct['tax'] : 0,
            'is_ruler' => 0,
            'is_crop_mark' => 0,
            'is_safe_zone' => 0,
            'crop_value' => 0,
            'safe_value' => 0,
            'is_3d_preview' => 0,
            '3d_object_file' => '',
            '3d_object' => '{}',
            'scale_unit_id' => $getScaleUnit,
            'print_unit' => $getScaleUnitName,
            'is_configurator' => 0,
            'is_product_image' => 0,
            'attributes' => $getStoreProduct['attributes'],
            'tier_prices' => isset($getStoreProduct['tier_prices']) ? $getStoreProduct['tier_prices'] : [],
            'configurator_image' => [],
            'sides' => array_values($sides),
            'is_price_rule' => 0,
            'print_profiles' => $printProfiles,
            'is_svg_configurator' => 0,
            'imported_product_id' => "",
            'is_use_full_width' => 0
        ];
        return $productDecorationSettingData;
    }

    /**
     * Get: Get product settings details along with other related records
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     *
     * @author steve@imprintnext.com
     * @date   22 Aug 2024
     * @return Array
     */
    public function productOptionsBaseSettingDetails($request, $response, $args)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [
            'status' => 0,
            'data' => [],
            'message' => message('Settings Details', 'error')
        ];

        $settingsDetail = [];
        $getStoreDetails = get_store_details($request);
        $storeId = $getStoreDetails['store_id'];
        $productId = $args['product_id'];
        $returnType = !empty($args['return_type']) ? $args['return_type'] : 'json';

        $optionSettingIds = !empty($args['option_setting_ids']) ? $args['option_setting_ids'] : [];
        $prodSettingObj = new ProductSetting();
        $settingsAssocRecords = $prodSettingObj->with('sides');
        $settingsAssocRecords->with('sides.product_decoration_setting');
        $settingsAssocRecords->with('sides.product_decoration_setting.print_profile_decoration_settings');
        $settingsAssocRecords->with('sides.product_decoration_setting.print_profile_decoration_settings.print_profile');
        $settingsAssocRecords->with('sides.product_decoration_setting.print_area');
        $settingsAssocRecords->with('print_profiles', 'print_profiles.profile');
        $settingsAssocRecords->where('store_id', '=', $storeId);
        $settingsAssocRecords->wherein('xe_id', $optionSettingIds);

        if ($settingsAssocRecords->count() > 0) {
            $settingsDetail = $settingsAssocRecords->orderBy('xe_id', 'desc')->get()->toArray();
            $jsonResponse = [
                'status' => 1,
                'data' => $settingsDetail
            ];
        }
        if ($returnType == 'json') {
            return response($response, [
                'data' => $jsonResponse, 'status' => $serverStatusCode
            ]);
        }
        return $settingsDetail;
    }

     /**
     * Save: Optiona Based Product setting
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     * @param $returnType     response return type
     *
     * @author steve@imprintnext.com
     * @date   21 Aug 2024
     * @return Json
     */
    public function saveOptionBasedProductDecorations($request, $response){

        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [
            'status' => 0,
            'message' => message('Decoration Setting', 'error')
        ];

        $isProductImage = $is3dPreviewAll = 0;
        $allPostPutVars = $request->getParsedBody();

        $getProdDecoInfoArray = !empty($allPostPutVars['decorations']) ? json_clean_decode($allPostPutVars['decorations'], true) : null;

        $replaceExisting = (int)!empty($allPostPutVars['replace'])
        ? $allPostPutVars['replace'] : 0;
        $storeId = $allPostPutVars['store_id'] ? $allPostPutVars['store_id'] : 1;


        $prodSettInit = new ProductSetting();
        $pid = $getProdDecoInfoArray[0]['product_id'];

        // Clear old records if replace is set to 1
        $checkRecord = $prodSettInit->where([
            'product_id' => $pid,
            'store_id' => $storeId
        ]);

        if ($checkRecord->count() > 0) {
            $checkRecord->delete();
        }

        $optionSettingRelObj = new productOptionSettingRel();

        $optionDeleteObj = $optionSettingRelObj->where('product_id', $pid);
        if ($optionDeleteObj->count() > 0) {
            $optionDeleteObj->delete();
        }

        foreach ($getProdDecoInfoArray as $key => $getProdDecoInfoAValue) {
            $getProdDecoInfo = $getProdDecoInfoAValue;
            $isVariableDecoration = !empty($getProdDecoInfo['is_variable_decoration'])
            ? $getProdDecoInfo['is_variable_decoration'] : 0;
            $uploadedFiles = $request->getUploadedFiles();
            $optionId = !empty($getProdDecoInfo['option_id']) ? $getProdDecoInfo['option_id'] : '';
            $optionValue = !empty($getProdDecoInfo['option_value']) ? $getProdDecoInfo['option_value'] : '';


            // if ($checkRecord->count() > 0) {
            //     if ($replaceExisting != 1) {
            //         $jsonResponse = [
            //             'status' => 0,
            //             'message' => message('Variable Decoration', 'exist')
            //         ];
            //         return response($response, [
            //             'data' => $jsonResponse,
            //             'status' => OPERATION_OKAY
            //         ]);
            //     }

            //     // if(!$isOptionPrintArea){
            //     //     $checkRecord->delete();
            //     // }

            // }

            // Save Product Decorations
            $prodSettInsId = $this->saveProductSetting($getProdDecoInfo, $storeId);


            $optionSettingArray = [
                "product_id" => $pid,
                "option_id" => $optionId,
                "option_value" => strtolower($optionValue),
                "product_setting_id" => $prodSettInsId
            ];

            $optionSettingSave = new productOptionSettingRel($optionSettingArray);
            $optionSettingSave->save();


            /**
             * Processing for Table: print_profile_product_setting_rel
             * - For saving the outer Print profile Ids
             */

            if (!empty($prodSettInsId) && !empty($getProdDecoInfo['print_profile_ids'])) {
                $this->setProductPrintProfileRel($prodSettInsId, $getProdDecoInfo['print_profile_ids']);
            }

            if (!empty($getProdDecoInfo['is_product_image_all'])) {
                $isProductImage = 1;
            }
            if (!empty($getProdDecoInfo['is_3d_preview_all'])) {
                $is3dPreviewAll = 1;
            }
            if (!empty($prodSettInsId)) {
                if (!empty($getProdDecoInfo['product_setting'])) {
                    $this->svaeProductSettingsRel(
                        $getProdDecoInfo['product_setting'],
                        $prodSettInsId,
                        $isProductImage,
                        $is3dPreviewAll,
                        $getProdDecoInfo['product_id']
                    );
                }
                $jsonResponse = [
                    'status' => 1,
                    'product_settings_insert_id' => $prodSettInsId,
                    'message' => message('Product Decoration Setting', 'saved')
                ];
            }
            if (strtolower(STORE_NAME) == "shopify") {
                $this->getStore()->saveProductAPIasCache($getProdDecoInfo['product_id']);
            }

            if ($isVariableDecoration === 1) {
                // Process for variable decoration area
                $variableDecoResp = $this->saveVariableProductDecoration(
                    $getProdDecoInfo,
                    $uploadedFiles,
                    $storeId,
                    $replaceExisting,
                    false
                );
                return response($response, [
                    'data' => $variableDecoResp['response'],
                    'status' => $variableDecoResp['server_status_code']
                ]);
            }
        }
        return $jsonResponse;
    }

    /**
     * Get: Fetch all Product Decoration Settings
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     * @param $returnType     response return type
     *
     * @author steve@imprintnext.com
     * @date   21 Aug 2024
     * @return Json
     */

    public function getProductOptionsDecorations($request, $response, $args, $returnType = 0)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [];
        $productDecorationSettingData = [];
        $productSideImages = [];
        $getFinalArray = [];
        $getScaleUnit = 0;
        $productId = !empty($args['product_id']) ? $args['product_id'] : null;
        $storeId = $request->getQueryParam('store_id');
        $is3dPreviewAll = $isProductImage = $isDecoration = 0;
        $productImgId = 0;
        $importedProductId = '';
        /**
         * (#001) Get Product Image Sides from Respective Stores If the
         * store has no product images then, create a blank array with
         * exception error
         */
        $getStoreProduct = $this->getStore()->getProducts($request, $response, [
            'id' => $productId
        ]);
        // do not proceed if product not found
        if (empty($getStoreProduct) || empty($getStoreProduct['products'])) {
            return response($response, [
                'data' => $jsonResponse,
                'status' => $serverStatusCode
            ]);
        }
        /**
         * Relational Tables by their function names from Model size_variant_id
         */
        // $getSettingsAssociatedRecords = $this->productSettingDetails($request, $response, [
        //     'product_id' => $productId,
        //     'return_type' => 'array'
        // ]);



        $optionSettingRelObj = new productOptionSettingRel();
        $optionsSettingData = $optionSettingRelObj->where('product_id', $productId);
        if ($optionsSettingData->count() > 0) {
            $optionSettingData = $optionsSettingData->get()->toArray();
            $optionSettingIds = array_column($optionSettingData, 'product_setting_id');
        }


        $optionBasedSettings = $this->productOptionsBaseSettingDetails($request, $response, [
            'product_id' => $productId,
            'return_type' => 'array',
            'option_setting_ids' => $optionSettingIds
        ]);
        //print_r($optionBasedSettings); exit;
        // get the store attributes
        $getProductDetails = $getStoreProduct['products'];
        $getSizeData = $this->getProductAttributeOption($getProductDetails['attributes'], 'size');

        $optionSettings = [];
        foreach ($optionBasedSettings as $key => $optionBasedSettingsvalue) {
            $settingId = $optionBasedSettingsvalue['xe_id'];
            $OptionSettingIndex = array_search($settingId, $optionSettingIds);
            $optionId = $optionSettingData[$OptionSettingIndex]['option_id'];
            $optionValue = $optionSettingData[$OptionSettingIndex]['option_value'];
            // product images
            $productSideImages = $getProductDetails['images'];
            // product variant id
            $productVariantId = $getProductDetails['variant_id'];


            $productDecorationSettingData = [
                'product_id' => $productId,
                //'variant_id' => !empty($productVariantId) ? $productVariantId : 0,
                'product_name' => !empty($getProductDetails['name']) ? $getProductDetails['name'] : '',
                'type' => $getProductDetails['type'],
                //'sku' => $getProductDetails['sku'],
                //'price' => $getProductDetails['price'],
                'is_variable_decoration' => 0,
                'is_custom_size' => 0,
                'decoration_type' => "",
                'custom_size_unit_price' => "",
                'decoration_dimensions' => "",
                'is_ruler' => 0,
                'is_crop_mark' => 0,
                'is_safe_zone' => 0,
                'crop_value' => 0,
                'safe_value' => 0,
                'is_3d_preview' => 0,
                '3d_object_file' => "",
                '3d_object' => "",
                'scale_unit_id' => $getScaleUnit,
                'is_configurator' => 0,
                'is_product_image' => 0,
                'product_image_id' => 0,
                'is_decoration_exists' => 0,
                'is_svg_configurator' => 0,
                'is_incremental_qty' => 0,
                'incremental_qty_values' => "{}",
                'store_images' => $productSideImages,
                'sides' => [],
                'print_profiles' => [],
                'configurator_image' => [],
                'imported_product_id' => $importedProductId,
                'option_id' => $optionId,
                'option_value' => $optionValue,
            ];

            if (!empty($getSizeData)) {
                $productDecorationSettingData['size'] = $getSizeData;
            }

            // Check if any record(s) exist
            if (!empty($optionBasedSettingsvalue)) {
                $getFinalArray = $optionBasedSettingsvalue;
                /**
                 * If the DB has it's own image product ID, send product_image_id, or
                 * send 0
                 */
                if ($isProductImage || !$isDecoration) {
                    $prodImgSettRelObj = new ProductImageSettingsRel();
                    $checkForProductImage = $prodImgSettRelObj->where('product_setting_id', $getFinalArray['xe_id'])->first();
                    $productImgId = to_int($checkForProductImage['product_image_id']);
                }

                if (!empty($getFinalArray['decoration_dimensions'])) {
                    $productDecorationSettingData['decoration_dimensions'] = json_clean_decode($getFinalArray['decoration_dimensions'], true);
                }

                if ($getFinalArray['is_configurator'] == 1) {
                    $configuratorImage = $this->getConfiguratorImages($productId);
                    $productDecorationSettingData['configurator_image'] = $configuratorImage;
                }
                if ($is3dPreviewAll || !$isDecoration) {
                    $decorationObjInit = new DecorationObjects();
                    $objFileDetails = $decorationObjInit->where('product_id', $getFinalArray['product_id'])->select('3d_object_file', 'cloud_storage')->first();
                    $objFile = $objFileDetails['3d_object_file'];
                    if ($objFileDetails['cloud_storage'] == 1) {
                        $objFile = $this->getS3URL($objFile, $storeId);
                    }
                    $productDecorationSettingData['3d_object_file'] = !empty($objFile) ? $objFile : "";
                }

                $productDecorationSettingData['is_product_image'] = $productImgId > 0 ? 1 : 0;
                $productDecorationSettingData['product_image_id'] = $productImgId;
                $productDecorationSettingData['is_variable_decoration'] = $getFinalArray['is_variable_decoration'];
                $productDecorationSettingData['is_custom_size'] = $getFinalArray['is_custom_size'];
                $productDecorationSettingData['decoration_type'] = $getFinalArray['decoration_type'];
                $productDecorationSettingData['custom_size_unit_price'] = $getFinalArray['custom_size_unit_price'];
                $productDecorationSettingData['is_ruler'] = $getFinalArray['is_ruler'];
                $productDecorationSettingData['is_crop_mark'] = $getFinalArray['is_crop_mark'];
                $productDecorationSettingData['is_safe_zone'] = $getFinalArray['is_safe_zone'];
                $productDecorationSettingData['crop_value'] = (float) $getFinalArray['crop_value'];
                $productDecorationSettingData['safe_value'] = (float) $getFinalArray['safe_value'];
                $productDecorationSettingData['is_3d_preview'] = $getFinalArray['is_3d_preview'];
                // $productDecorationSettingData['3d_object_file'] = $getFinalArray['3d_object_file'];
                $productDecorationSettingData['3d_object'] = $getFinalArray['3d_object'];
                $productDecorationSettingData['scale_unit_id'] = $getFinalArray['scale_unit_id'];
                $productDecorationSettingData['is_configurator'] = (isset($getFinalArray['is_configurator'])) ? $getFinalArray['is_configurator'] : 0;
                $productDecorationSettingData['is_decoration_exists'] = 1;
                $productDecorationSettingData['is_svg_configurator'] = $getFinalArray['is_svg_configurator'];
                $productDecorationSettingData['is_incremental_qty'] = $getFinalArray['is_increment'];
                $productDecorationSettingData['incremental_qty_values'] = (!empty($getFinalArray['increment_values'])) ? json_clean_decode($getFinalArray['increment_values'], true) : "{}";

                // Check if requested array is for Decoration or for variable Decoration
                if (!empty($getFinalArray['sides'])) {
                    $productDecorationSides = $this->getProductSideData($getFinalArray['sides'], $productSideImages, $productImgId, $storeId);

                    $productDecorationSettingData['sides'] = $productDecorationSides;
                } else {
                    // Get variable decoration settings data
                    $varProdDecoData = $this->getVaiableDecoData($getFinalArray['xe_id']);
                    $productDecorationSettingData += $varProdDecoData;
                }
                // Processing Print Profiles
                if (!empty($getFinalArray['print_profiles'])) {
                    foreach ($getFinalArray['print_profiles'] as $printProfile) {
                        if (!empty($printProfile['profile']['xe_id']) && !empty($printProfile['profile']['name'])) {
                            $productDecorationSettingData['print_profiles'][] = [
                                'id' => $printProfile['profile']['xe_id'],
                                'name' => $printProfile['profile']['name'],
                            ];
                        }
                    }
                }
            }

            $optionSettings[$optionId][urlencode($optionValue)][] = $productDecorationSettingData;
        }


        if (empty($getSettingsAssociatedRecords)) {
            $settingData = $this->getSettingsIdByProductId($productId, $getStoreProduct['products']['categories']);
            if (!empty($settingData)) {
                $is3dPreviewAll = $settingData->is_3d_preview;
                $isProductImage = $settingData->is_product_image;
                $isDecoration = 1;
                $importedProductId = $settingData->product_id;
                $getSettingsAssociatedRecords = $this->productSettingDetails($request, $response, [
                    'product_id' => $settingData->product_id,
                    'return_type' => 'array'
                ]);
            }
        }
        $jsonResponse = [
            'status' => 1,
            'data' => $optionSettings
        ];

        if ($returnType == 1) {
            return $jsonResponse;
        }

        return response($response, [
            'data' => $jsonResponse,
            'status' => $serverStatusCode
        ]);
    }

    /**
     * Put: Update Product Decoration Settings
     *
     * @param $request  Slim's Request object
     * @param $response Slim's Response object
     * @param $args     Slim's Argument parameters
     *
     * @author steve@imprintnext.com
     * @date   5 Oct 2019
     * @return Json
     */

    public function updateOptionProductDecorations($request, $response, $args)
    {
        $serverStatusCode = OPERATION_OKAY;
        $jsonResponse = [
            'status' => 0,
            'message' => message('Decoration Setting', 'error')
        ];
        try {
            $isProductImage = $is3dPreviewAll = 0;
            $storeDetails = get_store_details($request);
            $storeId = $storeDetails['store_id'];
            $allPostPutVars = $request->getParsedBody();
            $productUpdateId = $args['product_id'];
            $getProductDecorationDataArray = json_clean_decode($allPostPutVars['decorations'], true);

            $uploadedFiles = $request->getUploadedFiles();
            // get the file keys fields
            $uploadedFileKeys = array_keys($uploadedFiles);

            foreach ($getProductDecorationDataArray as $key => $getProductDecorationData) {
                // get product settings details
                $prodSettGtInit = new ProductSetting();
                $productSettingsGet = $prodSettGtInit->where('product_id', $productUpdateId);

                //Check option based print area
                $pid = $productUpdateId;
                $optionSettingRelObj = new productOptionSettingRel();

                $selectedOption = !empty($getProductDecorationData['option_id']) ? $getProductDecorationData['option_id'] : '';
                $selectedValue = !empty($getProductDecorationData['option_value']) ? $getProductDecorationData['option_value'] : '';

                $optionsSettingData = $optionSettingRelObj->where('product_id', $pid)
                ->where('option_id', $selectedOption)
                    ->where('option_value', strtolower($selectedValue))
                    ->select('*');

                if ($optionsSettingData->count() > 0) {
                    $optionsSettingData = $optionsSettingData->first()->toArray();
                    $optionSettingId = $optionsSettingData['product_setting_id'];
                    $productSettingsGet = $prodSettGtInit->where('xe_id', $optionSettingId);
                }


                $productSettingsGet = $productSettingsGet->orderBy('xe_id', 'desc')->first();

                // create product decoration
                if (empty($productSettingsGet)) {
                    return $this->saveProductDecorations($request, $response);
                }
                $productSettingInsertId = $productSettingsGet->xe_id;

                $isVariableDecoration = $getProductDecorationData['is_variable_decoration'];

                if (!empty($isVariableDecoration) && $isVariableDecoration === 1) {
                    // Process for variable decoration area
                    $getVariableProductDecoration = $this->saveVariableProductDecoration(
                        $getProductDecorationData,
                        $uploadedFiles,
                        $storeId,
                        0,
                        true
                    );
                    return response($response, [
                        'data' => $getVariableProductDecoration['response'],
                        'status' => $getVariableProductDecoration['server_status_code']
                    ]);
                }

                // update product settings
                $this->updateProductSettings($getProductDecorationData, $productSettingInsertId, $productUpdateId);

                // Processing for Table: product_image_settings_rel
                if (empty($getProductDecorationData['product_image_id'])) {
                    (new ProductImageSettingsRel())->where(['product_setting_id' => $productSettingInsertId])->delete();
                } else {
                    $this->updateImageSettingsRel($productSettingInsertId, $getProductDecorationData['product_image_id']);
                }

                // Processing for Table: product_sides, product_decoration_settings
                $this->updateProductSides($getProductDecorationData, $productSettingInsertId, $uploadedFileKeys);

                // Processing for Table: print_profile_product_setting_rel
                $this->setProductPrintProfileRel($productSettingInsertId, $getProductDecorationData['print_profile_ids']);

                // update product setting rel
                if (!empty($getProductDecorationData['product_setting'])) {
                    if (!empty($getProductDecorationData['is_product_image_all'])) {
                        $isProductImage = 1;
                    }
                    if (!empty($getProductDecorationData['is_3d_preview_all'])) {
                        $is3dPreviewAll = 1;
                    }
                    $this->svaeProductSettingsRel($getProductDecorationData['product_setting'], $productSettingInsertId, $isProductImage, $is3dPreviewAll, $productUpdateId);
                }
            }

            if (strtolower(STORE_NAME) == "shopify") {
                $this->saveProductAPIasCache($args['product_id']);
            }

            $jsonResponse = [
                'status' => 1,
                'product_settings_insert_id' => $productSettingInsertId,
                'message' => message('Product Decoration Setting', 'updated')
            ];
        } catch (\Exception $e) {
            $jsonResponse['message'] = $e->getMessage();
        }
        return $jsonResponse;
    }


}
