<?php

defined('ABSPATH') || exit;

class ShopCentral_Store_API
{
    private $namespace;

    private function format_product($product)
    {
        $image_id = $product->get_image_id();
        $image_url = wp_get_attachment_image_url($image_id, 'thumbnail');

        return [
            'id' => $product->get_id(),
            'name' => $product->get_name(),
            'type' => $product->get_type(),
            'status' => $product->get_status(),
            'date_created' => $product->get_date_created() ? $product->get_date_created()->date('Y-m-d H:i:s') : null,
            'price' => $product->get_price(),
            'price_html' => $product->get_price_html(),
            'stock_status' => $product->get_stock_status(),
            'stock_quantity' => $product->get_stock_quantity(),
            'total_sales' => (int) $product->get_total_sales(),
            'images' => [
                ['thumbnail' => $image_url, 'src' => $image_url]
            ],
        ];
    }

    private function format_product_array($p)
    {
        return [
            'id' => $p['id'] ?? 0,
            'name' => $p['name'] ?? 'Unknown Product',
            'type' => $p['type'] ?? 'simple',
            'status' => $p['status'] ?? 'publish',
            'date_created' => $p['date_created'] ?? null,
            'price' => $p['price'] ?? 0,
            'price_html' => '', // Hard to get without object
            'stock_status' => $p['stock_status'] ?? 'instock',
            'stock_quantity' => (int)($p['stock_quantity'] ?? 0),
            'total_sales' => (int)($p['total_sales'] ?? 0),
            'images' => $p['images'] ?? [],
        ];
    }

    public function __construct($namespace)
    {
        $this->namespace = $namespace;
        add_action('rest_api_init', [$this, 'register_routes']);
        add_action('admin_init', [$this, 'auto_register_webhooks']);
        add_action('shopcentral_order_sync_batch', [$this, 'process_sync_batch'], 10, 6);
    }

