<?php

namespace Webkul\ShopifyBundle\Connector\Writer;

class ProductTranslationUpdater extends BaseWriter
{
    const DEFAULTS_SECTION = 'shopify_connector_defaults';

    const INVENTORY_LOCATION = 'inventory_locations';

    const OTHER_SETTING_SECTION = 'shopify_connector_others';
    
    protected $mappedFields;
    
    protected $defaultValues;
 
    protected $jobLocales;

    protected $storeLocaleMapping;

    protected $otherSettings;

    protected $shopifyDefaultLocale;

    public function updateTransaltion($productId, $baseCurrency, $defaultLocale, $item)
    {
        $credential = $this->connectorService->getCredentials();
        if (!$this->mappedFields) {
            $this->mappedFields = $this->connectorService->getSettings();
            $this->defaultValues = $this->connectorService->getSettings(self::DEFAULTS_SECTION);
            // $this->jobLocales = $this->stepExecution->getJobParameters()->get('filters')['structure']['locales'];
            $this->storeLocaleMapping = $credential['storelocaleMapping'] ?? [];
            $this->channel = $this->getDefaultScope();
        }
        
        if (empty($this->storeLocaleMapping)) {
            return;
        }
       
        $formatedVariable = $this->formatData($productId, $baseCurrency, $defaultLocale, $item);

        if ($formatedVariable) {
            $credential = new \Webkul\ShopifyBundle\Classes\GraphQLApiClient($credential['shopUrl'], $credential['apiPassword'], $credential['apiVersion']);
    
            $response = $credential->request('createTranslation', $formatedVariable);
            $response = json_decode($response, 1);
        }
    }

    protected function formatData($productId, $baseCurrency, $defaultLocale, $item)
    {
        $formatedVariable = [
            'id' => "gid://shopify/Product/" . $productId,
            "translations" => []
        ];
        
        
        $attributes = $this->formatAttributes($item['values'], $baseCurrency, true);
        
        
        foreach ($this->translationShopifyFields as $translationShopifyField) {
            if (isset($this->mappedFields[$translationShopifyField])) {
                if (is_array(json_decode($this->mappedFields[$translationShopifyField]))) {
                    continue;
                }
                $akeneoAttributeCode = $this->mappedFields[$translationShopifyField];
                if (isset($attributes[$akeneoAttributeCode])) {
                    $defaultValue = $attributes[$akeneoAttributeCode][$defaultLocale];
                    // $defaultValue = strip_tags($defaultValue);
                    foreach ($this->storeLocaleMapping as $shopifyLocaleCode => $akeneoLocaleCode) {
                        if (in_array($akeneoLocaleCode, $this->jobLocales) && $shopifyLocaleCode !== $this->shopifyDefaultLocale) {
                            $value = $attributes[$akeneoAttributeCode][$akeneoLocaleCode] ?? '';
                            $formatedVariable['translations'][] = [
                                'key' => $translationShopifyField,
                                'value' => $value,
                                'locale' => $shopifyLocaleCode,
                                'translatableContentDigest' => hash('sha256', $defaultValue)
                            ];
                        }
                    }
                }
            }
        }

        return !empty($formatedVariable['translations']) ? $formatedVariable : null;
    }


    protected $translationShopifyFields = [
        'title',
        'body_html',
        'meta_title',
        'meta_description'
    ];

    /**
     * formatAttributes according to types
     */
    public function formatAttributes($attributes, $baseCurrency, $withMetricUnit)
    {
        $withMetricUnitValue = false;
        $formatedAttributes = [];
        foreach ($this->jobLocales as $locale) {
            foreach ($attributes as $name => $value) {
                $attributeTypes = $this->connectorService->getAttributeAndTypes();
                if ($withMetricUnit && $attributeTypes[$name] === 'pim_catalog_metric') {
                    $withMetricUnitValue =  true;
                }
    
                $formatedValue = $this->formatValue($value, $baseCurrency, $locale, $withMetricUnitValue);
                switch ($attributeTypes[$name]) {
                    case 'pim_catalog_simpleselect':
                    case 'pim_reference_data_simpleselect':
                        if (isset($this->mappedFields[self::INVENTORY_LOCATION]) && $name === $this->mappedFields[self::INVENTORY_LOCATION]) {
                            $value = $formatedValue;
                            break;
                        }
                        $value = $this->connectorService->getOptionNameByCodeAndLocale($name . '.' . $formatedValue, $locale);
                        break;
                    case 'pim_catalog_multiselect':
                    case 'pim_reference_data_multiselect':
                        $vals = [];
                        foreach ($formatedValue as $val) {
                            $vals[] = $this->connectorService->getOptionNameByCodeAndLocale($name . '.' . $val, $locale);
                        }
                        $value = implode(',', $vals);
                        break;
                    case 'pim_catalog_number':
                        $value = (int)$formatedValue;
                        break;
                    case 'pim_catalog_date':
                        $value = $this->formatDate($formatedValue);
                        break;
                    case 'pim_catalog_boolean':
                        $value = $formatedValue || strtolower($formatedValue) == 'yes' ? 'Yes' : 'No';
                        break;
                    case 'pim_catalog_metric':
                        $value = $this->connectorService->formateMatricValue($formatedValue);
                        break;
                    case 'pim_catalog_image':
                    case 'pim_catalog_file':
                    case 'pim_catalog_identifier':
                    case 'pim_catalog_price_collection':
                    case 'pim_catalog_text':
                    case 'pim_catalog_textarea':
                        $value = (string)$formatedValue;
                        break;
                }
                $formatedAttributes[$name][$locale] = $value;
            }
        }
        
        return $formatedAttributes;
    }

