<?php
/**
 * wp_compat.php
 * لایه شبیه‌ساز توابع و کلاس‌های هسته وردپرس برای محیط Standalone
 * شامل مکانیزم احراز هویت سفارشی (Bcrypt/MD5/$wp$2y$)
 */

declare(strict_types=1);

if ( ! defined( 'ABSPATH' ) ) {
    define( 'ABSPATH', dirname(__DIR__) . '/' );
}

// تعریف ثابت‌های زمانی در صورت عدم وجود
if ( ! defined( 'MINUTE_IN_SECONDS' ) ) define( 'MINUTE_IN_SECONDS', 60 );
if ( ! defined( 'HOUR_IN_SECONDS' ) )   define( 'HOUR_IN_SECONDS',   3600 );
if ( ! defined( 'DAY_IN_SECONDS' ) )    define( 'DAY_IN_SECONDS',    86400 );
if ( ! defined( 'WEEK_IN_SECONDS' ) )   define( 'WEEK_IN_SECONDS',   604800 );
if ( ! defined( 'MONTH_IN_SECONDS' ) )  define( 'MONTH_IN_SECONDS',  2592000 );
if ( ! defined( 'YEAR_IN_SECONDS' ) )   define( 'YEAR_IN_SECONDS',   31536000 );

// متغیرهای عمومی سیستم REST و Transientها
$GLOBALS['wp_rest_routes']   = [];
$GLOBALS['acc_rest_routes']  = [];
$GLOBALS['acc_transients']   = [];

/* ──────────────────────────────────────────────────────────────────────────
   ۱. کلاس‌های مورد نیاز برای REST API
   ────────────────────────────────────────────────────────────────────────── */

/* ──────────────────────────────────────────────────────────────────────────
   ۱. کلاس‌های مورد نیاز برای REST API
   ────────────────────────────────────────────────────────────────────────── */

if ( ! class_exists( 'WP_REST_Server' ) ) {
    class WP_REST_Server {
        public const READABLE   = 'GET';
        public const CREATABLE  = 'POST';
        public const EDITABLE   = 'PUT, PATCH';
        public const DELETABLE  = 'DELETE';
        public const ALLMETHODS = 'GET, POST, PUT, PATCH, DELETE';

        /**
         * بررسی و اجرای روت مطابق با متد و URL درخواستی
         */
        public function dispatch( string $request_uri, string $method ) {
            $method = strtoupper($method);
            $path   = parse_url($request_uri, PHP_URL_PATH) ?: '/';

            // حذف پیشوند api.php از مسیر در صورت وجود
            if ( strpos( $path, 'api.php' ) !== false ) {
                $parts = explode( 'api.php', $path, 2 );
                $path  = $parts[1] ?? '/';
            }
            $path = '/' . trim($path, '/');

            // دسترسی به روت‌های ثبت شده در سیستم
            $routes = $GLOBALS['wp_rest_routes'] ?? [];

            foreach ( $routes as $route_pattern => $endpoints ) {
                // تبدیل فرمت روت وردپرس به رگکس استاندارد
                // به عنوان مثال تبدیل /acc/v1/chat/support/rooms/(?P<id>\d+) به رگکس معتبر
                $pattern = '#^' . $route_pattern . '$#';
                $matches = [];

                if ( preg_match( $pattern, $path, $matches ) ) {
                    foreach ( $endpoints as $endpoint ) {
                        // بررسی متدهای مجاز برای این روت
                        $allowed_methods = array_map('trim', explode(',', strtoupper($endpoint['methods'])));
                        if ( ! in_array( $method, $allowed_methods, true ) ) {
                            continue;
                        }

                        // استخراج پارامترهای نام‌گذاری شده از Regex (مانند id)
                        $url_params = [];
                        foreach ( $matches as $key => $value ) {
                            if ( is_string( $key ) ) {
                                $url_params[ $key ] = $value;
                            }
                        }

                        // ساخت شیء درخواست وردپرسی
                        $request = new WP_REST_Request( $method, $path );
                        
                        // تنظیم هدرها
                        $headers = [];
                        foreach ( $_SERVER as $k => $v ) {
                            if ( strpos( $k, 'HTTP_' ) === 0 ) {
                                $headers[ substr( $k, 5 ) ] = $v;
                            }
                        }
                        $request->set_headers( $headers );

                        // تنظیم پارامترهای URL استخراج شده از Regex
                        $request->set_url_params( $url_params );
                        
                        // تنظیم پارامترهای Query String (GET)
                        $request->set_query_params( $_GET );

                        // تنظیم پارامترهای Body و JSON
                        $raw_body = file_get_contents('php://input');
                        $request->set_body( $raw_body );
                        
                        $content_type = $_SERVER['CONTENT_TYPE'] ?? '';
                        if ( stripos( $content_type, 'application/json' ) !== false && ! empty( $raw_body ) ) {
                            $json_data = json_decode( $raw_body, true );
                            if ( is_array( $json_data ) ) {
                                $request->set_json_params( $json_data );
                            }
                        } else {
                            $request->set_body_params( $_POST );
                        }

                        // بررسی تابع دسترسی (Permission Callback)
                        if ( ! empty( $endpoint['permission_callback'] ) ) {
                            $permission = call_user_func( $endpoint['permission_callback'], $request );
                            if ( is_wp_error( $permission ) ) {
                                return $permission;
                            }
                            if ( $permission === false ) {
                                return new WP_Error( 'rest_forbidden', 'اجازه دسترسی به این روت را ندارید.', [ 'status' => 403 ] );
                            }
                        }

                        // اجرای کنترلر و بازگرداندن پاسخ
                        $response = call_user_func( $endpoint['callback'], $request );
                        return rest_ensure_response( $response );
                    }
                }
            }

            return new WP_Error( 'rest_no_route', 'روتی مطابق با این متد و آدرس یافت نشد.', [ 'status' => 404 ] );
        }
    }
}


if ( ! class_exists( 'WP_Error' ) ) {
    class WP_Error {
        public $code;
        public $message;
        public $data;

        public function __construct( $code = '', $message = '', $data = [] ) {
            $this->code    = $code;
            $this->message = $message;
            $this->data    = $data;
        }

        public function get_error_code() {
            return $this->code;
        }

        public function get_error_message( $code = '' ) {
            return $this->message;
        }

        public function get_error_data( $code = '' ) {
            return $this->data;
        }
    }
}

if ( ! function_exists( 'is_wp_error' ) ) {
    function is_wp_error( $thing ): bool {
        return ( $thing instanceof WP_Error );
    }
}

