<?php

namespace Webkul\WooCommerceBundle\Services;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Oro\Bundle\ConfigBundle\Entity\ConfigValue;
use Webkul\WooCommerceBundle\Classes\ApiClient;
use Webkul\WooCommerceBundle\Entity\DataMapping;
use Webkul\WpmlProductBundle\Entity\DataMapping as WpmlDataMapping;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Webkul\WooCommerceBundle\Entity\EntityTracker;
use Webkul\WooCommerceBundle\Entity\CredentialConfig;

class WooCommerceConnector
{
    const SECTION = 'woocommerce_connector';
    const SETTING_SECTION = 'woocommerce_connector_settings';
    const DEFAULTS_SECTION = 'woocommerce_connector_defaults';
    const OTHER_MAPPING_SECTION = 'woocommerce_other_mappings';
    const EXPORT_CONNECTOR_SECTION = 'woocommerce_export_connector';

    private $em;
    private $container;
    private $stepExecution;
    protected $localeRepo;
    protected $categoryRepo;
    protected $attributesRepo;
    protected $attributeOptionRepo;
    protected $attributeGroupRepo;
    protected $currencyRepo;
    protected $channelRepo;
    protected $familyRepo;
    protected $familyVariantRepo;
    protected $fileStorage;
    protected $productRepo;
    protected $productModelRepo;
    protected $jobInstanceRepo;
    // protected $wkAwsIntegrationService;
    protected $router;
    protected $imagineController;
    protected $parameters;


    protected $requiredFields = ['shopUrl', 'consumerKey', 'consumerSecret', 'hostname', 'scheme'];
    protected $attributeLabels = [];

    public function __construct(
        $container,
        \Doctrine\ORM\EntityManager $em,
        $localeRepo, 
        $categoryRepo,
        $attributesRepo,
        $attributeOptionRepo,
        $attributeGroupRepo,
        $currencyRepo,
        $channelRepo,
        $familyRepo,
        $familyVariantRepo,
        $fileStorage,
        $productRepo,
        $productModelRepo,
        $jobInstanceRepo,
        $router,
        $imagineController

    ) {
        $this->container = $container;
        $this->em = $em;
        $this->localeRepo = $localeRepo;
        $this->categoryRepo = $categoryRepo;
        $this->attributesRepo = $attributesRepo;
        $this->attributeOptionRepo = $attributeOptionRepo;
        $this->attributeGroupRepo = $attributeGroupRepo;
        $this->currencyRepo = $currencyRepo;
        $this->channelRepo = $channelRepo;
        $this->familyRepo = $familyRepo;
        $this->familyVariantRepo = $familyVariantRepo;
        $this->fileStorage = $fileStorage;
        $this->productRepo = $productRepo;
        $this->productModelRepo = $productModelRepo;
        $this->jobInstanceRepo = $jobInstanceRepo;
        $this->router = $router;
        $this->imagineController = $imagineController;
    }

    public function setStepExecution($stepExecution)
    {
        $this->stepExecution = $stepExecution;
    }

    /**
     * This function is used to fetch all the credentials from db.
     */
    public function getAllCredentials($id = null)
    {
        $activeCredentials = [];
        
        if (!is_null($id)) {
            $credentials = $this->em->getRepository(CredentialConfig::class)->findById($id);
            
            if($credentials) {
                
                $activeCredentials = [
                    'id' => $credentials[0]->getId(),
                    'shopUrl' => $credentials[0]->getShopUrl(),
                    'consumerKey' => $credentials[0]->getConsumerKey(),
                    'consumerSecret' => $credentials[0]->getConsumerSecret()
                    
                ];
                 
            }
        } else {
            $credentials =  $this->em->getRepository(CredentialConfig::class)->createQueryBuilder('c')
            ->select('c.id, c.shopUrl, c.active, c.defaultSet')
            ->getQuery()->getResult();
            
            foreach($credentials as $credential) {
                $activeCredentials[$credential['id']] = $credential['shopUrl'];
            }
        } 
             
        return $activeCredentials;
    }

    public function getCredentials()
    {
        static $credentials;

        if (empty($credentials)) {
            /* job wise credentials */
            $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
            $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
            $credential = $this->em->getRepository(CredentialConfig::class)->findById($exportProfile);
         
            $repo = $this->em->getRepository('OroConfigBundle:ConfigValue');
            $configs = $repo->findBy([
                            'section' => self::SECTION
                            ]);
            
            $commonCredentials = $this->indexValuesByName($configs);
            
            if (!empty($this->stepExecution) 
            && $this->stepExecution instanceof \StepExecution &&
                !empty($params['shopUrl']) && !empty($params['consumerKey']) && !empty($params['consumerSecret'])) {
                $credentials = [
                    'shopUrl' => $credential['shopUrl'],
                    'consumerKey' => $credential['consumerKey'],
                    'consumerSecret' => $credential['consumerSecret'],
                    'hostname' => !empty($commonCredentials['hostname']) ? $commonCredentials['hostname'] : '',
                    'scheme' => !empty($commonCredentials['scheme']) ? $commonCredentials['scheme'] : '',
                    'extraResources' => !empty($commonCredentials['extraResources']) ? $commonCredentials['extraResources'] : ''
                ];
            } else {
                $credentials = $commonCredentials;
            }
        }
        
        return $credentials;
        $credentials = $this->em->getRepository(CredentialConfig::class)->findAll();
        
        $data = [];

        foreach ($credentials as $credential) {
            $data[$credential->getId()] = $credential->getShopUrl();
        }
        return $data;
    }


   
    public function getDefaultCredential()
    {
        $credential = $this->em->getRepository(CredentialConfig::class)->findOneByDefaultSet(1);
        
        if(!$credential){
            throw new \Exception('Default Credential For Quick Export Not Found.');
        }
       
        return $credential;
    }

    public function getCredentialById($id){
       
        $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
        $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
        $credential = $this->em->getRepository(CredentialConfig::class)->findById($exportProfile);
        if(!empty($exportProfile)){
            $credentials = [
                'id' => $credential[0]->getId(),
                'shopUrl' => $credential[0]->getShopUrl(),
                'consumerKey' => $credential[0]->getConsumerKey(),
                'consumerSecret' => $credential[0]->getConsumerSecret()
            ];
        }
         return $credential;
    }


    public function checkCredentials($params)
    {

        $oauthClient = new ApiClient($params['shopUrl'], $params['consumerKey'], $params['consumerSecret']);
        $response = $oauthClient->request('settings', [], []);
        return !empty($response['code']) && Response::HTTP_OK == $response['code'] && strpos($params['shopUrl'], "/wp-login.php") === false;
    }


    public function saveCredentials($params)
    {
        
        $repo = $this->em->getRepository('OroConfigBundle:ConfigValue');
        
        foreach ($params as $key => $value) {
            if (in_array($key, $this->requiredFields) && gettype($value) == 'string') {
                $field = $repo->findOneBy([
                    'section' => self::SECTION,
                    'name' => $key,
                    ]);
                if (!$field) {
                    $field = new ConfigValue();
                }
                $field->setName($key);
                $field->setSection(self::SECTION);
                $field->setValue($value);
                $this->em->persist($field);
            }
            $this->em->flush();
        }
    }

