<?php

namespace GriffinForms\Admin\App\Html\Modals\Integrations;

use GriffinForms\Includes\Integrations\Providers;
use GriffinForms\Includes\Integrations\FormSettingsManager;
use GriffinForms\Includes\Integrations\FormControls\Factory;
use GriffinForms\Admin\App\Html\Modals\Integrations\Renders\Gridview;
use GriffinForms\Admin\App\Html\Modals\Integrations\Renders\InfoView;

/**
 * Integrations Modal - Responses Trait
 *
 * Handles AJAX responses for integration-related operations.
 * Processes requests and returns data to the frontend.
 *
 * @since 1.0.0
 */
trait Responses
{
    /**
     * Phase 1: Get integrations list for grid view
     *
     * Returns all available integrations with their metadata and current status.
     * Renders the HTML for the grid view and returns it.
     *
     * @AJAX Handler: wp_ajax_getIntegrationsList
     */
    public function getIntegrationsList()
    {
        // Verify nonce for security
        check_ajax_referer('griffinforms-integrations', 'nonce');

        // Verify user capability
        if (!current_user_can('manage_options')) {
            wp_send_json_error([
                'msg' => __('Access denied', 'griffinforms-form-builder')
            ]);
        }

        try {
            // Get all available providers
            $providers = Providers::getInstance();
            $all_providers = $providers->getAllIncludingPaidBlocked();

            // Update configuration status for each provider
            // Note: In Phase 1, integration classes may not exist yet, so we use defaults
            foreach ($all_providers as $id => &$provider) {
                $integration = $providers->getIntegration($id);
                if ($integration) {
                    $status = $integration->getStatus();
                    $provider['configured'] = $status['configured'] ?? false;
                    $provider['active'] = $status['active'] ?? false;
                    $provider['lib_installed'] = $integration->isLibraryInstalled();
                    if (!empty($provider['library']) && is_array($provider['library'])) {
                        $provider['library']['state']['active'] = $provider['lib_installed'];
                    }
                } else {
                    // Preserve registry-derived library state when the integration class is not available yet.
                    $provider['configured'] = false;
                    $provider['active'] = false;
                }
            }

            // Get categories
            $categories = $providers->getCategories();
            sort($categories);

            // Render category filter pills
            $filters_html = $this->renderCategoryFilters($categories);

            // Render grid view
            $grid_view = new Gridview();
            $grid_html = $grid_view->render([
                'providers'  => $all_providers,
            ]);

            // Combine filters and grid
            $full_html = $filters_html . $grid_html;

            // Return success response with rendered HTML
            wp_send_json_success([
                'html'        => $full_html,
                'providers'   => $all_providers,
                'categories'  => $categories,
                'message'     => __('Integrations loaded', 'griffinforms-form-builder')
            ]);

        } catch (\Exception $e) {
            wp_send_json_error([
                'msg' => __('Failed to load integrations', 'griffinforms-form-builder'),
                'error' => $e->getMessage()
            ]);
        }

        wp_die();
    }

    /**
     * Render category filter pills HTML
     *
     * @param array $categories List of category names
     * @return string HTML
     */
    private function renderCategoryFilters(array $categories): string
    {
        $html = '<div class="gf-integrations-filters">' . PHP_EOL;

        // "All" pill
        $html .= '<button type="button" class="gf-integrations-filter-pill active" data-category="all">'
            . esc_html__('All', 'griffinforms-form-builder')
            . '</button>' . PHP_EOL;

        // Category pills
        foreach ($categories as $category) {
            $html .= '<button type="button" class="gf-integrations-filter-pill" data-category="'
                . esc_attr(sanitize_text_field($category)) . '">'
                . esc_html($category)
                . '</button>' . PHP_EOL;
        }

        $html .= '</div>' . PHP_EOL;
        return $html;
    }

    // ========== Phase 2 Handlers (Placeholder) ==========

