<?php

namespace Components\Data;

class LegacyStoreData
{
    /** @var array<int, array{group_id:string, group_name:string}>|null */
    private static ?array $customerGroupDataCache = null;

    /** @var array<int|string, mixed>|null */
    private static ?array $segmentationCategoriesCache = null;

    /** @var array<string, array<int, array{id:string,name:string}>> */
    private static array $segmentationProductsCache = [];

    /**
     * @return array<int, array{group_id:string, group_name:string}>
     */
    public static function getCustomerGroupData(): array
    {
        if (self::$customerGroupDataCache !== null) {
            return self::$customerGroupDataCache;
        }

        $out = [];

        // Re-use legacy provider when available.
        if (class_exists('\\filter_check_group')) {
            try {
                $provider = new \filter_check_group();
                if (method_exists($provider, 'get_groups')) {
                    $rows = $provider->get_groups();
                    if (is_array($rows)) {
                        foreach ($rows as $row) {
                            if (!is_array($row)) {
                                continue;
                            }
                            $gid = trim((string)($row['group_id'] ?? ''));
                            $gname = trim((string)($row['group_name'] ?? ''));
                            if ($gid === '' || $gname === '') {
                                continue;
                            }
                            $out[] = ['group_id' => $gid, 'group_name' => $gname];
                        }
                    }
                }
            } catch (\Throwable $e) {
                // fall back to direct lookup below
            }
        }

        if (empty($out)) {
            $out = self::getCustomerGroupDataFromDb();
        }

        self::$customerGroupDataCache = $out;
        return self::$customerGroupDataCache;
    }

    /**
     * @return array<int|string, mixed>
     */
    public static function getSegmentationCategoriesData(): array
    {
        if (self::$segmentationCategoriesCache !== null) {
            return self::$segmentationCategoriesCache;
        }

        $provider = self::makeSegmentationCategoriesProvider();
        if (!$provider || !method_exists($provider, 'get_categories')) {
            self::$segmentationCategoriesCache = [];
            return self::$segmentationCategoriesCache;
        }

        try {
            $categories = $provider->get_categories();
        } catch (\Throwable $e) {
            $categories = [];
        }

        self::$segmentationCategoriesCache = is_array($categories) ? $categories : [];
        return self::$segmentationCategoriesCache;
    }

    /**
     * @param mixed $productsIdList
     * @param int|null $languageId
     * @return array<int, array{id:string,name:string}>
     */
    public static function loadProductsForConfig($productsIdList, ?int $languageId = null): array
    {
        $normalizedIds = self::normalizeNumericIdList($productsIdList);
        if (empty($normalizedIds)
            || !function_exists('mh_db_query')
            || !function_exists('mh_db_fetch_array')
            || !defined('TABLE_PRODUCTS')
            || !defined('TABLE_PRODUCTS_DESCRIPTION')) {
            return [];
        }

        $resolvedLanguageId = self::resolveLanguageId($languageId);
        $cacheKey = $resolvedLanguageId . '|' . implode(',', $normalizedIds);
        if (isset(self::$segmentationProductsCache[$cacheKey])) {
            return self::$segmentationProductsCache[$cacheKey];
        }

        $productsInSql = implode(',', $normalizedIds);
        $dataQuerySql = "SELECT DISTINCT p.products_id, pd.products_name\n"
            . "FROM " . TABLE_PRODUCTS . " p\n"
            . "   , " . TABLE_PRODUCTS_DESCRIPTION . " pd\n"
            . "WHERE p.products_id = pd.products_id\n"
            . "  AND p.products_id IN (" . $productsInSql . ")\n"
            . "  AND pd.language_id = '" . (int)$resolvedLanguageId . "'";

        $result = [];
        try {
            $dataQuery = mh_db_query($dataQuerySql);
            while ($dataItem = mh_db_fetch_array($dataQuery)) {
                if (!is_array($dataItem)) {
                    continue;
                }
                $productId = trim((string)($dataItem['products_id'] ?? ''));
                if ($productId === '' || !preg_match('/^\d+$/', $productId)) {
                    continue;
                }

                $result[] = [
                    'id' => (string)((int)$productId),
                    'name' => (string)($dataItem['products_name'] ?? ''),
                ];
            }
        } catch (\Throwable $e) {
            // keep empty result
        }

        self::$segmentationProductsCache[$cacheKey] = $result;
        return self::$segmentationProductsCache[$cacheKey];
    }

    /**
     * @param mixed $productsIdList
     * @param int|null $languageId
     */
    public static function loadProductsForConfigJson($productsIdList, ?int $languageId = null): string
    {
        $result = [];
        foreach (self::loadProductsForConfig($productsIdList, $languageId) as $item) {
            $name = (string)($item['name'] ?? '');
            if (function_exists('mh_force_utf8')) {
                $name = (string)mh_force_utf8($name);
            }

            $result[] = [
                'id' => (string)($item['id'] ?? ''),
                'name' => htmlentities($name),
            ];
        }

        return json_encode($result);
    }

