<?php
/**
 * BigCommerce Connector - Real-time import from BigCommerce.
 *
 * @package PrimeLink
 */

namespace PrimeLink\Modules\Imports\Connectors;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

final class BigCommerceConnector implements PlatformConnectorInterface {

    /**
     * Get connector name.
     *
     * @return string
     */
    public function get_name() {
        return 'bigcommerce';
    }

    /**
     * Get connector display name.
     *
     * @return string
     */
    public function get_display_name() {
        return 'BigCommerce';
    }

    /**
     * Get required credentials fields.
     *
     * @return array
     */
    public function get_credentials_fields() {
        return array(
            'store_hash' => array(
                'label'       => 'Store Hash',
                'type'        => 'text',
                'placeholder' => 'abc123',
                'required'    => false,
                'description' => 'Your BigCommerce store hash. Find it in: 1) Your store URL (store-{hash}.mybigcommerce.com), 2) API Accounts section in BigCommerce Admin, or 3) API path: stores/{hash}/v3/... If you have Account UUID, leave this empty.',
            ),
            'account_uuid' => array(
                'label'       => 'Account UUID',
                'type'        => 'text',
                'placeholder' => '3127fbd8-767b-472b-b551-3ed4478dca55',
                'required'    => false,
                'description' => 'Your BigCommerce account UUID (alternative to Store Hash). Provide either Store Hash or Account UUID.',
            ),
            'access_token' => array(
                'label'       => 'Access Token',
                'type'        => 'password',
                'placeholder' => 'Your BigCommerce access token',
                'required'    => true,
                'description' => 'Store-level API access token. Create it in BigCommerce Admin → Settings → Store-level API Accounts. Ensure it has the required OAuth scopes (e.g., Orders, Products) enabled for the resources you want to import.',
            ),
            'client_id' => array(
                'label'       => 'Client ID',
                'type'        => 'text',
                'placeholder' => 'Your BigCommerce client ID',
                'required'    => false,
                'description' => 'Optional: Client ID for OAuth (if using OAuth flow)',
            ),
            'client_secret' => array(
                'label'       => 'Client Secret',
                'type'        => 'password',
                'placeholder' => 'Your BigCommerce client secret',
                'required'    => false,
                'description' => 'Optional: Client Secret for OAuth (if using OAuth flow)',
            ),
        );
    }

    /**
     * Build API URL.
     *
     * @param string $store_hash Store hash.
     * @param string $endpoint   API endpoint.
     * @return string
     */
    private function build_api_url( $store_hash, $endpoint ) {
        $store_hash = trim( $store_hash );
        // Remove leading slash from endpoint if present
        $endpoint = ltrim( $endpoint, '/' );
        return 'https://api.bigcommerce.com/stores/' . $store_hash . '/v3/' . $endpoint;
    }

    /**
     * Build API URL for v2 endpoints (used for resources not available in v3, e.g. coupons).
     *
     * @param string $store_hash Store hash.
     * @param string $endpoint   API endpoint.
     * @return string
     */
    private function build_api_url_v2( $store_hash, $endpoint ) {
        $store_hash = trim( $store_hash );
        $endpoint   = ltrim( $endpoint, '/' );
        return 'https://api.bigcommerce.com/stores/' . $store_hash . '/v2/' . $endpoint;
    }

    /**
     * Extract store hash from URL for debugging.
     *
     * @param string $url API URL.
     * @return string Store hash or 'N/A'.
     */
    private function extract_store_hash_from_url( $url ) {
        if ( preg_match( '/stores\/([^\/]+)\/v3/', $url, $matches ) ) {
            return $matches[1];
        }
        return 'N/A';
    }

    /**
     * Make API request.
     *
     * @param string $url          API URL.
     * @param string $access_token Access token.
     * @param string $method       HTTP method.
     * @param array  $data         Request data.
     * @return array
     */
    private function api_request( $url, $access_token, $method = 'GET', $data = array() ) {
        // Ensure access token is not empty and properly trimmed
        $access_token = trim( $access_token );
        
        if ( empty( $access_token ) ) {
            return array(
                'success' => false,
                'error'   => 'Access token is empty or invalid.',
                'code'    => 401,
            );
        }
        
        $args = array(
            'headers' => array(
                'X-Auth-Token' => $access_token,
                'Content-Type' => 'application/json',
                'Accept'       => 'application/json',
                // Some BigCommerce endpoints may require specific Accept headers
                'Accept-Encoding' => 'gzip, deflate',
            ),
            'timeout'     => 30,
            'retry'       => 2, // Retry up to 2 times on failure
            'retry_delay' => 1, // 1 second delay between retries
        );

        if ( ! empty( $data ) && in_array( $method, array( 'POST', 'PUT', 'PATCH' ), true ) ) {
            $args['body'] = $data; // HttpHelper will handle JSON encoding
        }

        // Log request details for debugging (especially for orders)
        if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
            $is_orders_request = strpos( $url, '/orders' ) !== false;
            if ( $is_orders_request ) {
                \PrimeLink\Helpers\LoggerHelper::debug(
                    'BigCommerce Orders API Request Details',
                    array(
                        'url'           => $url,
                        'method'        => $method,
                        'has_token'     => ! empty( $access_token ),
                        'token_length'  => strlen( $access_token ),
                        'token_preview' => substr( $access_token, 0, 10 ) . '...' . substr( $access_token, -5 ),
                        'headers'       => $args['headers'],
                    )
                );
            }
        }

