/**
 * AJAX Handler Module
 *
 * Provides standardized AJAX operations with CSRF protection,
 * error handling, and user feedback.
 *
 * Usage:
 *   import { ajaxGet, ajaxPost, ajaxDelete, ajaxSubmitForm } from './modules/ajax-handler';
 *
 *   // GET request
 *   ajaxGet('/api/users/1', {
 *       onSuccess: (data) => console.log(data)
 *   });
 *
 *   // DELETE with confirmation
 *   ajaxDelete('/api/users/1', {
 *       confirm: true,
 *       confirmTitle: 'Delete User?',
 *       onSuccess: () => table.row('#row-1').remove().draw()
 *   });
 *
 *   // Form submission
 *   ajaxSubmitForm('#userForm', {
 *       onSuccess: (response) => window.location.href = response.redirect
 *   });
 */

/**
 * Get CSRF token from meta tag
 * @returns {string|null}
 */
function getCsrfToken() {
    return document.querySelector('meta[name="csrf-token"]')?.content;
}

/**
 * Default headers for AJAX requests
 */
function getDefaultHeaders() {
    return {
        'X-CSRF-TOKEN': getCsrfToken(),
        'Accept': 'application/json',
        'X-Requested-With': 'XMLHttpRequest'
    };
}

/**
 * Handle AJAX error response
 * @param {XMLHttpRequest} xhr
 * @param {Object} options
 */
function handleError(xhr, options) {
    let message = 'An error occurred. Please try again.';

    if (xhr.status === 422 && xhr.responseJSON?.errors) {
        // Validation errors
        const errors = Object.values(xhr.responseJSON.errors).flat();
        message = errors.join('<br>');
    } else if (xhr.status === 419) {
        message = 'Session expired. Please refresh the page.';
    } else if (xhr.status === 403) {
        message = 'You do not have permission to perform this action.';
    } else if (xhr.status === 404) {
        message = 'The requested resource was not found.';
    } else if (xhr.status === 500) {
        message = 'Server error. Please try again later.';
    } else if (xhr.responseJSON?.message) {
        message = xhr.responseJSON.message;
    }

    if (options.onError) {
        options.onError(xhr, message);
    } else if (window.toastr) {
        toastr.error(message);
    } else {
        alert(message);
    }
}

/**
 * Perform a GET request
 *
 * @param {string} url - Request URL
 * @param {Object} options - Configuration options
 */
export function ajaxGet(url, options = {}) {
    const defaults = {
        onSuccess: () => {},
        onError: null,
        onComplete: () => {}
    };
    const config = { ...defaults, ...options };

    $.ajax({
        url: url,
        type: 'GET',
        headers: getDefaultHeaders(),
        success: function(response) {
            config.onSuccess(response);
        },
        error: function(xhr) {
            handleError(xhr, config);
        },
        complete: function() {
            config.onComplete();
        }
    });
}

/**
 * Perform a POST request
 *
 * @param {string} url - Request URL
 * @param {Object} data - Data to send
 * @param {Object} options - Configuration options
 */
export function ajaxPost(url, data = {}, options = {}) {
    const defaults = {
        onSuccess: () => {},
        onError: null,
        onComplete: () => {},
        successMessage: null,
        showLoader: false
    };
    const config = { ...defaults, ...options };

    if (config.showLoader) {
        showLoader();
    }

    $.ajax({
        url: url,
        type: 'POST',
        headers: getDefaultHeaders(),
        data: data,
        success: function(response) {
            if (config.successMessage && window.toastr) {
                toastr.success(config.successMessage);
            } else if (response.message && window.toastr) {
                toastr.success(response.message);
            }
            config.onSuccess(response);
        },
        error: function(xhr) {
            handleError(xhr, config);
        },
        complete: function() {
            if (config.showLoader) {
                hideLoader();
            }
            config.onComplete();
        }
    });
}