    /**
     * Phase 2: Get integration details/info view
     *
     * Returns detailed information view for a specific integration,
     * including all metadata, requirements, status, and action buttons.
     *
     * @AJAX Handler: wp_ajax_getIntegrationInfo
     */
    public function getIntegrationInfo()
    {
        // Verify nonce for security
        check_ajax_referer('griffinforms-integrations', 'nonce');

        // Verify user capability
        if (!current_user_can('manage_options')) {
            wp_send_json_error([
                'msg' => __('Access denied', 'griffinforms-form-builder')
            ]);
        }

        try {
            // Get integration ID from request
            $integration_id = isset($_POST['integration_id']) ? sanitize_text_field($_POST['integration_id']) : '';

            if (empty($integration_id)) {
                wp_send_json_error([
                    'msg' => __('Integration ID is required', 'griffinforms-form-builder')
                ]);
            }

            // Get provider metadata — includes paid-but-blocked providers so the info view
            // can render the Pro-locked upsell shell when package_admitted is false.
            $providers = Providers::getInstance();
            $provider = $providers->getRegistered($integration_id);

            if (!$provider) {
                wp_send_json_error([
                    /* translators: %s: integration ID */
                    'msg' => sprintf(__('Integration "%s" not found', 'griffinforms-form-builder'), esc_html($integration_id))
                ]);
            }

            // Get integration instance for status
            $integration = $providers->getIntegration($integration_id);
            $status = [];

            if ($integration) {
                $status = $integration->getStatus();
                $provider['lib_installed'] = $integration->isLibraryInstalled();
                if (!empty($provider['library']) && is_array($provider['library'])) {
                    $provider['library']['state']['active'] = $provider['lib_installed'];
                }
            } else {
                // Preserve registry-derived library state when the integration class is not available yet.
            }

            // Render info view
            $info_view = new InfoView();
            $html = $info_view->render([
                'integration_id' => $integration_id,
                'provider'       => $provider,
                'status'         => $status,
            ]);

            // Return success response with rendered HTML
            wp_send_json_success([
                'html'       => $html,
                'provider'   => $provider,
                'status'     => $status,
                /* translators: %s: integration name */
                'message'    => sprintf(__('Integration "%s" loaded', 'griffinforms-form-builder'), esc_html($provider['name']))
            ]);

        } catch (\Exception $e) {
            wp_send_json_error([
                'msg'   => __('Failed to load integration details', 'griffinforms-form-builder'),
                'error' => $e->getMessage()
            ]);
        }

        wp_die();
    }

    // ========== Phase 3b: Configuration Handlers ==========

    /**
     * Phase 3b: Get configuration form for specific integration
     *
     * Returns the configuration form HTML for a given integration.
     * The form is generated by the integration class itself.
     *
     * @AJAX Handler: wp_ajax_getIntegrationConfigurationForm
     */
    public function getIntegrationConfigurationForm()
    {
        // Verify nonce for security
        check_ajax_referer('griffinforms-integrations', 'nonce');

        // Verify user capability
        if (!current_user_can('manage_options')) {
            wp_send_json_error([
                'msg' => __('Access denied', 'griffinforms-form-builder')
            ]);
        }

        try {
            // Get integration ID from request
            $integration_id = isset($_POST['integration_id']) ? sanitize_text_field($_POST['integration_id']) : '';

            if (empty($integration_id)) {
                wp_send_json_error([
                    'msg' => __('Integration ID is required', 'griffinforms-form-builder')
                ]);
            }

            // Get integration instance
            $providers = Providers::getInstance();
            $integration = $providers->getIntegration($integration_id);

            if (!$integration) {
                wp_send_json_error([
                    /* translators: %s: integration ID */
                    'msg' => sprintf(__('Integration "%s" not found or not available', 'griffinforms-form-builder'), esc_html($integration_id))
                ]);
            }

            if (method_exists($integration, 'setFormContextId')) {
                $integration->setFormContextId($this->getRequestFormId());
            }

            $provider = $providers->getRegistered($integration_id) ?? [];
            if (!empty($provider['coming_soon'])) {
                wp_send_json_error([
                    'msg' => __('This integration is launching soon and cannot be configured yet.', 'griffinforms-form-builder')
                ]);
            }

            if (!empty($provider['is_paid']) && empty($provider['package_admitted'])) {
                wp_send_json_error([
                    'msg' => __('This integration requires GriffinForms Pro.', 'griffinforms-form-builder')
                ]);
            }

            // Check if integration has configuration form method
            if (!method_exists($integration, 'getConfigurationFormHtml')) {
                wp_send_json_error([
                    /* translators: %s: integration ID */
                    'msg' => sprintf(__('Integration "%s" does not support configuration', 'griffinforms-form-builder'), esc_html($integration_id))
                ]);
            }

            // Check if library is required and installed
            if (($provider['requires_lib'] ?? false) && !$integration->isLibraryInstalled()) {
                $lib_instructions = '';
                if (method_exists($integration, 'getLibraryInstructions')) {
                    $lib_instructions = $integration->getLibraryInstructions();
                }

                wp_send_json_error([
                    /* translators: %s: integration name */
                    'msg' => sprintf(__('The required library for "%s" is not installed. Please install it first.', 'griffinforms-form-builder'), esc_html($provider['name'])),
                    'requires_lib' => true,
                    'lib_instructions' => $lib_instructions
                ]);
            }

            // Get configuration form HTML from integration
            $form_html = $integration->getConfigurationFormHtml();

            // Get configuration JS from integration
            $form_js = '';
            if (method_exists($integration, 'getConfigurationJs')) {
                $form_js = $integration->getConfigurationJs();
            }

            // Return success response with form HTML and JS
            wp_send_json_success([
                'html'    => $form_html,
                'js'      => $form_js,
                /* translators: %s: integration ID */
                'message' => sprintf(__('Configuration form for "%s" loaded', 'griffinforms-form-builder'), esc_html($integration_id))
            ]);

        } catch (\Exception $e) {
            wp_send_json_error([
                'msg'   => __('Failed to load configuration form', 'griffinforms-form-builder'),
                'error' => $e->getMessage()
            ]);
        }

        wp_die();
    }