        $response = \PrimeLink\Helpers\HttpHelper::request( $url, $method, $args );

        if ( ! $response['success'] ) {
            // Include HTTP code in error response for better debugging
            $error_message = $response['error'] ?? 'API request failed';
            $http_code = isset( $response['code'] ) ? $response['code'] : 0;
            
            // Provide specific error messages for 403 Forbidden
            if ( $http_code === 403 ) {
                // Detect which resource is being accessed from the URL
                $resource_name = 'this resource';
                if ( strpos( $url, '/orders' ) !== false ) {
                    $resource_name = 'Orders';
                } elseif ( strpos( $url, '/products' ) !== false || strpos( $url, '/catalog/products' ) !== false ) {
                    $resource_name = 'Products';
                } elseif ( strpos( $url, '/customers' ) !== false ) {
                    $resource_name = 'Customers';
                }
                
                // Extract store hash from URL for better context
                $store_hash = $this->extract_store_hash_from_url( $url );
                
                $error_message = sprintf(
                    'Authentication failed (403 Forbidden): Your BigCommerce Store-level API token does not have "%s" read permissions enabled. ' .
                    'This is a Store-level API account issue. ' .
                    'To fix this: ' .
                    '1. Go to BigCommerce Admin → Settings → Store-level API Accounts ' .
                    '2. Find your API account (Store Hash: %s) ' .
                    '3. Click "Edit" on the API account ' .
                    '4. Under "OAuth Scopes", ensure "%s" is set to "Read" or "Modify" (not "None") ' .
                    '5. Save the changes ' .
                    'Note: Store-level API accounts require separate permissions for each resource. ' .
                    'Even if your token works for Products, it may not have Orders permissions unless explicitly enabled.',
                    $resource_name,
                    $store_hash !== 'N/A' ? $store_hash : 'your store',
                    $resource_name
                );
            }
            
            $error_response = array(
                'success' => false,
                'error'   => $error_message,
            );
            
            // Include HTTP code if available
            if ( $http_code ) {
                $error_response['code'] = $http_code;
            }
            
            // Include response body if available for debugging
            if ( isset( $response['body'] ) && defined( 'WP_DEBUG' ) && WP_DEBUG ) {
                $error_response['debug_body'] = substr( $response['body'], 0, 500 );
            }
            
            return $error_response;
        }

        $body = $response['body'];
        $code = $response['code'];
        $headers = $response['headers'];
        $decoded_data = json_decode( $body, true );
        