if ( ! class_exists( 'WP_REST_Request' ) ) {
    class WP_REST_Request implements ArrayAccess {
        private string $method = 'GET';
        private string $route = '';
        private string $body = '';
        private array $headers = [];

        private array $url_params = [];
        private array $query_params = [];
        private array $body_params = [];
        private array $json_params = [];
        private array $file_params = [];
        private array $attributes = [];
        private array $default_params = [];

        public function __construct( string $method = 'GET', string $route = '', array $attributes = [] ) {
            $this->method = strtoupper( $method );
            $this->route = $route;
            $this->attributes = $attributes;
        }

        public function get_method(): string {
            return $this->method;
        }

        public function set_method( string $method ): void {
            $this->method = strtoupper( $method );
        }

        public function get_route(): string {
            return $this->route;
        }

        public function set_route( string $route ): void {
            $this->route = $route;
        }

        public function get_body(): string {
            return $this->body;
        }

        public function set_body( string $body ): void {
            $this->body = $body;
        }

        public function get_headers(): array {
            return $this->headers;
        }

        public function set_headers( array $headers ): void {
            $normalized = [];

            foreach ( $headers as $key => $value ) {
                $name = strtolower( str_replace( '_', '-', (string) $key ) );
                $normalized[ $name ] = $value;
            }

            $this->headers = $normalized;
        }

        public function get_header( string $key ) {
            $key = strtolower( str_replace( '_', '-', $key ) );

            return $this->headers[ $key ] ?? null;
        }

        public function set_header( string $key, $value ): void {
            $key = strtolower( str_replace( '_', '-', $key ) );

            $this->headers[ $key ] = $value;
        }

        public function get_content_type(): array {
            $content_type = $this->get_header( 'content-type' );

            if ( is_array( $content_type ) ) {
                $content_type = reset( $content_type );
            }

            $content_type = (string) $content_type;

            if ( $content_type === '' ) {
                return [
                    'value'      => '',
                    'parameters' => [],
                ];
            }

            $parts = array_map( 'trim', explode( ';', $content_type ) );
            $value = strtolower( array_shift( $parts ) );
            $parameters = [];

            foreach ( $parts as $part ) {
                if ( strpos( $part, '=' ) !== false ) {
                    [ $k, $v ] = array_map( 'trim', explode( '=', $part, 2 ) );
                    $parameters[ strtolower( $k ) ] = trim( $v, '"' );
                }
            }

            return [
                'value'      => $value,
                'parameters' => $parameters,
            ];
        }

        public function is_json_content_type(): bool {
            $content_type = $this->get_content_type();

            return isset( $content_type['value'] )
                && (
                    $content_type['value'] === 'application/json'
                    || str_ends_with( $content_type['value'], '+json' )
                );
        }

        public function set_url_params( array $params ): void {
            $this->url_params = $params;
        }

        public function get_url_params(): array {
            return $this->url_params;
        }

        public function set_query_params( array $params ): void {
            $this->query_params = $params;
        }

        public function get_query_params(): array {
            return $this->query_params;
        }

        public function set_body_params( array $params ): void {
            $this->body_params = $params;
        }

        public function get_body_params(): array {
            return $this->body_params;
        }

        public function set_json_params( array $params ): void {
            $this->json_params = $params;
        }

        public function get_json_params(): array {
            return $this->json_params;
        }

        public function set_file_params( array $params ): void {
            $this->file_params = $params;
        }

        public function get_file_params(): array {
            return $this->file_params;
        }

        public function set_attributes( array $attributes ): void {
            $this->attributes = $attributes;
        }

        public function get_attributes(): array {
            return $this->attributes;
        }

        public function set_default_params( array $params ): void {
            $this->default_params = $params;
        }

        public function get_default_params(): array {
            return $this->default_params;
        }

        public function set_params( array $params ): void {
            if ( $this->is_json_content_type() ) {
                $this->json_params = $params;
            } else {
                $this->body_params = $params;
            }
        }

        private function get_parameter_order(): array {
            return [
                'json',
                'body',
                'query',
                'url',
                'defaults',
            ];
        }

        public function get_params(): array {
            return array_merge(
                $this->default_params,
                $this->url_params,
                $this->query_params,
                $this->body_params,
                $this->json_params
            );
        }

        public function get_param( string $key ) {
            foreach ( $this->get_parameter_order() as $type ) {
                switch ( $type ) {
                    case 'json':
                        if ( array_key_exists( $key, $this->json_params ) ) {
                            return $this->json_params[ $key ];
                        }
                        break;

                    case 'body':
                        if ( array_key_exists( $key, $this->body_params ) ) {
                            return $this->body_params[ $key ];
                        }
                        break;

                    case 'query':
                        if ( array_key_exists( $key, $this->query_params ) ) {
                            return $this->query_params[ $key ];
                        }
                        break;

                    case 'url':
                        if ( array_key_exists( $key, $this->url_params ) ) {
                            return $this->url_params[ $key ];
                        }
                        break;

                    case 'defaults':
                        if ( array_key_exists( $key, $this->default_params ) ) {
                            return $this->default_params[ $key ];
                        }
                        break;
                }
            }

            return null;
        }

        public function set_param( string $key, $value ): void {
            if ( $this->is_json_content_type() ) {
                $this->json_params[ $key ] = $value;
            } else {
                $this->body_params[ $key ] = $value;
            }
        }

        public function has_param( string $key ): bool {
            foreach ( $this->get_parameter_order() as $type ) {
                switch ( $type ) {
                    case 'json':
                        if ( array_key_exists( $key, $this->json_params ) ) {
                            return true;
                        }
                        break;

                    case 'body':
                        if ( array_key_exists( $key, $this->body_params ) ) {
                            return true;
                        }
                        break;

                    case 'query':
                        if ( array_key_exists( $key, $this->query_params ) ) {
                            return true;
                        }
                        break;

                    case 'url':
                        if ( array_key_exists( $key, $this->url_params ) ) {
                            return true;
                        }
                        break;

                    case 'defaults':
                        if ( array_key_exists( $key, $this->default_params ) ) {
                            return true;
                        }
                        break;
                }
            }

            return false;
        }

        // پیاده‌سازی متدهای اینترفیس ArrayAccess برای دسترسی به شیء مانند آرایه: $request['param']
        public function offsetExists( $offset ): bool {
            return $this->has_param( (string) $offset );
        }

        #[\ReturnTypeWillChange]
        public function offsetGet( $offset ) {
            return $this->get_param( (string) $offset );
        }

        public function offsetSet( $offset, $value ): void {
            $this->set_param( (string) $offset, $value );
        }

        public function offsetUnset( $offset ): void {
            $key = (string) $offset;
            unset( $this->url_params[ $key ] );
            unset( $this->query_params[ $key ] );
            unset( $this->body_params[ $key ] );
            unset( $this->json_params[ $key ] );
            unset( $this->default_params[ $key ] );
        }
    }
}


if ( ! class_exists( 'WP_REST_Response' ) ) {
    class WP_REST_Response {
        private $data;
        private int $status;
        private array $headers = [];

        public function __construct( $data = null, int $status = 200, array $headers = [] ) {
            $this->data    = $data;
            $this->status  = $status;
            $this->headers = $headers;
        }

        public function get_data() {
            return $this->data;
        }

        public function get_status(): int {
            return $this->status;
        }

        public function get_headers(): array {
            return $this->headers;
        }
    }
}