    /**
     * Phase 3b: Save integration configuration
     *
     * Receives configuration data from the frontend form and passes it to
     * the integration class for validation and saving.
     *
     * @AJAX Handler: wp_ajax_saveIntegrationConfiguration
     */
    public function saveIntegrationConfiguration()
    {
        // Verify nonce for security
        check_ajax_referer('griffinforms-integrations', 'nonce');

        // Verify user capability
        if (!current_user_can('manage_options')) {
            wp_send_json_error([
                'msg' => __('Access denied', 'griffinforms-form-builder')
            ]);
        }

        try {
            // Get integration ID from request
            $integration_id = isset($_POST['integration_id']) ? sanitize_text_field($_POST['integration_id']) : '';

            if (empty($integration_id)) {
                wp_send_json_error([
                    'msg' => __('Integration ID is required', 'griffinforms-form-builder')
                ]);
            }

            // Get integration instance
            $providers = Providers::getInstance();
            $integration = $providers->getIntegration($integration_id);

            if (!$integration) {
                wp_send_json_error([
                    /* translators: %s: integration ID */
                    'msg' => sprintf(__('Integration "%s" not found or not available', 'griffinforms-form-builder'), esc_html($integration_id))
                ]);
            }

            if (method_exists($integration, 'setFormContextId')) {
                $integration->setFormContextId($this->getRequestFormId());
            }

            $provider = $providers->getRegistered($integration_id) ?? [];
            if (!empty($provider['coming_soon'])) {
                wp_send_json_error([
                    'msg' => __('This integration is launching soon and cannot be configured yet.', 'griffinforms-form-builder')
                ]);
            }

            if (!empty($provider['is_paid']) && empty($provider['package_admitted'])) {
                wp_send_json_error([
                    'msg' => __('This integration requires GriffinForms Pro.', 'griffinforms-form-builder')
                ]);
            }

            // Check if integration has configuration saving method
            if (!method_exists($integration, 'saveConfig')) {
                wp_send_json_error([
                    /* translators: %s: integration ID */
                    'msg' => sprintf(__('Integration "%s" does not support configuration saving', 'griffinforms-form-builder'), esc_html($integration_id))
                ]);
            }

            // Extract configuration data from POST (exclude action, nonce, etc.)
            $config_data = [];
            foreach ($_POST as $key => $value) {
                if (in_array($key, ['action', 'nonce', 'integration_id'], true)) {
                    continue;
                }
                if (is_array($value)) {
                    $config_data[$key] = array_map('sanitize_text_field', $value);
                } else {
                    $config_data[$key] = sanitize_text_field($value);
                }
            }

            // Call integration's saveConfig method (public interface)
            $result = $integration->saveConfig($config_data);
            $success = $result['success'] ?? false;

            if (!$success) {
                wp_send_json_error([
                    /* translators: %s: integration ID */
                    'msg' => sprintf(__('Failed to save configuration for "%s"', 'griffinforms-form-builder'), esc_html($integration_id))
                ]);
            }

            // Return success response
            wp_send_json_success([
                /* translators: %s: integration ID */
                'message' => sprintf(__('Configuration for "%s" saved successfully', 'griffinforms-form-builder'), esc_html($integration_id))
            ]);

        } catch (\Exception $e) {
            wp_send_json_error([
                'msg'   => __('Failed to save configuration', 'griffinforms-form-builder'),
                'error' => $e->getMessage()
            ]);
        }

        wp_die();
    }