    public function saveSettings($params, $section = self::SETTING_SECTION)
    {
        $repo = $this->em->getRepository('OroConfigBundle:ConfigValue');
        
        foreach ($params as $key => $value) {
            if (gettype($value) == 'array') {
                $value = implode(",", $value);
            }

            if (gettype($value) == 'string') {
                $field = $repo->findOneBy([
                    'section' => $section,
                    'name' => $key,
                    ]);
                    
                if (null != $value) {
                    if (!$field) {
                        $field = new ConfigValue();
                    }
                    $field->setName($key);
                    $field->setSection($section);
                    $field->setValue($value);
                    $this->em->persist($field);
                } elseif ($field) {
                    $this->em->remove($field);
                }
            }

            $this->em->flush();
        }
    }  

    public function getRootTreeByChannelCode($code)
    {
        return $this->channelRepo->findOneByIdentifier($code);
    }

    public function getMappingByCode($code, $entity, $id)
    {
        
        
        if(!empty($id)){
            $exportProfile = $id;
          
        } 

        if($id == null){
            $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
            $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
            
          
        } 
        
        if ($this->getJobName() == 'woocommerce_quick_export') {
           
            $exportProfile1 = $this->getDefaultCredential() ? $this->getDefaultCredential()->getId() : '';
            $exportProfile = strval($exportProfile1);
            
        }

        
        if(!empty($exportProfile)){
           
            $credentials = $this->em->getRepository(CredentialConfig::class)->findById($exportProfile);
            
        }else{
            
            $credentials = $this->getCredentials();
        }

       
        $apiUrl_dummy =  $credentials[0]->getShopUrl();
        $apiUrl = preg_replace ('/https/','http',$apiUrl_dummy,1);
        
        $mapping = $this->em->getRepository('WooCommerceBundle:DataMapping')->findOneBy([
            'code' => $code,
            'entityType' => $entity,
            'apiUrl' => $apiUrl,
        ]);
        
        return $mapping;
    }

    public function getIdbyValue($code, $entity)
    {
        $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
        $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
        if(!empty($exportProfile)){
            $credentials = $this->getCredentialById($exportProfile);
        }else{
            $credentials = $this->getCredentials();
        }
        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/','https'], ['','','http'], $credentials['shopUrl']) : '';
        $mapping = $this->em->getRepository('WooCommerceBundle:DataMapping')->findOneBy([
            'langLabel'   => $code,
            'entityType' => $entity,
            'apiUrl' => $apiUrl,
        ]);
       
        if ($mapping) {
            return $mapping->getExternalId();
        }
    }

    public function getLabelbyCodeAndLang($code, $lang, $entity)
    {
        $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
        $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
        if(!empty($exportProfile)){
            $credentials = $this->getCredentialById($exportProfile);
        }else{
            $credentials = $this->getCredentials();
        }
        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/','https'], ['','','http'], $credentials['shopUrl']) : '';
        $mapping = $this->em->getRepository('WooCommerceBundle:DataMapping')->findOneBy([
            'code'   => $code,
            'relatedLanguage'   => $lang,
            'entityType' => $entity,
            'apiUrl' => $apiUrl,
        ]);
        
        if ($mapping) {
            return $mapping->getLangLabel();
        }
    }

    public function getAllMappingByCode($code, $entity, $id, $attrId = null)
    {
        if(!empty($id)){
            $credentials = $this->getCredentialById($id);
        }else{
            $credentials = $this->getCredentials();
        }
        
        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/','https'], ['','','http'], $credentials['shopUrl']) : '';
        
        $mapping = $this->em->getRepository('WooCommerceBundle:DataMapping')->findBy([
            'code'   => $code,
            'entityType' => $entity,
            'apiUrl' => $apiUrl,
            'jobInstanceId' => $attrId
        ]);

        return $mapping;
    }

    public function getMappingByExternalId($externalId, $entity, $id)
    {
        if(!empty($id)){
            $credentials = $this->getCredentialById($id);
        }else{
            $credentials = $this->getCredentials();
        }
        
        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/','https'], ['','','http'], $credentials['shopUrl']) : '';
        
        $mapping = $this->em->getRepository('WooCommerceBundle:DataMapping')->findOneBy([
            'externalId'   => $externalId,
            'entityType' => $entity,
            'apiUrl' => $apiUrl,
        ]);
        
        return $mapping;
    }

  
    public function getMappingByEntity($entity)
    {
        $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
        $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
        
        if(!empty($exportProfile)){
            $credentials = $this->getCredentialById($exportProfile);
            
        }else{
            $credentials = $this->getCredentials();
        }
       // $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/','https'], ['','','http'], $credentials['shopUrl']) : '';
        $apiUrl_dummy =  $credentials[0]->getShopUrl();
        $apiUrl = preg_replace ('/https/','http',$apiUrl_dummy,1);
        
        $mapping = $this->em->getRepository('WooCommerceBundle:DataMapping')->findBy([
            'entityType' => $entity,
            'apiUrl' => $apiUrl,
        ]);
          
        return $mapping;
    }

    public function getMappingByEntityForFamily($entity, $exportProfile){
        
        $id = (int)$exportProfile;
        $credential = $this->em->getRepository(CredentialConfig::class)->findById($id);
        $credentials = [
            'shopUrl' => $credential[0]->getShopUrl(),
            'consumerKey' => $credential[0]->getConsumerKey(),
            'consumerSecret' => $credential[0]->getConsumerSecret()
        ];
        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/','https'], ['','','http'], $credentials['shopUrl']) : '';
        $mapping = $this->em->getRepository('WooCommerceBundle:DataMapping')->findBy([
            'entityType' => $entity,
            'apiUrl' => $apiUrl,
        ]);
            
        return $mapping;
    }

                                                             
    public function addOrUpdateMapping($mapping, $code, $entity, $externalId, $id, $relatedId = null, $jobInstanceId = null)
    {
        
        
        $exportProfile = (int)$id;  
        
        if(!empty($exportProfile)){
            $credentials = $this->em->getRepository(CredentialConfig::class)->findById($exportProfile);
            
        }else{
            $credentials = $this->getCredentials();
        }
        
        $apiUrl_dummy =  $credentials[0]->getShopUrl();
        
        $apiUrl = preg_replace ('/https/','http',$apiUrl_dummy,1);
        
        if (!($mapping && $mapping instanceof DataMapping)) {
            $mapping = new DataMapping();
        }
        
        $mapping->setApiUrl($apiUrl);
        $mapping->setEntityType($entity);
        $mapping->setCode($code);
        $mapping->setExternalId($externalId);
        if ($relatedId) {
            $mapping->setRelatedId($relatedId);
        }
        
        $this->em->persist($mapping);
        $this->em->flush();
    }

    public function deleteMapping($mapping)
    {
        if ($mapping) {
            $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
            $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
            if ('product' == $mapping->getEntityType()) {
                if(!empty($exportProfile)){
                    $credentials = $this->getCredentialById($exportProfile);
                }else{
                    $credentials = $this->getCredentials();
                }
                $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/','https'], ['','','http'], $credentials['shopUrl']) : '';
                $mappings = $this->em->getRepository('WooCommerceBundle:DataMapping')->findBy([
                    'entityType' => 'product',
                    'apiUrl' => $apiUrl,
                    'relatedId' => $mapping->getExternalId(),
                ]);
                foreach ($mappings as $relatedMapping) {
                    $this->em->remove($relatedMapping);
                }
                $this->em->flush();
            }
            $this->em->remove($mapping);
            $this->em->flush();
        }
    }    
    /**
     * Get job name
     *
     * @return string
     */
    public function getJobName()
    {
        return $this->stepExecution->getJobExecution()->getJobInstance()->getJobName();
    }

