<?php
/**
 * @author 1902 Software
 * @copyright Copyright © 2023 1902 Software (https://1902software.com/magento/)
 * @package WriteTextAI_WriteTextAI
 */

namespace WriteTextAI\WriteTextAI\Helper;

class Data extends Settings
{
    /**
     * Get API auth Url
     *
     * @return string
     */
    public function getApiAuthUrl()
    {
        return $this->getApiSettings('auth_url');
    }
    
    /**
     * Get API web Url
     *
     * @return string
     */
    public function getApiWebUrl()
    {
        return $this->getApiSettings('web_url');
    }
    
    /**
     * Get Signalr Url
     *
     * @return string
     */
    public function getSignalrUrl()
    {
        $signalRUrl =  $this->getApiSettings('signalr_url');
        $regionUrl = (string) $this->getApiSettings('region');
        if ($regionUrl) {
            $signalRUrl = sprintf($signalRUrl, $regionUrl);
        }
        return $signalRUrl;
    }

    /**
     * Get API region Url
     *
     * @return string
     */
    public function getRegion()
    {
        $region = (string) $this->getApiSettings('region');
        $regionUrl = $region;
        if (substr($regionUrl, 0, 4) !== "http") {
            $regionUrl = "https://{$region}/";
        }

        return $regionUrl;
    }

    /**
     * Get API client id
     *
     * @return string
     */
    public function getClientId()
    {
        return $this->getApiSettings('client_id');
    }

    /**
     * Get account token
     *
     * @return string
     */
    public function getAccountToken()
    {
        return $this->getApiSettings('account_token');
    }

    /**
     * Check if logger is enabled
     *
     * @return bool
     */
    public function isLoggerEnabled()
    {
        return (bool)$this->getApiSettings('enable_logger');
    }

    /**
     * Get tones
     *
     * @return string
     */
    public function getTones()
    {
        return $this->getGeneralSettings('tones');
    }

    /**
     * Get styles
     *
     * @return string
     */
    public function getStyles()
    {
        return $this->getGeneralSettings('styles');
    }

    /**
     * Get audiences
     *
     * @return string
     */
    public function getAudiences()
    {
        return $this->getGeneralSettings('audiences');
    }

    /**
     * Is translation notice enabled
     */
    public function isTranslationNoticeEnabled()
    {
        return (bool)$this->getTranslationSettings('notice');
    }

    /**
     * Set account token
     *
     * @param string $token
     *
     * @return void
     */
    public function setAccountToken($token)
    {
        $this->setConfig(self::API_SETTINGS_CONFIG_PATH . 'account_token', $token);
    }

    /**
     * Set region
     *
     * @param string $region
     *
     * @return void
     */
    public function setRegion($region)
    {
        $this->setConfig(self::API_SETTINGS_CONFIG_PATH . 'region', $region);
    }

    /**
     * Check if custom open graph is enabled
     *
     * @return bool
     */
    public function getCustomOpenGraph()
    {
        return (bool)$this->getMappingSettings('custom_open_graph');
    }
    
    /**
     * Get data mapping fields
     *
     * @return array
     */
    public function getDataMappingFields()
    {
        return [
            'page_title'                => __('Product meta title'),
            'page_description'          => __('Product meta description'),
            'product_description'       => __('Product description'),
            'short_product_description' => __('Product short description'),
            'open_graph'                => __('Product Open Graph')
        ];
    }

    /**
     * Get data mapping fields
     *
     * @return array
     */
    public function getCategoryDataMappingFields()
    {
        return [
            'category_description'      => __('Category description'),
        ];
    }

    /**
     * Get text type attributes
     *
     * @return array
     */
    public function getTextTypeAttributes()
    {
        return $this->textTypeAttributes->toOptionArray();
    }

       /**
        * Get text type attributes
        *
        * @return array
        */
    public function getCateoryTextTypeAttributes()
    {
        $data = $this->categoryTextTypeAttributes->toOptionArray();
        return $data;
    }