    /**
     * Phase 4: Test integration connection
     *
     * Tests the connection for a specific integration by calling its testConnection() method.
     * Returns success/failure status with message.
     *
     * @AJAX Handler: wp_ajax_testIntegration
     */
    public function testIntegration()
    {
        // Verify nonce for security
        $nonce = $_REQUEST['nonce'] ?? '';
        $nonce_valid = wp_verify_nonce($nonce, 'griffinforms-integrations') !== false;
        if (!$nonce_valid) {
            wp_send_json_error([
                'msg' => __('Security check failed', 'griffinforms-form-builder')
            ]);
        }

        // Verify user capability
        if (!current_user_can('manage_options')) {
            wp_send_json_error([
                'msg' => __('Access denied', 'griffinforms-form-builder')
            ]);
        }

        try {
            // Get integration ID from request
            $integration_id = isset($_POST['integration_id']) ? sanitize_text_field($_POST['integration_id']) : '';

            if (empty($integration_id)) {
                wp_send_json_error([
                    'msg' => __('Integration ID is required', 'griffinforms-form-builder')
                ]);
            }

            // Get integration instance
            $providers = Providers::getInstance();
            $integration = $providers->getIntegration($integration_id);

            if (!$integration) {
                wp_send_json_error([
                    /* translators: %s: integration ID */
                    'msg' => sprintf(__('Integration "%s" not found or not available', 'griffinforms-form-builder'), esc_html($integration_id))
                ]);
            }

            if (method_exists($integration, 'setFormContextId')) {
                $integration->setFormContextId($this->getRequestFormId());
            }

            $provider = $providers->getRegistered($integration_id) ?? [];
            if (!empty($provider['coming_soon'])) {
                wp_send_json_error([
                    'msg' => __('This integration is launching soon and cannot be tested yet.', 'griffinforms-form-builder')
                ]);
            }

            if (!empty($provider['is_paid']) && empty($provider['package_admitted'])) {
                wp_send_json_error([
                    'msg' => __('This integration requires GriffinForms Pro.', 'griffinforms-form-builder')
                ]);
            }

            // Test the connection
            $test_result = $integration->testConnection();

            if (isset($test_result['success']) && $test_result['success']) {
                wp_send_json_success([
                    /* translators: %s: integration ID */
                    'message' => $test_result['message'] ?? sprintf(__('Connection test for "%s" passed', 'griffinforms-form-builder'), esc_html($integration_id))
                ]);
            } else {
                wp_send_json_error([
                    /* translators: %s: integration ID */
                    'msg' => $test_result['message'] ?? sprintf(__('Connection test for "%s" failed', 'griffinforms-form-builder'), esc_html($integration_id))
                ]);
            }

        } catch (\Exception $e) {
            wp_send_json_error([
                'msg'   => __('Failed to test connection', 'griffinforms-form-builder'),
                'error' => $e->getMessage()
            ]);
        }

        wp_die();
    }

    /**
     * Enable integration
     * @todo Implement in Phase 2
     */
    public function enableIntegration()
    {
        check_ajax_referer('griffinforms-app-nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['msg' => __('Access denied', 'griffinforms-form-builder')]);
        }

        wp_send_json_error(['msg' => 'Not yet implemented']);
        wp_die();
    }