    public function requestApiAction($action, $data, $parameters)
    {   
        $exportProfile = 0;
        if (!empty($parameters['exportProfile'])){
            $exportProfile = $parameters['exportProfile'];
          
        } 
        
        if ($this->getJobName() == 'woocommerce_quick_export') {
            $exportProfile = $this->getDefaultCredential() ? $this->getDefaultCredential()->getId() : '';
            
        }
        
        $credential = $this->em->getRepository(CredentialConfig::class)->findById($exportProfile);
        
        if(!empty($credential)){
           
            $credentials = [
                'shopUrl' => $credential[0]->getShopUrl(),
                'consumerKey' => $credential[0]->getConsumerKey(),
                'consumerSecret' => $credential[0]->getConsumerSecret()
            ];
        }
        
         if (empty($credentials['shopUrl'])) {
            throw new \Exception('Error! Save credentials before Exporting data.');
            exit();
        }
        
        $oauthClient = new ApiClient($credentials['shopUrl'], $credentials['consumerKey'], $credentials['consumerSecret']);
        
        $response = $oauthClient->request($action, $parameters, $data);
        
        return $response;
    }

    


    public function requestMediaAction($data, $parameters = [])
    {
        $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
        $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
        if(!empty($exportProfile)){
            $credentials = $this->getCredentialById($exportProfile);
        }else{
            $credentials = $this->getCredentials();
        }
        $oauthClient = new ApiClient($credentials['shopUrl'], $credentials['consumerKey'], $credentials['consumerSecret'], ['type' => 'wp']);
        $response = $oauthClient->request('addMedia', $parameters, $data);
        return $response;
    }

    public function getFileAttributeCodes()
    {
        return $this->attributesRepo->getAttributeCodesByType(
            'pim_catalog_file'
        );
    }

    public function getAssetsImageAttributeCodes()
    {
        return $this->attributesRepo->getAttributeCodesByType(
            'pim_catalog_asset_group'
        );
    }

    public function getImageAttributeCodes()
    {
        return $this->attributesRepo->getAttributeCodesByType(
            'pim_catalog_image'
        );
    }

    public function getSelectAttributeCodes()
    {
        return $this->attributesRepo->getAttributeCodesByType(
            'pim_catalog_simpleselect'
        );
    }

    public function getMultiSelectAttributeCodes()
    {
        return $this->attributesRepo->getAttributeCodesByType(
            'pim_catalog_multiselect'
        );
    }

    public function getNumberAttributeCodes()
    {
        return $this->attributesRepo->getAttributeCodesByType(
            'pim_catalog_number'
        );
    }

    public function getPriceAttributeCodes()
    {
        return $this->attributesRepo->getAttributeCodesByType(
            'pim_catalog_price_collection'
        );
    }

    public function getOptionByCode($code)
    {
        return $this->attributeOptionRepo->findOneByIdentifier(
            $code
        );
    }

    public function checkAws3module()
    {
        $fs = $this->fileStorage->getFilesystem('catalogStorage');
        $result = false;
        
        if (get_class($fs->getAdapter()) == 'League\Flysystem\Adapter\Local') {
            $result = true;
            
        }
        
        return $result;
    }

    public function generateFileUrl($filename, $host = null)
    {
        $filename = urldecode($filename);
        $url = '';
        if (!$filename) {
            return $url;
        }
        $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
        $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
        
        $fs = $this->fileStorage->getFilesystem('catalogStorage');
        switch (get_class($fs->getAdapter())) {
            case 'League\Flysystem\AwsS3v3\AwsS3Adapter':
                $url = $this->container->get('wk_aws_integration.service')->generateUrlByFileName($filename);
                break;
            default:
                if(!empty($exportProfile)){
                    $credentials = $this->getCredentialById($exportProfile);
                }else{
                    $credentials = $this->getCredentials();
                }
                $host = !empty($credentials['hostname']) ? $credentials['hostname'] : null;
                $scheme = !empty($credentials['scheme']) ? $credentials['scheme'] : null;
                $router = $this->router;
                if ($host) {
                    $context = $router->getContext();
                    $context->setHost($host);
                    $context->setScheme('https');
                    $context->setScheme($scheme);
                }
                $request = new Request();

                try {
                    
                    $url = $router->generate('pim_enrich_media_download', [
                                                            'filename' => urlencode($filename)
                                                        ], UrlGeneratorInterface::ABSOLUTE_URL);
                } catch (\Exception $e) {
                    $url  = '';
                }
        }
        
        return $url;
    }

    public function generateImageUrl($filename, $id, $host = null)
    {
        
        $filename = urldecode($filename);
        
        $url = '';
        if (!$filename) {
            return $url;
        }

        $fs = $this->fileStorage->getFilesystem('catalogStorage');
        
        switch (get_class($fs->getAdapter())) {
            case 'League\Flysystem\AwsS3v3\AwsS3Adapter':
                $url = $this->container->get('wk_aws_integration.service')->generateUrlByFileName($filename);
                break;
            default:
                if(!empty($id)){
                    $credentials = $this->getCredentialById($id);
                }else{
                    $credentials = $this->getCredentials();
                }
                $host = !empty($credentials['hostname']) ? $credentials['hostname'] : null;
                $scheme = !empty($credentials['scheme']) ? $credentials['scheme'] : null;
                $router = $this->router;
                if ($host) {
                    $context = $router->getContext();
                    $context->setHost($host);
                    $context->setScheme($scheme);
                }
                $request = new Request();

                try {
                    $url = $this->container->get('liip_imagine.controller')->filterAction($request, $filename, 'preview')->getTargetUrl();

                    
                } catch (\Exception $e) {
                    $url  = '';
                }
                
        }
         return $url;
    }

    public function createImageMapping($url, $imageCode)
    {
        $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
        $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
        $imageMapping = $this->getMappingByCode($imageCode, "image");
        $this->addOrUpdateMapping(
            $imageMapping,
            $imageCode,
            "image",
            $url,
            $exportProfile,
            '',
            $this->stepExecution->getJobExecution()->getId()
        );

        return $imageCode;
    }
    public function getOptionsByAttribute($code, $locale)
    {
        $attribute = $this->attributesRepo->findOneByCode($code);
        
        $codes = [];
        if ($attribute) {
            foreach ($attribute->getOptions() as $option) {
                $getCode = $option->getCode();
                $option->setLocale($locale);
                $codes[] = $option->__toString() !== '[' . $getCode . ']' ? $option->__toString() : $getCode;
            }
        }

        return $codes;
    }

    private function indexValuesByName($values)
    {
        $result = [];
        foreach ($values as $value) {
           $result[$value->getName()] = $value->getValue();
        }
        
        return $result;
    }
    
    public function getQuickSettingCurrency()
    {
       
        $currency = $this->getMultiSetting("quicksettings");
        
        return $currency['qcurrency'];
    }
    