        // Log for debugging (only in development)
        if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
            \PrimeLink\Helpers\LoggerHelper::debug(
                'BigCommerce API Request',
                array(
                    'url'      => $url,
                    'method'   => $method,
                    'code'     => $code,
                    'response' => substr( $body, 0, 500 ),
                )
            );
        }

        if ( $code >= 200 && $code < 300 ) {
            return array(
                'success' => true,
                'data'    => $decoded_data,
            );
        }

        $error_message = 'API request failed';
        
        // Handle 403 Forbidden - usually means token doesn't have required permissions
        if ( $code === 403 ) {
            // Detect resource type from URL to provide specific guidance
            $resource_type = 'this resource';
            if ( strpos( $url, '/orders' ) !== false ) {
                $resource_type = 'orders';
            } elseif ( strpos( $url, '/products' ) !== false || strpos( $url, '/catalog/products' ) !== false ) {
                $resource_type = 'products';
            } elseif ( strpos( $url, '/customers' ) !== false ) {
                $resource_type = 'customers';
            }
            
            $error_message = 'Access denied (403 Forbidden). Your API token may not have the required permissions for ' . $resource_type . '. ';
            $error_message .= 'Please check your BigCommerce API token permissions in BigCommerce Admin → Advanced Settings → API Accounts. ';
            
            if ( $resource_type === 'orders' ) {
                $error_message .= 'For orders, you need "Orders" read permissions. ';
                $error_message .= 'Even if you have "Orders" permissions set to "full", please verify: ';
                $error_message .= '1) The API token is associated with the correct store (Store Hash: ' . ( isset( $url ) ? $this->extract_store_hash_from_url( $url ) : 'N/A' ) . '), ';
                $error_message .= '2) The token type is correct (API Token, not OAuth token), ';
                $error_message .= '3) The token has not expired, ';
                $error_message .= '4) Try creating a new API token with Orders permissions if the issue persists.';
            } elseif ( $resource_type === 'products' ) {
                $error_message .= 'For products, you need "Products" read permissions. Make sure your API token has the "Products" scope enabled.';
            } elseif ( $resource_type === 'customers' ) {
                $error_message .= 'For customers, you need "Customers" read permissions. Make sure your API token has the "Customers" scope enabled.';
            } else {
                $error_message .= 'Make sure your API token has the required read permissions for this resource.';
            }
            
            if ( isset( $decoded_data['title'] ) ) {
                $error_message .= ' Error: ' . $decoded_data['title'];
            }
            if ( isset( $decoded_data['message'] ) ) {
                $error_message .= ' ' . $decoded_data['message'];
            }
        } elseif ( isset( $decoded_data['errors'] ) && is_array( $decoded_data['errors'] ) ) {
            $error_messages = array();
            foreach ( $decoded_data['errors'] as $error ) {
                if ( isset( $error['message'] ) ) {
                    $error_messages[] = $error['message'];
                }
            }
            if ( ! empty( $error_messages ) ) {
                $error_message = implode( ', ', $error_messages );
            }
        } elseif ( isset( $decoded_data['title'] ) ) {
            $error_message = $decoded_data['title'];
        }

        // Add specific guidance for common error codes (only if not already handled above)
        if ( $code === 401 ) {
            $error_message .= ' (Unauthorized). Please verify that your Access Token is correct and has not expired.';
        } elseif ( $code === 404 ) {
            $error_message .= ' (Not Found). The API endpoint was not found. Please verify your Store Hash is correct.';
        }

        return array(
            'success' => false,
            'error'   => $error_message,
            'code'    => $code,
            'response_body' => $body, // Include response body for debugging
        );
    }

    /**
     * Get store hash from account UUID.
     *
     * @param string $account_uuid Account UUID.
     * @param string $access_token Access token.
     * @return string|false Store hash on success, false on failure.
     */
    private function get_store_hash_from_uuid( $account_uuid, $access_token ) {
        // BigCommerce v3 API doesn't directly support getting store hash from account UUID
        // We need to try different approaches:
        
        // Method 1: Try to get store info using account UUID in v2 API (if available)
        $url = 'https://api.bigcommerce.com/stores';
        $args = array(
            'headers' => array(
                'X-Auth-Token' => $access_token,
                'Content-Type' => 'application/json',
                'Accept'       => 'application/json',
            ),
            'timeout'     => 30,
            'retry'       => 1,
            'retry_delay' => 1,
        );

        $response = \PrimeLink\Helpers\HttpHelper::request( $url, 'GET', $args );

        if ( $response['success'] ) {
            $body = $response['body'];
            $code = $response['code'];
            $data = json_decode( $body, true );

            if ( $code >= 200 && $code < 300 ) {
                // If data is an array of stores, search for matching account UUID
                if ( is_array( $data ) ) {
                    foreach ( $data as $store ) {
                        if ( isset( $store['account_uuid'] ) && $store['account_uuid'] === $account_uuid ) {
                            return $store['store_hash'] ?? false;
                        }
                    }
                }
                // If data is a single store object
                if ( is_array( $data ) && isset( $data['store_hash'] ) ) {
                    if ( isset( $data['account_uuid'] ) && $data['account_uuid'] === $account_uuid ) {
                        return $data['store_hash'];
                    }
                }
            }
        }

        // Method 2: Try common store hash patterns (if account UUID contains store hash)
        // Some account UUIDs might have store hash embedded
        // This is a fallback - not reliable but might work in some cases
        
        // Method 3: Try to extract from access token metadata (if available)
        // This would require parsing the token, which is not standard
        
        return false;
    }

    /**
     * Resolve store hash from credentials.
     *
     * @param array $credentials Connection credentials.
     * @return string|false Store hash on success, false on failure.
     */
    private function resolve_store_hash( $credentials ) {
        $store_hash   = trim( $credentials['store_hash'] ?? '' );
        $account_uuid = trim( $credentials['account_uuid'] ?? '' );
        $access_token = $credentials['access_token'] ?? '';

        // If store hash is provided, use it
        if ( ! empty( $store_hash ) ) {
            return $store_hash;
        }

        // If account UUID is provided, try to get store hash
        if ( ! empty( $account_uuid ) && ! empty( $access_token ) ) {
            $resolved_hash = $this->get_store_hash_from_uuid( $account_uuid, $access_token );
            if ( $resolved_hash ) {
                return $resolved_hash;
            }
        }

        return false;
    }

    /**
     * Test connection with platform.
     *
     * @param array $credentials Connection credentials.
     * @return array
     */
    public function test_connection( $credentials ) {
        $access_token = $credentials['access_token'] ?? '';

        if ( empty( $access_token ) ) {
            return array(
                'success' => false,
                'message' => 'Missing required credentials: Access Token is required.',
            );
        }

        // Resolve store hash
        $store_hash = $this->resolve_store_hash( $credentials );

        if ( ! $store_hash ) {
            $has_account_uuid = ! empty( $credentials['account_uuid'] ?? '' );
            $has_store_hash = ! empty( $credentials['store_hash'] ?? '' );
            
            if ( $has_account_uuid && ! $has_store_hash ) {
                return array(
                    'success' => false,
                    'message' => 'Could not resolve Store Hash from Account UUID. Please provide Store Hash directly. You can find it in BigCommerce Admin → Advanced Settings → API Accounts, or in your store URL (store-{hash}.mybigcommerce.com).',
                );
            }
            
            return array(
                'success' => false,
                'message' => 'Missing required credentials: Please provide either Store Hash or Account UUID. Store Hash can be found in BigCommerce Admin → Advanced Settings → API Accounts.',
            );
        }

        // Test with a valid endpoint - try multiple endpoints to find one that works
        // First try: catalog/products (most common)
        $url = $this->build_api_url( $store_hash, 'catalog/products?limit=1' );
        $result = $this->api_request( $url, $access_token );

        // If products endpoint fails, try store information endpoint
        if ( ! $result['success'] && isset( $result['code'] ) && $result['code'] === 403 ) {
            // Try a different endpoint - time endpoint (if available)
            $url2 = $this->build_api_url( $store_hash, 'time' );
            $result2 = $this->api_request( $url2, $access_token );
            
            // If time endpoint works, use that result
            if ( $result2['success'] ) {
                $result = $result2;
            }
        }

        if ( $result['success'] ) {
            // Connection is successful - we got a response (even if empty)
            return array(
                'success' => true,
                'message' => 'Connection successful!',
                'data'    => array(
                    'store_hash' => $store_hash,
                    'products_count' => isset( $result['data']['data'] ) ? count( $result['data']['data'] ) : 0,
                ),
            );
        }

        // Provide more detailed error message
        $error_message = $result['error'] ?? 'Connection failed.';
        if ( isset( $result['code'] ) ) {
            $error_message .= ' (HTTP ' . $result['code'] . ')';
        }

        return array(
            'success' => false,
            'message' => $error_message,
            'debug'   => array(
                'store_hash'   => $store_hash,
                'url'          => $url,
                'response_code' => $result['code'] ?? 'N/A',
            ),
        );
    }

    /**
     * Fetch products from platform.
     *
     * @param array $credentials Connection credentials.
     * @param array $options     Fetch options.
     * @return array
     */
    public function fetch_products( $credentials, $options = array() ) {
        $access_token = $credentials['access_token'] ?? '';
        $limit        = isset( $options['limit'] ) ? absint( $options['limit'] ) : 250;
        $page         = isset( $options['page'] ) ? absint( $options['page'] ) : 1;

        if ( empty( $access_token ) ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials: Access Token is required.',
            );
        }

        $store_hash = $this->resolve_store_hash( $credentials );
        if ( ! $store_hash ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials: Please provide either Store Hash or Account UUID.',
            );
        }

        $endpoint = 'catalog/products?limit=' . $limit . '&page=' . $page;
        $url = $this->build_api_url( $store_hash, $endpoint );
        $result = $this->api_request( $url, $access_token );

        if ( ! $result['success'] ) {
            return $result;
        }

        $products = $result['data']['data'] ?? array();
        $meta = $result['data']['meta'] ?? array();
        $pagination = $meta['pagination'] ?? array();
        $total = isset( $pagination['total'] ) ? absint( $pagination['total'] ) : count( $products );
        $has_more = isset( $pagination['current_page'] ) && isset( $pagination['total_pages'] ) 
            ? absint( $pagination['current_page'] ) < absint( $pagination['total_pages'] )
            : count( $products ) >= $limit;

        return array(
            'success'  => true,
            'data'    => $products,
            'total'   => $total,
            'has_more' => $has_more,
        );
    }

    /**
     * Fetch orders from platform.
     *
     * @param array $credentials Connection credentials.
     * @param array $options     Fetch options.
     * @return array
     */
    public function fetch_orders( $credentials, $options = array() ) {
        // Get access token and ensure it's not empty
        $access_token = isset( $credentials['access_token'] ) ? trim( $credentials['access_token'] ) : '';
        $limit        = isset( $options['limit'] ) ? absint( $options['limit'] ) : 250;
        $page         = isset( $options['page'] ) ? absint( $options['page'] ) : 1;
        $status_id    = isset( $options['status_id'] ) ? absint( $options['status_id'] ) : 0;

        if ( empty( $access_token ) ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials: Access Token is required. Please check that the token is saved correctly.',
                'debug'   => array(
                    'has_credentials' => ! empty( $credentials ),
                    'credentials_keys' => array_keys( $credentials ?? array() ),
                ),
            );
        }

        $store_hash = $this->resolve_store_hash( $credentials );
        if ( ! $store_hash ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials: Please provide either Store Hash or Account UUID.',
            );
        }
        
        // Verify token is not just whitespace
        if ( strlen( $access_token ) < 10 ) {
            return array(
                'success' => false,
                'error'   => 'Invalid access token: Token appears to be too short or invalid. Please verify your API token in BigCommerce Admin.',
            );
        }

        $endpoint = 'orders?limit=' . $limit . '&page=' . $page;
        if ( $status_id > 0 ) {
            $endpoint .= '&status_id=' . $status_id;
        }

        $url = $this->build_api_url( $store_hash, $endpoint );
        
        // Log request details for debugging
        if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
            \PrimeLink\Helpers\LoggerHelper::debug(
                'BigCommerce Orders API Request',
                array(
                    'url'         => $url,
                    'store_hash'  => $store_hash,
                    'endpoint'    => $endpoint,
                    'has_token'   => ! empty( $access_token ),
                    'token_length' => strlen( $access_token ),
                    'token_preview' => substr( $access_token, 0, 10 ) . '...' . substr( $access_token, -5 ),
                )
            );
        }
        
        $result = $this->api_request( $url, $access_token );
        
        // If we get 403, try to get more details from the response
        if ( ! $result['success'] && isset( $result['code'] ) && $result['code'] === 403 ) {
            // Log the full response for debugging
            if ( defined( 'WP_DEBUG' ) && WP_DEBUG && isset( $result['response_body'] ) ) {
                \PrimeLink\Helpers\LoggerHelper::debug(
                    'BigCommerce Orders 403 Response Details',
                    array(
                        'url'           => $url,
                        'response_body' => $result['response_body'],
                        'error'        => $result['error'] ?? 'Unknown error',
                    )
                );
            }
            
            // Check if response body contains more specific error information
            if ( isset( $result['response_body'] ) ) {
                $response_data = json_decode( $result['response_body'], true );
                if ( $response_data && isset( $response_data['title'] ) ) {
                    $result['error'] = $result['error'] . ' Server response: ' . $response_data['title'];
                    if ( isset( $response_data['message'] ) ) {
                        $result['error'] .= ' - ' . $response_data['message'];
                    }
                }
            }
        }

        if ( ! $result['success'] ) {
            // Add more context to error for orders
            if ( isset( $result['code'] ) && $result['code'] === 403 ) {
                $result['error'] = ( $result['error'] ?? 'Access denied' ) . ' For orders API, ensure your token has "Orders" scope enabled and is associated with the correct store. Store Hash: ' . $store_hash;
            }
            return $result;
        }

        $orders = $result['data']['data'] ?? array();
        $meta = $result['data']['meta'] ?? array();
        $pagination = $meta['pagination'] ?? array();
        $total = isset( $pagination['total'] ) ? absint( $pagination['total'] ) : count( $orders );
        $has_more = isset( $pagination['current_page'] ) && isset( $pagination['total_pages'] ) 
            ? absint( $pagination['current_page'] ) < absint( $pagination['total_pages'] )
            : count( $orders ) >= $limit;

        return array(
            'success'  => true,
            'data'    => $orders,
            'total'   => $total,
            'has_more' => $has_more,
        );
    }

    /**
     * Fetch customers from platform.
     *
     * @param array $credentials Connection credentials.
     * @param array $options     Fetch options.
     * @return array
     */
    public function fetch_customers( $credentials, $options = array() ) {
        $access_token = $credentials['access_token'] ?? '';
        $limit        = isset( $options['limit'] ) ? absint( $options['limit'] ) : 250;
        $page         = isset( $options['page'] ) ? absint( $options['page'] ) : 1;

        if ( empty( $access_token ) ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials: Access Token is required.',
            );
        }

        $store_hash = $this->resolve_store_hash( $credentials );
        if ( ! $store_hash ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials: Please provide either Store Hash or Account UUID.',
            );
        }

        $endpoint = 'customers?limit=' . $limit . '&page=' . $page;
        $url = $this->build_api_url( $store_hash, $endpoint );
        $result = $this->api_request( $url, $access_token );

        if ( ! $result['success'] ) {
            return $result;
        }

        $customers = $result['data']['data'] ?? array();
        $meta = $result['data']['meta'] ?? array();
        $pagination = $meta['pagination'] ?? array();
        $total = isset( $pagination['total'] ) ? absint( $pagination['total'] ) : count( $customers );
        $has_more = isset( $pagination['current_page'] ) && isset( $pagination['total_pages'] ) 
            ? absint( $pagination['current_page'] ) < absint( $pagination['total_pages'] )
            : count( $customers ) >= $limit;

        return array(
            'success'  => true,
            'data'    => $customers,
            'total'   => $total,
            'has_more' => $has_more,
        );
    }

    /**
     * Fetch coupons from platform.
     *
     * @param array $credentials Connection credentials.
     * @param array $options     Fetch options.
     * @return array
     */
    public function fetch_coupons( $credentials, $options = array() ) {
        $access_token = $credentials['access_token'] ?? '';
        $limit        = isset( $options['limit'] ) ? absint( $options['limit'] ) : 250;
        $page         = isset( $options['page'] ) ? absint( $options['page'] ) : 1;

        if ( empty( $access_token ) ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials: Access Token is required.',
            );
        }

        $store_hash = $this->resolve_store_hash( $credentials );
        if ( ! $store_hash ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials: Please provide either Store Hash or Account UUID.',
            );
        }

        // Coupons are only available in the v2 API, not v3.
        $endpoint = 'coupons?limit=' . $limit . '&page=' . $page;
        $url      = $this->build_api_url_v2( $store_hash, $endpoint );
        $result   = $this->api_request( $url, $access_token );

        if ( ! $result['success'] ) {
            return $result;
        }

        // v2 coupons endpoint returns an array of coupons directly, without "data"/"meta" wrapper.
        $decoded = $result['data'] ?? array();
        if ( isset( $decoded['data'] ) && is_array( $decoded['data'] ) ) {
            // Just in case the response is wrapped
            $coupons = $decoded['data'];
        } elseif ( is_array( $decoded ) ) {
            $coupons = $decoded;
        } else {
            $coupons = array();
        }

        $total    = count( $coupons );
        // We don't have reliable pagination info from v2 body; use a simple heuristic
        $has_more = $total >= $limit;

        return array(
            'success'  => true,
            'data'     => $coupons,
            'total'    => $total,
            'has_more' => $has_more,
        );
    }

    /**
     * Convert BigCommerce entity to WooCommerce-like format used by the importer.
     *
     * @param array  $bc_data BigCommerce data (product, order, customer, coupon).
     * @param string $type    Data type: product|order|customer|coupon (singular or plural).
     * @return array
     */
    public function convert_to_woocommerce( $bc_data, $type = 'product' ) {
        // Normalize type (accept both singular and plural)
        $type = strtolower( $type );
        if ( in_array( $type, array( 'products', 'orders', 'customers', 'coupons' ), true ) ) {
            $type = rtrim( $type, 's' );
        }

        if ( $type === 'product' ) {
            $product = array(
                'post' => array(
                    'post_title'   => $bc_data['name'] ?? '',
                    'post_content' => $bc_data['description'] ?? '',
                    'post_excerpt' => $bc_data['meta_description'] ?? '',
                    'post_status'  => ( $bc_data['is_visible'] ?? false ) ? 'publish' : 'draft',
                ),
                'product' => array(
                    'sku'            => $bc_data['sku'] ?? '',
                    'regular_price'  => $this->get_price( $bc_data ),
                    'stock'          => $bc_data['inventory_level'] ?? 0,
                    'stock_status'   => $this->get_stock_status( $bc_data ),
                    'weight'         => $bc_data['weight'] ?? '',
                    'product_type'   => $bc_data['type'] ?? 'simple',
                ),
                'images' => array(
                    'images' => $this->extract_images( $bc_data ),
                ),
                'tax' => array(
                    'product_cat' => $this->extract_categories( $bc_data ),
                    'product_tag' => $this->extract_tags( $bc_data ),
                ),
                'attrs' => $this->extract_attributes( $bc_data ),
            );

            return $product;
        }

        if ( $type === 'order' ) {
            // Basic order mapping for preview & auto-mapping
            $billing  = $bc_data['billing_address'] ?? array();
            $shipping = $bc_data['shipping_addresses'][0] ?? array();

            $order = array(
                'order' => array(
                    'order_id'    => $bc_data['id'] ?? '',
                    'order_key'   => $bc_data['id'] ?? '',
                    'order_date'  => $bc_data['date_created'] ?? '',
                    'order_total' => $bc_data['total_inc_tax'] ?? ( $bc_data['total_ex_tax'] ?? '' ),
                    'currency'    => $bc_data['currency_code'] ?? '',
                    'status'      => $bc_data['status'] ?? '',
                    'created_via' => 'bigcommerce',
                ),
                'customer' => array(
                    'customer_id'         => $bc_data['customer_id'] ?? 0,
                    'customer_email'      => $billing['email'] ?? '',
                    'customer_name'       => trim( ( $billing['first_name'] ?? '' ) . ' ' . ( $billing['last_name'] ?? '' ) ),
                    'customer_phone'      => $billing['phone'] ?? '',
                    'customer_ip_address' => $bc_data['ip_address'] ?? '',
                ),
            );

            // Include billing fields inside order bucket so they become columns like order_billing_first_name
            $order['order']['billing_first_name'] = $billing['first_name'] ?? '';
            $order['order']['billing_last_name']  = $billing['last_name'] ?? '';
            $order['order']['billing_company']    = $billing['company'] ?? '';
            $order['order']['billing_address_1']  = $billing['street_1'] ?? '';
            $order['order']['billing_address_2']  = $billing['street_2'] ?? '';
            $order['order']['billing_city']       = $billing['city'] ?? '';
            $order['order']['billing_state']      = $billing['state'] ?? '';
            $order['order']['billing_postcode']   = $billing['zip'] ?? '';
            $order['order']['billing_country']    = $billing['country_iso2'] ?? '';
            $order['order']['billing_email']      = $billing['email'] ?? '';
            $order['order']['billing_phone']      = $billing['phone'] ?? '';

            // Shipping (first address)
            $order['order']['shipping_first_name'] = $shipping['first_name'] ?? '';
            $order['order']['shipping_last_name']  = $shipping['last_name'] ?? '';
            $order['order']['shipping_company']    = $shipping['company'] ?? '';
            $order['order']['shipping_address_1']  = $shipping['street_1'] ?? '';
            $order['order']['shipping_address_2']  = $shipping['street_2'] ?? '';
            $order['order']['shipping_city']       = $shipping['city'] ?? '';
            $order['order']['shipping_state']      = $shipping['state'] ?? '';
            $order['order']['shipping_postcode']   = $shipping['zip'] ?? '';
            $order['order']['shipping_country']    = $shipping['country_iso2'] ?? '';

            return $order;
        }

        if ( $type === 'customer' ) {
            // Map BigCommerce customer to WooCommerce-style customer structure
            $customer = array(
                'customer' => array(
                    'customer_id'    => $bc_data['id'] ?? 0,
                    'customer_email' => $bc_data['email'] ?? '',
                    'customer_name'  => trim( ( $bc_data['first_name'] ?? '' ) . ' ' . ( $bc_data['last_name'] ?? '' ) ),
                    'customer_phone' => $bc_data['phone'] ?? '',
                ),
                'post' => array(
                    'post_title'   => trim( ( $bc_data['first_name'] ?? '' ) . ' ' . ( $bc_data['last_name'] ?? '' ) ),
                    'post_status'  => 'publish',
                    'post_content' => '',
                    'post_excerpt' => '',
                ),
            );

            return $customer;
        }

        if ( $type === 'coupon' ) {
            // Map BigCommerce coupon to WooCommerce-style coupon structure
            $coupon = array(
                'coupon' => array(
                    'code'        => $bc_data['code'] ?? '',
                    'amount'      => isset( $bc_data['amount'] ) ? (string) $bc_data['amount'] : '',
                    'discount_type' => $bc_data['type'] ?? '', // percent/absolute
                    'description' => $bc_data['name'] ?? '',
                    'date_expires'=> $bc_data['expires'] ?? '',
                    'usage_limit' => $bc_data['max_uses'] ?? '',
                    'usage_limit_per_user' => $bc_data['max_uses_per_customer'] ?? '',
                    'minimum_amount' => $bc_data['min_purchase'] ?? '',
                    'id'          => $bc_data['id'] ?? '',
                ),
            );

            return $coupon;
        }

        // Unsupported type for now
        return array();
    }

    /**
     * Get product price.
     *
     * @param array $bc_product BigCommerce product.
     * @return string
     */
    private function get_price( $bc_product ) {
        $price = $bc_product['price'] ?? '';
        // BigCommerce returns price as string, may need formatting
        return $price;
    }

    /**
     * Get stock status.
     *
     * @param array $bc_product BigCommerce product.
     * @return string
     */
    private function get_stock_status( $bc_product ) {
        $inventory_level = isset( $bc_product['inventory_level'] ) ? absint( $bc_product['inventory_level'] ) : 0;
        $inventory_tracking = $bc_product['inventory_tracking'] ?? 'none';
        
        if ( $inventory_tracking === 'none' ) {
            return 'instock';
        }
        
        return $inventory_level > 0 ? 'instock' : 'outofstock';
    }

    /**
     * Extract images from BigCommerce product.
     *
     * @param array $bc_product BigCommerce product.
     * @return array
     */
    private function extract_images( $bc_product ) {
        $images = array();
        
        // Primary image
        if ( ! empty( $bc_product['primary_image']['url_standard'] ) ) {
            $images[] = $bc_product['primary_image']['url_standard'];
        }
        
        // Additional images
        $custom_fields = $bc_product['custom_fields'] ?? array();
        foreach ( $custom_fields as $field ) {
            if ( isset( $field['name'] ) && strpos( strtolower( $field['name'] ), 'image' ) !== false ) {
                if ( ! empty( $field['value'] ) ) {
                    $images[] = $field['value'];
                }
            }
        }
        
        // Images from images array (if available)
        $product_images = $bc_product['images'] ?? array();
        foreach ( $product_images as $img ) {
            if ( ! empty( $img['url_standard'] ) ) {
                $images[] = $img['url_standard'];
            }
        }
        
        return array_unique( $images );
    }

    /**
     * Extract categories from BigCommerce product.
     *
     * @param array $bc_product BigCommerce product.
     * @return array
     */
    private function extract_categories( $bc_product ) {
        $categories = array();
        $category_ids = $bc_product['categories'] ?? array();
        
        // In a full implementation, you'd fetch category names by IDs
        // For now, return empty array as category names aren't in product data
        return $categories;
    }

    /**
     * Extract tags from BigCommerce product.
     *
     * @param array $bc_product BigCommerce product.
     * @return array
     */
    private function extract_tags( $bc_product ) {
        $tags = array();
        $custom_fields = $bc_product['custom_fields'] ?? array();
        
        foreach ( $custom_fields as $field ) {
            if ( isset( $field['name'] ) && strtolower( $field['name'] ) === 'tags' ) {
                if ( ! empty( $field['value'] ) ) {
                    $tags = array_map( 'trim', explode( ',', $field['value'] ) );
                }
            }
        }
        
        return $tags;
    }

    /**
     * Extract attributes from BigCommerce product.
     *
     * @param array $bc_product BigCommerce product.
     * @return array
     */
    private function extract_attributes( $bc_product ) {
        $attrs = array();
        
        // BigCommerce custom fields can be used as attributes
        $custom_fields = $bc_product['custom_fields'] ?? array();
        foreach ( $custom_fields as $field ) {
            $name = $field['name'] ?? '';
            if ( $name && strpos( strtolower( $name ), 'tag' ) === false ) {
                $value = $field['value'] ?? '';
                if ( $value ) {
                    $attrs[ $name ] = array(
                        'values'    => array( $value ),
                        'visible'   => true,
                        'variation' => false,
                    );
                }
            }
        }
        
        return $attrs;
    }

    /**
     * Register webhook for real-time sync.
     *
     * @param array  $credentials Connection credentials.
     * @param string $event      Event type.
     * @param string $webhook_url Webhook URL.
     * @return array
     */
    public function register_webhook( $credentials, $event, $webhook_url ) {
        $access_token = $credentials['access_token'] ?? '';

        if ( empty( $access_token ) ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials: Access Token is required.',
            );
        }

        $store_hash = $this->resolve_store_hash( $credentials );
        if ( ! $store_hash ) {
            return array(
                'success' => false,
                'error'   => 'Missing required credentials: Please provide either Store Hash or Account UUID.',
            );
        }

        // Map event names to BigCommerce webhook scopes
        $event_map = array(
            'created' => 'store/product/created',
            'updated' => 'store/product/updated',
            'deleted' => 'store/product/deleted',
        );
        
        $scope = $event_map[ $event ] ?? 'store/product/' . $event;

        $url = $this->build_api_url( $store_hash, 'hooks' );
        $data = array(
            'scope' => $scope,
            'destination' => $webhook_url,
            'is_active' => true,
        );

        $result = $this->api_request( $url, $access_token, 'POST', $data );

        if ( $result['success'] ) {
            $webhook = $result['data']['data'] ?? array();
            return array(
                'success'    => true,
                'webhook_id' => $webhook['id'] ?? '',
            );
        }

        return array(
            'success' => false,
            'error'   => $result['error'] ?? 'Failed to register webhook.',
        );
    }

    /**
     * Unregister webhook.
     *
     * @param array  $credentials Connection credentials.
     * @param string $webhook_id  Webhook ID.
     * @return bool
     */
    public function unregister_webhook( $credentials, $webhook_id ) {
        $access_token = $credentials['access_token'] ?? '';

        if ( empty( $access_token ) || empty( $webhook_id ) ) {
            return false;
        }

        $store_hash = $this->resolve_store_hash( $credentials );
        if ( ! $store_hash ) {
            return false;
        }

        $url = $this->build_api_url( $store_hash, 'hooks/' . absint( $webhook_id ) );
        $result = $this->api_request( $url, $access_token, 'DELETE' );

        return $result['success'];
    }
}