    private function formatValue($value, $baseCurrency, $locale, $withMetricUnit = false)
    {
        if (is_array($value)) {
            foreach ($value as $key => $aValue) {
                if (is_array($aValue)) {
                    if (isset($aValue['scope']) &&  $aValue['scope'] !== $this->channel) {
                        continue;
                    }
                    if (array_key_exists('locale', $aValue)) {
                        if (!$aValue['locale'] || $aValue['locale'] == $locale) {
                            $newValue = $aValue['data'];
                            break;
                        }
                    } else {
                        break;
                    }
                } else {
                    break;
                }
            }
        }
        $value = isset($newValue) ? $newValue : null;
        if ($value && is_array($value)) {
            /* price */
            foreach ($value as $key => $aValue) {
                if (is_array($aValue)) {
                    if (array_key_exists('currency', $aValue)) {
                        if (!$aValue['currency'] || $aValue['currency'] == $baseCurrency) {
                            $value = $aValue['amount'];
                            break;
                        }
                        if ($key == count($value)-1) {
                            $value = !empty($value[0]['amount']) ? $value[0]['amount'] : null ;
                        }
                    }
                } else {
                    break;
                }
            }
            /* metric */
            if (is_array($value) && array_key_exists('unit', $value)) {
                if ($withMetricUnit) {
                    $value = !empty($value['amount']) ? $value['amount'] . ' ' . $value['unit'] : null;
                } else {
                    $value = !empty($value['amount']) ? $value['amount'] : null;
                }
            }
        }

        return $value;
    }

    private function formatDate($date)
    {
        $dateObj = new \DateTime($date);

        return $dateObj->format('Y-m-d H:i:s');
    }

    protected function getDefaultScope()
    {
        try {
            $filters = $this->stepExecution->getJobParameters()->get('filters');
            if (isset($filters['structure']['scope'])) {
                $scope = $this->stepExecution->getJobParameters()->get('filters')['structure']['scope'];
            } else {
                $scope = $this->stepExecution->getJobParameters()->get('filters')[0]['context']['scope'];
            }
        } catch (\Exception $e) {
            $scope = '';
        }

        return $scope;
    }

    public function updateMetafieldTranslation($baseCurrency, $defaultLocale, $item, $addedMetaFields)
    {

        $formatedVariable = [
            'id' => "gid://shopify/ProductVariant/40339717947587",
            "translations" => []
        ];
        $formatedVariable['translations'][] = [
            'key' => 'option1',
            'value' => 'Blue-fr',
            'locale' => 'fr',
            'translatableContentDigest' => hash('sha256', 'Blue')
        ];


        $credential = $this->connectorService->getCredentials();
        if (!$this->mappedFields) {
            $this->mappedFields = $this->connectorService->getSettings();
            $this->defaultValues = $this->connectorService->getSettings(self::DEFAULTS_SECTION);
            // $this->jobLocales = $this->stepExecution->getJobParameters()->get('filters')['structure']['locales'];
            $this->storeLocaleMapping = $credential['storelocaleMapping'] ?? [];
            $this->channel = $this->getDefaultScope();
            $this->shopifyDefaultLocale = $credential['store_locales']['defaultLocale'];
        }
        
        $attributes = $this->formatAttributes($item['values'], $baseCurrency, true);
        
        $graphQLApiClient = new \Webkul\ShopifyBundle\Classes\GraphQLApiClient($credential['shopUrl'], $credential['apiPassword'], $credential['apiVersion']);        
        foreach ($addedMetaFields as $addedMetaField) {
            $formatedVariable = [
                'id' => "gid://shopify/Metafield/".$addedMetaField['id'],
                "translations" => []
            ];
            
            foreach ($this->storeLocaleMapping as $shopifyLocaleCode => $akeneoLocaleCode) {
                if (in_array($akeneoLocaleCode, $this->jobLocales) && $akeneoLocaleCode !== $defaultLocale) {
                    $value = $attributes[$addedMetaField['key']][$akeneoLocaleCode] ?? '';
                    $formatedVariable['translations'][] = [
                        'key' => 'value',
                        'value' => $value,
                        'locale' => $shopifyLocaleCode,
                        'translatableContentDigest' => hash('sha256', $addedMetaField['value'])
                    ];
                }
            }
            
            if ($formatedVariable) {                
                $response = $graphQLApiClient->request('createTranslation', $formatedVariable);
                $response = json_decode($response, 1);
                
            }
        }
    }

