<?php
namespace EasyChat\Library\Catalog;






class CmsCatalogCapability {

    




    public static function shouldValidateOnSettingsSave(array $previous, array $next): bool {
        $next_enabled = (int)($next['chat_productsearch'] ?? 0) > 0;
        if (!$next_enabled) {
            return false;
        }

        $previous_enabled = (int)($previous['chat_productsearch'] ?? 0) > 0;
        if (!$previous_enabled) {
            return true;
        }

        return strtolower(trim((string)($previous['chat_cms_type'] ?? '')))
                !== strtolower(trim((string)($next['chat_cms_type'] ?? '')))
            || trim((string)($previous['chat_cms_prefix'] ?? ''))
                !== trim((string)($next['chat_cms_prefix'] ?? ''));
    }

    public static function requiredTables(string $cms_type, string $prefix): array {
        $cms_type = strtolower(trim($cms_type));
        if ($cms_type === 'opencart') {
            return array(
                $prefix . 'product',
                $prefix . 'product_description',
                $prefix . 'product_to_store',
                $prefix . 'stock_status',
                $prefix . 'setting',
                $prefix . 'store',
            );
        }
        if (in_array($cms_type, array('wordpress', 'woocommerce'), true)) {
            return array(
                $prefix . 'posts',
                $prefix . 'postmeta',
                $prefix . 'options',
                $prefix . 'terms',
                $prefix . 'term_taxonomy',
                $prefix . 'term_relationships',
            );
        }
        if ($cms_type === 'bitrix') {
            return array(
                $prefix . 'iblock',
                $prefix . 'iblock_element',
                $prefix . 'iblock_property',
                $prefix . 'iblock_element_property',
                $prefix . 'iblock_section',
                $prefix . 'catalog_product',
                $prefix . 'catalog_price',
                $prefix . 'catalog_group',
            );
        }
        if (in_array($cms_type, array('webasyst', 'shopscript'), true)) {
            return array(
                $prefix . 'shop_product',
                $prefix . 'shop_product_skus',
                $prefix . 'shop_currency',
            );
        }
        return array();
    }

    



    public static function alternativeTableGroups(string $cms_type, string $prefix): array {
        if (strtolower(trim($cms_type)) === 'opencart') {
            return array(array(
                $prefix . 'product_special',
                $prefix . 'product_discount',
            ));
        }
        return array();
    }

    public static function inspect($db, string $cms_type, string $prefix): array {
        $required = self::requiredTables($cms_type, $prefix);
        $alternative_groups = self::alternativeTableGroups($cms_type, $prefix);
        if (empty($required)) {
            return array('supported' => false, 'ready' => false, 'reason' => 'cms_not_supported');
        }

        $probe_tables = $required;
        foreach ($alternative_groups as $group) {
            $probe_tables = array_merge($probe_tables, $group);
        }
        $probe_tables = array_values(array_unique($probe_tables));
        foreach ($probe_tables as $table) {
            if (!preg_match('/^[A-Za-z0-9_]+$/', $table)) {
                return array('supported' => true, 'ready' => false, 'reason' => 'invalid_table_prefix');
            }
        }

        try {
            $quoted = array_map(function (string $table) use ($db): string {
                return "'" . $db->escape($table) . "'";
            }, $probe_tables);
            $result = $db->query(
                'SELECT table_name FROM information_schema.tables'
                . ' WHERE table_schema = DATABASE() AND table_name IN (' . implode(',', $quoted) . ')'
            );
            $found = array();
            foreach (($result->rows ?? array()) as $row) {
                $found[(string)($row['table_name'] ?? $row['TABLE_NAME'] ?? '')] = true;
            }
            foreach ($required as $table) {
                if (empty($found[$table])) {
                    return array('supported' => true, 'ready' => false, 'reason' => 'catalog_tables_missing');
                }
            }
            foreach ($alternative_groups as $group) {
                $matched = false;
                foreach ($group as $table) {
                    if (!empty($found[$table])) {
                        $matched = true;
                        break;
                    }
                }
                if (!$matched) {
                    return array('supported' => true, 'ready' => false, 'reason' => 'catalog_tables_missing');
                }
            }
        } catch (\Throwable $e) {
             
             
             
            $found = self::probeTablesDirectly($db, $probe_tables);
            if ($found === null) {
                return array('supported' => true, 'ready' => false, 'reason' => 'catalog_probe_failed');
            }
            foreach ($required as $table) {
                if (empty($found[$table])) {
                    return array('supported' => true, 'ready' => false, 'reason' => 'catalog_tables_missing');
                }
            }
            foreach ($alternative_groups as $group) {
                if (!self::hasAnyTable($found, $group)) {
                    return array('supported' => true, 'ready' => false, 'reason' => 'catalog_tables_missing');
                }
            }
        }

        if (in_array(strtolower(trim($cms_type)), array('wordpress', 'woocommerce'), true)) {
            try {
                $result = $db->query(
                    "SELECT option_value FROM `{$prefix}options`
                     WHERE option_name = 'woocommerce_version' LIMIT 1"
                );
                if (empty($result->row['option_value'])) {
                    return array('supported' => true, 'ready' => false, 'reason' => 'woocommerce_not_detected');
                }
            } catch (\Throwable $e) {
                return array('supported' => true, 'ready' => false, 'reason' => 'woocommerce_probe_failed');
            }
        }

        return array('supported' => true, 'ready' => true, 'reason' => 'ready');
    }