    public function getQuickSettingLocales()
    {
        $locales = $this->getMultiSetting("quicksettings");
        $locales = $locales['locales'];
        
        if (is_array($locales)) {
            $locales = reset($locales);
        }
        
        return $locales;
    }
    public function getOtherMappings()
    {

        $mapping = $this->getSettings(self::OTHER_MAPPING_SECTION);
        $mappings['custom_fields'] = isset($mapping['custom_fields']) ? array_map('trim', explode(',', $mapping['custom_fields'])) : [];
        $mappings['images'] = isset($mapping['images']) ? array_map('trim', explode(',', $mapping['images'])) : [];
        $mappings['files'] = isset($mapping['files']) ? array_map('trim', explode(',', $mapping['files'])) : [];
        
        return $mappings;
    }

    public function convertToCode($name)
    {
        setlocale(LC_ALL, 'en_US.utf8');
        $name = iconv('utf-8', 'ascii//TRANSLIT', $name);
        $name = preg_replace('/[^a-zA-Z0-9\']/', '_', $name);
        $name = ltrim($name, '_');
        $code = preg_replace(['#\s#', '#-#', '#[^a-zA-Z0-9_\s]#'], ['_', '_', ''], strtolower($name));

        return $code;
    }

    public function getCategoryCode($code)
    {
        $repository = $this->categoryRepo;
        $value = $repository->findOneBy(['code' => $code]);
        if (!$value) {
            return null;
        }
        return $value->getCreated();
    }

    protected $attRepository;

    public function getAttributeCode($code)
    {
        if (!$this->attRepository) {
            $this->attRepository = $this->attributesRepo;
        }
        $attribute = $this->attRepository->findOneBy(['code' => $code]);

        return $attribute ? $attribute->getCode() : null;
    }


    public function getAttrTypeByCode($code)
    {
        if (!$this->attributeRepo) {
            $this->attributeRepo = $this->attributesRepo;
        }
        
        $result = $this->attributeRepo->createQueryBuilder('a')
                        -> select('a.type')
                        -> where('a.code = :attrCode')
                        -> setParameter('attrCode', $code)
                        -> getQuery()->getResult();

        return $result;
    }


    public function getAttributeByCode($code)
    {
        $repository = $this->attributesRepo;
        
        return $repository->findOneBy(['code' => $code]);
    }

    public function getAttributeCodes($attributeType)
    {
        $repository = $this->attributesRepo;
     
        $values = $repository->findBy(['type' => $attributeType]);
        $attrCodes = [];
        foreach ($values as $value) {
            $attrCodes[] = $value->getCode();
        }

        return $attrCodes;
    }

    public function findFamilyByCode($code, $entity)
    {
        if ($entity === 'product') {
            try {
                $repo = $this->productRepo;

                $result = $repo->createQueryBuilder('p')
                                ->leftJoin('p.family', 'f')
                                ->where('p.identifier = :identifier')
                                ->setParameter('identifier', $code)
                                ->select('f.code')
                                ->getQuery()->getResult();
                
                if (isset($result[0])) {
                    return $result[0]['code'] ? $result[0]['code'] : null;
                }
            } catch (\Exception $e) {
                $family = null;
            }
        } elseif ($entity === 'productmodel') {
            try {
                $repo = $this->productModelRepo;

                $result = $repo->createQueryBuilder('p')
                                ->leftJoin('p.familyVariant', 'fv')
                                ->leftJoin('fv.family', 'f')
                                ->where('p.code = :code')
                                ->setParameter('code', $code)
                                ->select('f.code')
                                ->getQuery()->getResult();

                if (isset($result[0])) {
                    return $result[0]['code'] ? $result[0]['code'] : null;
                }
            } catch (\Exception $e) {
                $family = null;
            }
        }
    }


    public function getAttributeOption($attribute, $code, $locale)
    {
        $attrCode = $attribute . '.' . $code;
        if (empty($this->attributeOptions[$attrCode])) {
            $this->attributeOptions[$attrCode] = $this->attributeOptionRepo->findOneByIdentifier($attrCode);
        }

        $attributeOption = $this->attributeOptions[$attrCode];
        if ($attributeOption) {
            $attributeOption->setLocale($locale);

            return $attributeOption->__toString() !== '[' . $code . ']' ? $attributeOption->__toString() : $code;
        }
    }

    public function getAttributeOptionCode($attribute, $code)
    {
        $attrCode = $attribute . '.' . $code;
        if (empty($this->attributeOptions[$attrCode])) {
            $this->attributeOptions[$attrCode] = $this->attributeOptionRepo->findOneByIdentifier($attrCode);
        }

        $attributeOption = $this->attributeOptions[$attrCode];
        $code = null;
        if ($attributeOption) {
            $code = $attributeOption->getCode();
        }
        
        return $code;
    }

    public function checkScope($code)
    {
        $repository = $this->attributesRepo;
        $value = $repository->findOneBy(['code' => $code]);
        if (!$value) {
            return null;
        }

        return $value->isScopable();
    }
    public function checkLocale($code)
    {
        $repository = $this->attributesRepo;
        $value = $repository->findOneBy(['code' => $code]);
        if (!$value) {
            return null;
        }
        return $value->isLocalizable();
    }
    public function getDefaultUnit($code)
    {
        $repository = $this->attributesRepo;
        $value = $repository->findOneBy(['code' => $code]);
        if (!$value) {
            return null;
        }
        return $value->getDefaultMetricUnit();
    }

    public function getFamilyVariant($code)
    {
        return $this->familyVariantRepo->findOneByIdentifier($code);
    }

    public function getAllProductCodeByEntity($entity)
    {
        $entityData = $this->getMappingByEntity($entity);
        if ($entityData) {
            $code = [];
            foreach ($entityData as $value) {
                $code[] = $value->getCode();
            }

            return $code;
        }
        
        return null;
    }

    public function getProductModelFamilyVariant()
    {
        return $this->productModelRepo;
    }

    public function getProductFamily()
    {
        return $this->productRepo;
    }

    public function getParentCategory($code)
    {
        $repository = $this->channelRepo;
        $value = $repository->findOneBy(['code' => $code]);
        if (!$value) {
            return null;
        }

        return $value->getCategory()->getCode();
    }

    public function getCategoryiesCodes()
    {
        $repository = $this->categoryRepo->findAll();
        $categoryCodes = [];
        foreach ($repository as $category) {
            $categoryCodes[] = $category->getCode();
        }

        return $categoryCodes;
    }
    
    public function getAttributeLabelByCodeAndLocale($code, $locale)
    {
        if (empty($this->attributeLabels[$code . '-' . $locale])) {
            $label = $code;
            $attribute = $this->attributesRepo->findOneByIdentifier($code);
            if ($attribute) {
                $attribute->setLocale($locale);
                $label = $attribute->__toString() !== '[' . $code . ']' ? $attribute->__toString() : $code;
            }
            $this->attributeLabels[$code . '-' . $locale] = $label;
        }
        return $this->attributeLabels[$code . '-' . $locale];
    }

    protected $attributeRepo;

    public function getAttributeCodeByLabel($label, $locale)
    {
        if (!$this->attributeRepo) {
            $this->attributeRepo = $this->attributesRepo;
        }
        
        $result = $this->attributeRepo->createQueryBuilder('attr')
                    ->select('attr')
                    ->leftJoin('attr.translations', 't')
                    ->where('t.locale = ?1')
                    ->andWhere('t.label = ?2')
                    ->setParameter(1, $locale)
                    ->setParameter(2, $label)
                    ->setMaxResults(1)
                    ->getQuery()
                    ->getOneOrNullResult();
        
        return $resultCode = $result ? $result->getCode() : null;
    }