    /**
     * Phase 4: Disable integration
     *
     * Disables a specific integration by clearing its configuration settings.
     * Returns to the info view with updated status after disabling.
     *
     * @AJAX Handler: wp_ajax_disableIntegration
     */
    public function disableIntegration()
    {
        // Verify nonce for security
        $nonce_valid = wp_verify_nonce($_REQUEST['nonce'] ?? '', 'griffinforms-integrations') !== false;
        if (!$nonce_valid) {
            wp_send_json_error([
                'msg' => __('Security check failed', 'griffinforms-form-builder')
            ]);
        }

        // Verify user capability
        if (!current_user_can('manage_options')) {
            wp_send_json_error([
                'msg' => __('Access denied', 'griffinforms-form-builder')
            ]);
        }

        try {
            // Get integration ID from request
            $integration_id = isset($_POST['integration_id']) ? sanitize_text_field($_POST['integration_id']) : '';

            if (empty($integration_id)) {
                wp_send_json_error([
                    'msg' => __('Integration ID is required', 'griffinforms-form-builder')
                ]);
            }

            // Get integration instance
            $providers = Providers::getInstance();
            $integration = $providers->getIntegration($integration_id);

            if (!$integration) {
                wp_send_json_error([
                    /* translators: %s: integration ID */
                    'msg' => sprintf(__('Integration "%s" not found or not available', 'griffinforms-form-builder'), esc_html($integration_id))
                ]);
            }

            if (method_exists($integration, 'setFormContextId')) {
                $integration->setFormContextId($this->getRequestFormId());
            }

            $provider = $providers->getRegistered($integration_id) ?? [];
            if (!empty($provider['coming_soon'])) {
                wp_send_json_error([
                    'msg' => __('This integration is launching soon and does not need to be disabled.', 'griffinforms-form-builder')
                ]);
            }

            if (!empty($provider['is_paid']) && empty($provider['package_admitted'])) {
                wp_send_json_error([
                    'msg' => __('This integration requires GriffinForms Pro.', 'griffinforms-form-builder')
                ]);
            }

            // Clear all options for this integration
            // This is done through the base Format class helper method
            if (method_exists($integration, 'clearAllOptions')) {
                $integration->clearAllOptions();
            } else {
                // Fallback: manually clear options using Settings class
                $settings = \GriffinForms\Settings::getInstance();
                $meta = $integration->getMeta();

                // Get all options and delete those matching the integration's meta prefix
                $all_options = $settings->getAllOptions();
                $prefix = $meta . '_';

                foreach ($all_options as $key => $value) {
                    if (strpos($key, $prefix) === 0) {
                        $settings->deleteOption($key);
                    }
                }
            }

            // Return success response
            wp_send_json_success([
                /* translators: %s: integration ID */
                'message' => sprintf(__('Integration "%s" has been disabled', 'griffinforms-form-builder'), esc_html($integration_id))
            ]);

        } catch (\Exception $e) {
            wp_send_json_error([
                'msg'   => __('Failed to disable integration', 'griffinforms-form-builder'),
                'error' => $e->getMessage()
            ]);
        }

        wp_die();
    }

    /**
     * Fetch per-form integration settings
     *
     * @AJAX Handler: wp_ajax_getFormIntegrationSettings
     */
    public function getFormIntegrationSettings()
    {
        check_ajax_referer('griffinforms-integrations', 'nonce', true);

        if (!current_user_can('manage_options')) {
            wp_send_json_error(['msg' => __('Access denied', 'griffinforms-form-builder')]);
        }

        $form_id = isset($_POST['form_id']) ? absint($_POST['form_id']) : 0;
        $integration_id = isset($_POST['integration_id']) ? sanitize_text_field($_POST['integration_id']) : '';

        if (empty($form_id) || empty($integration_id)) {
            wp_send_json_error(['msg' => __('Form ID and Integration ID are required.', 'griffinforms-form-builder')]);
        }

        $providers = Providers::getInstance();
        $provider = $providers->getRegistered($integration_id) ?? [];
        $integration = $providers->getIntegration($integration_id);

        if (empty($provider) || !$integration) {
            wp_send_json_error(['msg' => __('Integration not found.', 'griffinforms-form-builder')]);
        }

        if (method_exists($integration, 'setFormContextId')) {
            $integration->setFormContextId($form_id);
        }

        if (!empty($provider['coming_soon'])) {
            wp_send_json_error(['msg' => __('This integration is launching soon and cannot be configured.', 'griffinforms-form-builder')]);
        }

        if (!empty($provider['is_paid']) && empty($provider['package_admitted'])) {
            wp_send_json_error(['msg' => __('This integration requires GriffinForms Pro.', 'griffinforms-form-builder')]);
        }

        $allow_override = $provider['scope']['allow_override'] ?? false;
        if (!$allow_override) {
            wp_send_json_error(['msg' => __('Per-form settings are not available for this integration.', 'griffinforms-form-builder')]);
        }

        $live_status = $integration->getStatus();
        if (empty($live_status['configured'])) {
            wp_send_json_error(['msg' => __('Configure this integration globally before adding form-specific settings.', 'griffinforms-form-builder')]);
        }

        $schema = method_exists($integration, 'getFormSettingsSchema') ? $integration->getFormSettingsSchema() : [];
        $defaults = method_exists($integration, 'getDefaultFormSettings') ? $integration->getDefaultFormSettings() : [];
        $manager = FormSettingsManager::getInstance();
        $stored = $manager->getIntegrationSettings($form_id, $integration_id);

        $payload = $stored ?? [
            'mode'       => 'inherit',
            'settings'   => $defaults,
            'updated_at' => null,
            'updated_by' => null,
        ];

        $form_html = $this->renderFormSettingsHtml($integration_id, $provider, $schema, $payload, $form_id);

        wp_send_json_success([
            'schema'    => $schema,
            'settings'  => $payload,
            'defaults'  => $defaults,
            'html'      => $form_html,
        ]);
    }

