import apiFetch from '@wordpress/api-fetch';
import {glue} from './glue';

/**
 * Generic API handler for onboarding actions
 * @param {string} action - The action to perform
 * @param {Object} data - Data to send with the request
 * @returns {Promise<*>}
 */

export const handleRequest = async (args) => {
    const { method, path, data, fallbackPath } = args;

    if (method === 'GET') {
        args.path = `${args.path}${glue(args.path)}${buildQueryString(args.data)}`;
        delete args.data;
    }

    let response;

    try {
        response = await apiFetch(args);

        if (!response.request_success) {
            throw new Error('invalid data error');
        }
        if (response.code) {
            throw new Error(response.message);
        }

        delete response.request_success;
    } catch (error) {
        console.log(error.message, args.path);
        response = await ajaxRequest(method, path, data, fallbackPath);
    }

    document.dispatchEvent(new CustomEvent('teamupdraft_api_response', {
        detail: { response, method, path, data }
    }));

    return response;
};


export const updateAction = async( data = {}, action ) => {
    const onboardingData = window[`teamupdraft_onboarding`] || {}
    const endpointUrl = onboardingData.prefix + '/v1/onboarding/do_action/'+action;
    data.nonce = onboardingData.nonce;
    const path = endpointUrl;
    const method = 'POST';

    let args = {
        path,
        method,
        data,
    };

    return await handleRequest(args);
}

const siteUrl = (fallbackPath = null ) => {
    const onboardingData = window[`teamupdraft_onboarding`] || {}
    let url = onboardingData.admin_ajax_url;
    if ( fallbackPath ) {
        //replace everything after action= with fallbackPath
        url = url.replace( /(action=)[^\&]+/, `action=${fallbackPath}` );
    }
    if ( 'https:' === window.location.protocol && -1 === url.indexOf( 'https://' ) ) {
        return url.replace( 'http://', 'https://' );
    }
    return url;
};

const ajaxRequest = async( method, path, requestData = null, fallbackPath = null ) => {
    //if requestData is an object, convert it to an array
    const queryString = buildQueryString( requestData );

    const ajaxUrl = siteUrl(fallbackPath);
    //add path to request data
    requestData.path = path;
    const url = 'GET' === method ? `${ajaxUrl}&rest_action=${path.replace( '?', '&' )}&`+queryString : ajaxUrl;
    const options = {
        method,
        headers: { 'Content-Type': 'application/json; charset=UTF-8' }
    };

    if ( 'POST' === method ) {

        options.body = JSON.stringify({ path, data: requestData } );
    }
    try {
        const response = await fetch( url, options );
        if ( ! response.ok ) {
            return Promise.reject( new Error( 'AJAX request failed' ) );
        }

        const responseData = await response.json();
        if (
            ! responseData.data ||
            ! Object.prototype.hasOwnProperty.call( responseData.data, 'request_success' )
        ) {
            return Promise.reject( new Error( 'AJAX request failed' ) );
        }

        delete responseData.data.request_success;

        // return promise with the data object
        return Promise.resolve( responseData.data );
    } catch ( error ) {
        return Promise.reject( new Error( 'AJAX request failed' ) );
    }
}

/**
 * Build query string from object of parameters
 * @param {Object} params
 * @returns {string}
 */
const buildQueryString = ( params ) => {
    return Object.keys( params )
        .filter( ( key ) => params[key] !== undefined && null !== params[key])
        .map( ( key ) => {
            const value = serializeValue( params[key]);
            if ( Array.isArray( value ) ) {

                // Handle arrays by using the PHP array syntax: metrics[]=value1&metrics[]=value2
                return value
                    .map( ( v ) => `${encodeURIComponent( key )}[]=${encodeURIComponent( v )}` )
                    .join( '&' );
            }
            return `${encodeURIComponent( key )}=${encodeURIComponent( value )}`;
        })
        .join( '&' );
};

/**
 * Serialize value for URL parameters, handling arrays and objects
 * @param {*} value - Value to serialize
 * @returns {string} Serialized value
 */
const serializeValue = ( value ) => {
    if ( Array.isArray( value ) ) {

        // For arrays, add [] to the key and keep values separate
        return value;
    }
    if ( 'object' === typeof value && null !== value ) {
        return JSON.stringify( value );
    }
    return value;
};
