<?php
namespace EasyChat\Model\Cms;

use EasyChat\Library\Catalog\CatalogSearchUnavailableException;

class CmsModelWebAsyst extends CmsModelBase {

     
    private $currency_cache = null;

    


    public function getProducts(): array {
        $p      = $this->prefix;
        $result = $this->db->query(
            "SELECT id, name FROM `{$p}shop_product` WHERE status = 1 ORDER BY id ASC"
        );
        return $result->rows ?? [];
    }

    public function getProductsBatch(int $after_id, int $limit): array {
        $after_id = max(0, $after_id);
        $limit = max(1, min(100, $limit));
        $result = $this->db->query(
            "SELECT id, name FROM `{$this->prefix}shop_product`
             WHERE status = 1 AND id > {$after_id} ORDER BY id ASC LIMIT {$limit}"
        );
        return $result->rows ?? array();
    }

    


    public function getProductText(int $product_id): string {
        $parts = [];
        $p     = $this->prefix;

        $result  = $this->db->query(
            "SELECT name, COALESCE(NULLIF(description, ''), summary, '') AS description
             FROM `{$p}shop_product`
             WHERE id = $product_id AND status = 1
             LIMIT 1"
        );
        $product = $result->row ?? [];

        if (empty($product)) {
            return '';
        }

        if ($this->settings['chat_embedding_use_name'] ?? false) {
            if (!empty($product['name'])) $parts[] = $product['name'];
        }

        if ($this->settings['chat_embedding_use_desc'] ?? false) {
            if (!empty($product['description'])) $parts[] = strip_tags($product['description']);
        }

         

        if ($this->settings['chat_embedding_use_sku'] ?? false) {
            $sku = $this->getFirstSku($product_id, $p);
            if ($sku !== '') $parts[] = 'Артикул: ' . $sku;
        }

        if ($this->settings['chat_embedding_use_attrs'] ?? false) {
            $attrs = $this->getFeatures($product_id, $p);
            if (!empty($attrs)) $parts[] = 'Характеристики: ' . implode(', ', $attrs);
        }

        if ($this->settings['chat_embedding_use_options'] ?? false) {
            $options = $this->getSkuNames($product_id, $p);
            if (!empty($options)) $parts[] = 'Варианты: ' . implode('; ', $options);
        }

        return implode('. ', array_filter(array_map('trim', $parts)));
    }

    


    public function getPages(): array {
        $p      = $this->prefix;
        $result = $this->db->query(
            "SELECT id, name FROM `{$p}site_pages` WHERE status = 'published' ORDER BY id ASC"
        );
        return $result->rows ?? [];
    }

    public function getPagesBatch(int $after_id, int $limit): array {
        $after_id = max(0, $after_id);
        $limit = max(1, min(100, $limit));
        $result = $this->db->query(
            "SELECT id, name FROM `{$this->prefix}site_pages`
             WHERE status = 'published' AND id > {$after_id} ORDER BY id ASC LIMIT {$limit}"
        );
        return $result->rows ?? array();
    }

    


    public function getPageText(int $page_id): string {
        $p      = $this->prefix;
        $result = $this->db->query(
            "SELECT name, content AS description
             FROM `{$p}site_pages`
             WHERE id = $page_id
             LIMIT 1"
        );
        $page = $result->row ?? [];

        $parts = [];
        if (!empty($page['name']))        $parts[] = $page['name'];
        if (!empty($page['description'])) $parts[] = strip_tags($page['description']);

        return implode('. ', array_filter(array_map('trim', $parts)));
    }

    