    /**
     * Check if all text fields are mapped to an existing attribute
     *
     * @return boolean
     */
    public function isDataMapped()
    {
        if (empty($this->getMappingSettings())) {
            return false;
        }
        
        $attributes = array_column($this->getTextTypeAttributes(), 'value');
        foreach ($this->getMappingSettings() as $field => $attribute) {
            if ($field === 'open_graph' && !$this->getCustomOpenGraph()) {
                continue;
            }
            if (!$attribute || !in_array($attribute, $attributes)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Get not mapped field
     *
     * @return string
     */
    public function getNotMappedField()
    {
        // Set first field as not mapped field in case all field is not mapped
        $notMappedField = 'page_title';

        if (empty($this->getMappingSettings())) {
            return $this->getFieldLabel($notMappedField);
        }

        $attributes = array_column($this->getTextTypeAttributes(), 'value');
        foreach ($this->getMappingSettings() as $field => $attribute) {
            if ($field === 'open_graph' && !$this->getCustomOpenGraph()) {
                continue;
            }
            if (!$attribute || !in_array($attribute, $attributes)) {
                $notMappedField = $field;
            }
        }

        return $this->getFieldLabel($notMappedField);
    }

    /**
     * Get field label
     *
     * @param string $field
     * @return string
     */
    public function getFieldLabel($field)
    {
        switch ($field) {
            case 'page_title':
                return __('Meta title');
            case 'page_description':
                return __('Meta description');
            case 'product_description':
                return __('Description');
            case 'short_product_description':
                return __('Short description');
            case 'open_graph':
                return __('Open Graph text');
        }
    }

    /**
     * Check if final step is done
     *
     * @return boolean
     */
    public function isFinalStepDone()
    {
        $keywordOptimizationFields = $this->getKeywordOptimizationSettings();

        $generalFields = $this->getGeneralSettings();
        if (empty($generalFields) || empty($keywordOptimizationFields)) {
            return false;
        }

        $keywordMergedArray = array_merge($keywordOptimizationFields, $keywordOptimizationFields['pipeline_keyword']);
        unset($keywordMergedArray['pipeline_keyword']);
        
        $requiredFields = [
            'tones',
            'styles',
        ];

        foreach ($generalFields as $field => $value) {
            if (empty($value) && in_array($field, $requiredFields)) {
                return false;
            }
        }

        $requiredKeywords = [
            'cluster_based_pipelines_count',
            'notification',
            'trigger_action',
            'trigger_action_n_position',
            'trigger_action_n_days',
            'automatic_text_optimization',
            'products',
            'categories',
            'trigger_action_n_days',
            'trigger_action_n_position'
        ];
        
        foreach ($keywordMergedArray as $field => $value) {
            if (empty($value) && in_array($field, $requiredKeywords)) {
                if ($field === 'trigger_action_n_position') {
                    if ($keywordMergedArray['trigger_action'] !== 'when_page_is_ranking') {
                        continue;
                    }
                }
                if ($field === 'trigger_action_n_days') {
                    if ($keywordMergedArray['trigger_action'] !== 'after_n_days') {
                        continue;
                    }
                }
                if ($field === 'products' ||
                    $field === 'categories' ||
                    $field === 'automatic_text_optimization') {
                    if ($keywordMergedArray['trigger_action'] === 'none') {
                        continue;
                    }
                }
                if ($field === 'cluster_based_pipelines_count') {
                    if ($value === '0') {
                        continue;
                    }
                }
                return false;
            }
        }

        return true;
    }

    /**
     * Check if setup is finalized
     *
     * @return bool
     */
    public function isSetupFinalized()
    {
        return $this->getSetupSettings('finalized');
    }

    /**
     * Get attributes values
     *
     * @param \Magento\Catalog\Api\Data\ProductInterface $product
     * @param string $field
     * @return string
     */
    public function getAttributesValues($product, $field)
    {
        $mapping = $this->getMappingSettings();
        $html = '';

        if (isset($mapping[$field])) {
            $attribute = $mapping[$field];
            $value = $product->getData($attribute);
            
            if ($value) {
                $html = $this->catalogOutput->productAttribute($product, $value, $attribute);
            }
        }

        return $html;
    }

    /**
     * Get Automatic Text Optimizations options
     *
     * @param bool $usedInFilter
     * @return array
     */
    public function getAutomaticTextOptimizationOptions($usedInFilter = false)
    {
        $automaticTextOptimization = $this->automaticTextOptimization->toOptionArray();
        if ($usedInFilter) {
            $automaticTextOptimization = $this->automaticTextOptimization->toOptionArrayForFilters();
        }
        return $automaticTextOptimization;
    }
    
    /**
     * Get force failed
     *
     * @return string
     */
    public function getForceFailed()
    {
        return $this->getDevSettings('force_failed');
    }

    /**
     * Get ko dev
     *
     * @return string
     */
    public function getKoDev()
    {
        return $this->getDevSettings('ko_dev');
    }

    /**
     * Get build no
     *
     * @return string
     */
    public function getBuildNo()
    {
        return $this->getDevSettings('build_no');
    }

    /**
     * Get ko static url
     *
     * @return string
     */
    public function getKoStaticUrl()
    {
        return $this->getDevSettings('ko_static_url');
    }

    /**
     * Get first visit cannibalization
     *
     * @return string
     */
    public function isFirstVisitCannibalization()
    {
        $visited = filter_var($this->getCannibalizationSettings('first_visit'), FILTER_VALIDATE_BOOLEAN);

        return !$visited;
    }

    /**
     * Get config timezone
     *
     * @return string
     */
    public function getConfigTimezone()
    {
        return $this->conf('general/locale/timezone');
    }

    /**
     * Get formatted timezone
     *
     * @return string
     */
    public function getFormattedTimezone()
    {
        $configTimeZone = $this->conf('general/locale/timezone');
        $datetime = new \DateTime("now", new \DateTimeZone($configTimeZone));
        $offsetInSeconds = $datetime->getOffset();
        $offsetHours = $offsetInSeconds / 3600;
        $prefix = $offsetHours >= 0 ? '+' : '-';
        $formattedTimeZone = 'UTC' . $prefix . str_pad((string) abs($offsetHours), 2, '0', STR_PAD_LEFT);
        return $formattedTimeZone;
    }

    /**
     * Convert time to config timezone
     * 
     * @param string $time
     * @return string
     */
    public function convertToConfigTimezone($time)
    {
        //get time based on config timezone
        $configTimeZone = $this->getConfigTimezone();
        $datetime = new \DateTime($time, new \DateTimeZone($configTimeZone));
        //convert back to utc
        $datetime->setTimezone(new \DateTimeZone('UTC'));
        return $datetime->format('H:i');
    }

    /**
     * Convert time to store timezone
     * 
     * @param string $time
     * @return string
     */
    public function convertToStoreTimezone($time)
    {
        //convert to utc
        $datetime = new \DateTime($time, new \DateTimeZone('UTC'));
        //convert back to store timezone
        $storeTimeZone = $this->getConfigTimezone();
        $datetime->setTimezone(new \DateTimeZone($storeTimeZone));
        return $datetime->format('H:i');
    }

    /**
     * Convert cron expression to time
     * 
     * @param string $cron
     * @return string
     */
    public function cronToTime(string $cron){
        // Split cron expression
        $parts = preg_split('/\s+/', trim($cron));
        if (count($parts) < 2) {
            return null; // Invalid expression
        }
    
        [$minute, $hour] = $parts;
    
        // Handle wildcards
        if ($minute === '*') $minute = '00';
        if ($hour === '*') $hour = '00';
    
        // Ensure formatting
        $minute = str_pad($minute, 2, '0', STR_PAD_LEFT);
        $hour   = str_pad($hour, 2, '0', STR_PAD_LEFT);
    
        return "{$hour}:{$minute}";
    }

    /**
     * Get formatted auto transfer time label (HH:mm <timezone>)
     *
     * @return string
     */
    public function getAutoTransferTimeLabel(): string
    {
        // Get cron schedule from config
        $cronExpr = $this->getAutotransferSettings('cron_schedule');
        // Default fallback
        $hour = '00';
        $minute = '00';
        if (preg_match('/^(\d{1,2}) (\d{1,2})/', $cronExpr, $matches)) {
            $minute = str_pad($matches[1], 2, '0', STR_PAD_LEFT);
            $hour = str_pad($matches[2], 2, '0', STR_PAD_LEFT);
        }
        $formattedTimeZone = $this->getFormattedTimezone();
        return sprintf('%s:%s %s', $hour, $minute, $formattedTimeZone);
    }

    /**
     * Convert to cron schedule
     * 
     * @param string $time
     * @return string
     */
    public function convertToCronSchedule($hourString)
    {
        // $hourString sample = 18:00
        // get only 18
        $hour = explode(':', $hourString)[0];
        $hourPadded = str_pad($hour, 2, '0', STR_PAD_LEFT); // 18 -> 18
        return "00 {$hourPadded} * * *"; // 00 18 * * *
    }
}