    public function updateProductOptionsAndVariantTranslation($baseCurrency, $defaultLocale, $item, $options, $variantId)
    {
        $credential = $this->connectorService->getCredentials();
        if (!$this->mappedFields) {
            $this->mappedFields = $this->connectorService->getSettings();
            $this->defaultValues = $this->connectorService->getSettings(self::DEFAULTS_SECTION);
            // $this->jobLocales = $this->stepExecution->getJobParameters()->get('filters')['structure']['locales'];
            $this->storeLocaleMapping = $credential['storelocaleMapping'] ?? [];
            $this->channel = $this->getDefaultScope();
        }

        if (!$this->otherSettings) {
            $this->otherSettings = $this->connectorService->getScalarSettings(self::OTHER_SETTING_SECTION);
        }

        $graphQLApiClient = new \Webkul\ShopifyBundle\Classes\GraphQLApiClient($credential['shopUrl'], $credential['apiPassword'], $credential['apiVersion']);
        
        $attributes = $this->formatAttributes($item['values'], $baseCurrency, true);
        $variants = [];
        $optionsName = [];
        foreach ($item['variantAttributes'] as $key => $attrCode) {
            
            if (!empty($attributes[$attrCode]) && !empty($attrCode)) {
                if (isset($this->otherSettings['option_name_label']) && true === $this->otherSettings['option_name_label']) {
                    $attributeLabel = $this->connectorService->getAttributeLabelByCodeAndLocale($attrCode, $defaultLocale);
                } else {
                    $attributeLabel = $attrCode;
                }
                $optionsName[$attributeLabel] = $attrCode;
            }
            $variants['option' . (1+$key)] = $attributes[$attrCode];
        }
        
        

        $this->addVariantTranslation($variants, $variantId, $defaultLocale, $graphQLApiClient);
        $this->addOptionsTranslations($options, $optionsName, $defaultLocale, $graphQLApiClient);
    }

    protected function addOptionsTranslations($options, $optionsName, $defaultLocale, $graphQLApiClient)
    {
        foreach($options as $option) {
            $formatedVariable = [
                'id' => "gid://shopify/ProductOption/".$option['id'],
                "translations" => []
            ];
            $defaultValue = $option['name'];

            foreach ($this->storeLocaleMapping as $shopifyLocaleCode => $akeneoLocaleCode) {
                if (in_array($akeneoLocaleCode, $this->jobLocales) && $akeneoLocaleCode !== $defaultLocale) {
                    $attrCode = $optionsName[$option['name']];
                    $attrLabel = $this->connectorService->getAttributeLabelByCodeAndLocale($attrCode, $akeneoLocaleCode);
                    $formatedVariable['translations'][] = [
                        'key' => 'name',
                        'value' => $attrLabel,
                        'locale' => $shopifyLocaleCode,
                        'translatableContentDigest' => hash('sha256', $defaultValue)
                    ];
                }
            }
            if ($formatedVariable) {                
                $response = $graphQLApiClient->request('createTranslation', $formatedVariable);
                $response = json_decode($response, 1);
            } 
            
        }
    }

    protected function addVariantTranslation($variants, $variantId, $defaultLocale, $graphQLApiClient)
    {
        
        foreach ($variants as $variantKey => $variantValue) {
            $formatedVariable = [
                'id' => "gid://shopify/ProductVariant/".$variantId,
                "translations" => []
            ];
            $defaultValue = $variantValue[$defaultLocale];
            foreach ($this->storeLocaleMapping as $shopifyLocaleCode => $akeneoLocaleCode) {
                if (in_array($akeneoLocaleCode, $this->jobLocales) && $akeneoLocaleCode !== $defaultLocale) {
                    $value = $variantValue[$akeneoLocaleCode];
                    $formatedVariable['translations'][] = [
                        'key' => $variantKey,
                        'value' => $value,
                        'locale' => $shopifyLocaleCode,
                        'translatableContentDigest' => hash('sha256', $defaultValue)
                    ];
                }
            }

            if ($formatedVariable) {                
                $response = $graphQLApiClient->request('createTranslation', $formatedVariable);
                $response = json_decode($response, 1);
            } 
        }
    }
}