    protected $attributeOptRepo;

    public function getAttributeOptionCodeByLabel($label, $attrCode, $locale)
    {
        if (!$this->attributeOptRepo) {
            $this->attributeOptRepo = $this->attributeOptionRepo;
        }

        $result = $this->attributeOptRepo->createQueryBuilder('attrO')
                    ->select('attrO')
                    ->leftJoin('attrO.attribute', 'attr')
                    ->leftJoin('attrO.optionValues', 'ov')
                    ->andWhere('ov.locale = ?1')
                    ->andWhere('ov.value = ?2')
                    ->andWhere('attr.code = :attrCode')
                    ->setParameters([
                        '1' => $locale,
                        '2' => $label,
                        'attrCode' => $attrCode
                    ])
                    ->setMaxResults(1)
                    ->getQuery()
                    ->getOneOrNullResult();
            
        return $resultCode = $result ? $result->getCode() : null;
    }


    public function filterDublicateValue($checkDublicateNames)
    {
        foreach ($checkDublicateNames as $name) {
            if ($name > 1) {
                return 1;
            } else {
                continue;
            }
        }
        
        return null;
    }
    public function getEntityTrackByEntityAndCode($entity, $code, $id = null)
    {
      
        $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : [];
        $exportProfile = $params['exportProfile'];
        $credentials = $this->getCredentialById($exportProfile);
        $track = false;
        $repo = $this->em->getRepository('WooCommerceBundle:EntityTracker');
        $track = $repo->findOneBy(['entityType' => $entity, 'code' => $code]);
        if (!empty($credentials)) {
            if ($track) {
                if ($track->getShopUrl()) {
                    $trackedUrls = json_decode($track->getShopUrl(), true);
                    $shopUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/','https'], ['','','http'], $credentials['shopUrl']) : '';
                    if($trackedUrls) {
                        if (!in_array($shopUrl, $trackedUrls)) {
                            $track = false;
                        }  
                    }
                }
            }
        }

        return $track;
    }


    public function convertAssetToPath($attrValue)
    {
        if(!$this->container->has('webkul_dam.repository.asset')) {
            return;
        }
        $assetImages = [];
        $key = 0;
        // foreach($attrValue as $key => $values) { 
            $damService = $this->container->get('webkul_dam.repository.asset');
            $assets = $damService->getArrayResultsByIdentifiers($attrValue);
            $medias = array_column($assets, 'medias');
           
            $imagePath = [];
            foreach($medias as $media){
                $images = array_column($media,'filePath');
                $imagePath = array_merge($imagePath, $images);
            }
            
            $assetImages['data'] = $imagePath;
        // }

        return $assetImages;
    }



    public function getEntityTrackByEntity($entity,$exportProfile)
    {
        // return $track;
        
        
        $credentials = $this->getCredentialById($exportProfile);
        $repo = $this->em->getRepository('WooCommerceBundle:EntityTracker');
        $tracks = $repo->findBy(['entityType' => $entity, 'action' => 'delete']);
        if (!empty($credentials)) {
            if ($tracks) {
                foreach($tracks as $trackKey => $track) {
                    if ($track->getShopUrl()) {
                        $trackedUrls = json_decode($track->getShopUrl(), true);
                        $shopUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/','https'], ['','','http'], $credentials['shopUrl']) : '';
                        if (!in_array($shopUrl, $trackedUrls)) {
                            unset($tracks[$trackKey]);
                        }
                    }
                }
            }
        }

        return $tracks;    

    }

    public function removeTrack($track, $id = null)
    {
        if ($track && $track instanceof \Webkul\WooCommerceBundle\Entity\EntityTracker) {
            $entity = $track->getEntityType();
            $code = $track->getCode();
            $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : [];
            $exportProfile = $params['exportProfile'];
            $credentials = $this->getCredentialById($exportProfile);
            $trackedUrls = json_decode($track->getShopUrl(), true);
            $shopUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/','https'], ['','','http'], $credentials['shopUrl']) : '';
            if($trackedUrls) {
                $untrackUrlKey = array_search($shopUrl, $trackedUrls);    
            } else {
                $untrackUrlKey = null;
            }
            
            if ($untrackUrlKey == 0 || $untrackUrlKey) {
                unset($trackedUrls[$untrackUrlKey]);
                $shopUrls = json_encode($trackedUrls, true);
                
                $repo = $this->em->getRepository('WooCommerceBundle:EntityTracker');
                $track = $repo->findOneBy(['entityType' => $entity, 'code' => $code]);
                $track->setShopUrl($shopUrls);
                $this->em->persist($track);
                $this->em->flush();
            }
        }
    }

    public function updateOrCreateTrackByEntityCodeAndAction($entity, $code, $action)
    {
        $shopUrls = json_encode($this->getShopUrls(), true);
        $repo = $this->em->getRepository('WooCommerceBundle:EntityTracker');
        $track = $repo->findOneBy(['entityType' => $entity, 'code' => $code]);
        if (!$track) {
            $track = new EntityTracker();
        }
        $track->setEntityType($entity);
        $track->setCode($code);
        $track->setAction($action);
        $track->setShopUrl($shopUrls);
        $this->em->persist($track);
        $this->em->flush();
    }

  
     
    public function getFamilyVariantAttributes($familyVariantCode)
    {
        $repo = $this->familyVariantRepo->findOneByIdentifier($familyVariantCode);
        $attrCodes = [];
        if ($repo) {
            foreach ($repo->getCommonAttributes() as $attr) {
                $attrCodes[] = $attr->getCode();
            }
        }

        return $attrCodes;
    }



    public function getVariantAttrCode($familyVariantCode)
    {
        $repo = $this->familyVariantRepo->findOneByIdentifier($familyVariantCode);
        
        $attrCodes = [];
        if ($repo) {
            foreach ($repo->getAttributes() as $attr) {
                $attrCodes[] = $attr->getCode();
            }
        }

        return $attrCodes;
    }

    public function getAttributeByFamily($familyAttributeCode)
    {
        $repo = $this->familyRepo->findOneByIdentifier($familyAttributeCode);
        $attrCodes = [];
        if ($repo) {
            foreach ($repo->getAttributes() as $attr) {
                $attrCodes[] = $attr->getCode();
            }
        }

        return $attrCodes;
    }

    public function getFamilyImageAttributes($familyImageCode)
    {
        $repo = $this->familyVariantRepo->findOneByIdentifier($familyImageCode);
        $familyImageVariant = [];
        if ($repo) {
            foreach ($repo->getImageAttributes() as $imageAttr) {
                $familyImageVariant = $imageAttr->getCode();
            }
        }
    }

    public function formateOption($selectedAttrs)
    {
        $optionData = [];
        if (isset($selectedAttrs)) {
            $i=0;
            foreach ($selectedAttrs as $key => $values) {
                foreach ($values as $value) {
                    $optionData[] = [
                        "code" => $value,
                        "attribute" => $key,
                        "sort_order" => $i,
                        "labels" => [
                            $this->defaultLocale => $value
                        ]
                    ];
                    $i++;
                }
            }
        }

        return $optionData;
    }