/**
 * Perform a DELETE request with optional confirmation
 *
 * @param {string} url - Request URL
 * @param {Object} options - Configuration options
 */
export function ajaxDelete(url, options = {}) {
    const defaults = {
        confirm: true,
        confirmTitle: 'Are you sure?',
        confirmText: 'This action cannot be undone.',
        confirmButtonText: 'Yes, delete it',
        cancelButtonText: 'Cancel',
        onSuccess: () => {},
        onError: null,
        onComplete: () => {},
        successMessage: 'Deleted successfully!'
    };
    const config = { ...defaults, ...options };

    function performDelete() {
        $.ajax({
            url: url,
            type: 'DELETE',
            headers: getDefaultHeaders(),
            success: function(response) {
                if (config.successMessage && window.toastr) {
                    toastr.success(config.successMessage);
                }
                config.onSuccess(response);
            },
            error: function(xhr) {
                handleError(xhr, config);
            },
            complete: function() {
                config.onComplete();
            }
        });
    }

    if (config.confirm && window.Swal) {
        Swal.fire({
            title: config.confirmTitle,
            text: config.confirmText,
            icon: 'warning',
            showCancelButton: true,
            confirmButtonColor: '#d33',
            cancelButtonColor: '#6c757d',
            confirmButtonText: config.confirmButtonText,
            cancelButtonText: config.cancelButtonText
        }).then((result) => {
            if (result.isConfirmed) {
                performDelete();
            }
        });
    } else if (config.confirm) {
        if (confirm(config.confirmTitle + '\n' + config.confirmText)) {
            performDelete();
        }
    } else {
        performDelete();
    }
}

/**
 * Perform a PUT/PATCH request
 *
 * @param {string} url - Request URL
 * @param {Object} data - Data to send
 * @param {Object} options - Configuration options
 */
export function ajaxPut(url, data = {}, options = {}) {
    return ajaxPost(url, { ...data, _method: 'PUT' }, options);
}

/**
 * Submit a form via AJAX
 *
 * @param {string|HTMLFormElement} form - Form selector or element
 * @param {Object} options - Configuration options
 */
export function ajaxSubmitForm(form, options = {}) {
    const $form = $(form);
    const formData = new FormData($form[0]);

    const defaults = {
        onSuccess: () => {},
        onError: null,
        onComplete: () => {},
        successMessage: null,
        resetOnSuccess: false,
        showLoader: true
    };
    const config = { ...defaults, ...options };

    if (config.showLoader) {
        showLoader();
    }

    $.ajax({
        url: $form.attr('action'),
        type: $form.attr('method') || 'POST',
        headers: {
            'X-CSRF-TOKEN': getCsrfToken(),
            'Accept': 'application/json'
        },
        data: formData,
        processData: false,
        contentType: false,
        success: function(response) {
            if (config.successMessage && window.toastr) {
                toastr.success(config.successMessage);
            } else if (response.message && window.toastr) {
                toastr.success(response.message);
            }
            if (config.resetOnSuccess) {
                $form[0].reset();
            }
            config.onSuccess(response);
        },
        error: function(xhr) {
            handleError(xhr, config);
        },
        complete: function() {
            if (config.showLoader) {
                hideLoader();
            }
            config.onComplete();
        }
    });
}

/**
 * Show loading indicator
 */
function showLoader() {
    if ($('#ajax-loader').length === 0) {
        $('body').append(`
            <div id="ajax-loader" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%;
                 background: rgba(255,255,255,0.7); z-index: 9999; display: flex;
                 align-items: center; justify-content: center;">
                <div class="spinner-border text-primary" role="status">
                    <span class="sr-only">Loading...</span>
                </div>
            </div>
        `);
    }
    $('#ajax-loader').show();
}

/**
 * Hide loading indicator
 */
function hideLoader() {
    $('#ajax-loader').hide();
}

export default {
    ajaxGet,
    ajaxPost,
    ajaxPut,
    ajaxDelete,
    ajaxSubmitForm
};