    /**
     * Save per-form integration settings
     *
     * @AJAX Handler: wp_ajax_saveFormIntegrationSettings
     */
    public function saveFormIntegrationSettings()
    {
        check_ajax_referer('griffinforms-integrations', 'nonce', true);

        if (!current_user_can('manage_options')) {
            wp_send_json_error(['msg' => __('Access denied', 'griffinforms-form-builder')]);
        }

        $form_id = isset($_POST['form_id']) ? absint($_POST['form_id']) : 0;
        $integration_id = isset($_POST['integration_id']) ? sanitize_text_field($_POST['integration_id']) : '';
        $mode = isset($_POST['mode']) ? sanitize_text_field($_POST['mode']) : 'inherit';
        $raw_settings = isset($_POST['settings']) ? wp_unslash($_POST['settings']) : [];

        if (empty($form_id) || empty($integration_id)) {
            wp_send_json_error(['msg' => __('Form ID and Integration ID are required.', 'griffinforms-form-builder')]);
        }

        $providers = Providers::getInstance();
        $provider = $providers->getRegistered($integration_id) ?? [];
        $integration = $providers->getIntegration($integration_id);

        if (empty($provider) || !$integration) {
            wp_send_json_error(['msg' => __('Integration not found.', 'griffinforms-form-builder')]);
        }

        if (method_exists($integration, 'setFormContextId')) {
            $integration->setFormContextId($form_id);
        }

        if (!empty($provider['coming_soon'])) {
            wp_send_json_error(['msg' => __('This integration is launching soon and cannot be configured.', 'griffinforms-form-builder')]);
        }

        if (!empty($provider['is_paid']) && empty($provider['package_admitted'])) {
            wp_send_json_error(['msg' => __('This integration requires GriffinForms Pro.', 'griffinforms-form-builder')]);
        }

        $allow_override = $provider['scope']['allow_override'] ?? false;
        if (!$allow_override) {
            wp_send_json_error(['msg' => __('Per-form settings are not available for this integration.', 'griffinforms-form-builder')]);
        }

        $live_status = $integration->getStatus();
        if (empty($live_status['configured'])) {
            wp_send_json_error(['msg' => __('Configure this integration globally before adding form-specific settings.', 'griffinforms-form-builder')]);
        }

        $allowed_modes = ['inherit', 'custom', 'disabled'];
        if (!in_array($mode, $allowed_modes, true)) {
            $mode = 'inherit';
        }

        // Settings payload can arrive as JSON string or array
        $settings = is_string($raw_settings) ? json_decode($raw_settings, true) : $raw_settings;
        if (!is_array($settings)) {
            $settings = [];
        }

        $validated = method_exists($integration, 'validateFormSettings')
            ? $integration->validateFormSettings($settings)
            : $settings;

        if (is_wp_error($validated)) {
            wp_send_json_error(['msg' => $validated->get_error_message()]);
        }

        $payload = [
            'mode'       => $mode,
            'settings'   => $validated,
            'updated_at' => gmdate('c'),
            'updated_by' => get_current_user_id(),
        ];

        $manager = FormSettingsManager::getInstance();
        $save_result = $manager->saveIntegrationSettings($form_id, $integration_id, $payload);

        if (is_wp_error($save_result)) {
            wp_send_json_error(['msg' => $save_result->get_error_message()]);
        }

        if (is_object($this->log)) {
            $this->log->add(
                'info',
                'form',
                $form_id,
                (int) get_current_user_id(),
                sprintf(__('Integration %s settings saved for form %d.', 'griffinforms-form-builder'), $integration_id, $form_id),
                'audit'
            );
        }

        $this->fireFormModifiedHook($form_id, $integration_id, array(
            'mode' => $mode,
        ));

        wp_send_json_success([
            'message'  => __('Form settings saved.', 'griffinforms-form-builder'),
            'settings' => $payload,
        ]);
    }