    public function getPimRepository(string $type)
    {
        $repository =null;
        
        if (!in_array($type, ['locale', 'category', 'attribute', 'attribute_option', 'channel', 'family', 'family_variant', 'attribute_group', 'currency'])) {
            return null;
        }

        switch ($type) {
            case 'locale':
                $repository = $this->localeRepo;

                break;
            case 'category':
                $repository = $this->categoryRepo;

                break;
            case 'attribute':
                $repository = $this->attributesRepo;

                break;
            case 'attribute_option':
                $repository = $this->attributeOptionRepo;

                break;
            case 'attribute_group':
                $repository = $this->attributeGroupRepo;
                
                break;
            case 'currency':
                $repository = $this->currencyRepo;

                break;
            case 'channel':
                $repository = $this->channelRepo;

                break;
            case 'family':
                $repository = $this->familyRepo;

                break;
            case 'family_variant':
                $repository = $this->familyVariantRepo;

                break;
                
        }

        return $repository;
    }

    // wpml connector service

    public function requestWpmlApiAction($action, $data, $parameters = [])
    { 
        $credentials = $this->getCredentials();
        //dump($credentials); die;
        if (empty($credentials['shopUrl'])) {
            throw new \Exception('Error! Save credentials before Exporting data.');
            exit();
        }
        $setting = $this->getSettings();
        $oauthClient = new ApiClient($credentials['shopUrl'], $credentials['consumerKey'], $credentials['consumerSecret'], ['type' => 'wk-wpml', 'version' => 'v3']);

        $response = $oauthClient->request($action, $parameters, $data);

        return $response;
    }

    public function getSettings($section = self::SETTING_SECTION)
    {
        $repo = $this->em->getRepository('OroConfigBundle:ConfigValue');
        if (empty($settings)) {
            $configs = $repo->findBy([
                'section' => $section,
                ]);

            $settings = $this->indexValuesByName($configs);
        }

        return $settings;

    }

    public function getAttributeOptions($allLocales = null)
    {
        $channel = $this->stepExecution->getJobParameters()->get('filters')['structure']['scope'];
        $defaultLocale = $this->getQuickSettingLocales();
        $defaultLocale = reset($defaultLocale);
        if (!$allLocales) {
            $allLocales = $this->stepExecution->getJobParameters()->get('filters')['structure']['locales'];
        }

        $currency = $this->stepExecution->getJobParameters()->get('filters')['structure']['currency'];

        $mappings = $this->getOtherMappings();
        $exportAttributeCodes = !empty($mappings['custom_fields']) ? $mappings['custom_fields'] : [];
        $this->getSelectAttributeCodes();
        $defaultKeys = ['name'];
        $unionArray = array_intersect($exportAttributeCodes, $this->getSelectAttributeCodes());

        $unionArray = array_merge($unionArray, $defaultKeys);

        foreach ($unionArray as $union) {
            $key = array_search($union, $exportAttributeCodes);
            unset($exportAttributeCodes[$key]);
        }

        $productOption = $this->getOptionByProduct($exportAttributeCodes, $channel, $defaultLocale, $allLocales, $currency);
        $productModelOptions = $this->getOptionByProductModel($exportAttributeCodes, $channel, $defaultLocale, $allLocales, $currency);

        $valuesForLocale = array_merge($productOption, $productModelOptions);

        $out = array();
        foreach ($valuesForLocale as $row) {
            $out[$row['code']] = $row;
        }
        $uniqueOptions = array_values($out);

        return $uniqueOptions;
    }

    public function getWpmlMappingByCode($code, $entity)
    {
        $credentials = $this->getCredentials();

        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/', 'https'], ['', '', 'http'], $credentials['shopUrl']) : '';
        $mapping = $this->em->getRepository('WpmlProductBundle:DataMapping')->findOneBy([
            'code' => $code,
            'entityType' => $entity,
            'apiUrl' => $apiUrl,
        ]);
       
        return $mapping;
    }

    public function addOrUpdateWPMLMapping($mapping, $code, $entity, $externalId, $relatedLang = null, $langLabel = null, $relatedId = null, $jobInstanceId = null)
    { 
        $credentials = $this->getCredentials();

        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/', 'https'], ['', '', 'http'], $credentials['shopUrl']) : '';
        if (!($mapping && $mapping instanceof WpmlDataMapping)) {
            $mapping = new WpmlDataMapping();
        }

        $mapping->setApiUrl($apiUrl);
        $mapping->setEntityType($entity);
        $mapping->setCode($code);
        $mapping->setExternalId($externalId);
        if ($relatedLang) {
            $mapping->setRelatedLanguage($relatedLang);
        }
        if ($relatedId) {
            $mapping->setRelatedId($relatedId);
        }
        if ($langLabel) {
            $mapping->setLangLabel($langLabel);
        }
        if ($jobInstanceId) {
            $mapping->setJobInstanceId($jobInstanceId);
        }

        $this->em->persist($mapping);
        $this->em->flush();
    }

    public function getVariationAttributeCode($variation)
    {
        $repository = $this->attributesRepo;

        $values = $repository->findBy(['type' => $variation]);
        $attrCodes = [];
        foreach ($values as $value) {
            $attrCodes[] = $value->getCode();
        }

        return $attrCodes;
    }

    public function getWpmlOptionsByAttribute($code)
    {
        $attribute = $this->attributesRepo->findOneByCode($code);

        $codes = [];
        if ($attribute) {
            foreach ($attribute->getOptions() as $option) {
                $codes[] = $option->getCode();
            }
        }

        return $codes;
    }

    public function getVariationIdByCodeAndLang($item, $code, $lang, $entity, $attr = null)
    {
        $credentials = $this->getCredentials();
        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/', 'https'], ['', '', 'http'], $credentials['shopUrl']) : '';
        $attrId = null;
        if ($attr) {
            $attrCode = $attr->getCode();
            $attrId = $attr->getExternalId();
        }

        $codes = $this->getOptionsByAttributeAndItem($item, $code, $lang);

        $codeIds = [];
        foreach ($codes as $code) {
            $mapping = $this->em->getRepository('WpmlProductBundle:DataMapping')->findOneBy([
                'code' => $code,
                'relatedLanguage' => $lang,
                'entityType' => $entity,
                'apiUrl' => $apiUrl,
                'jobInstanceId' => $attrId,
            ]);

            if ($mapping) {
                $codeIds[] = $mapping->getExternalId();
            }
        }
    }

    public function getOptionsByAttributeAndItem($item, $code, $locale)
    {
        $parent = $item['code'];
        $variantAttributeValues = [];

        $productModel = $this->productModelRepo->findOneByIdentifier($parent);
        
        
        foreach ($productModel->getProducts()->getValues() as $variations) {
            foreach ($variations->getValuesForVariation()->getValues() as $var) {
             
                $attrCode =  method_exists($var,'getAttribute') ? $var->getAttribute()->getCode() : $var->getAttributeCode();
                if ($code == $attrCode) {
                    $variantAttributeValues[] = is_string($var->getData()) ? $var->getData() : $var->getData()->getCode();
                }
            }
        }

        $attribute = $this->attributesRepo->findOneByCode($code);

        $codes = [];
        if ($attribute) {
            foreach ($attribute->getOptions() as $option) {
                $getCode = $option->getCode();
                if (in_array($getCode, $variantAttributeValues)) {
                    $option->setLocale($locale);
                    $codes[] = $option->__toString() !== '['.$getCode.']' ? $option->__toString() : $getCode;
                }
            }
        }

        return $codes;
    }

