/**
 * WC Licensed Product API Client for JavaScript
 *
 * A JavaScript client for interacting with the WC Licensed Product REST API.
 * Works in both browser and Node.js environments.
 *
 * Browser usage:
 *   <script src="javascript-client.js"></script>
 *   const client = new WcLicensedProductClient('https://your-site.com');
 *   const result = await client.validate('XXXX-XXXX-XXXX-XXXX', 'example.com');
 *
 * Node.js usage:
 *   const WcLicensedProductClient = require('./javascript-client');
 *   const client = new WcLicensedProductClient('https://your-site.com');
 */

class WcLicensedProductError extends Error {
    constructor(message, errorCode = null, httpCode = null) {
        super(message);
        this.name = 'WcLicensedProductError';
        this.errorCode = errorCode;
        this.httpCode = httpCode;
    }
}

class RateLimitError extends WcLicensedProductError {
    constructor(retryAfter) {
        super(`Rate limit exceeded. Retry after ${retryAfter} seconds.`);
        this.name = 'RateLimitError';
        this.retryAfter = retryAfter;
    }
}

class WcLicensedProductClient {
    /**
     * Initialize the client
     * @param {string} siteUrl - Your WordPress site URL (e.g., 'https://example.com')
     * @param {Object} options - Optional configuration
     * @param {number} options.timeout - Request timeout in milliseconds (default: 30000)
     */
    constructor(siteUrl, options = {}) {
        this.baseUrl = siteUrl.replace(/\/$/, '') + '/wp-json/wc-licensed-product/v1';
        this.timeout = options.timeout || 30000;
    }

    /**
     * Validate a license key for a specific domain
     * @param {string} licenseKey - The license key to validate
     * @param {string} domain - The domain to validate against
     * @returns {Promise<Object>} Response data with 'valid' boolean and license info
     */
    async validate(licenseKey, domain) {
        return this._request('/validate', {
            license_key: licenseKey,
            domain: domain,
        });
    }

    /**
     * Get the status of a license
     * @param {string} licenseKey - The license key to check
     * @returns {Promise<Object>} License status data
     */
    async status(licenseKey) {
        return this._request('/status', {
            license_key: licenseKey,
        });
    }

    /**
     * Activate a license on a domain
     * @param {string} licenseKey - The license key to activate
     * @param {string} domain - The domain to activate on
     * @returns {Promise<Object>} Response with 'success' boolean and message
     */
    async activate(licenseKey, domain) {
        return this._request('/activate', {
            license_key: licenseKey,
            domain: domain,
        });
    }

    /**
     * Make an API request
     * @private
     * @param {string} endpoint - API endpoint path
     * @param {Object} data - Request data
     * @returns {Promise<Object>} Decoded response data
     */
    async _request(endpoint, data) {
        const url = this.baseUrl + endpoint;

        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), this.timeout);

        try {
            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Accept': 'application/json',
                },
                body: JSON.stringify(data),
                signal: controller.signal,
            });

            clearTimeout(timeoutId);

            // Handle rate limiting
            if (response.status === 429) {
                const retryAfter = parseInt(response.headers.get('Retry-After') || '60', 10);
                throw new RateLimitError(retryAfter);
            }

            const result = await response.json();

            // Check for API errors
            if (response.status >= 400 && result.error) {
                throw new WcLicensedProductError(
                    result.message || 'Unknown error',
                    result.error,
                    response.status
                );
            }

            return result;
        } catch (error) {
            clearTimeout(timeoutId);

            if (error instanceof WcLicensedProductError) {
                throw error;
            }

            if (error.name === 'AbortError') {
                throw new WcLicensedProductError('Request timeout');
            }

            throw new WcLicensedProductError(`Request failed: ${error.message}`);
        }
    }
}

// =============================================================================
// Usage Examples
// =============================================================================

// Example usage (uncomment to run):

/*
(async () => {
    const client = new WcLicensedProductClient('https://your-wordpress-site.com');

    // Example 1: Validate a license
    console.log('=== Validate License ===');
    try {
        const result = await client.validate('XXXX-XXXX-XXXX-XXXX', 'myapp.example.com');

        if (result.valid) {
            console.log('License is valid!');
            console.log('Status:', result.license?.status || 'active');
            console.log('Expires:', result.license?.expires_at || 'Never');
        } else {
            console.log('License is not valid:', result.message || 'Unknown error');
        }
    } catch (error) {
        if (error instanceof RateLimitError) {
            console.log(`Rate limited. Retry after ${error.retryAfter} seconds.`);
        } else {
            console.log('Error:', error.message);
        }
    }

    console.log();

    // Example 2: Check license status
    console.log('=== Check License Status ===');
    try {
        const status = await client.status('XXXX-XXXX-XXXX-XXXX');

        console.log('Valid:', status.valid ? 'Yes' : 'No');
        console.log('Status:', status.status || 'unknown');
        console.log('Domain:', status.domain || 'None');
        console.log('Expires:', status.expires_at || 'Never');
        console.log('Activations:', `${status.activations_count || 0}/${status.max_activations || 1}`);
    } catch (error) {
        if (error instanceof RateLimitError) {
            console.log(`Rate limited. Retry after ${error.retryAfter} seconds.`);
        } else {
            console.log('Error:', error.message);
        }
    }

    console.log();

    // Example 3: Activate license on a domain
    console.log('=== Activate License ===');
    try {
        const result = await client.activate('XXXX-XXXX-XXXX-XXXX', 'newsite.example.com');

        if (result.success) {
            console.log('License activated successfully!');
        } else {
            console.log('Activation failed:', result.message || 'Unknown error');
        }
    } catch (error) {
        if (error instanceof RateLimitError) {
            console.log(`Rate limited. Retry after ${error.retryAfter} seconds.`);
        } else {
            console.log(`Error (${error.errorCode}):`, error.message);
        }
    }
})();
*/

// Export for Node.js
if (typeof module !== 'undefined' && module.exports) {
    module.exports = WcLicensedProductClient;
    module.exports.WcLicensedProductError = WcLicensedProductError;
    module.exports.RateLimitError = RateLimitError;
}