if ( ! function_exists( 'rest_ensure_response' ) ) {
    function rest_ensure_response( $response ) {
        if ( $response instanceof WP_REST_Response ) {
            return $response;
        }
        if ( $response instanceof WP_Error ) {
            return $response;
        }
        return new WP_REST_Response( $response );
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   ۲. ثبت REST Routeها در موتور
   ────────────────────────────────────────────────────────────────────────── */

if ( ! function_exists( 'register_rest_route' ) ) {
    function register_rest_route( string $namespace, string $route, array $args = [] ): void {
        // حذف اسلش‌های اضافی در کل آدرس به صورت کاملاً یکدست
        $namespace_clean = trim( $namespace, '/' );
        $route_clean     = '/' . ltrim( $route, '/' );
        $formatted_route = '/' . trim( $namespace_clean . $route_clean, '/' );

        if ( ! isset( $GLOBALS['wp_rest_routes'] ) || ! is_array( $GLOBALS['wp_rest_routes'] ) ) {
            $GLOBALS['wp_rest_routes'] = [];
        }

        if ( ! isset( $GLOBALS['acc_rest_routes'] ) || ! is_array( $GLOBALS['acc_rest_routes'] ) ) {
            $GLOBALS['acc_rest_routes'] = [];
        }

        $is_multi_endpoint = isset( $args[0] ) && is_array( $args[0] );
        $endpoints = $is_multi_endpoint ? $args : [ $args ];

        foreach ( $endpoints as $endpoint ) {
            if ( ! is_array( $endpoint ) ) {
                continue;
            }

            $route_entry = [
                'namespace'           => $namespace,
                'route'               => $route,
                'methods'             => $endpoint['methods'] ?? 'GET',
                'callback'            => $endpoint['callback'] ?? null,
                'permission_callback' => $endpoint['permission_callback'] ?? null,
                'args'                => $endpoint['args'] ?? [],
            ];

            $GLOBALS['wp_rest_routes'][ $formatted_route ][] = $route_entry;
            $GLOBALS['acc_rest_routes'][] = $route_entry;
        }
    }
}



/* ──────────────────────────────────────────────────────────────────────────
   ۳. توابع کمکی JSON و Response
   ────────────────────────────────────────────────────────────────────────── */

if ( ! function_exists( 'wp_json_encode' ) ) {
    function wp_json_encode( $data, $options = 0, $depth = 512 ) {
        return json_encode( $data, $options, $depth );
    }
}

if ( ! function_exists( 'acc_json_response' ) ) {
    function acc_json_response( $data, int $status_code = 200 ): void {
        if ( ! headers_sent() ) {
            header( 'Content-Type: application/json; charset=utf-8' );
            http_response_code( $status_code );
        }
        echo wp_json_encode( $data );
        exit;
    }
}

if ( ! function_exists( 'wp_send_json' ) ) {
    function wp_send_json( $response, $status_code = null, $options = 0 ): void {
        $status = is_int( $status_code ) ? $status_code : 200;
        acc_json_response( $response, $status );
    }
}

if ( ! function_exists( 'wp_send_json_success' ) ) {
    function wp_send_json_success( $data = null, $status_code = null, $options = 0 ): void {
        $response = [ 'success' => true ];
        if ( isset( $data ) ) {
            $response['data'] = $data;
        }
        wp_send_json( $response, $status_code, $options );
    }
}

if ( ! function_exists( 'wp_send_json_error' ) ) {
    function wp_send_json_error( $data = null, $status_code = null, $options = 0 ): void {
        $response = [ 'success' => false ];
        if ( isset( $data ) ) {
            $response['data'] = $data;
        }
        $status = is_int( $status_code ) ? $status_code : 400;
        wp_send_json( $response, $status, $options );
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   ۴. توابع پیش‌فرض Callback و Sanitization
   ────────────────────────────────────────────────────────────────────────── */

if ( ! function_exists( '__return_true' ) ) {
    function __return_true(): bool { return true; }
}
if ( ! function_exists( '__return_false' ) ) {
    function __return_false(): bool { return false; }
}
if ( ! function_exists( '__return_null' ) ) {
    function __return_null() { return null; }
}

if ( ! function_exists( 'sanitize_key' ) ) {
    function sanitize_key( $key ): string {
        $raw_key = (string) $key;
        $key     = preg_replace( '/[^a-z0-9_\-]/', '', strtolower( $raw_key ) );
        return $key;
    }
}

if ( ! function_exists( 'sanitize_textarea_field' ) ) {
    function sanitize_textarea_field( $str ): string {
        $filtered = strip_tags( (string) $str );
        $filtered = preg_replace( '/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', $filtered );
        return trim( $filtered );
    }
}

if ( ! function_exists( 'esc_url_raw' ) ) {
    function esc_url_raw( $url, $protocols = null ): string {
        return (string) filter_var( (string) $url, FILTER_SANITIZE_URL );
    }
}

if ( ! function_exists( 'sanitize_text_field' ) ) {
    function sanitize_text_field( $str ): string {
        $filtered = (string) $str;
        $filtered = strip_tags( $filtered );
        $filtered = htmlspecialchars( $filtered, ENT_QUOTES, 'UTF-8' );
        return trim( $filtered );
    }
}

if ( ! function_exists( 'sanitize_email' ) ) {
    function sanitize_email( $email ): string {
        return filter_var( trim((string)$email), FILTER_SANITIZE_EMAIL ) ?: '';
    }
}

if ( ! function_exists( 'is_email' ) ) {
    function is_email( $email ): bool {
        return filter_var( trim((string)$email), FILTER_VALIDATE_EMAIL ) !== false;
    }
}

if ( ! function_exists( 'sanitize_title' ) ) {
    function sanitize_title( $title ): string {
        $title = strip_tags( (string)$title );
        $title = preg_replace( '/\s+/', '-', $title );
        return strtolower( trim( $title, '-' ) );
    }
}

if ( ! function_exists( 'absint' ) ) {
    function absint( $maybeint ): int {
        return abs( (int) $maybeint );
    }
}

if ( ! function_exists( 'wp_unslash' ) ) {
    function wp_unslash( $value ) {
        if ( is_array( $value ) ) {
            foreach ( $value as $k => $v ) {
                $value[$k] = wp_unslash( $v );
            }
        } elseif ( is_string( $value ) ) {
            return stripslashes( $value );
        }
        return $value;
    }
}

if ( ! function_exists( 'wp_slash' ) ) {
    function wp_slash( $value ) {
        if ( is_array( $value ) ) {
            foreach ( $value as $k => $v ) {
                $value[$k] = wp_slash( $v );
            }
        } elseif ( is_string( $value ) ) {
            return addslashes( $value );
        }
        return $value;
    }
}

if ( ! function_exists( 'esc_sql' ) ) {
    function esc_sql( $data ) {
        if ( is_array( $data ) ) {
            foreach ( $data as $k => $v ) {
                $data[$k] = esc_sql( $v );
            }
            return $data;
        }
        if ( isset( $GLOBALS['wpdb'] ) && method_exists( $GLOBALS['wpdb'], 'escape' ) ) {
            return $GLOBALS['wpdb']->escape( $data );
        }
        return addslashes( (string)$data );
    }
}

if ( ! function_exists( 'esc_html' ) ) {
    function esc_html( $text ): string {
        return htmlspecialchars( (string)$text, ENT_QUOTES, 'UTF-8' );
    }
}

if ( ! function_exists( 'esc_attr' ) ) {
    function esc_attr( $text ): string {
        return htmlspecialchars( (string)$text, ENT_QUOTES, 'UTF-8' );
    }
}

if ( ! function_exists( 'esc_url' ) ) {
    function esc_url( $url ): string {
        return filter_var( $url, FILTER_SANITIZE_URL ) ?: '';
    }
}

if ( ! function_exists( 'current_time' ) ) {
    function current_time( $type, $gmt = 0 ) {
        if ( 'mysql' === $type ) {
            return $gmt ? gmdate( 'Y-m-d H:i:s' ) : date( 'Y-m-d H:i:s' );
        }
        return $gmt ? time() : time() + (int) date( 'Z' );
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   ۵. پردازش داده‌ها و آرایه‌ها
   ────────────────────────────────────────────────────────────────────────── */

if ( ! function_exists( 'wp_parse_args' ) ) {
    function wp_parse_args( $args, $defaults = [] ): array {
        if ( is_object( $args ) ) {
            $r = get_object_vars( $args );
        } elseif ( is_array( $args ) ) {
            $r =& $args;
        } else {
            wp_parse_str( $args, $r );
        }
        return array_merge( $defaults, $r );
    }
}

if ( ! function_exists( 'wp_parse_str' ) ) {
    function wp_parse_str( $string, &$array ): void {
        parse_str( (string)$string, $array );
    }
}

if ( ! function_exists( 'wp_list_pluck' ) ) {
    function wp_list_pluck( array $list, $field, $index_key = null ): array {
        $new_list = [];
        foreach ( $list as $key => $value ) {
            if ( is_object( $value ) ) {
                $val = isset( $value->$field ) ? $value->$field : null;
            } else {
                $val = isset( $value[$field] ) ? $value[$field] : null;
            }

            if ( null === $index_key ) {
                $new_list[] = $val;
            } else {
                if ( is_object( $value ) ) {
                    $index = $value->$index_key;
                } else {
                    $index = $value[$index_key];
                }
                $new_list[$index] = $val;
            }
        }
        return $new_list;
    }
}

if ( ! function_exists( 'wp_parse_id_list' ) ) {
    function wp_parse_id_list( $list ): array {
        if ( ! is_array( $list ) ) {
            $list = preg_split( '/[\s,]+/', (string)$list );
        }
        return array_unique( array_filter( array_map( 'absint', $list ) ) );
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   ۶. سیستم Cache موقت (Transients) در حافظه
   ────────────────────────────────────────────────────────────────────────── */

if ( ! function_exists( 'set_transient' ) ) {
    function set_transient( $transient, $value, $expiration = 0 ): bool {
        $GLOBALS['acc_transients'][$transient] = [
            'value'  => $value,
            'expire' => $expiration > 0 ? ( time() + $expiration ) : 0
        ];
        return true;
    }
}

if ( ! function_exists( 'get_transient' ) ) {
    function get_transient( $transient ) {
        if ( isset( $GLOBALS['acc_transients'][$transient] ) ) {
            $item = $GLOBALS['acc_transients'][$transient];
            if ( $item['expire'] === 0 || $item['expire'] > time() ) {
                return $item['value'];
            }
            unset( $GLOBALS['acc_transients'][$transient] );
        }
        return false;
    }
}

if ( ! function_exists( 'delete_transient' ) ) {
    function delete_transient( $transient ): bool {
        if ( isset( $GLOBALS['acc_transients'][$transient] ) ) {
            unset( $GLOBALS['acc_transients'][$transient] );
            return true;
        }
        return false;
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   ۷. توابع Taxonomy و Termها
   ────────────────────────────────────────────────────────────────────────── */

if ( ! function_exists( 'taxonomy_exists' ) ) {
    function taxonomy_exists( $taxonomy ): bool {
        return in_array( $taxonomy, ['category', 'post_tag', 'product_cat', 'product_tag'] );
    }
}

if ( ! function_exists( 'get_terms' ) ) {
    function get_terms( $args = [] ): array {
        global $wpdb;
        $defaults = [ 'taxonomy' => 'category', 'hide_empty' => false ];
        $parsed   = wp_parse_args( $args, $defaults );
        $tax      = esc_sql( $parsed['taxonomy'] );

        if ( ! isset( $wpdb ) ) {
            return [];
        }

        try {
            $query = "
                SELECT t.term_id, t.name, t.slug, tt.term_taxonomy_id, tt.taxonomy, tt.parent, tt.count
                FROM {$wpdb->prefix}terms t
                INNER JOIN {$wpdb->prefix}term_taxonomy tt ON t.term_id = tt.term_id
                WHERE tt.taxonomy = '{$tax}'
            ";
            return $wpdb->get_results( $query, OBJECT );
        } catch ( \Throwable $e ) {
            return [];
        }
    }
}

if ( ! function_exists( 'get_term_meta' ) ) {
    function get_term_meta( $term_id, $key = '', $single = false ) {
        global $wpdb;
        if ( ! isset( $wpdb ) ) return '';
        $term_id = (int) $term_id;
        $key     = esc_sql( $key );

        try {
            if ( $single ) {
                $query = "SELECT meta_value FROM {$wpdb->prefix}termmeta WHERE term_id = {$term_id} AND meta_key = '{$key}' LIMIT 1";
                $val   = $wpdb->get_var( $query );
                return $val ? maybe_unserialize( $val ) : '';
            }
            $query = "SELECT meta_value FROM {$wpdb->prefix}termmeta WHERE term_id = {$term_id} AND meta_key = '{$key}'";
            $rows  = $wpdb->get_col( $query );
            return array_map( 'maybe_unserialize', $rows );
        } catch ( \Throwable $e ) {
            return $single ? '' : [];
        }
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   ۸. تصویر شاخص و آدرس وب‌سایت
   ────────────────────────────────────────────────────────────────────────── */

if ( ! function_exists( 'wp_get_attachment_image_url' ) ) {
    function wp_get_attachment_image_url( $attachment_id, $size = 'thumbnail', $icon = false ) {
        global $wpdb;
        if ( ! isset( $wpdb ) ) return '';
        $attachment_id = (int) $attachment_id;
        
        try {
            $query = "SELECT meta_value FROM {$wpdb->prefix}postmeta WHERE post_id = {$attachment_id} AND meta_key = '_wp_attached_file' LIMIT 1";
            $file  = $wpdb->get_var( $query );
            if ( $file ) {
                return site_url( 'wp-content/uploads/' . $file );
            }
        } catch ( \Throwable $e ) {
            // خطایی رخ داده، ادامه می‌دهیم
        }
        return '';
    }
}

if ( ! function_exists( 'site_url' ) ) {
    function site_url( $path = '' ): string {
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https://' : 'http://';
        $host     = $_SERVER['HTTP_HOST'] ?? 'localhost';
        $base     = rtrim( $protocol . $host . '/acc-engine', '/' );
        return $base . '/' . ltrim( $path, '/' );
    }
}

if ( ! function_exists( 'home_url' ) ) {
    function home_url( $path = '' ): string {
        return site_url( $path );
    }
}

if ( ! function_exists( 'maybe_unserialize' ) ) {
    function maybe_unserialize( $original ) {
        if ( is_string( $original ) ) {
            $trimmed = trim( $original );
            if ( 'N;' === $trimmed ) {
                return null;
            }
            if ( strlen( $trimmed ) < 4 || ':' !== $trimmed[1] ) {
                return $original;
            }
            $unserialized = @unserialize( $trimmed );
            if ( false !== $unserialized ) {
                return $unserialized;
            }
        }
        return $original;
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   ۹. سیستم احراز هویت و کاربران (هماهنگ با الگوهای دیتابیس)
   ────────────────────────────────────────────────────────────────────────── */

if ( ! class_exists( 'WP_User' ) ) {
    class WP_User {
        public int $ID = 0;
        public string $user_login = '';
        public string $user_pass = '';
        public string $user_nicename = '';
        public string $user_email = '';
        public string $user_url = '';
        public string $user_registered = '';
        public string $user_activation_key = '';
        public int $user_status = 0;
        public string $display_name = '';

        public function __construct( array $data = [] ) {
            foreach ( $data as $key => $val ) {
                if ( property_exists( $this, $key ) ) {
                    if ( $key === 'ID' || $key === 'user_status' ) {
                        $this->$key = (int) $val;
                    } else {
                        $this->$key = (string) $val;
                    }
                }
            }
        }

        public function exists(): bool {
            return $this->ID > 0;
        }
    }
}

if ( ! function_exists( 'get_user_by' ) ) {
    function get_user_by( string $field, $value ) {
        global $wpdb;
        if ( ! isset( $wpdb ) ) {
            return false;
        }

        $field = sanitize_key( $field );
        if ( ! in_array( $field, ['id', 'slug', 'email', 'login'] ) ) {
            return false;
        }

        // تبدیل نام فیلد به فیلد واقعی جدول
        $db_field = 'user_login';
        if ( $field === 'id' )    $db_field = 'ID';
        if ( $field === 'slug' )  $db_field = 'user_nicename';
        if ( $field === 'email' ) $db_field = 'user_email';

        $escaped_value = esc_sql( $value );
        
        try {
            $query = "SELECT * FROM {$wpdb->prefix}users WHERE {$db_field} = '{$escaped_value}' LIMIT 1";
            $row   = $wpdb->get_row( $query, ARRAY_A );
            if ( $row ) {
                return new WP_User( $row );
            }
        } catch ( \Throwable $e ) {
            return false;
        }
        return false;
    }
}

if ( ! function_exists( 'wp_check_password' ) ) {
    function wp_check_password( string $password, string $hash, int $user_id = 0 ): bool {
        
        // ۱. بررسی فرمت سفارشی $wp$2y$ و تبدیل آن با مکانیزم پیش‌هشینگ وردپرس ۶.۸+
        if ( strpos( $hash, '$wp$2y$' ) === 0 || strpos( $hash, '$wp$2a$' ) === 0 || strpos( $hash, '$wp$2b$' ) === 0 ) {
            // حذف پیشوند $wp برای رسیدن به هش استاندارد Bcrypt
            $standard_hash = substr( $hash, 3 ); 
            
            // پیش‌هش کردن پسورد خام مشابه رفتار وردپرس جدید
            $prehashed_password = base64_encode(
                hash_hmac(
                    'sha384',
                    $password,
                    'wp-sha384',
                    true
                )
            );

            if ( password_verify( $prehashed_password, $standard_hash ) ) {
                return true;
            }
        }

        // ۲. بررسی Bcrypt استاندارد (در صورتی که مستقیما با Bcrypt معمولی بدون پیش‌هش ذخیره شده باشد)
        if ( ( strpos( $hash, '$2y$' ) === 0 || strpos( $hash, '$2a$' ) === 0 || strpos( $hash, '$2b$' ) === 0 ) ) {
            if ( password_verify( $password, $hash ) ) {
                return true;
            }
        }

        // ۳. بررسی فرمت MD5 ساده
        if ( strlen( $hash ) === 32 ) {
            return ( md5( $password ) === $hash );
        }

        // ۴. بررسی فرمت‌های هش پیش‌فرض وردپرس ($P$ یا $H$) با استفاده از شبیه‌ساز ساده Phpass
        if ( strpos( $hash, '$P$' ) === 0 || strpos( $hash, '$H$' ) === 0 ) {
            $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
            $count_log2 = strpos( $itoa64, $hash[3] );
            if ( $count_log2 < 7 || $count_log2 > 30 ) {
                return false;
            }
            
            $count = 1 << $count_log2;
            $salt = substr( $hash, 4, 8 );
            $hash_calc = md5( $salt . $password, true );
            do {
                $hash_calc = md5( $hash_calc . $password, true );
            } while ( --$count );

            // تبدیل خروجی باینری به فرمت ۶۴ کاراکتری وردپرس
            $output = substr( $hash, 0, 12 );
            $output .= _acc_encode64( $hash_calc, 16, $itoa64 );
            
            return hash_equals( substr( $hash, 0, 34 ), substr( $output, 0, 34 ) );
        }

        return false;
    }
}


// تابع کمکی برای الگوریتم Phpass وردپرس
if ( ! function_exists( '_acc_encode64' ) ) {
    function _acc_encode64( string $input, int $count, string $itoa64 ): string {
        $output = '';
        $i = 0;
        do {
            $value = ord( $input[$i++] );
            $output .= $itoa64[$value & 0x3f];
            if ( $i < $count ) {
                $value |= ord( $input[$i] ) << 8;
            }
            $output .= $itoa64[($value >> 6) & 0x3f];
            if ( $i++ >= $count ) {
                break;
            }
            if ( $i < $count ) {
                $value |= ord( $input[$i] ) << 16;
            }
            $output .= $itoa64[($value >> 12) & 0x3f];
            if ( $i++ >= $count ) {
                break;
            }
            $output .= $itoa64[($value >> 18) & 0x3f];
        } while ( $i < $count );

        return $output;
    }
}

if ( ! function_exists( 'wp_authenticate' ) ) {
    function wp_authenticate( string $username, string $password ) {
        $user = is_email( $username )
            ? get_user_by( 'email', $username )
            : get_user_by( 'login', $username );

        if ( ! $user ) {
            return new WP_Error( 'invalid_username', 'نام کاربری نامعتبر است.' );
        }

        if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
            return new WP_Error( 'incorrect_password', 'رمز عبور نادرست است.' );
        }

        return $user;
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   ۱۰. شبیه‌ساز WP_Query و بازیابی پست‌ها/محصولات
   ────────────────────────────────────────────────────────────────────────── */

if ( ! class_exists( 'WP_Query' ) ) {
    class WP_Query {
        public array $posts = [];
        public int $found_posts = 0;
        public int $max_num_pages = 0;

        public function __construct( $query = '' ) {
            if ( ! empty( $query ) ) {
                $this->query( $query );
            }
        }

        public function query( $args ): array {
            global $wpdb;
            if ( ! isset( $wpdb ) ) {
                return [];
            }

            $defaults = [
                'post_type'      => 'post',
                'posts_per_page' => 10,
                'paged'          => 1,
                'post_status'    => 'publish',
            ];
            $parsed = wp_parse_args( $args, $defaults );

            $post_type = esc_sql( $parsed['post_type'] );
            $status    = esc_sql( $parsed['post_status'] );
            $limit     = (int) $parsed['posts_per_page'];
            $paged     = (int) $parsed['paged'];
            $offset    = ( $paged - 1 ) * $limit;
            $search    = isset( $parsed['s'] ) ? esc_sql( $parsed['s'] ) : '';
            $orderby   = $parsed['orderby'] ?? 'date';
            $order     = strtoupper( $parsed['order'] ?? 'DESC' ) === 'ASC' ? 'ASC' : 'DESC';

            $where = "post_type = '{$post_type}' AND post_status = '{$status}'";
            if ( $search ) {
                $where .= " AND post_title LIKE '%{$search}%'";
            }

            // فیلتر دسته‌بندی
            if ( ! empty( $parsed['product_cat'] ) ) {
                $cat_id = (int) $parsed['product_cat'];
                $where .= " AND ID IN (
                    SELECT tr.object_id FROM {$wpdb->prefix}term_relationships tr
                    INNER JOIN {$wpdb->prefix}term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
                    WHERE tt.taxonomy = 'product_cat' AND tt.term_id = {$cat_id}
                )";
            }

            $order_clause = $orderby === 'title'
                ? "post_title {$order}"
                : "post_date {$order}";

            if ( $orderby === 'meta_value_num' && ! empty( $parsed['meta_key'] ) ) {
                $meta_key = esc_sql( $parsed['meta_key'] );
                $order_clause = "CAST(pm.meta_value AS DECIMAL(12,2)) {$order}";
                $where_p = str_replace(
                    ['post_type', 'post_status', 'post_title', ' AND ID IN'],
                    ['p.post_type', 'p.post_status', 'p.post_title', ' AND p.ID IN'],
                    $where
                );
                $count_query = "
                    SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->prefix}posts p
                    LEFT JOIN {$wpdb->prefix}postmeta pm ON p.ID = pm.post_id AND pm.meta_key = '{$meta_key}'
                    WHERE {$where_p}
                ";
                $this->found_posts = (int) $wpdb->get_var( $count_query );

                $query = "
                    SELECT DISTINCT p.* FROM {$wpdb->prefix}posts p
                    LEFT JOIN {$wpdb->prefix}postmeta pm ON p.ID = pm.post_id AND pm.meta_key = '{$meta_key}'
                    WHERE {$where_p}
                    ORDER BY {$order_clause}
                    LIMIT {$limit} OFFSET {$offset}
                ";
                $rows = $wpdb->get_results( $query, ARRAY_A );
                $this->posts = [];
                foreach ( $rows as $row ) {
                    $this->posts[] = new WP_Post( $row );
                }
                $this->max_num_pages = (int) ceil( max( 1, $this->found_posts ) / $limit );
                return $this->posts;
            }

            try {
                $count_query = "SELECT COUNT(ID) FROM {$wpdb->prefix}posts WHERE {$where}";
                $this->found_posts = (int) $wpdb->get_var( $count_query );

                $query = "
                    SELECT * FROM {$wpdb->prefix}posts 
                    WHERE {$where}
                    ORDER BY {$order_clause}
                    LIMIT {$limit} OFFSET {$offset}
                ";
                
                $rows = $wpdb->get_results( $query, ARRAY_A );
                $this->posts = [];
                foreach ( $rows as $row ) {
                    $this->posts[] = new WP_Post( $row );
                }
                
                $this->max_num_pages = (int) ceil( $this->found_posts / $limit );
                return $this->posts;
            } catch ( \Throwable $e ) {
                return [];
            }
        }
    }
}

if ( ! class_exists( 'WP_Post' ) ) {
    class WP_Post {
        public int $ID = 0;
        public int $post_author = 0;
        public string $post_date = '';
        public string $post_content = '';
        public string $post_title = '';
        public string $post_excerpt = '';
        public string $post_status = '';
        public string $post_name = '';
        public string $post_type = '';

        public function __construct( array $data = [] ) {
            foreach ( $data as $key => $val ) {
                if ( property_exists( $this, $key ) ) {
                    if ( in_array( $key, ['ID', 'post_author'] ) ) {
                        $this->$key = (int) $val;
                    } else {
                        $this->$key = (string) $val;
                    }
                }
            }
        }
    }
}

if ( ! function_exists( 'get_post' ) ) {
    function get_post( $post_id = null, $output = OBJECT, $filter = 'raw' ) {
        global $wpdb;
        if ( ! isset( $wpdb ) ) return null;
        $post_id = (int) ( $post_id ?? 0 );
        if ( $post_id <= 0 ) return null;

        try {
            $row = $wpdb->get_row(
                "SELECT * FROM {$wpdb->prefix}posts WHERE ID = {$post_id} LIMIT 1",
                ARRAY_A
            );
            if ( ! $row ) return null;
            return new WP_Post( $row );
        } catch ( \Throwable $e ) {
            return null;
        }
    }
}

if ( ! function_exists( 'wp_reset_postdata' ) ) {
    function wp_reset_postdata(): void {}
}

if ( ! function_exists( 'get_post_meta' ) ) {
    function get_post_meta( $post_id, $key = '', $single = false ) {
        global $wpdb;
        if ( ! isset( $wpdb ) ) return '';
        $post_id = (int) $post_id;
        $key     = esc_sql( $key );

        try {
            if ( $single ) {
                $query = "SELECT meta_value FROM {$wpdb->prefix}postmeta WHERE post_id = {$post_id} AND meta_key = '{$key}' LIMIT 1";
                $val   = $wpdb->get_var( $query );
                return $val ? maybe_unserialize( $val ) : '';
            }
            $query = "SELECT meta_value FROM {$wpdb->prefix}postmeta WHERE post_id = {$post_id} AND meta_key = '{$key}'";
            $rows  = $wpdb->get_col( $query );
            return array_map( 'maybe_unserialize', $rows );
        } catch ( \Throwable $e ) {
            return $single ? '' : [];
        }
    }
}

if ( ! function_exists( 'wp_get_post_terms' ) ) {
    function wp_get_post_terms( $post_id, $taxonomy = 'post_tag', $args = [] ): array {
        global $wpdb;
        if ( ! isset( $wpdb ) ) return [];
        $post_id  = (int) $post_id;
        $taxonomy = esc_sql( $taxonomy );

        try {
            $query = "
                SELECT t.*, tt.*
                FROM {$wpdb->prefix}terms t
                INNER JOIN {$wpdb->prefix}term_taxonomy tt ON t.term_id = tt.term_id
                INNER JOIN {$wpdb->prefix}term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
                WHERE tr.object_id = {$post_id} AND tt.taxonomy = '{$taxonomy}'
            ";
            return $wpdb->get_results( $query, ARRAY_A );
        } catch ( \Throwable $e ) {
            return [];
        }
    }
}

/* ── JWT Simulation for Standalone ─────────────────── */

if ( ! defined( 'ACC_JWT_SECRET' ) ) {
    define( 'ACC_JWT_SECRET', '6f9a2b8c4d1e7f3a5b0c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f' );
}

if ( ! function_exists( 'acc_jwt_base64_url_encode' ) ) {
    function acc_jwt_base64_url_encode( $data ) {
        return rtrim( strtr( base64_encode( $data ), '+/', '-_' ), '=' );
    }
}

if ( ! function_exists( 'acc_jwt_generate_token' ) ) {
    function acc_jwt_generate_token( $user_or_id, $remember = false ) {
        // هم WP_User و هم ID عددی را پشتیبانی می‌کند
        $user_id = is_object( $user_or_id ) ? $user_or_id->ID : (int) $user_or_id;

        $header = json_encode( [
            'typ' => 'JWT',
            'alg' => 'HS256'
        ] );

        $payload = json_encode( [
            'sub' => $user_id,
            'iat' => time(),
            'exp' => time() + ( $remember ? ( DAY_IN_SECONDS * 30 ) : ( DAY_IN_SECONDS * 7 ) )
        ] );

        $base64Header  = acc_jwt_base64_url_encode( $header );
        $base64Payload = acc_jwt_base64_url_encode( $payload );

        $signature = hash_hmac(
            'sha256',
            $base64Header . "." . $base64Payload,
            ACC_JWT_SECRET,
            true
        );

        $base64Signature = acc_jwt_base64_url_encode( $signature );

        return $base64Header . "." . $base64Payload . "." . $base64Signature;
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   توابع شبیه‌ساز رسانه و تصاویر شاخص وردپرس (Media & Post Thumbnail Compat)
   ────────────────────────────────────────────────────────────────────────── */
if (!function_exists('get_post_thumbnail_id')) {
    function get_post_thumbnail_id($post_id = null) {
        $post_id = $post_id ?: 0;
        if (!$post_id) {
            return 0;
        }
        return (int) get_post_meta($post_id, '_thumbnail_id', true);
    }
}

if (!function_exists('has_post_thumbnail')) {
    function has_post_thumbnail($post_id = null) {
        return get_post_thumbnail_id($post_id) > 0;
    }
}

if (!function_exists('wp_get_attachment_url')) {
    function wp_get_attachment_url($attachment_id) {
        global $wpdb;

        $attachment_id = (int) $attachment_id;
        if ($attachment_id <= 0) {
            return false;
        }

        $post = $wpdb->get_row(
            $wpdb->prepare(
                "SELECT ID, post_type, guid FROM {$wpdb->posts} WHERE ID = %d LIMIT 1",
                $attachment_id
            )
        );

        if (!$post) {
            return false;
        }

        if (!empty($post->guid)) {
            return $post->guid;
        }

        $attached_file = get_post_meta($attachment_id, '_wp_attached_file', true);
        if (!$attached_file) {
            return false;
        }

        $base = defined('WP_CONTENT_URL')
            ? rtrim(WP_CONTENT_URL, '/')
            : '';

        if (!$base) {
            $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
            $host   = $_SERVER['HTTP_HOST'] ?? 'localhost';
            $base   = $scheme . '://' . $host . '/wp-content';
        }

        return $base . '/uploads/' . ltrim($attached_file, '/');
    }
}

if (!function_exists('wp_get_attachment_image_url')) {
    function wp_get_attachment_image_url($attachment_id, $size = 'full') {
        return wp_get_attachment_url($attachment_id);
    }
}

if (!function_exists('wp_get_attachment_image_src')) {
    function wp_get_attachment_image_src($attachment_id, $size = 'full', $icon = false) {
        $url = wp_get_attachment_image_url($attachment_id, $size);
        if (!$url) {
            return false;
        }

        return [$url, 0, 0, false];
    }
}



if ( ! function_exists( 'wp_get_attachment_url' ) ) {
    function wp_get_attachment_url( $attachment_id ) {
        $attachment_id = (int) $attachment_id;

        if ( $attachment_id <= 0 ) {
            return '';
        }

        if ( function_exists( 'get_post_meta' ) ) {
            $attached_file = get_post_meta( $attachment_id, '_wp_attached_file', true );

            if ( $attached_file ) {
                if ( preg_match( '/^(https?:)?\/\//i', $attached_file ) ) {
                    return $attached_file;
                }

                if ( function_exists( 'wp_upload_dir' ) ) {
                    $upload_dir = wp_upload_dir();
                    $base_url = $upload_dir['baseurl'] ?? '/wp-content/uploads';
                } else {
                    $base_url = '/wp-content/uploads';
                }

                return rtrim( $base_url, '/' ) . '/' . ltrim( $attached_file, '/' );
            }
        }

        return '';
    }
}

if ( ! function_exists( 'wp_get_attachment_image_src' ) ) {
    function wp_get_attachment_image_src( $attachment_id, $size = 'thumbnail', $icon = false ) {
        $url = wp_get_attachment_url( $attachment_id );

        if ( ! $url ) {
            return false;
        }

        return [ $url, 0, 0, false ];
    }
}

if ( ! function_exists( 'wp_get_attachment_image_url' ) ) {
    function wp_get_attachment_image_url( $attachment_id, $size = 'thumbnail', $icon = false ) {
        $image = wp_get_attachment_image_src( $attachment_id, $size, $icon );
        return $image ? $image[0] : '';
    }
}


if ( ! function_exists( 'wp_strip_all_tags' ) ) {
    /**
     * شبیه‌ساز حذف تگ‌های HTML و فضاهای خالی اضافه
     */
    function wp_strip_all_tags( $text, $remove_breaks = false ) {
        if ( null === $text ) {
            return '';
        }
        $text = preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $text );
        $text = strip_tags( $text );
        if ( $remove_breaks ) {
            $text = preg_replace( '/[\r\n\t ]+/', ' ', $text );
        }
        return trim( $text );
    }
}

// سیستم ساده مدیریت هوک‌ها (Hooks Manager)
global $wp_actions;
$wp_actions = [];

if ( ! function_exists( 'add_action' ) ) {
    function add_action( $hook_name, $callback, $priority = 10, $accepted_args = 1 ) {
        global $wp_actions;
        if ( ! isset( $wp_actions[ $hook_name ] ) ) {
            $wp_actions[ $hook_name ] = [];
        }
        // ذخیره کالبک بر اساس اولویت
        $wp_actions[ $hook_name ][ $priority ][] = $callback;
    }
}

if ( ! function_exists( 'do_action' ) ) {
    function do_action( $hook_name, ...$arg ) {
        global $wp_actions;
        if ( ! isset( $wp_actions[ $hook_name ] ) ) {
            return;
        }
        
        // مرتب‌سازی بر اساس اولویت (Priority)
        ksort( $wp_actions[ $hook_name ] );
        
        foreach ( $wp_actions[ $hook_name ] as $priority => $callbacks ) {
            foreach ( $callbacks as $callback ) {
                if ( is_callable( $callback ) ) {
                    call_user_func_array( $callback, $arg );
                }
            }
        }
    }
}

// شبیه‌سازی توابعی که در اکشن شما استفاده شده‌اند
if ( ! function_exists( 'is_admin' ) ) {
    function is_admin() {
        return false; // در حالت Standalone فرانت‌اند ما ادمین نیست
    }
}

if ( ! function_exists( 'get_rest_url' ) ) {
    function get_rest_url( $blog_id = null, $path = '', $scheme = 'rest' ) {
        // بازگرداندن مسیر API پروژه Standalone شما
        $base_url = '/acc-engine/api.php';
        return rtrim( $base_url, '/' ) . '/' . ltrim( $path, '/' );
    }
}

if ( ! function_exists( 'wp_create_nonce' ) ) {
    function wp_create_nonce( $action = -1 ) {
        return 'standalone_nonce'; // مقدار فرضی برای سازگاری
    }
}

if ( ! function_exists( 'esc_url' ) ) {
    function esc_url( $url ) {
        return htmlspecialchars( $url, ENT_QUOTES, 'UTF-8' );
    }
}

if ( ! function_exists( 'wp_json_encode' ) ) {
    function wp_json_encode( $data, $options = 0, $depth = 512 ) {
        return json_encode( $data, $options, $depth );
    }
}

if ( ! defined( 'ACC_URL' ) ) {
    define( 'ACC_URL', '/acc-engine/' );
}

/* ──────────────────────────────────────────────────────────────────────────
   get_option / update_option — ذخیره در جدول wp_options
   ────────────────────────────────────────────────────────────────────────── */

if ( ! function_exists( 'get_option' ) ) {
    function get_option( string $option, $default = false ) {
        global $wpdb;
        static $cache = [];

        if ( array_key_exists( $option, $cache ) ) {
            return $cache[ $option ];
        }

        if ( ! isset( $wpdb ) ) {
            return $default;
        }
        try {
            $val = $wpdb->get_var(
                $wpdb->prepare( "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", $option )
            );
            if ( $val === null || $val === false ) {
                $cache[ $option ] = $default;
                return $default;
            }
            $cache[ $option ] = maybe_unserialize( $val );
            return $cache[ $option ];
        } catch ( \Throwable $e ) {
            return $default;
        }
    }
}

if ( ! function_exists( 'update_option' ) ) {
    function update_option( string $option, $value, $autoload = null ): bool {
        global $wpdb;
        static $cache = [];
        if ( ! isset( $wpdb ) ) return false;
        $serialized = is_array( $value ) || is_object( $value ) ? serialize( $value ) : (string) $value;
        try {
            $existing = $wpdb->get_var(
                $wpdb->prepare( "SELECT option_id FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", $option )
            );
            if ( $existing ) {
                $wpdb->query(
                    $wpdb->prepare(
                        "UPDATE {$wpdb->options} SET option_value = %s WHERE option_name = %s",
                        $serialized, $option
                    )
                );
            } else {
                $wpdb->query(
                    $wpdb->prepare(
                        "INSERT INTO {$wpdb->options} (option_name, option_value, autoload) VALUES (%s, %s, 'yes')",
                        $option, $serialized
                    )
                );
            }
            $cache[ $option ] = is_array( $value ) || is_object( $value ) ? $value : maybe_unserialize( $serialized );
            return true;
        } catch ( \Throwable $e ) {
            return false;
        }
    }
}

if ( ! function_exists( 'delete_option' ) ) {
    function delete_option( string $option ): bool {
        global $wpdb;
        if ( ! isset( $wpdb ) ) return false;
        try {
            $wpdb->query(
                $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name = %s", $option )
            );
            return true;
        } catch ( \Throwable $e ) {
            return false;
        }
    }
}

/* ── User management ── */
if ( ! function_exists( 'wp_generate_password' ) ) {
    function wp_generate_password( int $length = 12, bool $special_chars = true ): string {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        if ( $special_chars ) $chars .= '!@#$%^&*()';
        $pass = '';
        for ( $i = 0; $i < $length; $i++ ) {
            $pass .= $chars[ random_int( 0, strlen( $chars ) - 1 ) ];
        }
        return $pass;
    }
}

if ( ! function_exists( 'wp_hash_password' ) ) {
    function wp_hash_password( string $password ): string {
        return password_hash( $password, PASSWORD_BCRYPT );
    }
}

if ( ! function_exists( 'username_exists' ) ) {
    function username_exists( string $username ): bool {
        return (bool) get_user_by( 'login', $username );
    }
}

if ( ! function_exists( 'wp_create_user' ) ) {
    function wp_create_user( string $username, string $password, string $email = '' ) {
        global $wpdb;
        if ( ! isset( $wpdb ) ) {
            return new WP_Error( 'db_error', 'دیتابیس در دسترس نیست' );
        }
        if ( username_exists( $username ) ) {
            return new WP_Error( 'existing_user_login', 'نام کاربری تکراری است' );
        }
        $email = $email ?: $username . '@shop.local';
        $max   = (int) $wpdb->get_var( "SELECT COALESCE(MAX(ID), 0) FROM {$wpdb->prefix}users" );
        $id    = $max + 1;
        $now   = date( 'Y-m-d H:i:s' );
        $hash  = wp_hash_password( $password );

        $wpdb->insert( "{$wpdb->prefix}users", [
            'ID'                  => $id,
            'user_login'          => $username,
            'user_pass'           => $hash,
            'user_nicename'       => sanitize_title( $username ),
            'user_email'          => $email,
            'user_url'            => '',
            'user_registered'     => $now,
            'user_activation_key' => '',
            'user_status'         => 0,
            'display_name'        => $username,
        ] );

        update_user_meta( $id, 'wp_capabilities', serialize( [ 'customer' => true ] ) );
        update_user_meta( $id, 'wp_user_level', '0' );

        return $id;
    }
}

if ( ! function_exists( 'wp_update_user' ) ) {
    function wp_update_user( array $userdata ) {
        global $wpdb;
        $id = (int) ( $userdata['ID'] ?? 0 );
        if ( $id <= 0 ) return new WP_Error( 'invalid_id', 'شناسه نامعتبر' );

        $fields = [];
        foreach ( [ 'display_name', 'user_email', 'user_pass' ] as $f ) {
            if ( isset( $userdata[ $f ] ) && $userdata[ $f ] !== '' ) {
                $fields[ $f ] = $f === 'user_pass' ? wp_hash_password( $userdata[ $f ] ) : $userdata[ $f ];
            }
        }
        if ( $fields ) {
            return (bool) $wpdb->update( "{$wpdb->prefix}users", $fields, [ 'ID' => $id ] );
        }
        return $id;
    }
}

if ( ! function_exists( 'update_user_meta' ) ) {
    function update_user_meta( int $user_id, string $key, $value ): bool {
        global $wpdb;
        $existing = $wpdb->get_var(
            "SELECT umeta_id FROM {$wpdb->prefix}usermeta WHERE user_id = {$user_id} AND meta_key = '" . esc_sql( $key ) . "' LIMIT 1"
        );
        $serialized = is_array( $value ) || is_object( $value ) ? serialize( $value ) : (string) $value;
        if ( $existing ) {
            return (bool) $wpdb->update( "{$wpdb->prefix}usermeta",
                [ 'meta_value' => $serialized ],
                [ 'umeta_id' => (int) $existing ]
            );
        }
        return (bool) $wpdb->insert( "{$wpdb->prefix}usermeta", [
            'user_id'    => $user_id,
            'meta_key'   => $key,
            'meta_value' => $serialized,
        ] );
    }
}

if ( ! function_exists( 'get_user_meta' ) ) {
    function get_user_meta( int $user_id, string $key = '', bool $single = true ) {
        global $wpdb;
        if ( ! $key ) return [];
        $row = $wpdb->get_var(
            "SELECT meta_value FROM {$wpdb->prefix}usermeta WHERE user_id = {$user_id} AND meta_key = '" . esc_sql( $key ) . "' LIMIT 1"
        );
        if ( $row === null || $row === false ) return $single ? '' : [];
        $val = maybe_unserialize( $row );
        return $single ? $val : [ $val ];
    }
}

if ( ! function_exists( 'wp_redirect' ) ) {
    function wp_redirect( string $location, int $status = 302 ): void {
        header( 'Location: ' . $location, true, $status );
        exit;
    }
}

if ( ! function_exists( 'sanitize_user' ) ) {
    function sanitize_user( string $username ): string {
        return preg_replace( '/[^a-z0-9_\-]/i', '', $username );
    }
}

if ( ! function_exists( 'sanitize_title' ) ) {
    function sanitize_title( string $title ): string {
        $title = preg_replace( '/\s+/', '-', trim( $title ) );
        return strtolower( preg_replace( '/[^a-z0-9\-]/i', '', $title ) );
    }
}