    public function register_routes()
    {
        // Stores
        register_rest_route($this->namespace, '/api/stores', [
            [
                'methods' => WP_REST_Server::READABLE,
                'callback' => [$this, 'get_stores'],
                'permission_callback' => [$this, 'check_permission'],
            ],
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'add_store'],
                'permission_callback' => [$this, 'check_permission'],
            ],
        ]);

        register_rest_route($this->namespace, '/api/stores/switch', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'switch_store'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/stores/(?P<id>\d+)', [
            'methods' => WP_REST_Server::DELETABLE,
            'callback' => [$this, 'delete_store'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // Toggle order import for a specific store
        register_rest_route($this->namespace, '/api/stores/(?P<id>\d+)/order-import', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'toggle_store_order_import'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // Toggle customer sync for a specific store
        register_rest_route($this->namespace, '/api/stores/(?P<id>\d+)/customer-sync', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [$this, 'toggle_store_customer_sync'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // Get per-store shared secret for Cloudflare WAF bypass setup
        register_rest_route($this->namespace, '/api/stores/(?P<id>\d+)/firewall-info', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [$this, 'get_store_firewall_info'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // Sync orders from a child store
        register_rest_route($this->namespace, '/api/store-manager/sync-orders', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'sync_orders_from_store'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/sync-orders/cancel', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'cancel_sync_orders'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/sync-orders/progress/(?P<store_id>\d+)', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_sync_progress_handler'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        // Re-register webhooks for all stores
        register_rest_route($this->namespace, '/api/stores/rerender-webhooks', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'rerender_webhooks_handler'],
            'permission_callback' => [$this, 'check_permission'],
        ]);



        // Store Manager Proxy Routes (Supports CRUD)
        register_rest_route($this->namespace, '/api/store-manager/(?P<endpoint>products|orders|customers|coupons)(?P<subpath>.*)', [
            'methods' => ['GET', 'POST', 'PUT', 'DELETE'],
            'callback' => [$this, 'proxy_store_manager_request'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/stats', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_store_manager_stats'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/order-metrics', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_store_manager_order_metrics'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/analytics/products', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_store_manager_product_analytics'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/sync-products', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'sync_products'],
            'permission_callback' => [$this, 'check_permission'],
        ]);



        register_rest_route($this->namespace, '/api/store-manager/global-price-update', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'global_price_update'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/logs', [
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => [$this, 'get_logs'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/logs/delete', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [$this, 'delete_logs'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/logs/clear', [
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => [$this, 'clear_logs'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/all-orders', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_all_orders_timeline'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/sync-orders', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'sync_orders_from_store'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/sync-orders/cancel', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'cancel_sync_orders'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/sync-orders/progress/(?P<store_id>\d+)', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_sync_progress_handler'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/bulk-order-status', [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => [$this, 'bulk_order_status_update'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/report-totals', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_store_manager_report_totals'],
            'permission_callback' => [$this, 'check_permission'],
        ]);

        register_rest_route($this->namespace, '/api/store-manager/sales-report', [
            'methods' => WP_REST_Server::READABLE,
            'callback' => [$this, 'get_store_manager_sales_report'],
            'permission_callback' => [$this, 'check_permission'],
        ]);
    }

    public function check_permission()
    {
        return current_user_can('manage_options');
    }

    public function get_all_orders_timeline($request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $params = $request->get_query_params();

        $store_id = $params['store_id'] ?? 'all';
        $status = $params['status'] ?? 'any';
        $after = $params['after'] ?? null;
        $before = $params['before'] ?? null;
        $page = max(1, intval($params['page'] ?? 1));
        $per_page = min(100, max(1, intval($params['per_page'] ?? 10)));

        $target_stores = [];
        if ($store_id === 'all') {
            $target_stores = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table ORDER BY id ASC LIMIT %d", $this->get_store_limit()));
        } else {
            $store = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $store_id));
            if ($store) $target_stores[] = $store;
        }

        $all_orders = [];

        foreach ($target_stores as $store) {
            // Fetch more orders to allow for pagination
            $query_params = ['per_page' => 100, 'page' => 1, 'orderby' => 'date', 'order' => 'desc'];
            if ($status !== 'any') {
                $query_params['status'] = str_replace('wc-', '', $status);
            }
            if ($after) {
                $query_params['after'] = date('Y-m-d\TH:i:s', strtotime($after));
            }
            if ($before) {
                $query_params['before'] = date('Y-m-d\TH:i:s', strtotime($before));
            }

            $orders = $this->get_remote_wc_data($store, "wc/v3/orders", $query_params);

            if (is_array($orders)) {
                foreach ($orders as $order) {
                    if (isset($order['code']) && isset($order['message'])) continue;

                    $order['source_store_id'] = $store->id;
                    $order['source_store_name'] = $store->name;
                    $order['source_store_url'] = $store->url;

                    $all_orders[] = $order;
                }
            }
        }

        // Sort by date created desc
        usort($all_orders, function ($a, $b) {
            $date_a = strtotime($a['date_created'] ?? '0');
            $date_b = strtotime($b['date_created'] ?? '0');
            return $date_b - $date_a;
        });

        // Pagination
        $total_orders = count($all_orders);
        $total_pages = max(1, ceil($total_orders / $per_page));
        $offset = ($page - 1) * $per_page;
        $timeline_orders = array_slice($all_orders, $offset, $per_page);

        return new WP_REST_Response([
            'data' => $timeline_orders,
            'total' => $total_orders,
            'total_pages' => $total_pages,
            'current_page' => $page,
            'per_page' => $per_page,
        ], 200);
    }

    public function bulk_order_status_update($request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $params = $request->get_json_params();

        $updates = $params['updates'] ?? []; // Array of { store_id, order_id, status }

        if (empty($updates)) {
            return new WP_Error('invalid_params', 'No updates provided', ['status' => 400]);
        }

        // Group updates by store
        $store_updates = [];
        foreach ($updates as $update) {
            $sid = $update['store_id'];
            if (!isset($store_updates[$sid])) {
                $store = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $sid));
                if (!$store) continue;
                $store_updates[$sid] = ['store' => $store, 'batch' => []];
            }
            $store_updates[$sid]['batch'][] = [
                'id' => $update['order_id'],
                'status' => $update['status']
            ];
        }

        $results = [];

        foreach ($store_updates as $sid => $data) {
            $store = $data['store'];
            $batch_payload = ['update' => $data['batch']];

            if (!empty($batch_payload['update'])) {
                $res = $this->send_remote_wc_request($store, "wc/v3/orders/batch", "POST", $batch_payload);
                if (!is_wp_error($res) && isset($res['update'])) {
                    $results[] = [
                        'store_id' => $sid,
                        'store_name' => $store->name,
                        'updated' => count($res['update'])
                    ];
                } else {
                    $results[] = [
                        'store_id' => $sid,
                        'store_name' => $store->name,
                        'error' => is_wp_error($res) ? $res->get_error_message() : 'Batch update failed'
                    ];
                }
            }
        }

        return new WP_REST_Response(['message' => 'Orders updated', 'results' => $results], 200);
    }

    /**
     * Initiates a background sync via Action Scheduler.
     * Returns immediately with a "scheduled" response; the frontend polls for progress.
     *
     * Body: { store_id: int, after?: ISO date, before?: ISO date, status?: string, limit?: int }
     */
    public function sync_orders_from_store($request)
    {
        global $wpdb;
        $table  = $wpdb->prefix . 'shopcentral_stores';
        $params = $request->get_json_params();

        $store_id = intval($params['store_id'] ?? 0);
        if ($store_id <= 0) {
            return new WP_Error('invalid_store', 'Please select a child store', ['status' => 400]);
        }

        $store = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $store_id));
        if (!$store) {
            return new WP_Error('store_not_found', 'Store not found', ['status' => 404]);
        }

        if ($this->is_store_local($store)) {
            return new WP_Error('local_store', 'Cannot sync from the hub (local) store. Only connected child stores are supported.', ['status' => 400]);
        }

        if (intval($store->order_import_enabled) !== 1) {
            return new WP_Error('import_disabled', 'Order import is not enabled for this store. Enable it first from Connected Stores.', ['status' => 400]);
        }

        $existing = $this->get_sync_progress($store_id);
        if ($existing && $existing['status'] === 'running') {
            return new WP_Error('sync_in_progress', 'A sync is already running for this store. Please wait for it to finish or cancel it first.', ['status' => 409]);
        }

        $after  = !empty($params['after'])  ? sanitize_text_field($params['after'])  : date('Y-m-d\TH:i:s', strtotime('-30 days'));
        $before = !empty($params['before']) ? sanitize_text_field($params['before']) : current_time('c');
        $status = !empty($params['status']) ? sanitize_text_field($params['status']) : '';
        $limit  = min(intval($params['limit'] ?? 100), 50000);

        $this->set_sync_progress($store_id, [
            'status'         => 'running',
            'total'          => $limit,
            'processed'      => 0,
            'synced'         => 0,
            'skipped_exists' => 0,
            'failed'         => 0,
            'started_at'     => current_time('mysql'),
            'finished_at'    => null,
            'cancel'         => false,
            'errors'         => [],
        ]);

        if (function_exists('as_enqueue_async_action')) {
            as_enqueue_async_action('shopcentral_order_sync_batch', [$store_id, $after, $before, $status, $limit, 1], 'shopcentral');
        } else {
            $this->set_sync_progress($store_id, null);
            return new WP_Error('no_scheduler', 'Action Scheduler is not available. Please make sure WooCommerce is active.', ['status' => 500]);
        }

        return new WP_REST_Response([
            'message'    => 'Order sync started in the background. You can close this modal and check progress later.',
            'store_id'   => $store_id,
            'store_name' => $store->name,
            'status'     => 'running',
        ], 200);
    }

    /**
     * Cancels a running sync.
     */
    public function cancel_sync_orders($request)
    {
        $params = $request->get_json_params();
        $store_id = intval($params['store_id'] ?? 0);
        if ($store_id <= 0) {
            return new WP_Error('invalid_store', 'Invalid store', ['status' => 400]);
        }

        $progress = $this->get_sync_progress($store_id);
        if (!$progress || $progress['status'] !== 'running') {
            return new WP_REST_Response(['message' => 'No running sync found for this store.'], 200);
        }

        $progress['cancel'] = true;
        $progress['status'] = 'cancelling';
        $this->set_sync_progress($store_id, $progress);

        return new WP_REST_Response(['message' => 'Sync cancellation requested.'], 200);
    }

    /**
     * Returns the current sync progress for a store.
     */
    public function get_sync_progress_handler($request)
    {
        $store_id = intval($request->get_param('store_id') ?? 0);
        if ($store_id <= 0) {
            return new WP_Error('invalid_store', 'Invalid store', ['status' => 400]);
        }

        $progress = $this->get_sync_progress($store_id);
        if (!$progress) {
            return new WP_REST_Response(['status' => 'idle'], 200);
        }

        return new WP_REST_Response($progress, 200);
    }

    /**
     * Reads sync progress from the stores table.
     */
    private function get_sync_progress($store_id)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $json = $wpdb->get_var($wpdb->prepare("SELECT sync_progress FROM $table WHERE id = %d", $store_id));
        if (empty($json)) return null;
        $data = json_decode($json, true);
        return is_array($data) ? $data : null;
    }

    /**
     * Writes sync progress to the stores table.
     */
    private function set_sync_progress($store_id, $data)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $json = $data === null ? null : wp_json_encode($data);
        $wpdb->update($table, ['sync_progress' => $json], ['id' => $store_id]);
    }

    public function get_logs($request)
    {
        $store_id_param = $request->get_param('store_id');
        $args = [
            'feature'  => $request->get_param('feature') ?: '',
            'level'    => $request->get_param('level') ?: '',
            'store_id' => ($store_id_param !== null && $store_id_param !== '') ? intval($store_id_param) : '',
            'after'    => $request->get_param('after') ?: '',
            'before'   => $request->get_param('before') ?: '',
            'search'   => $request->get_param('search') ?: '',
            'per_page' => $request->get_param('per_page') ?: 50,
            'page'     => $request->get_param('page') ?: 1,
            'orderby'  => $request->get_param('orderby') ?: 'created_at',
            'order'    => $request->get_param('order') ?: 'DESC',
        ];

        $result = ShopCentral_Logger::get_logs($args);

        $result['features'] = ShopCentral_Logger::get_features();
        $result['levels']   = ShopCentral_Logger::get_levels();

        return new WP_REST_Response($result, 200);
    }

    public function delete_logs($request)
    {
        $ids = $request->get_param('ids');

        if (empty($ids) || !is_array($ids)) {
            return new WP_Error('missing_ids', 'ids array is required', ['status' => 400]);
        }

        $deleted = ShopCentral_Logger::bulk_delete($ids);

        return new WP_REST_Response([
            'message' => sprintf('%d log(s) deleted', $deleted),
            'deleted' => $deleted,
        ], 200);
    }

    public function clear_logs()
    {
        $deleted = ShopCentral_Logger::clear_all();

        return new WP_REST_Response([
            'message' => 'All logs cleared',
            'success' => true,
        ], 200);
    }

    /**
     * Action Scheduler callback: processes one chunk of orders.
     */
    public function process_sync_batch( $store_id, $after, $before, $status, $limit, $page ) {
        $progress = $this->get_sync_progress( $store_id );
        if ( ! $progress || $progress['status'] !== 'running' ) {
            return;
        }

        if ( ! empty( $progress['cancel'] ) ) {
            $progress['status']      = 'cancelled';
            $progress['finished_at'] = current_time( 'mysql' );
            $this->set_sync_progress( $store_id, $progress );
            return;
        }

        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $store = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table WHERE id = %d", $store_id ) );
        if ( ! $store ) {
            $progress['status']      = 'error';
            $progress['finished_at'] = current_time( 'mysql' );
            $this->set_sync_progress( $store_id, $progress );
            return;
        }

        $batch_size = $this->get_batch_size();

        $query_params = [
            'per_page' => $batch_size,
            'orderby'  => 'date',
            'order'    => 'desc',
            'after'    => $after,
            'before'   => $before,
            'page'     => $page,
        ];
        if ( $status && $status !== 'any' ) {
            $query_params['status'] = str_replace( 'wc-', '', $status );
        }

        ShopCentral_Product_Sync_Manager::flush_customer_cache();

        $remote_orders = $this->get_remote_wc_data( $store, 'wc/v3/orders', $query_params );

        if ( ! is_array( $remote_orders ) || empty( $remote_orders ) ) {
            $progress['status']      = 'completed';
            $progress['finished_at'] = current_time( 'mysql' );
            $this->set_sync_progress( $store_id, $progress );
            $wpdb->update( $table, [ 'last_order_sync' => current_time( 'mysql' ) ], [ 'id' => $store_id ] );
            return;
        }

        if ( ! class_exists( 'ShopCentral_Product_Sync_Manager' ) ) {
            require_once SHOPCENTRAL_PATH . 'includes/class-shopcentral-product-sync.php';
        }
        $sync_manager = new ShopCentral_Product_Sync_Manager();

        $customer_sync = ! empty( $store->customer_sync_enabled );

        foreach ( $remote_orders as $remote_order ) {
            if ( $progress['processed'] >= $limit ) {
                break;
            }
            $progress['processed']++;

            if ( ! is_array( $remote_order ) || isset( $remote_order['code'] ) ) {
                $progress['failed']++;
                continue;
            }

            $child_order_id = intval( $remote_order['id'] ?? 0 );
            if ( ! $child_order_id ) {
                $progress['failed']++;
                continue;
            }

            if ( $sync_manager->order_already_imported( $child_order_id, $store_id, $store->url ) ) {
                $progress['skipped_exists']++;
                continue;
            }

            try {
                $hub_order = $sync_manager->create_hub_order( $remote_order, $store_id, $store->url, $customer_sync );
                if ( $hub_order && is_a( $hub_order, 'WC_Order' ) ) {
                    $progress['synced']++;
                } else {
                    $progress['failed']++;
                }
            } catch ( \Throwable $e ) {
                $progress['failed']++;
                if ( count( $progress['errors'] ) < 5 ) {
                    $progress['errors'][] = "Order #{$child_order_id}: " . $e->getMessage();
                }
            }
        }

        $this->set_sync_progress( $store_id, $progress );

        if ( $progress['processed'] >= $limit || count( $remote_orders ) < $batch_size ) {
            $progress['status']      = 'completed';
            $progress['finished_at'] = current_time( 'mysql' );
            $this->set_sync_progress( $store_id, $progress );
            $wpdb->update( $table, [ 'last_order_sync' => current_time( 'mysql' ) ], [ 'id' => $store_id ] );
            return;
        }

        if ( function_exists( 'as_enqueue_async_action' ) ) {
            as_enqueue_async_action( 'shopcentral_order_sync_batch', [ $store_id, $after, $before, $status, $limit, $page + 1 ], 'shopcentral' );
        } else {
            $progress['status']      = 'completed';
            $progress['finished_at'] = current_time( 'mysql' );
            $this->set_sync_progress( $store_id, $progress );
        }
    }

    private function get_batch_size() {
        return (int) apply_filters( 'shopcentral_sync_batch_size', 50 );
    }

    public function sync_products($request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $params = $request->get_json_params();

        $source_store_id = $params['source_store_id'] ?? null;
        $target_store_ids = $params['target_store_ids'] ?? [];
        $product_ids = $params['product_ids'] ?? [];
        $options = $params['options'] ?? [];

        if (!$source_store_id || empty($target_store_ids) || empty($product_ids)) {
            return new WP_Error('invalid_params', 'Missing required parameters', ['status' => 400]);
        }

        $source_store = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $source_store_id));
        if (!$source_store) return new WP_Error('store_not_found', 'Source store not found', ['status' => 404]);

        $target_stores = [];
        foreach ($target_store_ids as $id) {
            $store = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $id));
            if ($store) $target_stores[] = $store;
        }

        $products_data = [];
        foreach ($product_ids as $pid) {
            $p_data = $this->get_remote_wc_data($source_store, "wc/v3/products/$pid");
            if ($p_data && !isset($p_data['code'])) {
                $products_data[] = $p_data;
            }
        }

        $results = [];
        foreach ($target_stores as $t_store) {
            $store_result = ['store_name' => $t_store->name, 'success' => 0, 'failed' => 0, 'details' => []];
            foreach ($products_data as $p) {
                $product_name = $p['name'] ?? ('Product ID ' . ($p['id'] ?? 'unknown'));
                $product_sku = $p['sku'] ?? '';

                // Check if product exists by SKU or Slug
                $existing = [];
                if (!empty($p['sku'])) {
                    $existing = $this->get_remote_wc_data($t_store, "wc/v3/products", ['sku' => $p['sku']]);
                }
                if (empty($existing) && !empty($p['slug'])) {
                    $existing = $this->get_remote_wc_data($t_store, "wc/v3/products", ['slug' => $p['slug']]);
                }

                $payload = [];

                // Content Options
                if (!empty($options['price'])) {
                    $payload['regular_price'] = $p['regular_price'] ?? '';
                    $payload['sale_price'] = $p['sale_price'] ?? '';
                }
                if (!empty($options['stock'])) {
                    $payload['manage_stock'] = $p['manage_stock'] ?? false;
                    $payload['stock_quantity'] = $p['stock_quantity'] ?? 0;
                    $payload['stock_status'] = $p['stock_status'] ?? 'instock';
                }
                if (!empty($options['description'])) {
                    $payload['description'] = $p['description'] ?? '';
                    $payload['short_description'] = $p['short_description'] ?? '';
                }
                if (!empty($options['image']) && !empty($p['images'])) {
                    $payload['images'] = array_map(function ($img) {
                        return ['src' => is_array($img) ? $img['src'] : $img->src];
                    }, $p['images']);
                }

                // Categories - sync with ID lookup on target store
                if (!empty($p['categories'])) {
                    $category_ids = $this->ensure_categories_on_remote($t_store, $p['categories']);
                    if (!empty($category_ids)) {
                        $payload['categories'] = $category_ids;
                    }
                }

                // Tags - sync with name (auto-create on target)
                if (!empty($p['tags'])) {
                    $tag_names = array_map(function ($tag) {
                        return is_array($tag) ? ($tag['name'] ?? '') : $tag;
                    }, $p['tags']);
                    $payload['tags'] = array_map(function ($name) {
                        return ['name' => $name];
                    }, array_filter($tag_names));
                }

                // Attributes are essential for Variable products
                if (!empty($p['attributes'])) {
                    $payload['attributes'] = $p['attributes'];
                }

                // Custom meta / ACF sync (event-driven whitelist)
                if (!empty($options['meta']) && !empty($p['meta_data']) && is_array($p['meta_data'])) {
                    $payload['meta_data'] = $this->filter_allowed_meta($p['meta_data'], $p['id'] ?? 0);
                }

                $endpoint = "wc/v3/products";
                $method = "POST";

                if (!empty($existing) && is_array($existing) && count($existing) > 0) {
                    $target_id = $existing[0]['id'];
                    $endpoint = "wc/v3/products/$target_id";
                    $method = "PUT";
                } else {
                    $payload['name'] = $p['name'] ?? 'Product';
                    $payload['type'] = $p['type'] ?? 'simple';
                    if (!empty($p['sku'])) $payload['sku'] = $p['sku'];
                    if (!empty($p['slug'])) $payload['slug'] = $p['slug'];
                }

                if (empty($payload)) continue;

                $res = $this->send_remote_wc_request($t_store, $endpoint, $method, $payload);

                if (!is_wp_error($res) && isset($res['id'])) {
                    $target_id = $res['id'];

                    // --- Handle Variations for Variable Products ---
                    if ($p['type'] === 'variable' && !empty($p['id'])) {
                        $variations = $this->get_remote_wc_data($source_store, "wc/v3/products/{$p['id']}/variations", ['per_page' => 100]);

                        if (is_array($variations)) {
                            foreach ($variations as $v) {
                                $v_payload = [
                                    'description' => $v['description'] ?? '',
                                    'regular_price' => $v['regular_price'] ?? '',
                                    'sale_price' => $v['sale_price'] ?? '',
                                    'manage_stock' => $v['manage_stock'] ?? false,
                                    'stock_quantity' => $v['stock_quantity'] ?? 0,
                                    'stock_status' => $v['stock_status'] ?? 'instock',
                                    'attributes' => $v['attributes'] ?? [],
                                    'sku' => $v['sku'] ?? '',
                                ];

                                // Handle variation image
                                if (!empty($v['image'])) {
                                    $v_payload['image'] = ['src' => $v['image']['src']];
                                }

                                // Check if variation exists on target
                                $v_endpoint = "wc/v3/products/$target_id/variations";
                                $v_method = "POST";

                                if (!empty($v['sku'])) {
                                    $v_existing = $this->get_remote_wc_data($t_store, "wc/v3/products/$target_id/variations", ['sku' => $v['sku']]);
                                    if (!empty($v_existing) && isset($v_existing[0]['id'])) {
                                        $v_id = $v_existing[0]['id'];
                                        $v_endpoint .= "/$v_id";
                                        $v_method = "PUT";
                                    }
                                }

                                $this->send_remote_wc_request($t_store, $v_endpoint, $v_method, $v_payload);
                            }
                        }
                    }

                    // Log success
                    $success_msg = sprintf('Product "%s" (SKU: %s) synced successfully to %s', $product_name, $product_sku ?: 'N/A', $t_store->name);
                    ShopCentral_Logger::success(
                        ShopCentral_Logger::FEATURE_PRODUCT_SYNC,
                        $success_msg,
                        [
                            'product_id'   => $p['id'] ?? null,
                            'product_sku'  => $product_sku,
                            'target_store' => $t_store->name,
                            'target_id'    => $target_id,
                            'method'       => $method,
                        ],
                        intval($t_store->id)
                    );

                    $store_result['details'][] = ['product' => $product_name, 'sku' => $product_sku, 'status' => 'success', 'message' => "Synced (ID: $target_id)"];
                    $store_result['success']++;
                } else {
                    // Capture the error reason
                    $error_message = 'Unknown error';
                    $error_code = 'unknown';
                    if (is_wp_error($res)) {
                        $error_message = $res->get_error_message();
                        $error_code = $res->get_error_code();
                        $error_data = $res->get_error_data();
                        if (!empty($error_data)) {
                            $error_message .= ' | Data: ' . wp_json_encode($error_data);
                        }
                    } elseif (is_array($res) && isset($res['message'])) {
                        $error_message = $res['message'];
                        $error_code = $res['code'] ?? 'api_error';
                    } elseif (is_array($res) && isset($res['code'])) {
                        $error_message = $res['message'] ?? $res['code'];
                        $error_code = $res['code'];
                    }

                    // Log failure with full context
                    $fail_msg = sprintf('Failed to sync product "%s" (SKU: %s) to %s', $product_name, $product_sku ?: 'N/A', $t_store->name);
                    ShopCentral_Logger::error(
                        ShopCentral_Logger::FEATURE_PRODUCT_SYNC,
                        $fail_msg . ': ' . $error_message,
                        [
                            'product_id'   => $p['id'] ?? null,
                            'product_sku'  => $product_sku,
                            'target_store' => $t_store->name,
                            'error_code'   => $error_code,
                            'endpoint'     => $endpoint,
                            'method'       => $method,
                            'payload'      => $payload,
                            'response'     => is_wp_error($res) ? null : $res,
                        ],
                        intval($t_store->id)
                    );

                    $store_result['details'][] = ['product' => $product_name, 'sku' => $product_sku, 'status' => 'failed', 'message' => $error_message, 'code' => $error_code];
                    $store_result['failed']++;
                }
            }
            $results[] = $store_result;
        }

        return new WP_REST_Response(['message' => 'Sync completed', 'results' => $results], 200);
    }

    /**
     * Ensure categories exist on remote store and return their IDs
     *
     * @param object $t_store Target store object
     * @param array $categories Category data from source product
     * @return array Array of category IDs for payload
     */
    private function ensure_categories_on_remote($t_store, $categories)
    {
        if (empty($categories) || !is_array($categories)) {
            return [];
        }

        $base_url = trailingslashit($t_store->url);
        $auth = base64_encode($t_store->consumer_key . ':' . $t_store->consumer_secret);
        $category_ids = [];

        foreach ($categories as $cat) {
            // Get category name - can be array with 'name' key or object
            $cat_name = '';
            if (is_array($cat)) {
                $cat_name = $cat['name'] ?? '';
            } elseif (is_object($cat)) {
                $cat_name = $cat->name ?? '';
            }

            $cat_name = trim($cat_name);
            if (empty($cat_name)) continue;

            // Try to find existing category by name
            $found_id = null;
            $search_response = $this->get_remote_wc_data($t_store, 'wc/v3/products/categories', [
                'search' => $cat_name,
                'per_page' => 100,
            ]);

            if (is_array($search_response) && !empty($search_response)) {
                foreach ($search_response as $remote_cat) {
                    if (isset($remote_cat['name']) && strcasecmp($remote_cat['name'], $cat_name) === 0) {
                        $found_id = $remote_cat['id'];
                        break;
                    }
                }
            }

            // If found, use it
            if ($found_id) {
                $category_ids[] = ['id' => $found_id];
                continue;
            }

            // Category not found, create it
            $create_response = $this->send_remote_wc_request(
                $t_store,
                'wc/v3/products/categories',
                'POST',
                ['name' => $cat_name]
            );

            if (is_array($create_response) && isset($create_response['id'])) {
                $category_ids[] = ['id' => $create_response['id']];
            }
        }

        return $category_ids;
    }

    public function global_price_update($request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $params = $request->get_json_params();

        $store_ids = $params['store_ids'] ?? [];
        $amount = (float)($params['amount'] ?? 0);
        $type = $params['type'] ?? 'percentage';
        $direction = $params['direction'] ?? 'increase';
        $category_id = $params['category_id'] ?? null;

        if (empty($store_ids) || $amount <= 0) {
            return new WP_Error('invalid_params', 'Invalid parameters', ['status' => 400]);
        }

        $target_stores = [];
        if (in_array('all', (array)$store_ids)) {
            $target_stores = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table ORDER BY id ASC LIMIT %d", $this->get_store_limit()));
        } else {
            foreach ($store_ids as $id) {
                $store = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $id));
                if ($store) $target_stores[] = $store;
            }
        }

        $results = [];
        foreach ($target_stores as $store) {
            $store_result = ['store_name' => $store->name, 'updated' => 0, 'failed' => 0];

            $query_params = ['per_page' => 100];
            if ($category_id) $query_params['category'] = $category_id;

            $products = $this->get_remote_wc_data($store, "wc/v3/products", $query_params);
            if (is_array($products)) {
                $batch_payload = ['update' => []];
                foreach ($products as $p) {
                    if ($p['type'] !== 'simple' && $p['type'] !== 'variable') continue;

                    $current_price = (float)($p['regular_price'] ?? 0);
                    if ($current_price <= 0 && $direction === 'decrease') continue;
                    if ($current_price <= 0) {
                        $current_price = (float)($p['price'] ?? 0);
                    }
                    if ($current_price <= 0) continue;

                    $adjustment = ($type === 'percentage') ? ($current_price * ($amount / 100)) : $amount;
                    $new_price = ($direction === 'increase') ? ($current_price + $adjustment) : ($current_price - $adjustment);

                    $batch_payload['update'][] = [
                        'id' => $p['id'],
                        'regular_price' => (string)round($new_price, 2)
                    ];
                }

                if (!empty($batch_payload['update'])) {
                    $res = $this->send_remote_wc_request($store, "wc/v3/products/batch", "POST", $batch_payload);
                    if (!is_wp_error($res) && isset($res['update'])) {
                        $store_result['updated'] = count($res['update']);
                    } else {
                        $store_result['failed'] = count($batch_payload['update']);

                        // Detailed logging for debugging remote failures
                        $error_msg = is_wp_error($res) ? $res->get_error_message() : (is_array($res) || is_object($res) ? wp_json_encode($res) : print_r($res, true));
                        error_log(sprintf("ShopCentral Debug: Global Price batch update failed for store '%s' (%s). Details: %s", $store->name, $store->url, $error_msg));
                    }
                }
            }
            $results[] = $store_result;
        }

        return new WP_REST_Response(['message' => 'Global price update completed', 'results' => $results], 200);
    }

    public function send_remote_wc_request($store, $route, $method = 'GET', $body = null, $params = [])
    {
        if ($this->is_store_local($store)) {
            $request = new WP_REST_Request($method, '/' . ltrim($route, '/'));
            $request->set_query_params($params);
            if ($body) {
                $request->set_body(wp_json_encode($body));
                $request->set_header('Content-Type', 'application/json');
            }
            $response = rest_do_request($request);

            if ($response->is_error()) {
                $error_data = $response->get_data();
                return new WP_Error(
                    $error_data['code'] ?? 'internal_rest_error',
                    $error_data['message'] ?? 'Internal REST Error',
                    $error_data
                );
            }
            return json_decode(wp_json_encode($response->get_data()), true);
        }

        $url = rtrim($store->url, '/');
        if (strpos($url, 'https://') === false) {
            $url .= '/';
            $params['rest_route'] = '/' . ltrim($route, '/');
        } else {
            if (strpos($url, '/wp-json/') === false) {
                $url .= '/wp-json/';
            }
            $url .= ltrim($route, '/');
        }

        $auth_params = [];
        if (!empty($store->consumer_key)) {
            $auth_params['consumer_key']    = $store->consumer_key;
            $auth_params['consumer_secret'] = $store->consumer_secret;
        }

        $url = add_query_arg(array_merge($params, $auth_params), $url);

        $version = defined('SHOPCENTRAL_VERSION') ? SHOPCENTRAL_VERSION : '2.5.0';

        $headers = [
            'Accept'      => 'application/json',
            'Connection'  => 'close',
            'User-Agent'  => 'ShopCentral-Core/' . $version . ' (+https://dominopress.com/shopcentral)',
            'Referer'     => home_url(),
        ];

        // Inject per-store shared secret for Cloudflare WAF bypass
        if (!empty($store->shared_secret)) {
            $headers['X-ShopCentral-Secret'] = $store->shared_secret;
        }

        if (!empty($store->consumer_key)) {
            $headers['Authorization'] = 'Basic ' . base64_encode($store->consumer_key . ':' . $store->consumer_secret);
        }

        $args = [
            'method'      => $method,
            'timeout'     => 60,
            'sslverify'   => false,
            'httpversion' => '1.1',
            'headers'     => $headers,
        ];

        if ($body) {
            $args['body'] = json_encode($body);
            $args['headers']['Content-Type'] = 'application/json';
        }

        $response = wp_remote_request($url, $args);

        if (is_wp_error($response)) {
            return $response;
        }

        $code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);

        if ($code < 200 || $code > 299) {
            // Decode the response body to get the actual error message from WooCommerce
            $error_body = json_decode($body, true);
            $error_message = $body;
            if (is_array($error_body)) {
                $error_message = $error_body['message'] ?? $error_body['code'] ?? $body;
            }
            return new WP_Error('http_error', "Remote server returned HTTP $code: $error_message", [
                'code' => $code,
                'body' => $body,
                'error_detail' => $error_message,
            ]);
        }

        $data = json_decode($body, true);

        if ($data === null && !empty($body)) {
            return new WP_Error('invalid_json', 'Remote server returned invalid JSON', ['body' => $body]);
        }

        return $data;
    }

    private function get_current_store()
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        // Get the store marked as current
        $store = $wpdb->get_row("SELECT * FROM $table WHERE is_current = 1 LIMIT 1");

        if (!$store) {
            $this->ensure_default_store();
            $store = $wpdb->get_row("SELECT * FROM $table WHERE is_current = 1 LIMIT 1");
        }

        return $store;
    }

    public function is_store_local($store)
    {
        if (!$store)
            return false;
        $store_url = preg_replace('/^https?:\/\//', '', untrailingslashit($store->url));
        $home_url = preg_replace('/^https?:\/\//', '', untrailingslashit(home_url()));
        return $store_url === $home_url;
    }

    public function get_stores()
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';

        // Ensure default store exists (the current WP site)
        $this->ensure_default_store();

        // Ensure schema is up to date before querying new columns.
        // Safe to call repeatedly — maybe_upgrade() exits early when already current.
        if (class_exists('ShopCentral_DB') && method_exists('ShopCentral_DB', 'maybe_upgrade')) {
            ShopCentral_DB::maybe_upgrade();
        }

        $limit = $this->get_store_limit();
        $stores = $wpdb->get_results($wpdb->prepare("SELECT id, name, url, is_current, maintenance_mode, order_import_enabled, customer_sync_enabled, last_order_sync FROM $table ORDER BY id ASC LIMIT %d", $limit));

        $has_current = false;
        foreach($stores as $s) {
            if ($s->is_current) {
                $has_current = true;
                break;
            }
        }

        if (!$has_current && count($stores) > 0) {
            $first_id = $stores[0]->id;
            $wpdb->update($table, ['is_current' => 0], ['is_current' => 1]);
            $wpdb->update($table, ['is_current' => 1], ['id' => $first_id]);
            $stores[0]->is_current = 1;
        }

        return new WP_REST_Response(['stores' => $stores], 200);
    }

    /**
     * Build remote WC API URL robustly
     */
    private function build_remote_url($store, $route, $params = [])
    {
        $url = rtrim($store->url, '/');

        if (strpos($url, 'https://') === false && strpos($url, 'http://') === false) {
            $url = 'https://' . $url;
        }

        // Add consumer key/secret to query for maximum compatibility
        $params['consumer_key'] = $store->consumer_key;
        $params['consumer_secret'] = $store->consumer_secret;

        // Support both Pretty and Plain permalinks
        if (strpos($url, '/index.php') !== false || strpos($url, '?') !== false) {
           $final_url = add_query_arg(array_merge($params, ['rest_route' => '/' . ltrim($route, '/')]), $url);
        } else {
            if (strpos($url, '/wp-json/') === false) {
                $url .= '/wp-json/' . ltrim($route, '/');
            } else {
                $url = rtrim($url, '/') . '/' . ltrim($route, '/');
            }
            $final_url = add_query_arg($params, $url);
        }
        return $final_url;
    }

    /**
     * Build remote request arguments with Smart Firewall Bypass headers.
     *
     * @param string      $method  HTTP method.
     * @param string|null $body    Raw request body.
     * @param object|null $store   Store row (used to inject X-ShopCentral-Secret).
     * @return array
     */
    private function get_remote_args($method = 'GET', $body = null, $store = null)
    {
        $version = defined('SHOPCENTRAL_VERSION') ? SHOPCENTRAL_VERSION : '2.5.0';

        $args = [
            'method'      => $method,
            'timeout'     => 60,
            'sslverify'   => false,
            'httpversion' => '1.1',
            'headers'     => [
                'Accept'     => 'application/json',
                // Branded UA – used in Cloudflare WAF rules
                'User-Agent' => 'ShopCentral-Core/' . $version . ' (+https://dominopress.com/shopcentral)',
                'Referer'    => home_url(),
            ],
        ];

        // Inject per-store shared secret when available
        if ($store && !empty($store->shared_secret)) {
            $args['headers']['X-ShopCentral-Secret'] = $store->shared_secret;
        }

        if ($body !== null && $body !== '') {
            $args['body']                     = $body;
            $args['headers']['Content-Type']  = 'application/json';
        }

        return $args;
    }

    private function ensure_default_store()
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';

        $exists = $wpdb->get_var($wpdb->prepare("SELECT id FROM $table WHERE url = %s", home_url()));

        if (!$exists) {
            $wpdb->insert($table, [
                'name' => get_bloginfo('name'),
                'url' => home_url(),
                'consumer_key' => '', // Empty for local
                'consumer_secret' => '',
                'is_current' => 1
            ]);
        }
    }

    /**
     * Get store limit based on Freemius plan
     */
    public function get_store_limit()
    {
        if (!function_exists('shopcentral_pro_fs')) {
            return 1; // Free version limit
        }

        $fs = shopcentral_pro_fs();

        // If not pro or no premium code, strictly 1 store
        if (!$fs->can_use_premium_code()) {
            return 1;
        }

        // Plan-based limits
        if ($fs->is_plan('unlimited') || $fs->is_plan('business') || $fs->is_plan('unlimited_lifetime')) {
            return 9999; // Unlimited stores
        }

        if ($fs->is_plan('professional') || $fs->is_plan('professional_lifetime')) {
            return 5;
        }

        if ($fs->is_plan('personal') || $fs->is_plan('personal_lifetime')) {
            return 3;
        }

        return 1; // Default fallback
    }

    public function add_store($request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $params = $request->get_params();

        // Check for store limit based on Freemius plan
        $store_count = $wpdb->get_var("SELECT COUNT(*) FROM $table");
        $limit = $this->get_store_limit();

        if ($store_count >= $limit) {
            $plan_name = 'Free';
            if (function_exists('shopcentral_pro_fs') && shopcentral_pro_fs()->can_use_premium_code()) {
                $plan = shopcentral_pro_fs()->get_plan();
                $plan_name = $plan ? $plan->name : 'Pro';
            }

            return new WP_Error(
                'limit_exceeded',
                sprintf('Your current %s plan allows a maximum of %d stores. Please upgrade to add more.', $plan_name, $limit),
                ['status' => 403]
            );
        }

        if (empty($params['url']) || empty($params['consumer_key']) || empty($params['consumer_secret'])) {
            return new WP_Error('validation_error', 'Missing required fields', ['status' => 400]);
        }

        // Generate a cryptographic shared secret for firewall bypass
        $shared_secret = bin2hex(random_bytes(32));

        $wpdb->insert($table, [
            'name'            => $params['name'] ?: $params['url'],
            'url'             => esc_url_raw($params['url']),
            'consumer_key'    => sanitize_text_field($params['consumer_key']),
            'consumer_secret' => sanitize_text_field($params['consumer_secret']),
            'is_current'      => 0,
            'shared_secret'   => $shared_secret,
        ]);

        $store_id = $wpdb->insert_id;
        $store = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $store_id));
        if ($store) {
            $this->ensure_order_webhook($store);
        }

        return new WP_REST_Response(['message' => 'Store added', 'id' => $store_id], 201);
    }

    public function switch_store($request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $id = $request->get_param('store_id');

        $limit = $this->get_store_limit();
        $allowed_stores = $wpdb->get_results($wpdb->prepare("SELECT id FROM $table ORDER BY id ASC LIMIT %d", $limit));
        $allowed_ids = array_map(function($s) { return $s->id; }, $allowed_stores);

        if (!in_array($id, $allowed_ids)) {
            return new WP_Error('store_limit_exceeded', 'Store limit exceeded. Please activate Pro to switch to this store.', ['status' => 403]);
        }

        $wpdb->update($table, ['is_current' => 0], ['is_current' => 1]);
        $wpdb->update($table, ['is_current' => 1], ['id' => $id]);

        return new WP_REST_Response(['message' => 'Store switched'], 200);
    }

    /**
     * Periodically ensure all stores have webhooks registered.
     * Bypasses transient check so database migrations always trigger a refresh.
     */
    public function auto_register_webhooks()
    {
        if (get_transient('shopcentral_webhooks_checked')) return;

        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $stores = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table ORDER BY id ASC LIMIT %d", $this->get_store_limit()));

        foreach ($stores as $store) {
            $this->ensure_order_webhook($store);
        }

        set_transient('shopcentral_webhooks_checked', true, DAY_IN_SECONDS);
    }

    /**
     * Force re-register webhooks for all stores (call this after store add or URL changes).
     */
    public function force_rereregister_webhooks()
    {
        delete_transient('shopcentral_webhooks_checked');
        $this->auto_register_webhooks();
    }
    public function ensure_order_webhook($store)
    {
        if ($this->is_store_local($store)) return;

        // Callback URL points back to our Main Site's API — includes both store_url and store_id
        $webhook_url = get_rest_url(null, 'shopcentral/v1/sync/order-callback');
        $webhook_url = add_query_arg([
            'store_url' => urlencode($store->url),
            'store_id'  => intval($store->id),
        ], $webhook_url);

        $payload = [
            'name' => 'ShopCentral Sync Listener',
            'topic' => 'order.created',
            'delivery_url' => $webhook_url,
            'status' => 'active'
        ];

        // Check if webhook already exists
        $webhooks = $this->send_remote_wc_request($store, 'wc/v3/webhooks', 'GET', null, ['search' => 'ShopCentral Sync Listener']);

        if (!empty($webhooks) && is_array($webhooks) && !is_wp_error($webhooks)) {
            $existing_webhook = $webhooks[0];
            // If URL is different, update it
            if ($existing_webhook['delivery_url'] !== $webhook_url) {
                $this->send_remote_wc_request($store, "wc/v3/webhooks/{$existing_webhook['id']}", 'PUT', ['delivery_url' => $webhook_url]);
            }
        } else {
            // Create new
            $this->send_remote_wc_request($store, 'wc/v3/webhooks', 'POST', $payload);
        }
    }



    public function delete_store($request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $id = $request['id'];

        // Don't delete the default local store if possible (or handle it)
        $store = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $id));
        if ($store && $store->url === home_url()) {
            return new WP_Error('forbidden', 'Cannot delete main store', ['status' => 403]);
        }

        $wpdb->delete($table, ['id' => $id]);
        return new WP_REST_Response(['message' => 'Store deleted'], 200);
    }

    /**
     * Toggle order-import on / off for a specific child store.
     * POST body: { "enabled": true|false }
     */
    public function toggle_store_order_import($request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $id    = intval($request['id']);

        $store = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $id));
        if (!$store) {
            return new WP_Error('store_not_found', 'Store not found', ['status' => 404]);
        }

        if ($this->is_store_local($store)) {
            return new WP_Error('hub_store', 'Order import cannot be toggled for the hub (local) site', ['status' => 400]);
        }

        $enabled = $request->get_param('enabled');

        if ($enabled === null) {
            return new WP_Error('missing_param', '`enabled` is required', ['status' => 400]);
        }

        $new_value = (int) $enabled ? 1 : 0;
        $wpdb->update($table, ['order_import_enabled' => $new_value], ['id' => $id]);

        if ($new_value) {
            $this->ensure_order_webhook($store);
        }

        return new WP_REST_Response([
            'message' => 'Order import ' . ($new_value ? 'enabled' : 'disabled'),
            'store_id' => $id,
            'order_import_enabled' => (bool) $new_value,
            'webhook_url' => get_rest_url(null, 'shopcentral/v1/sync/order-callback'),
        ], 200);
    }

    /**
     * Re-register webhooks for all stores.
     */
    public function rerender_webhooks_handler()
    {
        $this->force_rereregister_webhooks();

        return new WP_REST_Response([
            'message' => 'Webhooks re-registered for all stores',
            'callback_url' => get_rest_url(null, 'shopcentral/v1/sync/order-callback'),
        ], 200);
    }

    /**
     * Toggle customer-sync on / off for a specific store.
     * POST body: { "enabled": true|false }
     */
    public function toggle_store_customer_sync($request)
    {
        global $wpdb;
        $table  = $wpdb->prefix . 'shopcentral_stores';
        $id     = intval($request['id']);

        $store = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $id));
        if (!$store) {
            return new WP_Error('store_not_found', 'Store not found', ['status' => 404]);
        }

        if ($this->is_store_local($store)) {
            return new WP_Error('hub_store', 'Customer sync cannot be toggled for the hub (local) site', ['status' => 400]);
        }

        $enabled = $request->get_param('enabled');
        if ($enabled === null) {
            return new WP_Error('missing_param', '`enabled` is required', ['status' => 400]);
        }

        $new_value = (int) $enabled ? 1 : 0;
        $wpdb->update($table, ['customer_sync_enabled' => $new_value], ['id' => $id]);

        return new WP_REST_Response([
            'message'             => 'Customer sync ' . ($new_value ? 'enabled' : 'disabled'),
            'store_id'            => $id,
            'customer_sync_enabled' => (bool) $new_value,
        ], 200);
    }

    /**
     * Return the shared secret + firewall bypass instructions for a store.
     * Only the managing admin can access this — never exposed publicly.
     */
    public function get_store_firewall_info($request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $id    = intval($request['id']);

        $store = $wpdb->get_row($wpdb->prepare("SELECT id, name, url, shared_secret FROM $table WHERE id = %d", $id));
        if (!$store) {
            return new WP_Error('store_not_found', 'Store not found', ['status' => 404]);
        }

        // Ensure every store has a secret (back-fill for older installs)
        if (empty($store->shared_secret)) {
            $secret = bin2hex(random_bytes(32));
            $wpdb->update($table, ['shared_secret' => $secret], ['id' => $id]);
            $store->shared_secret = $secret;
        }

        $version    = defined('SHOPCENTRAL_VERSION') ? SHOPCENTRAL_VERSION : '2.5.0';
        $user_agent = 'ShopCentral-Core/' . $version . ' (+https://dominopress.com/shopcentral)';

        return new WP_REST_Response([
            'store_id'   => $id,
            'store_name' => $store->name,
            'store_url'  => $store->url,
            'secret'     => $store->shared_secret,
            'user_agent' => $user_agent,
            'cloudflare_rule' => [
                'description' => 'Allow ShopCentral hub requests through Cloudflare WAF',
                'expression'  => sprintf(
                    '(http.user_agent contains "ShopCentral") or (http.request.headers["X-ShopCentral-Secret"][0] eq "%s")',
                    $store->shared_secret
                ),
                'action'      => 'skip',
                'note'        => 'Go to Cloudflare Dashboard → Security → WAF → Custom Rules → Create Rule. Paste the expression above and set action to "Skip → All remaining custom rules".',
            ],
        ], 200);
    }

    public function proxy_store_manager_request($request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $current_store = $wpdb->get_row("SELECT * FROM $table WHERE is_current = 1");

        if (!$current_store) {
            $this->ensure_default_store();
            $current_store = $wpdb->get_row("SELECT * FROM $table WHERE is_current = 1");
        }

        $route = str_replace('/shopcentral/v1/api/store-manager/', 'wc/v3/', $request->get_route());
        $method = $request->get_method();
        $is_customers_list = ($route === 'wc/v3/customers' && $method === 'GET');
        $params = array_filter($request->get_query_params(), function ($value) {
            return $value !== '' && $value !== null;
        });

        // If local store, use local handlers or call standard WC API
        if (untrailingslashit($current_store->url) === untrailingslashit(home_url())) {
            $body = $request->get_json_params();
            return $this->handle_local_wc_request($route, $params, $method, $body);
        }

        // For remote stores, prioritize Analytics API for customers
        $remote_route = $route;
        if ($is_customers_list) {
            $remote_route = 'wc-analytics/customers';
        }

        // If remote store, use wp_remote_request with robust URL/Auth
        $url = $this->build_remote_url($current_store, $remote_route, $params);
        $args = $this->get_remote_args($method, $request->get_body(), $current_store);

        $response = wp_remote_request($url, $args);

        if (is_wp_error($response)) {
            error_log("ShopCentral Debug: Proxy Connection Failed: " . $response->get_error_message());
            return new WP_Error(
                'proxy_connection_failed',
                'Failed to connect to remote store: ' . $response->get_error_message(),
                ['status' => 500, 'url' => $url]
            );
        }

        $code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);
        $headers = wp_remote_retrieve_headers($response);

        // Fallback for customers: if Analytics API not found, try wc/v3
        if ($is_customers_list && $code == 404) {
            $route = 'wc/v3/customers';
            $url = $this->build_remote_url($current_store, $route, $params);
            $response = wp_remote_request($url, $args);
            if (is_wp_error($response)) {
                error_log("ShopCentral Debug: Proxy Connection Failed: " . $response->get_error_message());
                return $response;
            }
            $code = wp_remote_retrieve_response_code($response);
            $body = wp_remote_retrieve_body($response);
            $headers = wp_remote_retrieve_headers($response);
        }

        if ($code >= 400) {
            $err_data = json_decode($body, true);
            return new WP_Error(
                'proxy_error',
                $err_data['message'] ?? 'Remote store returned error ' . $code,
                ['status' => $code, 'url' => $url, 'body' => $body]
            );
        }

        $result = json_decode($body, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            return new WP_Error('invalid_json', 'Invalid JSON from remote store', ['status' => 500, 'url' => $url]);
        }

        return $this->format_proxy_response($route, $result, $headers);
    }

    private function handle_local_wc_request($route, $params, $method = 'GET', $body = null)
    {
        $mock_request = new WP_REST_Request($method, '');
        $mock_request->set_query_params($params);
        if ($body) $mock_request->set_body_params($body);

        if (strpos($route, 'wc/v3/products') !== false) {
            // Check if it's a specific product or a sub-route (like categories)
            $subpath = str_replace('wc/v3/products', '', $route);
            if (empty($subpath) || $subpath === '/') {
                // Products list
                $api = new ShopCentral_API();
                return $api->get_all_products($mock_request);
            }

            // For other product routes (single product, categories, etc.), use the standard REST request logic
            $mock_request = new WP_REST_Request($method, '/' . ltrim($route, '/'));
            $mock_request->set_query_params($params);
            if ($body) $mock_request->set_body_params($body);
            $response = rest_do_request($mock_request);
            return $response->get_data();
        }

        if (strpos($route, 'wc/v3/orders') !== false) {
            $args = [
                'limit' => isset($params['per_page']) ? $params['per_page'] : 10,
                'page' => isset($params['page']) ? $params['page'] : 1,
                'paginate' => true,
            ];

            if (!empty($params['after'])) $args['after'] = $params['after'];
            if (!empty($params['before'])) $args['before'] = $params['before'];

            if (!empty($params['status']) && $params['status'] !== 'any') {
                $args['status'] = $params['status'];
            }

            if (!empty($params['search'])) {
                $args['customer'] = $params['search']; // Simplified search
            }

            $results = wc_get_orders($args);
            $orders = [];
            $currency_symbol = html_entity_decode(get_woocommerce_currency_symbol(), ENT_QUOTES, 'UTF-8');
            $currency_symbol = str_replace(['&nbsp;', "\xc2\xa0"], ' ', $currency_symbol);
            $currency_symbol = trim($currency_symbol);
            foreach ($results->orders as $order) {
                $order_data = $order->get_data();
                // Format dates for JSON
                $order_data['date_created'] = $order_data['date_created'] ? $order_data['date_created']->date('Y-m-d H:i:s') : null;
                $order_data['date_modified'] = $order_data['date_modified'] ? $order_data['date_modified']->date('Y-m-d H:i:s') : null;
                $order_data['currency_symbol'] = $currency_symbol;
                $orders[] = $order_data;
            }
            return new WP_REST_Response([
                'data' => $orders,
                'total' => $results->total,
                'meta' => ['total' => $results->total]
            ], 200);
        }

        if (strpos($route, 'wc/v3/customers') !== false) {
            if ($method === 'POST') {
                $customer = new WC_Customer();
                if (!empty($body['email'])) $customer->set_email($body['email']);
                if (!empty($body['username'])) $customer->set_username($body['username']);
                if (!empty($body['password'])) $customer->set_password($body['password']);
                if (!empty($body['first_name'])) $customer->set_first_name($body['first_name']);
                if (!empty($body['last_name'])) $customer->set_last_name($body['last_name']);
                $id = $customer->save();
                return new WP_REST_Response($customer->get_data(), 201);
            }

            // DELETE
            if ($method === 'DELETE') {
                $id = (int)str_replace('wc/v3/customers/', '', $route);
                if ($id > 0) {
                    $force = isset($params['force']) ? (bool)$params['force'] : false;
                    $reassign = isset($params['reassign']) ? (int)$params['reassign'] : null;
                    wp_delete_user($id, $reassign);
                    return new WP_REST_Response(['message' => 'Customer deleted'], 200);
                }
            }

            global $wpdb;
            $table = $wpdb->prefix . 'wc_customer_lookup';
            $per_page = isset($params['per_page']) ? (int)$params['per_page'] : 10;
            $page = isset($params['page']) ? (int)$params['page'] : 1;
            $offset = ($page - 1) * $per_page;

            $where = "WHERE 1=1";
            if (!empty($params['search'])) {
                $search = $wpdb->esc_like($params['search']);
                $where .= " AND (first_name LIKE '%$search%' OR last_name LIKE '%$search%' OR email LIKE '%$search%' OR username LIKE '%$search%')";
            }

            if (!empty($params['role']) && $params['role'] !== 'all') {
                $role = $params['role'];
                $where .= " AND user_id IN (SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key = '{$wpdb->prefix}capabilities' AND meta_value LIKE '%\"$role\"%')";
            }

            $users = $wpdb->get_results("SELECT * FROM $table $where ORDER BY date_last_active DESC LIMIT $offset, $per_page");
            $total_count = $wpdb->get_var("SELECT COUNT(*) FROM $table $where");
            $customers = [];

            $currency_symbol = html_entity_decode(get_woocommerce_currency_symbol(), ENT_QUOTES, 'UTF-8');
            $currency_symbol = str_replace(['&nbsp;', "\xc2\xa0"], ' ', $currency_symbol);
            $currency_symbol = trim($currency_symbol);
            $currency_pos = get_option('woocommerce_currency_pos', 'left');

            foreach ($users as $user) {
                try {
                    $customer_id = (int)$user->customer_id;
                    $user_id = (int)$user->user_id;

                    $c_data = [];
                    if ($user_id > 0) {
                        $wc_customer = new WC_Customer($user_id);
                        $c_data = $wc_customer->get_data();
                    } else {
                        $c_data = [
                            'id' => 0,
                            'first_name' => $user->first_name,
                            'last_name' => $user->last_name,
                            'email' => $user->email,
                            'username' => $user->username ?: 'Guest',
                            'billing' => [
                                'first_name' => $user->first_name,
                                'last_name' => $user->last_name,
                                'email' => $user->email,
                                'country' => $user->country,
                                'city' => $user->city,
                                'state' => $user->state,
                                'postcode' => $user->postcode,
                            ]
                        ];
                    }

                    $stats = $wpdb->get_row($wpdb->prepare("
                        SELECT
                            COUNT(order_id) as count,
                            SUM(total_sales) as total
                        FROM {$wpdb->prefix}wc_order_stats
                        WHERE customer_id = %d
                        AND status IN ('wc-completed', 'wc-processing', 'wc-on-hold')
                    ", $customer_id));

                    $order_count = $stats ? (int)$stats->count : 0;
                    $total_spent = $stats ? (float)$stats->total : 0;

                    $c_data['orders_count'] = $order_count;
                    $c_data['total_spent'] = number_format($total_spent, 2, '.', '');
                    $c_data['aov'] = $order_count > 0 ? number_format($total_spent / $order_count, 2, '.', '') : '0.00';
                    $c_data['country'] = $user->country ?: '';
                    $c_data['currency_symbol'] = $currency_symbol;
                    $c_data['currency_pos'] = $currency_pos;

                    $customers[] = $c_data;
                } catch (Exception $e) { continue; }
            }
            return new WP_REST_Response([
                'data' => $customers,
                'meta' => ['total' => (int)$total_count]
            ], 200);
        }

        if (strpos($route, 'wc/v3/coupons') !== false) {
            // Use ShopCentral_API get_all_coupons method
            $api = new ShopCentral_API();
            $res = $api->get_all_coupons($mock_request);
            $data = $res->get_data();
            $coupons = $data['data']['allCoupons'] ?? [];
            return new WP_REST_Response([
                'data' => $coupons,
                'meta' => ['total' => count($coupons)]
            ], 200);
        }

        return new WP_REST_Response(['message' => 'Not implemented locally'], 501);
    }

    private function format_proxy_response($route, $result, $headers)
    {
        $total = $headers['x-wp-total'] ?? count($result);
        $is_list = $this->is_sequential_array($result);

        if ($is_list && strpos($route, 'products') !== false && strpos($route, 'products/') === false) {
            // Ensure result is an array and not an error object
            $is_error = isset($result['code']) && isset($result['message']);
            $products_list = (!$is_error && is_array($result)) ? $result : [];

            return new WP_REST_Response([
                'data' => [
                    'allProducts' => $products_list,
                    'totalProducts' => [] // stats not yet implemented for proxy
                ],
                'meta' => ['total' => $total]
            ], 200);
        }

        if (strpos($route, 'orders') !== false) {
            $is_error = isset($result['code']) && isset($result['message']);
            $orders_list = (!$is_error && is_array($result)) ? $result : [];

            return new WP_REST_Response([
                'data' => $orders_list,
                'total' => $total,
                'meta' => ['total' => $total]
            ], 200);
        }

        if ((strpos($route, 'customers') !== false) && $is_list) {
            $is_error = isset($result['code']) && isset($result['message']);
            $customers_list = (!$is_error && is_array($result)) ? $result : [];

            foreach ($customers_list as &$customer) {
                if (is_array($customer)) {
                    // Handle Analytics API data mapping
                    if (isset($customer['name']) && !isset($customer['first_name'])) {
                        $parts = explode(' ', $customer['name'], 2);
                        $customer['first_name'] = $parts[0];
                        $customer['last_name'] = $parts[1] ?? '';
                    }

                    if (isset($customer['total_spend'])) {
                        $customer['total_spent'] = $customer['total_spend'];
                    }

                    if (isset($customer['avg_order_value'])) {
                        $customer['aov'] = $customer['avg_order_value'];
                    }

                    $orders_count = (int)($customer['orders_count'] ?? 0);
                    $total_spent = (float)($customer['total_spent'] ?? 0);

                    $customer['aov'] = $customer['aov'] ?? ($orders_count > 0 ? number_format($total_spent / $orders_count, 2, '.', '') : '0.00');
                    $customer['country'] = $customer['country'] ?? ($customer['billing']['country'] ?? '');
                    $customer['total_spent'] = number_format($total_spent, 2, '.', '');
                }
            }

            return new WP_REST_Response([
                'data' => $customers_list,
                'meta' => ['total' => (int)$total]
            ], 200);
        }

        $is_error = isset($result['code']) && isset($result['message']);
        $final_data = (!$is_error && is_array($result)) ? $result : [];

        return new WP_REST_Response([
            'data' => $final_data,
            'meta' => ['total' => $total]
        ], 200);
    }

    public function get_store_manager_stats($request)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'shopcentral_stores';
        $current_store = $wpdb->get_row("SELECT * FROM $table WHERE is_current = 1");

        if (!$current_store) {
            $this->ensure_default_store();
            $current_store = $wpdb->get_row("SELECT * FROM $table WHERE is_current = 1");
        }

        if ($this->is_store_local($current_store)) {
            // Local Stats (HPOS compatible counting)
            $after = $request->get_param('after');
            $before = $request->get_param('before');

            $valid_statuses = ['completed', 'processing', 'on-hold'];
            $order_args = ['limit' => 1, 'paginate' => true, 'status' => $valid_statuses];
            if ($after) $order_args['after'] = $after;
            if ($before) $order_args['before'] = $before;

            $order_query = wc_get_orders($order_args);
            $total_orders = $order_query->total;

            $stats = [
                'products' => [
                    'total' => (int) wp_count_posts('product')->publish + (int) wp_count_posts('product')->draft + (int) wp_count_posts('product')->private,
                    'publish' => (int) wp_count_posts('product')->publish,
                    'draft' => (int) wp_count_posts('product')->draft,
                ],
                'orders' => [
                    'total' => $total_orders,
                ],
                'customers' => [
                    'total' => (new WP_User_Query(['role' => 'customer', 'number' => 1]))->get_total(),
                ],
                'categories' => [
                    'total' => (int) wp_count_terms('product_cat'),
                ],
                'coupons' => [
                    'total' => (int) wp_count_posts('shop_coupon')->publish,
                ],
                'refunds' => [
                    'total' => wc_get_orders(['limit' => -1, 'status' => 'refunded', 'return' => 'ids']) ? count(wc_get_orders(['limit' => -1, 'status' => 'refunded', 'return' => 'ids'])) : 0,
                ],
                'currency_symbol' => get_woocommerce_currency_symbol(),
                'currency_code' => get_woocommerce_currency(),
            ];
            return new WP_REST_Response($stats, 200);
        }

        // Fetch Remote Stats
        $after = $request->get_param('after');
        $before = $request->get_param('before');
        $date_params = [];
        if ($after) $date_params['after'] = $after;
        if ($before) $date_params['before'] = $before;

        error_log("ShopCentral Debug: Fetching stats for REMOTE Store: " . ($current_store->name ?? 'Unknown') . " (" . ($current_store->url ?? 'No URL') . ")");

        // Products, Customers, Categories, Coupons represent the aggregate size of the store.
        // We fetch totals for these tiles to ensure they are not 0 if chosen date range is too recent.
        $publish_count = $this->get_remote_wc_count($current_store, 'wc/v3/products', ['status' => 'publish']);
        $draft_count = $this->get_remote_wc_count($current_store, 'wc/v3/products', ['status' => 'draft']);
        $order_count = $this->get_remote_wc_count($current_store, 'wc/v3/orders', array_merge($date_params, ['status' => 'completed,processing,on-hold,pending']));
        $customer_count = $this->get_remote_wc_count($current_store, 'wc/v3/customers');
        $category_count = $this->get_remote_wc_count($current_store, 'wc/v3/products/categories');
        $coupon_count = $this->get_remote_wc_count($current_store, 'wc/v3/coupons');
        $refund_count = $this->get_remote_wc_count($current_store, 'wc/v3/orders', array_merge($date_params, ['status' => 'refunded']));

        return new WP_REST_Response([
            'products' => [
                'total' => $publish_count + $draft_count,
                'publish' => $publish_count,
                'draft' => $draft_count
            ],
            'orders' => ['total' => $order_count],
            'customers' => ['total' => $customer_count],
            'categories' => ['total' => $category_count],
            'coupons' => ['total' => $coupon_count],
            'refunds' => ['total' => $refund_count],
            'is_remote' => true
        ], 200);
    }

    public function get_remote_wc_count($store, $endpoint, $params = [])
    {
        $url = $this->build_remote_url($store, $endpoint, array_merge($params, ['per_page' => 1]));
        $args = $this->get_remote_args('GET', null, $store);

        $response = wp_remote_get($url, $args);
        if (is_wp_error($response)) {
            error_log("ShopCentral Debug: Remote Count Failed [$endpoint]: " . $response->get_error_message());
            return 0;
        }

        $code = wp_remote_retrieve_response_code($response);
        $headers = wp_remote_retrieve_headers($response);
        error_log("ShopCentral Debug: Remote Count Response Code [$endpoint]: " . $code . " | Total Header: " . ($headers['x-wp-total'] ?? 'N/A'));
        return isset($headers['x-wp-total']) ? (int) $headers['x-wp-total'] : 0;
    }

    public function get_store_manager_order_metrics($request)
    {
        $current_store = $this->get_current_store();

        if (!$current_store) {
            // Return dummy data if no store
            return new WP_REST_Response([
                'total_orders' => 0,
                'total_revenue' => 0,
                'total_items' => 0,
                'aov' => 0,
                'completed' => 0,
                'processing' => 0,
                'cancelled' => 0,
                'refunded' => 0,
                'pending' => 0,
            ], 200);
        }

        if ($this->is_store_local($current_store)) {
            // Fetch local WooCommerce orders metrics
            $after = $request->get_param('after');
            $before = $request->get_param('before');

            $valid_statuses = ['completed', 'processing', 'on-hold'];
            $args = ['limit' => -1, 'status' => $valid_statuses];
            if ($after) $args['after'] = $after;
            if ($before) $args['before'] = $before;

            $orders = wc_get_orders($args);

            $total_orders = count($orders);
            $total_revenue = 0;
            $total_items = 0;

            foreach ($orders as $order) {
                $total_revenue += $order->get_total();
                $total_items += $order->get_item_count();
            }

            $aov = $total_orders > 0 ? $total_revenue / $total_orders : 0;

            $metrics = [
                'total_orders' => $total_orders,
                'total_revenue' => $total_revenue,
                'total_items' => $total_items,
                'aov' => $aov,
                'completed' => count(wc_get_orders(['limit' => -1, 'status' => 'completed'])),
                'processing' => count(wc_get_orders(['limit' => -1, 'status' => 'processing'])),
                'cancelled' => count(wc_get_orders(['limit' => -1, 'status' => 'cancelled'])),
                'refunded' => count(wc_get_orders(['limit' => -1, 'status' => 'refunded'])),
                'pending' => count(wc_get_orders(['limit' => -1, 'status' => 'pending'])),
            'currency_symbol' => get_woocommerce_currency_symbol(),
            'currency_code' => get_woocommerce_currency(),
        ];

            return new WP_REST_Response($metrics, 200);
        }

        // Remote store - fetch via API
        $after = $request->get_param('after');
        $before = $request->get_param('before');

        $sales_params = [];
        if ($after && $before) {
            $sales_params['date_min'] = date('Y-m-d', strtotime($after));
            $sales_params['date_max'] = date('Y-m-d', strtotime($before));
        } else {
            $sales_params['period'] = 'year';
        }

        $sales_data = $this->get_remote_wc_data($current_store, 'wc/v3/reports/sales', $sales_params);
        $total_orders_rep = 0;
        $total_revenue = 0;
        $total_items = 0;
        $aov = 0;

        if (is_array($sales_data) && !empty($sales_data) && !isset($sales_data['code'])) {
            foreach ($sales_data as $report) {
                if (isset($report['code'])) continue;
                $total_orders_rep += (int) ($report['total_orders'] ?? 0);
                $total_revenue += (float) ($report['total_sales'] ?? 0);
                $total_items += (int) ($report['total_items'] ?? 0);
            }
        }

        $total_orders = $total_orders_rep;

        // Date params for raw order queries
        $order_params_base = [];
        if ($after) $order_params_base['after'] = $after;
        if ($before) $order_params_base['before'] = $before;

        // Check if we need to fetch order count independently if report is 0 but might have data
        if ($total_revenue <= 0 || $total_orders_rep === 0) {
            $order_params = array_merge($order_params_base, ['status' => 'completed,processing,on-hold']);
            $total_orders = $this->get_remote_wc_count($current_store, 'wc/v3/orders', $order_params);

            // If we have orders but 0 revenue from report, fetch orders to calculate manually
            if ($total_orders > 0 && $total_revenue <= 0) {
                 $orders = $this->get_remote_wc_data($current_store, 'wc/v3/orders', array_merge($order_params, ['per_page' => 50]));
                 if (is_array($orders) && !isset($orders['code'])) {
                     foreach ($orders as $o) {
                         $total_revenue += (float) ($o['total'] ?? 0);
                         if (isset($o['line_items']) && is_array($o['line_items'])) {
                             foreach ($o['line_items'] as $li) {
                                 $total_items += (int) ($li['quantity'] ?? 0);
                             }
                         }
                     }
                 }
            }
        }

        $aov = $total_orders > 0 ? $total_revenue / $total_orders : 0;
        $status_res = $this->get_remote_wc_data($current_store, 'wc/v3/system_status');

        $currency_symbol = '$';
        $currency_code = 'USD';
        if (is_array($status_res) && isset($status_res['settings']) && is_array($status_res['settings'])) {
            $currency_symbol = $status_res['settings']['currency_symbol'] ?? '$';
            $currency_code = $status_res['settings']['currency'] ?? 'USD';
        }

        return new WP_REST_Response([
            'total_orders' => $total_orders,
            'total_revenue' => $total_revenue,
            'total_items' => $total_items,
            'aov' => $aov,
            'completed' => $this->get_remote_wc_count($current_store, 'wc/v3/orders', array_merge($order_params_base, ['status' => 'completed'])),
            'processing' => $this->get_remote_wc_count($current_store, 'wc/v3/orders', array_merge($order_params_base, ['status' => 'processing'])),
            'cancelled' => $this->get_remote_wc_count($current_store, 'wc/v3/orders', array_merge($order_params_base, ['status' => 'cancelled'])),
            'refunded' => $this->get_remote_wc_count($current_store, 'wc/v3/orders', array_merge($order_params_base, ['status' => 'refunded'])),
            'pending' => $this->get_remote_wc_count($current_store, 'wc/v3/orders', array_merge($order_params_base, ['status' => 'pending'])),
            'currency_symbol' => $currency_symbol,
            'currency_code' => $currency_code,
            'is_remote' => true
        ], 200);
    }

    public function get_store_manager_product_analytics($request)
    {
        $current_store = $this->get_current_store();

        if (!$current_store) {
            return new WP_REST_Response([], 404);
        }

        if ($this->is_store_local($current_store)) {
            // Local Analytics Logic
            $after = $request->get_param('after');
            $before = $request->get_param('before');

            $order_args = [
                'limit' => -1,
                'status' => ['completed', 'processing', 'on-hold']
            ];
            if ($after)
                $order_args['date_after'] = $after;
            if ($before)
                $order_args['date_before'] = $before;

            $orders = wc_get_orders($order_args);
            $total_revenue = 0;
            $total_orders = count($orders);
            $product_revenue = [];

            foreach ($orders as $order) {
                // Only count revenue for successful/active orders (already filtered by status above, but extra safety)
                if (in_array($order->get_status(), ['completed', 'processing', 'on-hold'])) {
                    $total_revenue += (float) $order->get_total();
                    foreach ($order->get_items() as $item) {
                        if ($item instanceof WC_Order_Item_Product) {
                            $product_id = $item->get_product_id();
                            $line_total = (float) $item->get_total();
                            if (isset($product_revenue[$product_id])) {
                                $product_revenue[$product_id] += $line_total;
                            } else {
                                $product_revenue[$product_id] = $line_total;
                            }
                        }
                    }
                }
            }

            arsort($product_revenue);
            $top_rev_ids = array_slice(array_keys($product_revenue), 0, 5);
            $top_revenue_products = [];
            foreach ($top_rev_ids as $pid) {
                $p = wc_get_product($pid);
                if ($p) {
                    $formatted = $this->format_product($p);
                    $formatted['revenue'] = round($product_revenue[$pid], 2);
                    $top_revenue_products[] = $formatted;
                }
            }

            // Products stats
            $total_products = (int) wp_count_posts('product')->publish;
            $out_of_stock = count(wc_get_products(['stock_status' => 'outofstock', 'limit' => -1]));

            // Top Selling (popularity meta)
            $top_selling_objs = wc_get_products([
                'orderby' => 'popularity',
                'order' => 'DESC',
                'limit' => 5
            ]);
            $top_selling = [];
            foreach ($top_selling_objs as $p) {
                $top_selling[] = $this->format_product($p);
            }

            $no_sales = [];
            // We'll use the popularity ordered products to find those with 0 sales
            $zero_sales_objs = wc_get_products([
                'orderby' => 'popularity',
                'order' => 'ASC',
                'limit' => 20
            ]);
            foreach ($zero_sales_objs as $p) {
                if ((int) $p->get_total_sales() === 0) {
                    $no_sales[] = $this->format_product($p);
                }
                if (count($no_sales) >= 5)
                    break;
            }

            $trends = [];
            foreach ($orders as $order) {
                $date = $order->get_date_created()->date('Y-m-d');
                if (!isset($trends[$date])) {
                    $trends[$date] = ['date' => $date, 'revenue' => 0, 'orders' => 0];
                }
                $trends[$date]['orders']++;
                if (in_array($order->get_status(), ['completed', 'processing', 'on-hold'])) {
                    $trends[$date]['revenue'] += (float) $order->get_total();
                }
            }
            ksort($trends);
            $trends = array_values($trends);

            return new WP_REST_Response([
                'stats' => [
                    'total_products' => $total_products,
                    'out_of_stock' => $out_of_stock,
                    'low_stock' => 0,
                    'total_orders' => $total_orders,
                    'total_revenue' => round($total_revenue, 2),
                    'currency_symbol' => get_woocommerce_currency_symbol(),
                    'currency_code' => get_woocommerce_currency()
                ],
                'top_selling' => $top_selling,
                'no_sales' => $no_sales,
                'top_revenue_products' => $top_revenue_products,
                'trends' => $trends
            ], 200);
        }

        $after = $request->get_param('after');
        $before = $request->get_param('before');

        // Convert to YYYY-MM-DD for reports and stats
        $date_min = $after ? date('Y-m-d', strtotime($after)) : null;
        $date_max = $before ? date('Y-m-d', strtotime($before)) : null;

        // Remote Analytics
        $total_products = $this->get_remote_wc_count($current_store, 'wc/v3/products', ['status' => 'publish']);
        $out_of_stock = $this->get_remote_wc_count($current_store, 'wc/v3/products', ['stock_status' => 'outofstock']);
        $low_stock = 0;

        $sales_params = [];
        if ($date_min && $date_max) {
            $sales_params = ['date_min' => $date_min, 'date_max' => $date_max];
        } else {
            $sales_params = ['period' => 'year'];
        }

        $sales_reports = $this->get_remote_wc_data($current_store, 'wc/v3/reports/sales', $sales_params);

        $total_revenue = 0;
        $total_orders_count = 0;
        $trends_data = [];

        if (is_array($sales_reports) && !empty($sales_reports) && !isset($sales_reports['code'])) {
            foreach ($sales_reports as $report) {
                if (isset($report['code'])) continue;
                $total_revenue += (float) ($report['total_sales'] ?? 0);
                $total_orders_count += (int) ($report['total_orders'] ?? 0);

                // Extract daily totals for trends
                if (isset($report['totals']) && is_array($report['totals'])) {
                    foreach ($report['totals'] as $date => $day_data) {
                        if (!isset($trends_data[$date])) {
                            $trends_data[$date] = ['date' => $date, 'revenue' => 0, 'orders' => 0];
                        }
                        $trends_data[$date]['revenue'] += (float)($day_data['sales'] ?? 0);
                        $trends_data[$date]['orders'] += (int)($day_data['orders'] ?? 0);
                    }
                }
            }
        }

        // Manual Fallback if revenue is 0 but orders exist
        $order_args = [];
        if ($after) $order_args['after'] = $after;
        if ($before) $order_args['before'] = $before;

        $real_order_total = $this->get_remote_wc_count($current_store, 'wc/v3/orders', array_merge($order_args, ['status' => 'completed,processing,on-hold']));

        if ($real_order_total > 0 && ($total_revenue <= 0 || $total_orders_count === 0)) {
            $total_orders_count = $real_order_total;
            if ($total_revenue <= 0) {
                $orders = $this->get_remote_wc_data($current_store, 'wc/v3/orders', array_merge($order_args, ['per_page' => 50, 'status' => 'completed,processing,on-hold']));
                if (is_array($orders) && !isset($orders['code'])) {
                    foreach ($orders as $o) {
                        $total_revenue += (float)($o['total'] ?? 0);
                        $d = date('Y-m-d', strtotime($o['date_created']));
                        if (!isset($trends_data[$d])) {
                            $trends_data[$d] = ['date' => $d, 'revenue' => 0, 'orders' => 0];
                        }
                        $trends_data[$d]['revenue'] += (float)($o['total'] ?? 0);
                        $trends_data[$d]['orders']++;
                    }
                }
            }
        }

        ksort($trends_data);
        $trends = array_values($trends_data);

        $top_selling = $this->get_remote_wc_data($current_store, 'wc/v3/products', [
            'orderby' => 'popularity',
            'order' => 'desc',
            'per_page' => 7
        ]);

        // Top Revenue Products — try analytics API first, fall back to order line items
        $ana_params = ['orderby' => 'net_revenue', 'order' => 'desc', 'per_page' => 5];
        if ($after) $ana_params['after'] = date('Y-m-d\TH:i:s', strtotime($after));
        if ($before) $ana_params['before'] = date('Y-m-d\TH:i:s', strtotime($before));

        $top_rev_res = $this->get_remote_wc_data($current_store, 'wc-analytics/products', $ana_params);
        $top_revenue_products = [];

        if (!empty($top_rev_res) && !isset($top_rev_res['code'])) {
            // Analytics API worked
            foreach ($top_rev_res as $tr) {
                if (!isset($tr['product_id'])) continue;
                $p_id = $tr['product_id'];
                $p_info = $this->get_remote_wc_data($current_store, "wc/v3/products/{$p_id}");
                if (is_array($p_info) && !isset($p_info['code'])) {
                    $formatted = $this->format_product_array($p_info);
                    $formatted['revenue'] = (float)($tr['net_revenue'] ?? 0);
                    $top_revenue_products[] = $formatted;
                }
            }
        }

        // Fallback: aggregate revenue per product from order line_items
        if (empty($top_revenue_products)) {
            $orders_for_revenue = $this->get_remote_wc_data($current_store, 'wc/v3/orders', array_merge($order_args, [
                'status'   => 'completed,processing,on-hold',
                'per_page' => 50,
            ]));

            $product_revenue = [];
            if (is_array($orders_for_revenue) && !isset($orders_for_revenue['code'])) {
                foreach ($orders_for_revenue as $o) {
                    if (!isset($o['line_items'])) continue;
                    foreach ($o['line_items'] as $li) {
                        $pid = $li['product_id'] ?? 0;
                        if (!$pid) continue;
                        if (!isset($product_revenue[$pid])) {
                            $product_revenue[$pid] = ['revenue' => 0, 'quantity' => 0, 'name' => $li['name'] ?? ''];
                        }
                        $product_revenue[$pid]['revenue'] += (float)($li['total'] ?? 0);
                        $product_revenue[$pid]['quantity'] += (int)($li['quantity'] ?? 0);
                    }
                }
            }

            // Sort descending by revenue, take top 5
            arsort($product_revenue);
            $top5 = array_slice($product_revenue, 0, 5, true);

            foreach ($top5 as $pid => $rev_data) {
                $p_info = $this->get_remote_wc_data($current_store, "wc/v3/products/{$pid}");
                if (is_array($p_info) && !isset($p_info['code'])) {
                    $formatted = $this->format_product_array($p_info);
                    $formatted['revenue'] = round($rev_data['revenue'], 2);
                    $formatted['total_sales'] = $rev_data['quantity'];
                    $top_revenue_products[] = $formatted;
                } else {
                    // Minimal fallback with just name & revenue
                    $top_revenue_products[] = [
                        'id'            => $pid,
                        'name'          => $rev_data['name'],
                        'revenue'       => round($rev_data['revenue'], 2),
                        'total_sales'   => $rev_data['quantity'],
                        'stock_status'  => 'instock',
                        'stock_quantity'=> 0,
                        'images'        => [],
                    ];
                }
            }
        }

        $system_status = $this->get_remote_wc_data($current_store, 'wc/v3/system_status');
        $currency_symbol = '$';
        $currency_code = 'USD';

        if (is_array($system_status) && isset($system_status['settings'])) {
            $currency_symbol = $system_status['settings']['currency_symbol'] ?? '$';
            $currency_code = $system_status['settings']['currency'] ?? 'USD';
        }

        return new WP_REST_Response([
            'stats' => [
                'total_products' => $total_products,
                'out_of_stock' => $out_of_stock,
                'low_stock' => $low_stock,
                'total_orders' => $total_orders_count,
                'total_revenue' => round($total_revenue, 2),
                'currency_symbol' => $currency_symbol,
                'currency_code' => $currency_code
            ],
            'top_selling' => is_array($top_selling) && !isset($top_selling['code']) ? $top_selling : [],
            'no_sales' => [],
            'top_revenue_products' => $top_revenue_products,
            'trends' => $trends,
            'is_remote' => true
        ], 200);
    }

    public function get_store_manager_sales_report($request)
    {
        $current_store = $this->get_current_store();
        if (!$current_store) {
            return new WP_REST_Response(['error' => 'No store selected'], 404);
        }

        $after  = $request->get_param('after');
        $before = $request->get_param('before');

        // Convert ISO strings to Y-m-d
        $date_min = $after  ? date('Y-m-d', strtotime($after))  : date('Y-m-d', strtotime('-365 days'));
        $date_max = $before ? date('Y-m-d', strtotime($before)) : date('Y-m-d');

        $summary = [
            'total_sales'     => 0,
            'net_sales'       => 0,
            'total_orders'    => 0,
            'total_items'     => 0,
            'total_tax'       => 0,
            'total_shipping'  => 0,
            'total_refunds'   => 0,
            'total_discount'  => 0,
            'total_customers' => 0,
            'average_sales'   => 0,
        ];
        $trends = [];

        if ($this->is_store_local($current_store)) {
            // ── LOCAL STORE: query orders directly from the DB ──────────────
            $args = [
                'status'       => ['wc-completed', 'wc-processing', 'wc-on-hold'],
                'date_created' => $date_min . '...' . $date_max,
                'limit'        => -1,
                'return'       => 'objects',
            ];
            $orders = wc_get_orders($args);

            foreach ($orders as $order) {
                $day = $order->get_date_created() ? $order->get_date_created()->date('Y-m-d') : null;
                if (!$day) continue;

                $total    = (float) $order->get_total();
                $tax      = (float) $order->get_total_tax();
                $shipping = (float) $order->get_shipping_total();
                $discount = (float) $order->get_discount_total();
                $items    = (int)   $order->get_item_count();

                $summary['total_sales']    += $total;
                $summary['total_orders']   += 1;
                $summary['total_items']    += $items;
                $summary['total_tax']      += $tax;
                $summary['total_shipping'] += $shipping;
                $summary['total_discount'] += $discount;

                if (!isset($trends[$day])) {
                    $trends[$day] = ['date' => $day, 'sales' => 0, 'orders' => 0, 'items' => 0, 'customers' => 0];
                }
                $trends[$day]['sales']   += $total;
                $trends[$day]['orders']  += 1;
                $trends[$day]['items']   += $items;
            }

            $summary['net_sales'] = $summary['total_sales'] - $summary['total_tax'] - $summary['total_shipping'];

        } else {
            // ── REMOTE STORE: try reports/sales first, fall back to manual order aggregation ──
            $report_ok = false;
            $params    = ['date_min' => $date_min, 'date_max' => $date_max];
            $report    = $this->get_remote_wc_data($current_store, 'wc/v3/reports/sales', $params);

            if (is_array($report) && !isset($report['code'])) {
                // WC returns single object OR array of objects
                $rows = isset($report['total_sales']) ? [$report] : $report;

                foreach ($rows as $row) {
                    if (!is_array($row) || isset($row['code'])) continue;
                    $summary['total_sales']     += (float)($row['total_sales']    ?? 0);
                    $summary['net_sales']       += (float)($row['net_sales']      ?? 0);
                    $summary['total_orders']    += (int)  ($row['total_orders']   ?? 0);
                    $summary['total_items']     += (int)  ($row['total_items']    ?? 0);
                    $summary['total_tax']       += (float)($row['total_tax']      ?? 0);
                    $summary['total_shipping']  += (float)($row['total_shipping'] ?? 0);
                    $summary['total_refunds']   += (float)($row['total_refunds']  ?? 0);
                    $summary['total_discount']  += (float)($row['total_discount'] ?? 0);
                    $summary['total_customers'] += (int)  ($row['total_customers']?? 0);

                    if (isset($row['totals']) && is_array($row['totals'])) {
                        foreach ($row['totals'] as $date => $day) {
                            if (!isset($trends[$date])) {
                                $trends[$date] = ['date' => $date, 'sales' => 0, 'orders' => 0, 'items' => 0, 'customers' => 0];
                            }
                            $trends[$date]['sales']     += (float)($day['sales']     ?? 0);
                            $trends[$date]['orders']    += (int)  ($day['orders']    ?? 0);
                            $trends[$date]['items']     += (int)  ($day['items']     ?? 0);
                            $trends[$date]['customers'] += (int)  ($day['customers'] ?? 0);
                        }
                    }
                }

                if ($summary['total_sales'] > 0 || $summary['total_orders'] > 0) {
                    $report_ok = true;
                }
            }

            // Fallback: aggregate directly from orders (same pattern as Order Metrics)
            if (!$report_ok) {
                $page = 1;
                while ($page <= 10) {  // cap at 10 pages × 100 = 1000 orders
                    $order_params = [
                        'status'   => 'completed,processing,on-hold',
                        'after'    => $date_min . 'T00:00:00',
                        'before'   => $date_max . 'T23:59:59',
                        'per_page' => 100,
                        'page'     => $page,
                        'orderby'  => 'date',
                        'order'    => 'asc',
                    ];
                    $orders = $this->get_remote_wc_data($current_store, 'wc/v3/orders', $order_params);

                    if (!is_array($orders) || isset($orders['code']) || empty($orders)) break;

                    foreach ($orders as $order) {
                        if (!is_array($order) || isset($order['code'])) continue;

                        $total    = (float)($order['total']          ?? 0);
                        $tax      = (float)($order['total_tax']      ?? 0);
                        $shipping = (float)($order['shipping_total']  ?? 0);
                        $discount = (float)($order['discount_total']  ?? 0);
                        $items    = array_sum(array_column($order['line_items'] ?? [], 'quantity'));

                        // Parse date: "2025-03-01T12:34:56" → "2025-03-01"
                        $raw_date = $order['date_created'] ?? '';
                        $day      = substr($raw_date, 0, 10);
                        if (strlen($day) !== 10) continue;

                        $summary['total_sales']    += $total;
                        $summary['total_orders']   += 1;
                        $summary['total_items']    += $items;
                        $summary['total_tax']      += $tax;
                        $summary['total_shipping'] += $shipping;
                        $summary['total_discount'] += $discount;

                        if (!isset($trends[$day])) {
                            $trends[$day] = ['date' => $day, 'sales' => 0, 'orders' => 0, 'items' => 0, 'customers' => 0];
                        }
                        $trends[$day]['sales']  += $total;
                        $trends[$day]['orders'] += 1;
                        $trends[$day]['items']  += $items;
                    }

                    if (count($orders) < 100) break; // last page
                    $page++;
                }

                $summary['net_sales'] = $summary['total_sales'] - $summary['total_tax'] - $summary['total_shipping'];
            }
        }

        ksort($trends);
        // Strip days with no activity
        $trends = array_filter($trends, fn($d) => $d['sales'] > 0 || $d['orders'] > 0);

        $summary['average_sales'] = $summary['total_orders'] > 0
            ? round($summary['total_sales'] / $summary['total_orders'], 2)
            : 0;

        return new WP_REST_Response([
            'summary' => $summary,
            'trends'  => array_values($trends),
        ], 200);
    }

    public function get_store_manager_report_totals($request)
    {
        $current_store = $this->get_current_store();
        if (!$current_store) {
            return new WP_REST_Response(['error' => 'No store selected'], 404);
        }

        $endpoints = [
            'orders'    => 'wc/v3/reports/orders/totals',
            'customers' => 'wc/v3/reports/customers/totals',
            'products'  => 'wc/v3/reports/products/totals',
            'coupons'   => 'wc/v3/reports/coupons/totals',
        ];

        $result = [];

        foreach ($endpoints as $key => $route) {
            $data = $this->get_remote_wc_data($current_store, $route);
            $result[$key] = (is_array($data) && !isset($data['code'])) ? $data : [];
        }

        return new WP_REST_Response($result, 200);
    }

    public function get_remote_wc_data($store, $route, $params = [])
    {
        if ($this->is_store_local($store)) {
            // Internal REST request
            $request = new WP_REST_Request('GET', '/' . ltrim($route, '/'));
            $request->set_query_params($params);
            $response = rest_do_request($request);
            if ($response->is_error()) {
                return [];
            }
            return json_decode(json_encode($response->get_data()), true);
        }

        $url = $this->build_remote_url($store, $route, $params);
        $args = $this->get_remote_args('GET', null, $store);

        $response = wp_remote_get($url, $args);

        if (is_wp_error($response)) {
            error_log("ShopCentral Debug: Remote GET Failed [$route]: " . $response->get_error_message());
            return [];
        }


        $code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);


        $data = json_decode($body, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            error_log("ShopCentral Debug: JSON Decode Error: " . json_last_error_msg());
            return [];
        }

        return is_array($data) ? $data : [];
    }

    private function is_sequential_array($arr)
    {
        if (!is_array($arr)) return false;
        if (empty($arr)) return true;
        return array_keys($arr) === range(0, count($arr) - 1);
    }

    /**
     * Filter WC meta_data array by whitelist.
     *
     * @param array $meta_data Array of ['key' => ..., 'value' => ...] objects/arrays.
     * @param int   $product_id Source product ID (for filter context).
     * @return array Filtered meta_data.
     */
    private function filter_allowed_meta($meta_data, $product_id = 0)
    {
        $allowed_keys = apply_filters('shopcentral_allowed_product_meta', [], $product_id);

        if (empty($allowed_keys) || !is_array($allowed_keys)) {
            return [];
        }

        $allowed_map = array_fill_keys(array_map('strtolower', $allowed_keys), true);

        $filtered = [];
        foreach ($meta_data as $meta) {
            $is_obj = is_object($meta);
            $key    = $is_obj ? ($meta->key ?? '') : ($meta['key'] ?? '');
            $value  = $is_obj ? ($meta->value ?? '') : ($meta['value'] ?? '');

            if (empty($key)) continue;
            if (!isset($allowed_map[strtolower($key)])) continue;

            $filtered[] = [
                'key'   => $key,
                'value' => $value,
            ];
        }

        return $filtered;
    }
}