    public static function inspectMysqli($conn, string $cms_type, string $prefix): array {
        $required = self::requiredTables($cms_type, $prefix);
        $alternative_groups = self::alternativeTableGroups($cms_type, $prefix);
        if (empty($required) || !($conn instanceof \mysqli)) {
            return array('supported' => false, 'ready' => false, 'reason' => 'cms_not_supported');
        }

        $probe_tables = $required;
        foreach ($alternative_groups as $group) {
            $probe_tables = array_merge($probe_tables, $group);
        }
        $probe_tables = array_values(array_unique($probe_tables));
        foreach ($probe_tables as $table) {
            if (!preg_match('/^[A-Za-z0-9_]+$/', $table)) {
                return array('supported' => true, 'ready' => false, 'reason' => 'invalid_table_prefix');
            }
        }

        $quoted = array_map(function (string $table) use ($conn): string {
            return "'" . $conn->real_escape_string($table) . "'";
        }, $probe_tables);
        $result = $conn->query(
            'SELECT table_name FROM information_schema.tables'
            . ' WHERE table_schema = DATABASE() AND table_name IN (' . implode(',', $quoted) . ')'
        );
        if (!$result) {
            $found = self::probeTablesDirectlyMysqli($conn, $probe_tables);
            if ($found === null) {
                return array('supported' => true, 'ready' => false, 'reason' => 'catalog_probe_failed');
            }
        } else {
            $found = array();
            while ($row = $result->fetch_assoc()) {
                $found[(string)($row['table_name'] ?? $row['TABLE_NAME'] ?? '')] = true;
            }
            $result->free();
        }
        foreach ($required as $table) {
            if (empty($found[$table])) {
                return array('supported' => true, 'ready' => false, 'reason' => 'catalog_tables_missing');
            }
        }
        foreach ($alternative_groups as $group) {
            $matched = false;
            foreach ($group as $table) {
                if (!empty($found[$table])) {
                    $matched = true;
                    break;
                }
            }
            if (!$matched) {
                return array('supported' => true, 'ready' => false, 'reason' => 'catalog_tables_missing');
            }
        }

        if (in_array(strtolower(trim($cms_type)), array('wordpress', 'woocommerce'), true)) {
            $table = $prefix . 'options';
            $result = $conn->query(
                "SELECT option_value FROM `{$table}`
                 WHERE option_name = 'woocommerce_version' LIMIT 1"
            );
            $ready = $result && $result->num_rows > 0;
            if ($result) {
                $result->free();
            }
            if (!$ready) {
                return array('supported' => true, 'ready' => false, 'reason' => 'woocommerce_not_detected');
            }
        }

        return array('supported' => true, 'ready' => true, 'reason' => 'ready');
    }

    private static function probeTablesDirectly($db, array $tables) {
        $found = array();
        $successful = 0;
        foreach ($tables as $table) {
            try {
                $db->query("SELECT 1 FROM `{$table}` LIMIT 0");
                $found[$table] = true;
                $successful++;
            } catch (\Throwable $e) {
                $found[$table] = false;
            }
        }
        return $successful > 0 ? $found : null;
    }

    private static function probeTablesDirectlyMysqli($conn, array $tables) {
        $found = array();
        $successful = 0;
        foreach ($tables as $table) {
            $result = @$conn->query("SELECT 1 FROM `{$table}` LIMIT 0");
            if ($result) {
                $found[$table] = true;
                $successful++;
                $result->free();
            } else {
                $found[$table] = false;
            }
        }
        return $successful > 0 ? $found : null;
    }

    private static function hasAnyTable(array $found, array $group): bool {
        foreach ($group as $table) {
            if (!empty($found[$table])) {
                return true;
            }
        }
        return false;
    }
}