    public function getIdbyCodeAndLang($code, $lang, $entity, $attr = null)
    {
        $credentials = $this->getCredentials();
        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/', 'https'], ['', '', 'http'], $credentials['shopUrl']) : '';
        $attrId = null;
        if ($attr) {
            $attrCode = $attr->getCode();
            $attrId = $attr->getExternalId();
        }

        $mapping = $this->em->getRepository('WpmlProductBundle:DataMapping')->findOneBy([
            'code' => $code,
            'relatedLanguage' => $lang,
            'entityType' => $entity,
            'apiUrl' => $apiUrl,
            'jobInstanceId' => $attrId,
        ]);

        if ($mapping) {
            return $mapping->getExternalId();
        }
    }

    public function getSlugbyCodeAndLang($code, $lang, $entity)
    {
        $credentials = $this->getCredentials();
        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/', 'https'], ['', '', 'http'], $credentials['shopUrl']) : '';
        $mapping = $this->em->getRepository('WpmlProductBundle:DataMapping')->findOneBy([
            'code' => $code,
            'relatedLanguage' => $lang,
            'entityType' => $entity,
            'apiUrl' => $apiUrl,
        ]);

        if ($mapping) {
            return $mapping->getLangLabel();
        }
    }

    public function getMappingByCodeAndRelatedID($code, $entity, $rid)
    {
        $credentials = $this->getCredentials();
        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/', 'https'], ['', '', 'http'], $credentials['shopUrl']) : '';
        $mapping = $this->em->getRepository('WpmlProductBundle:DataMapping')->findOneBy([
            'code' => $code,
            'entityType' => $entity,
            'relatedLanguage' => $rid,
            'apiUrl' => $apiUrl,
        ]);

        return $mapping;
    }


    public function getWpmlAllMappingByCode($code, $entity, $attrId = null)
    {
        $credentials = $this->getCredentials();
        $apiUrl = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/', 'https'], ['', '', 'http'], $credentials['shopUrl']) : '';

        if ($entity == 'attribute') {
            $mapping = $this->em->getRepository('WpmlProductBundle:DataMapping')->findOneBy([
                'code' => $code,
                'entityType' => $entity,
                'apiUrl' => $apiUrl,
                'jobInstanceId' => $attrId,
            ]);
        } else {
            $mapping = $this->em->getRepository('WpmlProductBundle:DataMapping')->findBy([
                'code' => $code,
                'entityType' => $entity,
                'apiUrl' => $apiUrl,
                'jobInstanceId' => $attrId,
            ]);
        }

        return $mapping;
    }

    public function deleteWpmlMapping($mappings)
    {
        if (is_array($mappings) && $mappings) {
            foreach ($mappings as $mapping) {
                $this->em->remove($mapping);
            }
        } else {
            $this->em->remove($mappings);
        }

        $this->em->flush();
    }

    public function getOptionByProduct($exportAttributeCodes, $channel, $defaultLocale, $allLocales, $currency)
    {
        $valuesProductLocale = [];
        $productRepository = $this->productRepo;

        $qb = $productRepository->createQueryBuilder('p');
        $qb->select('attr.code', 'p.id')
            ->innerJoin('p.family', 'fv')
            ->innerJoin('fv.attributes', 'attr')
            ->where('attr.code in (:codes)')
            ->setParameter('codes', $exportAttributeCodes)
            ->distinct(true);

        $variantProductsAxes = $qb->getQuery()->getResult();

        foreach ($variantProductsAxes as $variantProductAxe) {
            if (isset($variantProductAxe['id']) && isset($variantProductAxe['code'])) {
                $entity = $productRepository->findOneById($variantProductAxe['id']);

                if ($this->checkLocale($variantProductAxe['code'])) {
                    if ($this->checkScope($variantProductAxe['code'])) {
                        $value = isset($entity->getRawValues()[$variantProductAxe['code']]) ? $entity->getRawValues()[$variantProductAxe['code']][$channel] : '';
                        if ($value) {
                            if (in_array($variantProductAxe['code'], $this->getPriceAttributeCodes())) {
                                $optionValue = [];
                                foreach ($value as $key => $values) {
                                    foreach ($values as $val) {
                                        if ($val['currency'] == $currency) {
                                            if ($val['amount']) {
                                                $optionValue[$key] = $val['amount'].' '.$currency;
                                            }
                                        }
                                    }
                                }
                                $value = $optionValue;
                            } elseif (in_array($variantProductAxe['code'], $this->getMetricAttributeCodes())) {
                                $optionValue = [];
                                foreach ($value as $key => $val) {
                                    if ($val['amount']) {
                                        $optionValue[$key] = $val['amount'].' '.$val['unit'];
                                    }
                                }
                                $value = $optionValue;
                            }

                            if (isset($value[$defaultLocale])) {
                                $valuesProductLocale[] = [
                                    'code' => $this->convertToCode($value[$defaultLocale]),
                                    'attribute' => $variantProductAxe['code'],
                                    'sort_order' => 0,
                                    'labels' => $value,
                                ];
                            }
                        }
                    } else {
                        $value = isset($entity->getRawValues()[$variantProductAxe['code']]) ? $entity->getRawValues()[$variantProductAxe['code']]['<all_channels>'] : null;
                        if ($value) {
                            if (in_array($variantProductAxe['code'], $this->getPriceAttributeCodes())) {
                                $optionValue = [];
                                foreach ($value as $key => $values) {
                                    foreach ($values as $val) {
                                        if ($val['currency'] == $currency) {
                                            if ($val['amount']) {
                                                $optionValue[$key] = $val['amount'].' '.$currency;
                                            }
                                        }
                                    }
                                }
                                $value = $optionValue;
                            } elseif (in_array($variantProductAxe['code'], $this->getMetricAttributeCodes())) {
                                $optionValue = [];
                                foreach ($value as $key => $val) {
                                    if ($val['amount']) {
                                        $optionValue[$key] = $val['amount'].' '.$val['unit'];
                                    }
                                }
                                $value = $optionValue;
                            }
                            if (isset($value[$defaultLocale])) {
                                $valuesProductLocale[] = [
                                    'code' => $this->convertToCode($value[$defaultLocale]),
                                    'attribute' => $variantProductAxe['code'],
                                    'sort_order' => 0,
                                    'labels' => $value,
                                ];
                            }
                        }
                    }
                } else {
                    $value = $entity->getValue($variantProductAxe['code']);
                    if ($value) {
                        $option = $value->getData();

                        if ($option) {
                            if (in_array($variantProductAxe['code'], $this->getPriceAttributeCodes())) {
                                $optionValue = null;
                                foreach ($option as $opt) {
                                    if ($opt->getCurrency() == $currency) {
                                        if ($opt->getData()) {
                                            $optionValue = $opt->getData().' '.$currency;
                                        }
                                    }
                                }
                                $option = $optionValue;
                            } elseif (in_array($variantProductAxe['code'], $this->getMetricAttributeCodes())) {
                                if ($option->getData()) {
                                    $option = $option->getData().' '.$option->getUnit();
                                }
                            }
                        }

                        $labels = [];
                        foreach ($allLocales as $locale) {
                            $labels[$locale] = $option;
                        }

                        $valuesProductLocale[] = [
                            'code' => $this->convertToCode($option),
                            'attribute' => $variantProductAxe['code'],
                            'sort_order' => 0,
                            'labels' => $labels,
                        ];
                    }
                }
            }
        }

        return $valuesProductLocale;
    }