    /**
     * @param mixed $productsIdList
     * @return int[]
     */
    private static function normalizeNumericIdList($productsIdList): array
    {
        $tokens = [];

        $collect = function ($value) use (&$collect, &$tokens): void {
            if (is_array($value)) {
                foreach ($value as $entry) {
                    $collect($entry);
                }
                return;
            }

            $scalar = trim((string)$value);
            if ($scalar === '') {
                return;
            }

            foreach (preg_split('/\s*,\s*/', $scalar) as $part) {
                if ($part === '') {
                    continue;
                }
                $tokens[] = $part;
            }
        };

        $collect($productsIdList);

        $ids = [];
        foreach ($tokens as $token) {
            if (!preg_match('/^\d+$/', (string)$token)) {
                continue;
            }
            $ids[(int)$token] = true;
        }

        return array_keys($ids);
    }

    private static function resolveLanguageId(?int $languageId): int
    {
        if ($languageId !== null && $languageId > 0) {
            return $languageId;
        }

        if (isset($_SESSION['languages_id']) && (int)$_SESSION['languages_id'] > 0) {
            return (int)$_SESSION['languages_id'];
        }

        return 2;
    }

    /**
     * @return object|null
     */
    private static function makeSegmentationCategoriesProvider()
    {
        if (!class_exists('\\segmentation_categories')) {
            $path = self::resolveSegmentationCategoriesPath();
            if ($path !== '' && is_file($path)) {
                require_once $path;
            }
        }

        if (!class_exists('\\segmentation_categories')) {
            return null;
        }

        try {
            return new \segmentation_categories();
        } catch (\Throwable $e) {
            return null;
        }
    }

    private static function resolveSegmentationCategoriesPath(): string
    {
        if (defined('MH_DIR_FS_CATALOG') && defined('MH_ROOT_PATH')) {
            return rtrim((string)MH_DIR_FS_CATALOG, '/\\')
                . '/'
                . trim((string)MH_ROOT_PATH, '/\\')
                . '/configbeez/config_segmentation_engine/segmentationbeez/segmentation_categories.php';
        }

        return dirname(__DIR__, 3)
            . '/configbeez/config_segmentation_engine/segmentationbeez/segmentation_categories.php';
    }

    /**
     * @return array<int, array{group_id:string, group_name:string}>
     */
    private static function getCustomerGroupDataFromDb(): array
    {
        if (!function_exists('mh_db_query') || !function_exists('mh_db_fetch_array')) {
            return [];
        }

        $platform = defined('MH_PLATFORM') ? (string)MH_PLATFORM : '';
        $groupData = [];
        $groupsQueryRaw = '';

        if ($platform === 'zencart') {
            $groupData[] = [
                'group_id' => '0',
                'group_name' => (string)mh_lng('TEXT_GROUP_NONE', 'None')
            ];
        }

        switch ($platform) {
            case 'creloaded':
                if (defined('TABLE_CUSTOMERS_GROUPS')) {
                    $groupsQueryRaw = "select customers_group_id as group_id, customers_group_name as group_name\n"
                        . "from " . TABLE_CUSTOMERS_GROUPS;
                }
                break;
            case 'zencart':
                if (defined('TABLE_GROUP_PRICING')) {
                    $groupsQueryRaw = "select *\n"
                        . "from " . TABLE_GROUP_PRICING;
                }
                break;
            case 'xtc':
            case 'gambio':
                if (defined('TABLE_CUSTOMERS_STATUS')) {
                    $languageId = isset($_SESSION['languages_id']) ? (int)$_SESSION['languages_id'] : 0;
                    $where = $languageId > 0 ? " where language_id = '" . $languageId . "'" : '';
                    $groupsQueryRaw = "select customers_status_name as group_name, customers_status_id as group_id\n"
                        . "from " . TABLE_CUSTOMERS_STATUS . $where;
                }
                break;
            default:
                if (defined('TABLE_CUSTOMERS_GROUPS')) {
                    $groupsQueryRaw = "select customers_group_id as group_id, customers_group_name as group_name\n"
                        . "from " . TABLE_CUSTOMERS_GROUPS;
                }
        }

        if ($groupsQueryRaw === '') {
            return $groupData;
        }

        try {
            $groupsQuery = mh_db_query($groupsQueryRaw);
            while ($groupItem = mh_db_fetch_array($groupsQuery)) {
                if (!is_array($groupItem)) {
                    continue;
                }
                $groupId = (string)($groupItem['group_id']
                    ?? $groupItem['customers_group_id']
                    ?? $groupItem['customers_status_id']
                    ?? $groupItem['pricing_group_id']
                    ?? '');
                $groupName = (string)($groupItem['group_name']
                    ?? $groupItem['customers_group_name']
                    ?? $groupItem['customers_status_name']
                    ?? $groupItem['pricing_group_name']
                    ?? '');

                $groupId = trim($groupId);
                $groupName = trim($groupName);
                if ($groupId === '' || $groupName === '') {
                    continue;
                }

                $groupData[] = [
                    'group_id' => $groupId,
                    'group_name' => $groupName,
                ];
            }
        } catch (\Throwable $e) {
            return $groupData;
        }

        return $groupData;
    }
}
