<?php
/**
 * @copyright    OCTemplates
 * @support      https://octemplates.net/
 * @license      LICENSE.txt
 */

class ModelOCTemplatesStickersOctStickers extends Model {

    public function getOCTStickers($result) {
        $oct_stickers_data = [];
        $oct_stickers = [];
    
        if ($this->config->get('oct_stickers_status') && !empty($result['product_id'])) {
            $languageId = (int)$this->config->get('config_language_id');
    
            $this->db->query("SET NAMES 'utf8mb4'");
    
            $query = $this->db->query(
                "SELECT `stickers_json` FROM `" . DB_PREFIX . "oct_product_stickers`
                 WHERE `product_id` = '" . (int)$result['product_id'] . "'
                 LIMIT 1"
            );
    
            if ($query->num_rows) {
                $decoded = json_decode($query->row['stickers_json'], true);
                if (!empty($decoded[$languageId]) && is_array($decoded[$languageId])) {
                    $oct_stickers_data['stickers'] = $decoded[$languageId];
                }
            }
    
            if (!empty($oct_stickers_data['stickers'])) {
                $complex = [];
                $simple = [];
    
                foreach ($oct_stickers_data['stickers'] as $key => $sticker) {
                    if (is_array($sticker) && !empty($sticker['image'])) {
                        $complex[$key] = $sticker;
                    } else {
                        $simple[$key] = $sticker;
                    }
                }
    
                $sortedStickers = array_merge($complex, $simple);
                $oct_stickers_data['stickers'] = $sortedStickers;
    
                foreach ($oct_stickers_data['stickers'] as $sticker_code => $sticker_info) {
                    if (is_array($sticker_info) && !empty($sticker_info['image'])) {
                    $oct_stickers['stickers'][$sticker_code] = [
                        'title'        => $sticker_info['title'] ?? '',
                        'description'  => $sticker_info['description'] ?? '',
                        'image'        => $sticker_info['image'],
                        'image_width'  => isset($sticker_info['image_width']) ? (int)$sticker_info['image_width'] : 20,
                        'image_height' => isset($sticker_info['image_height']) ? (int)$sticker_info['image_height'] : 20,
                        'image_only'   => !empty($sticker_info['image_only']),
                        'sort'         => isset($sticker_info['sort']) ? (int)$sticker_info['sort'] : null
                    ];
                    } elseif (is_array($sticker_info)) {
                        $oct_stickers['stickers'][$sticker_code] = $sticker_info['title'] ?? '';
                    } else {
                        $oct_stickers['stickers'][$sticker_code] = $sticker_info;
                    }
                }
            }
        }

        if (!empty($oct_stickers['stickers']['stickers_special']) && (empty($result['special']) || (float)$result['special'] <= 0)) {
            unset($oct_stickers['stickers']['stickers_special']);
            if (empty($oct_stickers['stickers'])) {
                $oct_stickers = [];
            }
        }
    
        return $oct_stickers;
    }

    public function generateStickersForAllProductsJson() {
        $this->load->model('localisation/language');
        $languages = $this->model_localisation_language->getLanguages();
        $originalLangId = $this->config->get('config_language_id');
    
        $allProducts = $this->getProductsForStickers();
    
        $this->db->query("SET NAMES 'utf8mb4'");
    
        $cache_table = DB_PREFIX . 'oct_product_stickers';
        $this->db->query("TRUNCATE TABLE `{$cache_table}`");
    
        $inserts = [];
        $chunkSize = 500;
    
        foreach ($allProducts as $product) {
            $productId = (int)$product['product_id'];
            $stickersJson = $this->generateStickersJson($product, $languages, $originalLangId);
    
            if ($stickersJson === null) {
                continue;
            }
    
            $inserts[] = "('" . (int)$productId . "', '" . $stickersJson . "')";
    
            if (count($inserts) >= $chunkSize) {
                $this->db->query(
                    "INSERT INTO `{$cache_table}` (`product_id`, `stickers_json`) VALUES " . implode(", ", $inserts)
                );
                $inserts = [];
            }
        }
    
        if (!empty($inserts)) {
            $this->db->query(
                "INSERT INTO `{$cache_table}` (`product_id`, `stickers_json`) VALUES " . implode(", ", $inserts)
            );
        }
    
        $this->config->set('config_language_id', $originalLangId);
    }
    