    protected function getOptionByProductModel($exportAttributeCodes, $channel, $defaultLocale, $allLocales, $currency)
    {
        $valuesProductLocale = [];
        $productRepository = $this->productModelRepo;

        $qb = $productRepository->createQueryBuilder('p');
        $qb->select('attr.code', 'p.id')
            ->innerJoin('p.familyVariant', 'fv')
            ->innerJoin('fv.family', 'f')
            ->innerJoin('f.attributes', 'attr')
            ->where('attr.code in (:codes)')
            ->setParameter('codes', $exportAttributeCodes)
            ->distinct(true);

        $variantProductsAxes = $qb->getQuery()->getResult();

        foreach ($variantProductsAxes as $variantProductAxe) {
            if (isset($variantProductAxe['id']) && isset($variantProductAxe['code'])) {
                $entity = $productRepository->findOneById($variantProductAxe['id']);

                if ($this->checkLocale($variantProductAxe['code'])) {
                    if ($this->checkScope($variantProductAxe['code'])) {
                        $value = isset($entity->getRawValues()[$variantProductAxe['code']]) ? $entity->getRawValues()[$variantProductAxe['code']][$channel] : '';
                        if ($value) {
                            if (in_array($variantProductAxe['code'], $this->getPriceAttributeCodes())) {
                                $optionValue = [];
                                foreach ($value as $key => $values) {
                                    foreach ($values as $val) {
                                        if ($val['currency'] == $currency) {
                                            if ($val['amount']) {
                                                $optionValue[$key] = $val['amount'].' '.$currency;
                                            }
                                        }
                                    }
                                }
                                $value = $optionValue;
                            } elseif (in_array($variantProductAxe['code'], $this->getMetricAttributeCodes())) {
                                $optionValue = [];
                                foreach ($value as $key => $val) {
                                    if ($val['amount']) {
                                        $optionValue[$key] = $val['amount'].' '.$val['unit'];
                                    }
                                }
                                $value = $optionValue;
                            }
                            if (isset($value[$defaultLocale])) {
                                $valuesProductLocale[] = [
                                    'code' => $this->convertToCode($value[$defaultLocale]),
                                    'attribute' => $variantProductAxe['code'],
                                    'sort_order' => 0,
                                    'labels' => $value,
                                ];
                            }
                        }
                    } else {
                        $value = isset($entity->getRawValues()[$variantProductAxe['code']]) ? $entity->getRawValues()[$variantProductAxe['code']]['<all_channels>'] : null;
                        if ($value) {
                            if (in_array($variantProductAxe['code'], $this->getPriceAttributeCodes())) {
                                $optionValue = [];
                                foreach ($value as $key => $values) {
                                    foreach ($values as $val) {
                                        if ($val['currency'] == $currency) {
                                            if ($val['amount']) {
                                                $optionValue[$key] = $val['amount'].' '.$currency;
                                            }
                                        }
                                    }
                                }
                                $value = $optionValue;
                            } elseif (in_array($variantProductAxe['code'], $this->getMetricAttributeCodes())) {
                                $optionValue = [];
                                foreach ($value as $key => $val) {
                                    if ($val['amount']) {
                                        $optionValue[$key] = $val['amount'].' '.$val['unit'];
                                    }
                                }
                                $value = $optionValue;
                            }
                            if (isset($value[$defaultLocale])) {
                                $valuesProductLocale[] = [
                                    'code' => $this->convertToCode($value[$defaultLocale]),
                                    'attribute' => $variantProductAxe['code'],
                                    'sort_order' => 0,
                                    'labels' => $value,
                                ];
                            }
                        }
                    }
                } else {
                    $value = $entity->getValue($variantProductAxe['code']);
                    if ($value) {
                        $option = $value->getData();
                        if ($option) {
                            if (in_array($variantProductAxe['code'], $this->getPriceAttributeCodes())) {
                                $optionValue = null;
                                foreach ($option as $opt) {
                                    if ($opt->getCurrency() == $currency) {
                                        if ($opt->getData()) {
                                            $optionValue = $opt->getData().' '.$currency;
                                        }
                                    }
                                }
                                $option = $optionValue;
                            } elseif (in_array($variantProductAxe['code'], $this->getMetricAttributeCodes())) {
                                if ($option->getData()) {
                                    $option = $option->getData().' '.$option->getUnit();
                                }
                            }
                        }
                        $labels = [];
                        foreach ($allLocales as $locale) {
                            $labels[$locale] = $option;
                        }
                        $valuesProductLocale[] = [
                            'code' => $this->convertToCode($option),
                            'attribute' => $variantProductAxe['code'],
                            'sort_order' => 0,
                            'labels' => $labels,
                        ];
                    }
                }
            }
        }

        return $valuesProductLocale;
    }

    public function getMetricAttributeCodes()
    {
        return $this->attributesRepo->getAttributeCodesByType(
            'pim_catalog_metric'
        );
    }
    
    // public function getShopUrls()
    // {
    //     $shopUrls = [];
    //     $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
    //     $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
    //     $credentials = $this->getCredentialById($exportProfile);
       
    //     var_dump($params);die;
       
    //     $url = $credentials[0]->getShopUrl();
    //     if ($url) {
    //         $shopUrls[] = $url;
    //     }
    //     return $shopUrls ? array_unique($shopUrls) : [];
    // }


    public function getShopUrls()
    {
        
        $shopUrls = [];
        $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
        $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
     
       $credentials = $this->getCredentialById($exportProfile);
        
        if ($credentials) {
            $url = array_key_exists('shopUrl', $credentials) ? str_replace(['/wp-admin', 'shop/','https'], ['','','http'], $credentials['shopUrl']) : '';
            if ($url) {
                $shopUrls[] = $url;
            }
        }
       
        return $shopUrls ? array_unique($shopUrls) : [];
    }

    public function getMultiSetting($section) 
    {
        $params = $this->stepExecution ? $this->stepExecution->getJobparameters()->all() : null;
        $exportProfile = (!empty($params['exportProfile'])) ? $params['exportProfile'] : "";
        if(empty($exportProfile)) {
            $credential = $this->em->getRepository(CredentialConfig::class)->findOneByDefaultSet(1);
        } else {
            $credential = $this->em->getRepository(CredentialConfig::class)->findOneById($exportProfile);
        }

        if($credential) {
            $credentials = [
                'extraResources' => $credential->getextraResources()
            ];

            if (empty($settings)) {
                $configs = $credentials['extraResources'][$section];               
               
                $settings = $this->indexMultiValuesByName($configs);
                
            }
            return $settings;
        } 
    }

    private function indexMultiValuesByName($values)
    {
        $result = [];
        foreach ($values as $key => $value) {
           $result[$key] = $value;
        }
        
        return $result;
    }

    public function getMultiOtherMappings()
    {
        $mapping = $this->getMultiSetting('other_mappings');
        $mappings['custom_fields'] = isset($mapping['custom_fields']) ? $mapping['custom_fields'] : [];
        $mappings['images'] = isset($mapping['images']) ? $mapping['images'] : [];
        $mappings['files'] = isset($mapping['files']) ? $mapping['files'] : [];
        
        return $mappings;
    }
    

}