    public function searchProducts(string $query, float $max_price = 0.0, array $options = array()): array {
        $p     = $this->prefix;
        $words = $this->splitWords($query);
        $limit = max(1, min(200, (int)($options['candidate_limit'] ?? $this->getSearchLimit()) * 2));

        $likes     = [];
        $relevance = [];
        foreach ($words as $word) {
            $esc         = $this->escapeLikeWord($word);
            $likes[] = "(LOWER(p.name) LIKE '%{$esc}%'
                        OR LOWER(COALESCE(s.sku, '')) LIKE '%{$esc}%'
                        OR LOWER(COALESCE(s.name, '')) LIKE '%{$esc}%')";
            $relevance[] = "(CASE
                WHEN LOWER(COALESCE(s.sku, '')) = '{$esc}' THEN 12
                WHEN LOWER(p.name) LIKE '%{$esc}%' THEN 4
                WHEN LOWER(COALESCE(s.sku, '')) LIKE '%{$esc}%' THEN 6
                ELSE 0 END)";
        }

        $rel_expr = implode(' + ', $relevance);
        $compact = mb_substr($this->normalizeSearchIdentifier($query), 0, 120, 'UTF-8');
        $compact_e = $this->db->escape($compact);
        $compact_sku = $this->compactSearchIdentifierSql('s.sku');
        $compact_name = $this->compactSearchIdentifierSql('p.name');
        $identifier_cond = $compact_e !== ''
            ? "({$compact_sku} = '{$compact_e}' OR {$compact_name} LIKE '%{$compact_e}%')"
            : '0';

        $make_sql = function (string $op) use ($p, $likes, $rel_expr, $limit, $max_price, $identifier_cond): string {
            $cond = implode(" {$op} ", $likes);
            $price_cond = !$max_price
                ? '1'
                : 'COALESCE(NULLIF(s.price, 0), p.price) <= ' . (float)$max_price;
            return "SELECT DISTINCT p.id AS product_id, p.name, p.price, p.url,
                        s.id AS sku_id, s.sku, s.name AS sku_name,
                        s.price AS sku_price, s.count AS sku_count, s.available AS sku_available,
                        ({$rel_expr}) AS relevance
                    FROM `{$p}shop_product` p
                    LEFT JOIN `{$p}shop_product_skus` s ON s.product_id = p.id AND s.status = 1
                    WHERE p.status = 1
                      AND (({$cond}) OR {$identifier_cond})
                      AND {$price_cond}
                    ORDER BY relevance DESC, p.id DESC
                    LIMIT {$limit}";
        };

        $multi = count($words) > 1;
        $sql   = $make_sql($multi ? 'AND' : 'OR');
        $started_at = microtime(true);

        [$shop_route_prefix, $url_type] = $this->resolveShopRouting();

        try {
            $result = $this->db->query($sql);

            if ($multi && empty($result->rows)) {
                $result = $this->db->query($make_sql('OR'));
            }

            $products = [];
            $base_url = $this->getBaseUrl();
            $currency = $this->getCurrencyCode();
            $query_identifier = $this->normalizeCatalogIdentifier($query);
            foreach ($result->rows as $row) {
                $product_id = (int)$row['product_id'];
                $slug   = !empty($row['url']) ? $row['url'] : $row['product_id'];
                $prefix = $url_type == 2 ? 'product/' : '';
                $link   = preg_replace(
                    '#([^:])//+#', '$1/',
                    $base_url . '/' . $shop_route_prefix . $prefix . $slug . '/'
                );
                if (!isset($products[$product_id])) {
                    $price_value = (float)($row['price'] ?? 0);
                    $products[$product_id] = [
                        'id' => (string)$product_id,
                        'name' => (string)$row['name'],
                        'model' => '',
                        'sku' => '',
                        'price' => $this->formatCatalogPrice($price_value, $currency),
                        'price_value' => $price_value,
                        'currency' => $currency,
                        'link' => $link,
                        'availability' => 'out_of_stock',
                        'availability_label' => 'Нет в наличии',
                        'can_order' => false,
                        'quantity' => null,
                        'relevance' => (int)($row['relevance'] ?? 0),
                        '_has_sku' => false,
                        '_exact_sku' => false,
                    ];
                }

                if (!empty($row['sku_id'])) {
                    $products[$product_id]['_has_sku'] = true;
                    $available = (int)($row['sku_available'] ?? 0) === 1;
                    $count_known = is_numeric($row['sku_count'] ?? null);
                    $count = $count_known ? (float)$row['sku_count'] : null;
                    $sku_state = !$available
                        ? 'out_of_stock'
                        : (($count === null || $count > 0) ? 'in_stock' : 'preorder');
                    $sku = trim((string)($row['sku'] ?? ''));
                    $sku_identifier = $this->normalizeCatalogIdentifier($sku);
                    $exact_sku = $sku_identifier !== ''
                        && mb_strlen($sku_identifier, 'UTF-8') >= 3
                        && strpos($query_identifier, $sku_identifier) !== false;
                    if ($exact_sku) {
                        $products[$product_id]['availability'] = $sku_state;
                        $products[$product_id]['availability_label'] = $this->availabilityLabel($sku_state);
                        $products[$product_id]['can_order'] = in_array($sku_state, array('in_stock', 'preorder'), true);
                        $products[$product_id]['quantity'] = $count;
                        $products[$product_id]['sku'] = $sku;
                        $sku_price = is_numeric($row['sku_price'] ?? null) ? (float)$row['sku_price'] : 0.0;
                        if ($sku_price > 0) {
                            $products[$product_id]['price_value'] = $sku_price;
                            $products[$product_id]['price'] = $this->formatCatalogPrice($sku_price, $currency);
                        }
                        $products[$product_id]['_exact_sku'] = true;
                        continue;
                    }
                    if ($products[$product_id]['_exact_sku']) {
                        continue;
                    }
                    if ($this->availabilityPriority($sku_state) > $this->availabilityPriority($products[$product_id]['availability'])) {
                        $products[$product_id]['availability'] = $sku_state;
                        $products[$product_id]['availability_label'] = $this->availabilityLabel($sku_state);
                        $products[$product_id]['can_order'] = in_array($sku_state, array('in_stock', 'preorder'), true);
                    }
                    if ($sku !== '' && ($products[$product_id]['sku'] === ''
                        || strpos($query_identifier, $this->normalizeCatalogIdentifier($sku)) !== false)) {
                        $products[$product_id]['sku'] = $sku;
                    }
                    if ($count_known) {
                        $current = is_numeric($products[$product_id]['quantity']) ? (float)$products[$product_id]['quantity'] : 0.0;
                        $products[$product_id]['quantity'] = $current + max(0.0, $count);
                    }
                    if ($products[$product_id]['price_value'] <= 0 && (float)($row['sku_price'] ?? 0) > 0) {
                        $products[$product_id]['price_value'] = (float)$row['sku_price'];
                        $products[$product_id]['price'] = $this->formatCatalogPrice((float)$row['sku_price'], $currency);
                    }
                }
            }
            $products = array_values($products);
            foreach ($products as &$product) {
                if (!$product['_has_sku']) {
                    $product['availability'] = 'unknown';
                    $product['availability_label'] = 'Наличие уточняется';
                }
                unset($product['_has_sku'], $product['_exact_sku']);
            }
            unset($product);
            $duration_ms = (int)round((microtime(true) - $started_at) * 1000);
            $this->log('[CmsSearch] Webasyst products mode=' . ($multi ? 'and' : 'or') . ' results=' . count($products) . ' duration_ms=' . $duration_ms);
            return $products;
        } catch (\Throwable $e) {
            $this->log('[CmsSearch] Webasyst products failed code=query_error');
            throw new CatalogSearchUnavailableException('webasyst', $e);
        }
    }

    



    public function searchPages(string $query): array {
        $p     = $this->prefix;
        $words = $this->splitWords($query);
        $limit = $this->getSearchLimit();

        $likes     = [];
        $relevance = [];
        foreach ($words as $word) {
            $esc         = $this->escapeLikeWord($word);
            $likes[]     = "(LOWER(name) LIKE '%{$esc}%' OR LOWER(content) LIKE '%{$esc}%')";
            $relevance[] = "(CASE WHEN LOWER(name) LIKE '%{$esc}%' THEN 2 WHEN LOWER(content) LIKE '%{$esc}%' THEN 1 ELSE 0 END)";
        }

        $rel_expr = implode(' + ', $relevance);
        $make_sql = function (string $op) use ($p, $likes, $rel_expr, $limit): string {
            $cond = implode(" {$op} ", $likes);
            return "SELECT DISTINCT id, name, content AS description, url,
                        ({$rel_expr}) AS relevance
                    FROM `{$p}site_pages`
                    WHERE status = 'published'
                      AND ({$cond})
                    ORDER BY relevance DESC, id DESC
                    LIMIT {$limit}";
        };

        $multi = count($words) > 1;
        $sql   = $make_sql($multi ? 'AND' : 'OR');
        $used_mode = $multi ? 'and' : 'or';

        try {
            $result = $this->db->query($sql);

            if ($multi && empty($result->rows)) {
                $sql = $make_sql('OR');
                $used_mode = 'or_fallback';
                $result = $this->db->query($sql);
            }

            $pages    = [];
            $base_url = $this->getBaseUrl();
            foreach ($result->rows as $row) {
                $slug    = !empty($row['url']) ? $row['url'] : $row['id'];
                $excerpt = mb_substr(trim(strip_tags((string)$row['description'])), 0, 200, 'UTF-8');
                $link    = preg_replace('#([^:])//+#', '$1/', $base_url . '/' . ltrim($slug, '/'));
                $pages[] = [
                    'name'    => $row['name'],
                    'excerpt' => $excerpt,
                    'link'    => $link,
                ];
            }
            $this->log('[CmsSearch] Webasyst pages mode=' . $used_mode . ' results=' . count($pages));
            return $pages;
        } catch (\Throwable $e) {
            $this->logFailure('[CmsSearch] Webasyst pages failed', $e);
            return [];
        }
    }

    


    public function resolvePageContext(string $page_type, string $page_id): array {
        $page_type = strtolower(preg_replace('/[^a-z0-9_-]/i', '', trim($page_type)));
        $id = (int)$page_id;
        if ($id <= 0) {
            return [];
        }

        if ($page_type === 'product') {
            return $this->resolveProductPageContext($id);
        }
        if ($page_type === 'category') {
            return $this->resolveCategoryPageContext($id);
        }
        if ($page_type === 'information') {
            return $this->resolveInformationPageContext($id);
        }

        return [];
    }

     
     
     

    private function resolveProductPageContext(int $product_id): array {
        $p = $this->prefix;
        try {
            $result = $this->db->query(
                "SELECT id, name, url, price,
                        COALESCE(NULLIF(description, ''), summary, '') AS description
                 FROM `{$p}shop_product`
                 WHERE id = {$product_id}
                   AND status = 1
                 LIMIT 1"
            );
        } catch (\Throwable $e) {
            $this->logFailure('[CmsContext] Webasyst product failed', $e);
            return [];
        }

        $row = $result->row ?? [];
        if (!$row) {
            return [];
        }

        $lines = ['Тип страницы: товар'];
        $this->addContextLine($lines, 'Название', (string)($row['name'] ?? ''));
        $this->addContextLine($lines, 'ID товара', (string)$product_id);
        $sku = $this->getFirstSku($product_id, $p);
        $this->addContextLine($lines, 'Артикул', $sku);
        $this->addContextLine($lines, 'Цена', $this->formatContextPrice($row['price'] ?? ''));
        $this->addContextLine($lines, 'Описание', $this->contextText((string)($row['description'] ?? ''), 620));

        $attrs = $this->getFeatures($product_id, $p);
        if ($attrs) {
            $this->addContextLine($lines, 'Характеристики', $this->contextText(implode('; ', array_slice($attrs, 0, 12)), 700));
        }
        $options = $this->getSkuNames($product_id, $p);
        if ($options) {
            $this->addContextLine($lines, 'Варианты', $this->contextText(implode('; ', array_slice($options, 0, 8)), 520));
        }

        [$shop_route_prefix, $url_type] = $this->resolveShopRouting();
        $slug = !empty($row['url']) ? $row['url'] : $product_id;
        $prefix = $url_type == 2 ? 'product/' : '';

        return [
            'kind' => 'product',
            'page_type' => 'product',
            'page_id' => (string)$product_id,
            'title' => (string)($row['name'] ?? ''),
            'url' => preg_replace('#([^:])//+#', '$1/', $this->getBaseUrl() . '/' . $shop_route_prefix . $prefix . $slug . '/'),
            'facts' => [
                'type' => 'product',
                'product_id' => (string)$product_id,
                'name' => (string)($row['name'] ?? ''),
                'sku' => $sku,
                'price' => $this->formatContextPrice($row['price'] ?? ''),
                'description_excerpt' => $this->contextText((string)($row['description'] ?? ''), 620),
                'features' => array_slice($attrs, 0, 12),
                'variants' => array_slice($options, 0, 8),
            ],
            'prompt_lines' => $lines,
        ];
    }

    private function resolveCategoryPageContext(int $category_id): array {
        $p = $this->prefix;
        try {
            $result = $this->db->query(
                "SELECT id, name, description, full_url, url
                 FROM `{$p}shop_category`
                 WHERE id = {$category_id}
                   AND status = 1
                 LIMIT 1"
            );
        } catch (\Throwable $e) {
            $this->logFailure('[CmsContext] Webasyst category failed', $e);
            return [];
        }

        $row = $result->row ?? [];
        if (!$row) {
            return [];
        }

        $lines = ['Тип страницы: категория'];
        $this->addContextLine($lines, 'Название', (string)($row['name'] ?? ''));
        $this->addContextLine($lines, 'ID категории', (string)$category_id);
        $this->addContextLine($lines, 'Описание', $this->contextText((string)($row['description'] ?? ''), 620));

        [$shop_route_prefix] = $this->resolveShopRouting();
        $slug = !empty($row['full_url']) ? $row['full_url'] : (!empty($row['url']) ? $row['url'] : $category_id);

        return [
            'kind' => 'category',
            'page_type' => 'category',
            'page_id' => (string)$category_id,
            'title' => (string)($row['name'] ?? ''),
            'url' => preg_replace('#([^:])//+#', '$1/', $this->getBaseUrl() . '/' . $shop_route_prefix . 'category/' . trim((string)$slug, '/') . '/'),
            'facts' => [
                'type' => 'category',
                'category_id' => (string)$category_id,
                'name' => (string)($row['name'] ?? ''),
                'description_excerpt' => $this->contextText((string)($row['description'] ?? ''), 620),
            ],
            'prompt_lines' => $lines,
        ];
    }

    private function resolveInformationPageContext(int $page_id): array {
        $p = $this->prefix;
        try {
            $result = $this->db->query(
                "SELECT id, name, content AS description, url
                 FROM `{$p}site_pages`
                 WHERE id = {$page_id}
                   AND status = 'published'
                 LIMIT 1"
            );
        } catch (\Throwable $e) {
            $this->logFailure('[CmsContext] Webasyst page failed', $e);
            return [];
        }

        $row = $result->row ?? [];
        if (!$row) {
            return [];
        }

        $lines = ['Тип страницы: информационная страница'];
        $this->addContextLine($lines, 'Название', (string)($row['name'] ?? ''));
        $this->addContextLine($lines, 'ID страницы', (string)$page_id);
        $this->addContextLine($lines, 'Содержание', $this->contextText((string)($row['description'] ?? ''), 700));

        $slug = !empty($row['url']) ? $row['url'] : $page_id;
        return [
            'kind' => 'information',
            'page_type' => 'information',
            'page_id' => (string)$page_id,
            'title' => (string)($row['name'] ?? ''),
            'url' => preg_replace('#([^:])//+#', '$1/', $this->getBaseUrl() . '/' . ltrim((string)$slug, '/')),
            'facts' => [
                'type' => 'information',
                'page_id' => (string)$page_id,
                'title' => (string)($row['name'] ?? ''),
                'content_excerpt' => $this->contextText((string)($row['description'] ?? ''), 700),
            ],
            'prompt_lines' => $lines,
        ];
    }

    private function availabilityPriority(string $availability): int {
        if ($availability === 'in_stock') {
            return 3;
        }
        if ($availability === 'preorder') {
            return 2;
        }
        if ($availability === 'unknown') {
            return 1;
        }
        return 0;
    }

    private function availabilityLabel(string $availability): string {
        if ($availability === 'in_stock') {
            return 'В наличии';
        }
        if ($availability === 'preorder') {
            return 'Доступно под заказ';
        }
        if ($availability === 'out_of_stock') {
            return 'Нет в наличии';
        }
        return 'Наличие уточняется';
    }

    private function getCurrencyCode(): string {
        if ($this->currency_cache !== null) {
            return $this->currency_cache;
        }
        $this->currency_cache = '';
        try {
            $result = $this->db->query(
                "SELECT code FROM `{$this->prefix}shop_currency`
                 WHERE rate = 1 ORDER BY code ASC LIMIT 1"
            );
            $currency = strtoupper(trim((string)($result->row['code'] ?? '')));
            if (preg_match('/^[A-Z]{3}$/', $currency)) {
                $this->currency_cache = $currency;
            }
        } catch (\Throwable $e) {
        }
        return $this->currency_cache;
    }

    private function formatCatalogPrice(float $price, string $currency): string {
        if ($price <= 0) {
            return 'Цена по запросу';
        }
        $formatted = number_format($price, 2, '.', '');
        return $currency !== '' ? $formatted . ' ' . $currency : $formatted;
    }

    private function normalizeCatalogIdentifier(string $value): string {
        $value = mb_strtolower(trim($value), 'UTF-8');
        $value = str_replace('\\', '', $value);
        return (string)preg_replace('/[\s\-_.\/]+/u', '', $value);
    }

    private function addContextLine(array &$lines, string $label, string $value): void {
        $value = $this->contextText($value, 900);
        if ($value !== '') {
            $lines[] = $label . ': ' . $value;
        }
    }

    private function contextText(string $value, int $limit): string {
        $value = html_entity_decode(strip_tags($value), ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $value = preg_replace('/\s+/u', ' ', trim($value));
        return mb_strlen($value, 'UTF-8') > $limit ? mb_substr($value, 0, $limit, 'UTF-8') : $value;
    }

    private function formatContextPrice($value): string {
        if ($value === null || $value === '') {
            return '';
        }
        $price = (float)$value;
        return $price > 0 ? number_format($price, 2, '.', '') : '';
    }

    private function getFirstSku(int $product_id, string $p): string {
        $result = $this->db->query(
            "SELECT sku FROM `{$p}shop_product_skus`
             WHERE product_id = $product_id AND status = 1
               AND sku IS NOT NULL AND sku != ''
             LIMIT 1"
        );
        return ($result->row && !empty($result->row['sku'])) ? (string)$result->row['sku'] : '';
    }

    private function getFeatures(int $product_id, string $p): array {
        $sql = "SELECT f.id AS feature_id, f.name AS feature_name, f.type AS feature_type, pf.feature_value_id
                FROM `{$p}shop_product_features` pf
                JOIN `{$p}shop_feature` f ON f.id = pf.feature_id
                WHERE pf.product_id = $product_id
                ORDER BY f.name ASC";
        try {
            $result = $this->db->query($sql);
            $attrs  = [];
            foreach ($result->rows as $row) {
                $value = $this->getFeatureValue(
                    (int)$row['feature_id'],
                    (int)$row['feature_value_id'],
                    (string)$row['feature_type'],
                    $p
                );
                if ($value !== '') {
                    $attrs[] = $row['feature_name'] . ': ' . $value;
                }
            }
            return $attrs;
        } catch (\Throwable $e) {
            return [];
        }
    }

    private function getFeatureValue(int $feature_id, int $feature_value_id, string $feature_type, string $p): string {
        if ($feature_id <= 0 || $feature_value_id <= 0) {
            return '';
        }

        $table = $this->featureValueTable($feature_type, $p);
        if ($table === '') {
            return '';
        }

        $fields = $this->featureValueSelectFields($feature_type);
        try {
            $result = $this->db->query(
                "SELECT {$fields}
                 FROM `{$table}`
                 WHERE id = {$feature_value_id}
                   AND feature_id = {$feature_id}
                 LIMIT 1"
            );
        } catch (\Throwable $e) {
            return '';
        }

        $row = $result->row ?? [];
        if (!$row) {
            return '';
        }

        if (isset($row['value'])) {
            $value = trim((string)$row['value']);
            if ($value === '') {
                return '';
            }
            if (!empty($row['unit'])) {
                $value .= ' ' . trim((string)$row['unit']);
            }
            return $value;
        }

        $begin = isset($row['begin']) ? trim((string)$row['begin']) : '';
        $end = isset($row['end']) ? trim((string)$row['end']) : '';
        $unit = isset($row['unit']) ? trim((string)$row['unit']) : '';
        $value = trim($begin . ($begin !== '' && $end !== '' ? '-' : '') . $end);
        return $value !== '' ? trim($value . ' ' . $unit) : '';
    }

    private function featureValueTable(string $feature_type, string $p): string {
        $type = strtolower(trim($feature_type));
        if (strpos($type, '.') !== false) {
            $type = substr($type, 0, strpos($type, '.'));
        }

        $map = [
            'color' => 'color',
            'dimension' => 'dimension',
            'double' => 'double',
            'range' => 'range',
            'text' => 'text',
            'varchar' => 'varchar',
        ];
        if (!isset($map[$type])) {
            return '';
        }

        return $p . 'shop_feature_values_' . $map[$type];
    }

    private function featureValueSelectFields(string $feature_type): string {
        $type = strtolower(trim($feature_type));
        if (strpos($type, '.') !== false) {
            $type = substr($type, 0, strpos($type, '.'));
        }

        if ($type === 'range') {
            return '`begin`, `end`, `unit`';
        }
        if ($type === 'dimension') {
            return '`value`, `unit`';
        }

        return '`value`';
    }

    private function getSkuNames(int $product_id, string $p): array {
        $sql = "SELECT name FROM `{$p}shop_product_skus`
                WHERE product_id = $product_id AND available = 1
                  AND name IS NOT NULL AND name != ''
                ORDER BY id ASC
                LIMIT 30";
        try {
            $result = $this->db->query($sql);
            $names  = [];
            foreach ($result->rows as $row) {
                $names[] = $row['name'];
            }
            return $names;
        } catch (\Throwable $e) {
            return [];
        }
    }

     
     
     

    



    private function resolveShopRouting(): array {
        $shop_route_prefix = 'shop/';
        $url_type          = 0;

        $parent_dir   = defined('SITE_PATH') ? dirname(SITE_PATH) : dirname(dirname(dirname(__DIR__)));
        $routing_file = $parent_dir . DIRECTORY_SEPARATOR . 'wa-config' . DIRECTORY_SEPARATOR . 'routing.php';

        if (!file_exists($routing_file)) {
            return [$shop_route_prefix, $url_type];
        }

        try {
            $routes = include($routing_file);
            if (!is_array($routes)) {
                return [$shop_route_prefix, $url_type];
            }

            $host        = \EasyChat\Library\RequestContext::server()['HTTP_HOST'] ?? '';
            $host_routes = $routes[$host] ?? [];

            if (empty($host_routes)) {
                foreach ($routes as $domain => $rules) {
                    if (strpos($host, $domain) !== false || strpos($domain, $host) !== false) {
                        $host_routes = $rules;
                        break;
                    }
                }
            }
            if (empty($host_routes)) {
                $host_routes = reset($routes);
            }

            if (is_array($host_routes)) {
                foreach ($host_routes as $route) {
                    if (isset($route['app']) && $route['app'] === 'shop') {
                        $url               = $route['url'] ?? '';
                        $shop_route_prefix = str_replace('*', '', $url);
                        if ($shop_route_prefix !== '') {
                            $shop_route_prefix = rtrim($shop_route_prefix, '/') . '/';
                        }
                        $url_type = (int)($route['url_type'] ?? 0);
                        break;
                    }
                }
            }
        } catch (\Throwable $e) {
            $this->logFailure('[CmsSearch] Webasyst routing failed', $e);
        }

        return [$shop_route_prefix, $url_type];
    }
}