    /**
     * Fires a unified form modified hook for per-form integration settings.
     *
     * @param int    $form_id        Form ID being modified.
     * @param string $integration_id Integration identifier.
     * @param array  $meta           Additional context about the modification.
     */
    protected function fireFormModifiedHook(int $form_id, string $integration_id, array $meta = array()): void
    {
        if ($form_id <= 0 || $integration_id === '') {
            return;
        }

        /**
         * Fires after a form is modified anywhere in the admin.
         *
         * @param int    $form_id Form ID being modified.
         * @param string $source  Source area triggering the modification.
         * @param array  $meta    Additional context about the modification.
         */
        do_action(
            'griffinforms_form_modified',
            $form_id,
            'integration_settings',
            array_merge(
                array('integration_id' => $integration_id),
                $meta
            )
        );

        /**
         * Fires after per-form integration settings are saved.
         *
         * @param int    $form_id        Form ID being modified.
         * @param string $integration_id Integration identifier.
         * @param array  $meta           Additional context about the modification.
         */
        do_action(
            'griffinforms_integration_settings_saved',
            $form_id,
            $integration_id,
            $meta
        );
    }

    /**
     * Render per-form settings form HTML using schema + form controls
     */
    private function renderFormSettingsHtml(string $integration_id, array $provider, array $schema, array $payload, int $form_id = 0): string
    {
        $settings = $payload['settings'] ?? [];

        // Allow integration to supply fully custom form settings HTML.
        // If it returns a non-empty string the schema-driven renderer is skipped.
        $fields_html = '';
        $integration  = Providers::getInstance()->getIntegration($integration_id);
        if ($integration && method_exists($integration, 'getFormSettingsHtml')) {
            $fields_html = (string) $integration->getFormSettingsHtml($form_id, $payload);
        }

        if (empty($fields_html)) {
        // Two-column mapping layout for payment gateways that use customer field mapping.
        $two_col_gateways = ['stripe', 'square'];
        if (in_array($integration_id, $two_col_gateways, true)) {
            $gateway_name = $provider['name'] ?? ucfirst($integration_id);
            $rows = [];
            $mode_value = $payload['mode'] ?? '';
            foreach ($schema as $field) {
                $name = $field['name'] ?? '';
                if (!$name) {
                    continue;
                }
                // Skip internal mode field but preserve its value via hidden input.
                if ($name === '__gf_form_settings_mode') {
                    $hidden_val = $mode_value ?: ($field['default'] ?? 'custom');
                    $rows[] = '<input type="hidden" name="' . esc_attr($name) . '" value="' . esc_attr($hidden_val) . '">';
                    continue;
                }

                $value = $settings[$name] ?? ($field['default'] ?? '');
                $label = $field['label'] ?? $name;
                $desc  = $field['description'] ?? '';
                $options = $field['options'] ?? [];
                $placeholder = $field['placeholder'] ?? __('Select a form field', 'griffinforms-form-builder');

                $select  = '<select name="' . esc_attr($name) . '" class="form-select gf-integration-control-input">';
                $select .= '<option value="">' . esc_html($placeholder) . '</option>';
                foreach ($options as $opt_value => $opt_label) {
                    $selected = ($value !== '' && (string) $value === (string) $opt_value) ? ' selected="selected"' : '';
                    $select .= '<option value="' . esc_attr($opt_value) . '"' . $selected . '>' . esc_html($opt_label) . '</option>';
                }
                $select .= '</select>';

                $row  = '<div class="gf-mapping-row mb-3 p-3">';
                $row .= '<div class="gf-mapping-flex">';
                $row .= '<div class="gf-mapping-col gf-mapping-col-label">';
                $row .= '<div class="fw-semibold">' . esc_html($label) . '</div>';
                if (!empty($desc)) {
                    $row .= '<div class="text-muted small">' . esc_html($desc) . '</div>';
                }
                $row .= '</div>';
                $row .= '<div class="gf-mapping-col gf-mapping-col-control mt-1">' . $select . '</div>';
                $row .= '</div>';
                $row .= '</div>';

                $rows[] = $row;
            }

            if (!empty($rows)) {
                $fields_html .= '<div class="mb-3">';
                $fields_html .= '<div class="d-flex fw-semibold mb-2 text-muted small gf-mapping-flex">';
                $fields_html .= '<div class="gf-mapping-col gf-mapping-col-label">' . esc_html(sprintf(__('%s attribute', 'griffinforms-form-builder'), $gateway_name)) . '</div>';
                $fields_html .= '<div class="gf-mapping-col gf-mapping-col-control">' . esc_html__('Map to form field', 'griffinforms-form-builder') . '</div>';
                $fields_html .= '</div>';
                $fields_html .= implode('', $rows);
                $fields_html .= '</div>';
            }
        } else {
            foreach ($schema as $field) {
                $name = $field['name'] ?? '';
                if (!$name) {
                    continue;
                }
                if ($name === '__gf_form_settings_mode') {
                    $field['value'] = $payload['mode'] ?? ($field['default'] ?? 'inherit');
                } else {
                    $field['value'] = $settings[$name] ?? ($field['default'] ?? '');
                }
                $control = Factory::create(
                    $field['type'] ?? 'text',
                    $name,
                    $field['value'],
                    $integration_id,
                    $field
                );
                $fields_html .= $control->render();
            }
        }
        } // end if (empty($fields_html))

        $name = $provider['name'] ?? $integration_id;
        $category = $provider['category'] ?? '';
        $icon = $provider['icon'] ?? ($provider['icon_dark'] ?? '');

        $html  = '<div class="gf-form-settings-panel">' . PHP_EOL;
        $html .= '<div class="gf-integration-config-wrapper d-flex" style="gap: 2rem;">' . PHP_EOL;
        $html .= '<div class="gf-integration-config-sidebar" style="flex: 0 0 160px; padding-top: 0.5rem;">' . PHP_EOL;
        $html .= '<div style="text-align: center;">' . PHP_EOL;
        if (!empty($icon)) {
            $html .= '<img src="' . esc_url($icon) . '" alt="' . esc_attr($name) . '" style="width: 60px; height: 60px; margin-bottom: 1rem; display: block; margin-left: auto; margin-right: auto;">' . PHP_EOL;
        }
        $html .= '<h3 style="margin: 0 0 0.5rem 0; font-size: 15px; font-weight: 600; color: #1f2937;">' . esc_html($name) . '</h3>' . PHP_EOL;
        if (!empty($category)) {
            $html .= '<p style="margin: 0; font-size: 11px; color: #999; text-transform: uppercase; letter-spacing: 0.5px;">' . esc_html($category) . '</p>' . PHP_EOL;
        }
        $html .= '</div>' . PHP_EOL; // sidebar inner
        $html .= '</div>' . PHP_EOL; // sidebar

        $html .= '<div class="gf-integration-config-content" style="flex: 1; min-width: 0;">' . PHP_EOL;
        $html .= '<form class="gf-integration-config-form gf-form-settings-form" data-integration-id="' . esc_attr($integration_id) . '">' . PHP_EOL;
        $html .= $fields_html;
        $html .= '<div class="gf-form-actions" style="display: flex; gap: 0.75rem; margin-top: 2rem;">' . PHP_EOL;
        $html .= '<button type="button" class="gf-btn gf-btn-primary" data-action="save-form-settings" data-integration-id="' . esc_attr($integration_id) . '">' . esc_html__('Save', 'griffinforms-form-builder') . '</button>' . PHP_EOL;
        $html .= '<button type="button" class="gf-btn gf-btn-secondary" data-action="close-form-settings" data-integration-id="' . esc_attr($integration_id) . '">' . esc_html__('Cancel', 'griffinforms-form-builder') . '</button>' . PHP_EOL;
        $html .= '</div>' . PHP_EOL;
        $html .= '</form>' . PHP_EOL;
        $html .= '</div>' . PHP_EOL; // content

        $html .= '</div>' . PHP_EOL; // wrapper
        $html .= '</div>' . PHP_EOL; // panel

        return $html;
    }