    public function generateStickersForSingleProductJson($product_id) {
        $rows = $this->getProductsForStickers($product_id);
        if (empty($rows)) {
            return;
        }
    
        $product = $rows[0];
    
        $this->load->model('localisation/language');
        $languages = $this->model_localisation_language->getLanguages();
        $originalLangId = $this->config->get('config_language_id');
    
        $json = $this->generateStickersJson($product, $languages, $originalLangId);
    
        if ($json === null) {
            return;
        }

        $this->db->query("SET NAMES 'utf8mb4'");

        $this->db->query(
            "DELETE FROM `" . DB_PREFIX . "oct_product_stickers` WHERE `product_id` = '" . (int)$product_id . "'"
        );
    
        $this->db->query(
            "INSERT INTO `" . DB_PREFIX . "oct_product_stickers` SET `product_id` = '" . (int)$product_id . "', `stickers_json` = '" . $json . "'"
        );
    }
    
    private function generateStickersJson($product, $languages, $originalLangId) {
        $stickersByLang = [];
    
        foreach ($languages as $lang) {
            $langId = (int)$lang['language_id'];
    
            $this->config->set('config_language_id', $langId);
            $stickersData = $this->getStickersLogic($product);
    
            if (!empty($stickersData['stickers'])) {
                $stickersByLang[$langId] = $stickersData['stickers'];
            }
        }
    
        $this->config->set('config_language_id', $originalLangId);
    
        if (empty($stickersByLang)) {
            return null;
        }
    
        return $this->db->escape(json_encode($stickersByLang, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
    }

    private function getProductsForStickers($product_id = null) {
        $sql = "
            SELECT
                p.product_id,
                p.date_added,
                p.viewed,
                p.quantity,
                p.oct_stickers,
                p.price,
                (
                    SELECT price
                    FROM " . DB_PREFIX . "product_special ps
                    WHERE ps.product_id = p.product_id
                    AND (
                        (ps.date_start = '0000-00-00' OR ps.date_start < NOW())
                        AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())
                    )
                    ORDER BY ps.priority ASC, ps.price ASC
                    LIMIT 1
                ) AS special
            FROM `" . DB_PREFIX . "product` p
            WHERE p.status = '1'
        ";

        if (!is_null($product_id)) {
            $sql .= " AND p.product_id = '" . (int)$product_id . "' LIMIT 1";
        }

        $query = $this->db->query($sql);
        $rows = $query->rows;

        foreach ($rows as &$row) {
            if (!empty($row['oct_stickers'])) {
                $temp = @unserialize($row['oct_stickers']);
                $row['oct_stickers'] = is_array($temp) ? $temp : [];
            } else {
                $row['oct_stickers'] = [];
            }
        }

        return $rows;
    }

    private function getStickersLogic($product_data) {
        $generated = [];
        $generated['stickers'] = [];

        if (!$this->config->get('oct_stickers_status')) {
            return $generated;
        }

        $oct_config = $this->config->get('oct_stickers_data');
        $is_special = (!empty($product_data['special']) && (float)$product_data['special']) ? true : false;

        $sticker_types = ['new', 'bestseller', 'popular', 'special', 'sold', 'ends', 'free_shipping', 'video'];

        foreach ($sticker_types as $type) {
            if ($this->checkAutoSticker($oct_config, $type, $product_data, $is_special)) {
                $generated['stickers']['stickers_' . $type] = $this->buildStickerData($oct_config, $type);
            }
        }

        if (!empty($product_data['oct_stickers'])) {
            $this->load->model('tool/image');
            $current_lang = (int)$this->config->get('config_language_id');

            foreach ($product_data['oct_stickers'] as $sticker_key) {
                $parts = explode('_', $sticker_key);
                if (empty($oct_config[$parts[0]][$parts[1]])) {
                    continue;
                }
                $cfg = $oct_config[$parts[0]][$parts[1]];
                if (empty($cfg['status'])) {
                    continue;
                }
                $title = !empty($cfg['title'][$current_lang]) ? $cfg['title'][$current_lang] : '';
                if (!$title) {
                    continue;
                }
                $description = !empty($cfg['description'][$current_lang]) ? nl2br($cfg['description'][$current_lang]) : false;
                $image = !empty($cfg['image']) ? $cfg['image'] : false;
                $sort_order = isset($cfg['sort']) ? (int)$cfg['sort'] : 0;
                
                $sticker_data = [
                    'title'       => $title,
                    'description' => $description,
                    'sort'        => $sort_order
                ];
                
                if ($image && is_file(DIR_IMAGE . $image)) {
                    $image_resized = $this->model_tool_image->resize($image, 32, 32);
                    $sticker_data['image'] = $image_resized;
                    $sticker_data['image_width'] = !empty($cfg['image_width']) ? (int)$cfg['image_width'] : 20;
                    $sticker_data['image_height'] = !empty($cfg['image_height']) ? (int)$cfg['image_height'] : 20;
                    $sticker_data['image_only'] = !empty($cfg['image_only']) ? true : false;
                }
                
                $generated['stickers']['stickers_' . $parts[1]] = $sticker_data;
            }
        }

        if (!empty($generated['stickers'])) {
            $sorts = [];
            foreach ($generated['stickers'] as $code => $info) {
                $sorts[$code] = isset($info['sort']) ? (int)$info['sort'] : 0;
            }
            array_multisort($sorts, SORT_ASC, $generated['stickers']);
        }

        return $generated;
    }

    private function checkAutoSticker($oct_config, $type, $product, $is_special) {
        if (empty($oct_config['stickers'][$type]['status']) ||
            empty($oct_config['stickers'][$type]['auto']) ||
            $oct_config['stickers'][$type]['auto'] !== 'on') {
            return false;
        }

        switch ($type) {
            case 'new':
                return strtotime($product['date_added']) >= strtotime('-' . (int)$oct_config['stickers'][$type]['count'] . ' day');
            case 'free_shipping':
                $actual_price = !empty($product['special']) ? (float)$product['special'] : (float)$product['price'];
                return $actual_price >= (float)$oct_config['stickers'][$type]['count'];
            case 'bestseller':
                return $this->getOCTBestSellerProducts($product['product_id']) >= (int)$oct_config['stickers'][$type]['count'];
            case 'popular':
                return $product['viewed'] > (int)$oct_config['stickers'][$type]['count'];
            case 'special':
                return $is_special;
            case 'sold':
                return ((int)$product['quantity'] === (int)$oct_config['stickers'][$type]['count']);
            case 'ends':
                return ((int)$product['quantity'] > 0) && ((int)$product['quantity'] <= (int)$oct_config['stickers'][$type]['count']);
            case 'video':
                $description = isset($product['description']) ? $product['description'] : '';
                if (empty($description)) {
                    $query = $this->db->query("SELECT description FROM " . DB_PREFIX . "product_description WHERE product_id = '" . (int)$product['product_id'] . "' AND language_id = '" . (int)$this->config->get('config_language_id') . "'");
                    if ($query->num_rows) {
                        $description = $query->row['description'];
                    }
                }
                $description = html_entity_decode($description, ENT_QUOTES, 'UTF-8');
                return preg_match('/<iframe[^>]*\ssrc=["\'](?:https?:)?\/\/(?:www\.)?youtube(?:-nocookie)?\.com\/embed\/[a-zA-Z0-9_-]{11}/i', $description) === 1;
            default:
                return false;
        }
    }

    private function getOCTBestSellerProducts($product_id) {
        $query = $this->db->query("SELECT SUM(op.quantity) AS total FROM " . DB_PREFIX . "order_product op LEFT JOIN `" . DB_PREFIX . "order` o ON (op.order_id = o.order_id) LEFT JOIN `" . DB_PREFIX . "product` p ON (op.product_id = p.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE o.order_status_id > '0' AND p.product_id = '". (int)$product_id ."' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id')."'");

        return $query->row['total'];
    }

    private function buildStickerData($oct_config, $type) {
        if ($type === 'special' && empty($oct_config['stickers']['special']['view_title'])) {
            return [];
        }

        $lang_id = (int)$this->config->get('config_language_id');
        $title = !empty($oct_config['stickers'][$type]['title'][$lang_id])
            ? $oct_config['stickers'][$type]['title'][$lang_id]
            : '';
        $description = !empty($oct_config['stickers'][$type]['description'][$lang_id])
            ? nl2br($oct_config['stickers'][$type]['description'][$lang_id])
            : false;
        $sort_val = !empty($oct_config['stickers'][$type]['sort'])
            ? (int)$oct_config['stickers'][$type]['sort']
            : 0;

        $result = [
            'title'       => $title,
            'description' => $description,
            'sort'        => $sort_val
        ];
        
        if (!empty($oct_config['stickers'][$type]['image'])) {
            $image_path = $oct_config['stickers'][$type]['image'];
            if (defined('HTTP_SERVER')) {
                $result['image'] = HTTP_SERVER . 'image/' . $image_path;
            } else {
                $result['image'] = $this->config->get('config_url') . 'image/' . $image_path;
            }
            
            $result['image_width'] = !empty($oct_config['stickers'][$type]['image_width']) 
                ? (int)$oct_config['stickers'][$type]['image_width'] 
                : 20;
            $result['image_height'] = !empty($oct_config['stickers'][$type]['image_height']) 
                ? (int)$oct_config['stickers'][$type]['image_height'] 
                : 20;
            $result['image_only'] = !empty($oct_config['stickers'][$type]['image_only']) ? true : false;
        }

        return $result;
    }
}