/**
 * Agenistrator - Chat API.
 *
 * Handles API calls for the chat functionality.
 *
 * @package   Agenistrator
 * @since     1.0.0
 * @author    Alex Ruban <alex@maximum.guru>
 * @author    Maximum Software Inc <contact@maximum.software>
 * @license   GPL-3.0-only
 * @link      https://maximum.software/
 *
 * SPDX-FileCopyrightText: 2025-2026 Alex Ruban <alex@maximum.guru>
 * SPDX-FileCopyrightText: 2025-2026 Maximum Software Inc <contact@maximum.software>
 * SPDX-License-Identifier: GPL-3.0-only
 */
jQuery(document).ready(function() {
    'use strict';

    window.Agenistrator = window.Agenistrator || {};

    // ChatAPI - Handles API calls for chat functionality
    Agenistrator.ChatAPI = {
        // Timeout ID for rate limit wait (used to cancel pending resume)
        rateLimitTimeoutId: null,

        // Flag to track if current window initiated the current agent loop
        isLoopInitiator: false,

        /**
         * Check if current window initiated the current agent loop
         *
         * @returns {boolean} True if current window initiated the loop
         * @since 1.0.0
         */
        isInitiator: function() {
            return this.isLoopInitiator;
        },

        /**
         * Clear the initiator flag
         *
         * @since 1.0.0
         */
        clearInitiator: function() {
            this.isLoopInitiator = false;
        },

        /**
         * Cancel any pending rate limit timeout
         *
         * @since 1.0.0
         */
        cancelRateLimitTimeout: function() {
            if (this.rateLimitTimeoutId !== null) {
                clearTimeout(this.rateLimitTimeoutId);
                this.rateLimitTimeoutId = null;
                this.clearInitiator();
            }
        },

        /**
         * Handle loop response status codes (timeout, rate_limit)
         * Automatically resumes the agent loop when needed
         *
         * @param {Object} data - The response data from sendMessage or resumeAgentLoop
         * @param {Function} successCallback - Callback for final successful response
         * @param {Function} errorCallback - Callback for error response
         * @returns {boolean} True if response was handled (timeout/rate_limit), false otherwise
         * @private
         * @since 1.0.0
         */
        _handleLoopResponse: function(data, successCallback, errorCallback) {
            var self = this;
            var status = data.data && data.data.status;

            if (status === 'timeout') {
                // Immediate resume - execution time was running low
                self.resumeAgentLoop(successCallback, errorCallback);
                return true;
            }

            if (status === 'rate_limit') {
                // Wait for specified time then resume
                var waitTime = (data.data.wait_time || 0) * 1000;
                this.rateLimitTimeoutId = setTimeout(function() {
                    self.rateLimitTimeoutId = null;
                    self.resumeAgentLoop(successCallback, errorCallback);
                }, waitTime);
                return true;
            }

            return false;
        },

        /**
         * Execute an agent loop request and handle the response
         *
         * Shared logic for sendMessage and resumeAgentLoop. Handles timeout/rate_limit
         * responses by automatically resuming the agent loop.
         *
         * @param {URLSearchParams} formData - The form data to send
         * @param {Function} successCallback - Callback for successful response
         * @param {Function} errorCallback - Callback for error response
         * @private
         * @since 1.0.0
         */
        _executeAgentRequest: function(formData, successCallback, errorCallback) {
            var self = this;

            fetch(ajaxurl, {
                method: 'POST',
                body: formData,
                credentials: 'same-origin',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
                }
            })
            .then(function(response) {
                var statusText = response.statusText;
                return response.json().then(function(data) {
                    return { data: data, statusText: statusText };
                });
            })
            .then(function(result) {
                var data = result.data;
                var statusText = result.statusText;

                // The response is just an acknowledgment - the actual content
                // will come through the SSE connection
                if (!data.success) {
                    self.clearInitiator();
                    var errorMessage = (data.data && data.data.message) ? data.data.message : (data.data || statusText);
                    // Call error callback if provided
                    if (errorCallback) {
                        errorCallback(new Error(errorMessage || agenistrator.strings.unknown_error), data.data);
                    }
                    return;
                }

                // Check if this is a timeout/rate_limit response that needs handling
                if (self._handleLoopResponse(data, successCallback, errorCallback)) {
                    return;
                }

                // Loop completed - clear initiator flag
                self.clearInitiator();

                // Call success callback if provided
                if (successCallback) {
                    successCallback(data);
                }
            })
            .catch(function(error) {
                self.clearInitiator();
                // Call error callback if provided
                if (errorCallback) {
                    errorCallback(error, null);
                }
            });
        },

        /**
         * Send a message to the assistant
         *
         * @param {string} message - The message to send
         * @param {Function} successCallback - Callback for successful response
         * @param {Function} errorCallback - Callback for error response
         * @since 1.0.0
         */
        sendMessage: function(message, successCallback, errorCallback) {
            // Mark current window as the initiator of the agent loop
            this.isLoopInitiator = true;

            var formData = new URLSearchParams();
            formData.append('action', 'agenistrator_chat_send_message');
            formData.append('nonce', agenistrator.nonce);
            formData.append('message', message);

            this._executeAgentRequest(formData, successCallback, errorCallback);
        },

        /**
         * Resume the agent loop after timeout or rate limit
         *
         * @param {Function} successCallback - Callback for successful response
         * @param {Function} errorCallback - Callback for error response
         * @since 1.0.0
         */
        resumeAgentLoop: function(successCallback, errorCallback) {
            // Continue as initiator (already set by sendMessage or previous resumeAgentLoop)
            this.isLoopInitiator = true;

            var formData = new URLSearchParams();
            formData.append('action', 'agenistrator_resume_agent_loop');
            formData.append('nonce', agenistrator.nonce);

            this._executeAgentRequest(formData, successCallback, errorCallback);
        },

        /**
         * Clear chat log
         *
         * @param {Function} successCallback - Callback for successful response
         * @param {Function} errorCallback - Callback for error response
         * @since 1.0.0
         */
        clearChatLog: function(successCallback, errorCallback) {
            // Create a formData object for the request
            var formData = new URLSearchParams();
            formData.append('action', 'agenistrator_chat_clear_chat_log');
            formData.append('nonce', agenistrator.nonce);

            // Send the request using fetch API
            fetch(ajaxurl, {
                method: 'POST',
                body: formData,
                credentials: 'same-origin',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
                }
            })
            .then(function(response) {
                if (!response.ok) {
                    throw new Error('Network response was not ok: ' + response.status);
                }
                return response.json();
            })
            .then(function(data) {
                if (!data.success) {
                    throw new Error(data.data || 'Unknown error');
                }

                // Call success callback if provided
                if (successCallback) {
                    successCallback(data);
                }
            })
            .catch(function(error) {
                // Call error callback if provided
                if (errorCallback) {
                    errorCallback(error);
                }
            });
        },

        /**
         * Stop the agent loop
         *
         * @param {Function} [successCallback] - Optional callback for successful response
         * @param {Function} [errorCallback] - Optional callback for error response
         * @since 1.0.0
         */
        stopAgentLoop: function(successCallback, errorCallback) {
            // Cancel any pending rate limit timeout
            this.cancelRateLimitTimeout();

            // Create a formData object for the request
            var formData = new URLSearchParams();
            formData.append('action', 'agenistrator_stop_agent_loop');
            formData.append('nonce', agenistrator.nonce);

            // Send the request using fetch API
            fetch(ajaxurl, {
                method: 'POST',
                body: formData,
                credentials: 'same-origin',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
                }
            })
            .then(function(response) {
                if (!response.ok) {
                    throw new Error('Network response was not ok: ' + response.status);
                }
                return response.json();
            })
            .then(function(data) {
                if (!data.success) {
                    throw new Error(data.data || 'Unknown error');
                }

                // Call success callback if provided
                if (successCallback) {
                    successCallback(data);
                }
            })
            .catch(function(error) {
                // Call error callback if provided
                if (errorCallback) {
                    errorCallback(error);
                }
            });
        },

        /**
         * Report an agent issue - generates report and optionally sends via email
         *
         * @param {string} description - User's description of the issue
         * @param {boolean} sendEmail - Whether to send the report via email
         * @param {Function} [successCallback] - Optional callback for successful response
         * @param {Function} [errorCallback] - Optional callback for error response
         * @since 1.0.0
         */
        reportIssue: function(description, sendEmail, successCallback, errorCallback) {
            var formData = new URLSearchParams();
            formData.append('action', 'agenistrator_report_issue');
            formData.append('nonce', agenistrator.nonce);
            formData.append('description', description);
            formData.append('send_email', sendEmail ? '1' : '0');

            fetch(ajaxurl, {
                method: 'POST',
                body: formData,
                credentials: 'same-origin',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
                }
            })
            .then(function(response) {
                if (!response.ok) {
                    throw new Error('Network response was not ok: ' + response.status);
                }
                return response.json();
            })
            .then(function(data) {
                if (!data.success) {
                    throw new Error(data.data || 'Unknown error');
                }
                if (successCallback) {
                    successCallback(data);
                }
            })
            .catch(function(error) {
                if (errorCallback) {
                    errorCallback(error);
                }
            });
        }
    };
});