    /**
     * Activate an AI provider sourced from a WP7 Connector without requiring
     * the user to navigate to Settings → AI.
     *
     * Writes butler_active_provider to the GriffinForms settings store.
     * Only accepts the three provider IDs that have WP Core connector counterparts.
     *
     * @AJAX Handler: wp_ajax_griffinforms_activate_provider_from_connector
     */
    public function activateProviderFromConnector()
    {
        check_ajax_referer('griffinforms_activate_provider', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(['msg' => __('Access denied', 'griffinforms-form-builder')]);
        }

        $allowed   = ['openai', 'anthropic', 'gemini'];
        $provider  = isset($_POST['provider_id']) ? sanitize_key($_POST['provider_id']) : '';

        if (!in_array($provider, $allowed, true)) {
            wp_send_json_error(['msg' => __('Invalid provider.', 'griffinforms-form-builder')]);
        }

        $settings = \GriffinForms\Settings::getInstance();
        $settings->updateOption('butler_active_provider', $provider, 'ai');

        wp_send_json_success(['provider' => $provider]);
    }

    /**
     * Resolve form ID from current AJAX request
     */
    private function getRequestFormId(): int
    {
        if (isset($_REQUEST['form_id'])) {
            return absint(wp_unslash($_REQUEST['form_id']));
        }

        return 0;
    }
}
