<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

if ( ! class_exists( 'SftcyWordformConnectBase' ) ) {
	class SftcyWordformConnectBase {

		/**
		 * Get provider help resources used across connector feedback messages.
		 *
		 * @return array
		 */
		public static function get_connect_provider_help_resources() {
			$applications = [
				'activecampaign' => [
					'url'   => 'https://help.activecampaign.com/hc/en-us/articles/221317447-Where-can-I-find-my-API-URL-and-key-',
					'label' => 'ActiveCampaign API Help',
				],
				'airtable'       => [
					'url'   => 'https://support.airtable.com/docs/creating-personal-access-tokens',
					'label' => 'Airtable Access Token Help',
				],
				'brevo'          => [
					'url'   => 'https://help.brevo.com/hc/en-us/articles/209467485-Create-and-manage-your-API-keys',
					'label' => 'Brevo API Key Help',
				],
				'googlecalendar' => [
					'url'   => 'https://developers.google.com/identity/protocols/oauth2/web-server',
					'label' => 'Google OAuth Setup Guide',
				],
				'googlesheet'    => [
					'url'   => 'https://developers.google.com/identity/protocols/oauth2/web-server',
					'label' => 'Google OAuth Setup Guide',
				],
				'hubspot'        => [
					'url'   => 'https://developers.hubspot.com/docs/api/private-apps',
					'label' => 'HubSpot Private Apps Help',
				],
				'mailchimp'      => [
					'url'   => 'https://mailchimp.com/help/about-api-keys/',
					'label' => 'Mailchimp API Key Help',
				],
				'mailerlite'     => [
					'url'   => 'https://developers.mailerlite.com/docs/',
					'label' => 'MailerLite API Token Help',
				],
				'salesforce'     => [
					'url'   => 'https://help.salesforce.com/s/articleView?id=sf.connected_app_create.htm&type=5',
					'label' => 'Salesforce Connected App Help',
				],
				'zohocrm'        => [
					'url'   => 'https://www.zoho.com/accounts/protocol/oauth-setup.html',
					'label' => 'Zoho OAuth Setup Help',
				],
			];

			return $applications;
		}

		/**
		 * Get provider help URL by integration slug.
		 *
		 * @param string $provider_slug Provider slug.
		 * @return string
		 */
		public static function get_connect_provider_help_url( $provider_slug = '' ) {
			$provider_slug = sanitize_key( (string) $provider_slug );
			$resources     = self::get_connect_provider_help_resources();

			return isset( $resources[ $provider_slug ]['url'] ) ? esc_url_raw( $resources[ $provider_slug ]['url'] ) : '';
		}

		/**
		 * Get provider help label by integration slug.
		 *
		 * @param string $provider_slug Provider slug.
		 * @return string
		 */
		public static function get_connect_provider_help_label( $provider_slug = '' ) {
			$provider_slug = sanitize_key( (string) $provider_slug );
			$resources     = self::get_connect_provider_help_resources();

			return isset( $resources[ $provider_slug ]['label'] ) ? sanitize_text_field( $resources[ $provider_slug ]['label'] ) : '';
		}

		/**
		 * Build a consistent connector feedback payload for configure UI actions.
		 *
		 * @param string $status Connector status.
		 * @param string $comment Visible feedback message.
		 * @param string $provider_slug Provider slug.
		 * @param array  $extra Additional response keys.
		 * @return array
		 */
		public static function build_connect_feedback_payload( $status = 'fail', $comment = '', $provider_slug = '', $extra = [] ) {
			$payload = [
				'status'  => sanitize_key( (string) $status ),
				'comment' => sanitize_text_field( (string) $comment ),
			];

			$provider_slug = sanitize_key( (string) $provider_slug );
			if ( ! empty( $provider_slug ) ) {
				$payload['providerSlug'] = $provider_slug;

				$help_url = self::get_connect_provider_help_url( $provider_slug );
				if ( ! empty( $help_url ) ) {
					$payload['providerHelpUrl'] = $help_url;
				}

				$help_label = self::get_connect_provider_help_label( $provider_slug );
				if ( ! empty( $help_label ) ) {
					$payload['providerHelpLabel'] = $help_label;
				}
			}

			if ( is_array( $extra ) ) {
				foreach ( $extra as $key => $value ) {
					$payload[ $key ] = $value;
				}
			}

			if ( 'fail' === $payload['status'] && ! empty( $provider_slug ) ) {
				$log_stage = isset( $extra['logStage'] ) ? sanitize_key( (string) $extra['logStage'] ) : 'configure';
				$log_context = [
					'providerSlug' => $provider_slug,
				];

				if ( ! empty( $payload['fixTip'] ) ) {
					$log_context['fixTip'] = sanitize_text_field( (string) $payload['fixTip'] );
				}
				if ( ! empty( $payload['providerHelpUrl'] ) ) {
					$log_context['providerHelpUrl'] = esc_url_raw( (string) $payload['providerHelpUrl'] );
				}
				if ( isset( $payload['responseStatusCode'] ) ) {
					$log_context['responseStatusCode'] = absint( $payload['responseStatusCode'] );
				}

				self::log_connection_configuration_event( $provider_slug, $log_stage, $payload['comment'], $log_context, 'error' );
			}

			return $payload;
		}

		/**
		 * Store connector configuration diagnostics in the central support log.
		 *
		 * @param string $provider_slug Provider slug.
		 * @param string $stage Stage identifier.
		 * @param string $message Log message.
		 * @param array  $context Context payload.
		 * @param string $severity Severity level.
		 * @return void
		 */
		public static function log_connection_configuration_event( $provider_slug = '', $stage = 'configure', $message = '', $context = [], $severity = 'error' ) {
			$provider_slug = sanitize_key( (string) $provider_slug );
			$stage         = sanitize_key( (string) $stage );
			$message       = sanitize_textarea_field( (string) $message );
			$severity      = in_array( $severity, [ 'info', 'warning', 'error' ], true ) ? $severity : 'error';

			if ( empty( $provider_slug ) || empty( $message ) || ! class_exists( 'SftcyWordformSupport' ) ) {
				return;
			}

			$context = is_array( $context ) ? $context : [];
			$context['providerSlug'] = $provider_slug;
			$context['stage']        = $stage;

			SftcyWordformSupport::log_event(
				'connection',
				$severity,
				sanitize_key( $provider_slug . '_' . $stage . '_failed' ),
				$message,
				$context
			);
		}

		/**
		 * Extract a human-readable provider API error message from a response body.
		 *
		 * @param string $response_body Raw response body.
		 * @return string
		 */
		public static function extract_connect_remote_error_message( $response_body = '' ) {
			$response_body = trim( (string) $response_body );
			if ( '' === $response_body ) {
				return '';
			}

			$decoded = json_decode( $response_body, true );
			if ( ! is_array( $decoded ) ) {
				return substr( sanitize_textarea_field( $response_body ), 0, 500 );
			}

			$common_keys = [ 'message', 'error_description', 'detail', 'title', 'description', 'error' ];
			foreach ( $common_keys as $key ) {
				if ( ! isset( $decoded[ $key ] ) ) {
					continue;
				}

				if ( is_string( $decoded[ $key ] ) && '' !== trim( $decoded[ $key ] ) ) {
					return substr( sanitize_textarea_field( $decoded[ $key ] ), 0, 500 );
				}

				if ( is_array( $decoded[ $key ] ) ) {
					$nested_message = self::extract_connect_remote_error_message( wp_json_encode( $decoded[ $key ] ) );
					if ( ! empty( $nested_message ) ) {
						return $nested_message;
					}
				}
			}

			if ( isset( $decoded['errors'] ) && is_array( $decoded['errors'] ) ) {
				$flattened_errors = [];
				foreach ( $decoded['errors'] as $error_item ) {
					if ( is_string( $error_item ) && '' !== trim( $error_item ) ) {
						$flattened_errors[] = trim( $error_item );
						continue;
					}

					if ( is_array( $error_item ) ) {
						foreach ( $common_keys as $key ) {
							if ( isset( $error_item[ $key ] ) && is_string( $error_item[ $key ] ) && '' !== trim( $error_item[ $key ] ) ) {
								$flattened_errors[] = trim( $error_item[ $key ] );
								break;
							}
						}
					}
				}

				if ( ! empty( $flattened_errors ) ) {
					return substr( sanitize_textarea_field( implode( ' | ', array_slice( $flattened_errors, 0, 3 ) ) ), 0, 500 );
				}
			}

			return substr( sanitize_textarea_field( wp_json_encode( $decoded ) ), 0, 500 );
		}

		/**
		 * Get current connection applications registry for Connects page rendering.
		 * Keep app definitions centralized so future integrations can be added
		 * without hardcoding cards in multiple places.
		 *
		 * @return array
		 */
		public static function get_connects_page_applications_registry() {
			$google_is_configured = false;
			$google_is_active     = false;
			if ( class_exists( 'SftcyWordformConnectGooglesheet' ) ) {
				$google_credentials   = SftcyWordformConnectGooglesheet::get_google_credentials();
				$google_token_info    = get_option( 'wordform_connect_google_sheet_token', [] );
				$google_has_token     = ! empty( $google_token_info['refresh_token'] ) || ! empty( $google_token_info['access_token'] );
				$google_is_configured = ! empty( $google_credentials['clientID'] ) && ! empty( $google_credentials['clientSecret'] ) && $google_has_token && ! SftcyWordformConnectGooglesheet::is_google_authencation_required();
				$google_is_active     = $google_is_configured && SftcyWordformConnectGooglesheet::is_googlesheet_configured_status_active();
			}
			$googlecalendar_info          = class_exists( 'SftcyWordformConnectGooglecalendar' ) ? SftcyWordformConnectGooglecalendar::get_googlecalendar_configured_info() : [];
			$googlecalendar_is_configured = isset( $googlecalendar_info['calendarId'] ) && ! empty( $googlecalendar_info['calendarId'] ) && class_exists( 'SftcyWordformConnectGooglecalendar' ) && ! SftcyWordformConnectGooglecalendar::is_googlecalendar_authentication_required();
			$googlecalendar_is_active     = $googlecalendar_is_configured && class_exists( 'SftcyWordformConnectGooglecalendar' ) && SftcyWordformConnectGooglecalendar::is_googlecalendar_configured_status_active();

			$zapier_info          = class_exists( 'SftcyWordformConnectZapier' ) ? SftcyWordformConnectZapier::get_zapier_webhook_url() : [];
			$zapier_is_configured = isset( $zapier_info['webhookPostUrl'] ) && ! empty( $zapier_info['webhookPostUrl'] );
			$zapier_is_active     = $zapier_is_configured && class_exists( 'SftcyWordformConnectZapier' ) && SftcyWordformConnectZapier::is_zapier_configured_status_active();

			$custom_webhook_info          = class_exists( 'SftcyWordformConnectCustomWebhook' ) ? SftcyWordformConnectCustomWebhook::get_custom_webhook_url() : [];
			$custom_webhook_is_configured = isset( $custom_webhook_info['webhookPostUrl'] ) && ! empty( $custom_webhook_info['webhookPostUrl'] );
			$custom_webhook_is_active     = $custom_webhook_is_configured && class_exists( 'SftcyWordformConnectCustomWebhook' ) && SftcyWordformConnectCustomWebhook::is_custom_webhook_configured_status_active();
			$slack_info                   = class_exists( 'SftcyWordformConnectSlack' ) ? SftcyWordformConnectSlack::get_slack_webhook_url() : [];
			$slack_is_configured          = isset( $slack_info['webhookPostUrl'] ) && ! empty( $slack_info['webhookPostUrl'] );
			$slack_is_active              = $slack_is_configured && class_exists( 'SftcyWordformConnectSlack' ) && SftcyWordformConnectSlack::is_slack_configured_status_active();
			$mailchimp_info               = class_exists( 'SftcyWordformConnectMailchimp' ) ? SftcyWordformConnectMailchimp::get_mailchimp_configured_info() : [];
			$mailchimp_is_configured      = isset( $mailchimp_info['apiKey'], $mailchimp_info['audienceId'] ) && ! empty( $mailchimp_info['apiKey'] ) && ! empty( $mailchimp_info['audienceId'] );
			$mailchimp_is_active          = $mailchimp_is_configured && class_exists( 'SftcyWordformConnectMailchimp' ) && SftcyWordformConnectMailchimp::is_mailchimp_configured_status_active();
			$mailerlite_info              = class_exists( 'SftcyWordformConnectMailerlite' ) ? SftcyWordformConnectMailerlite::get_mailerlite_configured_info() : [];
			$mailerlite_is_configured     = isset( $mailerlite_info['apiToken'], $mailerlite_info['groupId'] ) && ! empty( $mailerlite_info['apiToken'] ) && ! empty( $mailerlite_info['groupId'] );
			$mailerlite_is_active         = $mailerlite_is_configured && class_exists( 'SftcyWordformConnectMailerlite' ) && SftcyWordformConnectMailerlite::is_mailerlite_configured_status_active();
			$airtable_info                = class_exists( 'SftcyWordformConnectAirtable' ) ? SftcyWordformConnectAirtable::get_airtable_configured_info() : [];
			$airtable_is_configured       = isset( $airtable_info['accessToken'], $airtable_info['baseId'], $airtable_info['tableName'] ) && ! empty( $airtable_info['accessToken'] ) && ! empty( $airtable_info['baseId'] ) && ! empty( $airtable_info['tableName'] );
			$airtable_is_active           = $airtable_is_configured && class_exists( 'SftcyWordformConnectAirtable' ) && SftcyWordformConnectAirtable::is_airtable_configured_status_active();
			$brevo_info                   = class_exists( 'SftcyWordformConnectBrevo' ) ? SftcyWordformConnectBrevo::get_brevo_configured_info() : [];
			$brevo_is_configured          = isset( $brevo_info['apiKey'], $brevo_info['listId'] ) && ! empty( $brevo_info['apiKey'] ) && ! empty( $brevo_info['listId'] );
			$brevo_is_active              = $brevo_is_configured && class_exists( 'SftcyWordformConnectBrevo' ) && SftcyWordformConnectBrevo::is_brevo_configured_status_active();
			$hubspot_info                 = class_exists( 'SftcyWordformConnectHubspot' ) ? SftcyWordformConnectHubspot::get_hubspot_configured_info() : [];
			$hubspot_is_configured        = isset( $hubspot_info['privateAppToken'] ) && ! empty( $hubspot_info['privateAppToken'] );
			$hubspot_is_active            = $hubspot_is_configured && class_exists( 'SftcyWordformConnectHubspot' ) && SftcyWordformConnectHubspot::is_hubspot_configured_status_active();
			$make_info                    = class_exists( 'SftcyWordformConnectMake' ) ? SftcyWordformConnectMake::get_make_webhook_url() : [];
			$make_is_configured           = isset( $make_info['webhookPostUrl'] ) && ! empty( $make_info['webhookPostUrl'] );
			$make_is_active               = $make_is_configured && class_exists( 'SftcyWordformConnectMake' ) && SftcyWordformConnectMake::is_make_configured_status_active();
			$activecampaign_info          = class_exists( 'SftcyWordformConnectActivecampaign' ) ? SftcyWordformConnectActivecampaign::get_activecampaign_configured_info() : [];
			$activecampaign_is_configured = isset( $activecampaign_info['apiBaseUrl'], $activecampaign_info['apiKey'], $activecampaign_info['listId'] ) && ! empty( $activecampaign_info['apiBaseUrl'] ) && ! empty( $activecampaign_info['apiKey'] ) && ! empty( $activecampaign_info['listId'] );
			$activecampaign_is_active     = $activecampaign_is_configured && class_exists( 'SftcyWordformConnectActivecampaign' ) && SftcyWordformConnectActivecampaign::is_activecampaign_configured_status_active();
			$salesforce_credentials       = class_exists( 'SftcyWordformConnectSalesforce' ) ? SftcyWordformConnectSalesforce::get_salesforce_credentials() : [];
			$salesforce_token_info        = class_exists( 'SftcyWordformConnectSalesforce' ) ? SftcyWordformConnectSalesforce::get_salesforce_token_info() : [];
			$salesforce_is_configured     = ! empty( $salesforce_credentials ) && ! empty( $salesforce_token_info['refresh_token'] );
			$salesforce_is_active         = $salesforce_is_configured && class_exists( 'SftcyWordformConnectSalesforce' ) && SftcyWordformConnectSalesforce::is_salesforce_configured_status_active();
			$zohocrm_credentials          = class_exists( 'SftcyWordformConnectZohocrm' ) ? SftcyWordformConnectZohocrm::get_zohocrm_credentials() : [];
			$zohocrm_token_info           = class_exists( 'SftcyWordformConnectZohocrm' ) ? SftcyWordformConnectZohocrm::get_zohocrm_token_info() : [];
			$zohocrm_is_configured        = ! empty( $zohocrm_credentials ) && ! empty( $zohocrm_token_info['refresh_token'] );
			$zohocrm_is_active            = $zohocrm_is_configured && class_exists( 'SftcyWordformConnectZohocrm' ) && SftcyWordformConnectZohocrm::is_zohocrm_configured_status_active();

			$applications = [
				'googlesheet'  => [
					'slug'          => 'googlesheet',
					'name'          => 'Google Sheet',
					'category'      => 'data-storage',
					'category_label'=> 'Data & Storage',
					'program_name'  => 'GoogleSheetAPI',
					'modal_id'      => 'GoogleSheetAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/google-sheet-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="150" height="150" viewBox="0 0 48 48"><linearGradient id="gBjrhQfVvaLo6qORHi0_9a_6yIWVyFTE0no_gr1" x1="24" x2="24" y1="-166.87" y2="-248.839" gradientTransform="matrix(1 0 0 -1 0 -154)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#21ad64"></stop><stop offset="1" stop-color="#088242"></stop></linearGradient><path fill="url(#gBjrhQfVvaLo6qORHi0_9a_6yIWVyFTE0no_gr1)" d="M39,15v27c0,1.105-0.895,2-2,2H11c-1.105,0-2-0.895-2-2V6c0-1.105,0.895-2,2-2h17L39,15z"></path><path fill="#107c42" d="M28,4v10c0,0.552,0.448,1,1,1h10L28,4z"></path><path d="M16,33c-1.103,0-2-0.897-2-2V21c0-1.103,0.897-2,2-2h16c1.103,0,2,0.897,2,2v10c0,1.103-0.897,2-2,2	H16z M30,29v-1h-4v1H30z M22,29v-1h-4v1H22z M30,24v-1h-4v1H30z M22,24v-1h-4v1H22z" opacity=".05"></path><path d="M16,32.5c-0.827,0-1.5-0.673-1.5-1.5V21c0-0.827,0.673-1.5,1.5-1.5h16c0.827,0,1.5,0.673,1.5,1.5v10	c0,0.827-0.673,1.5-1.5,1.5H16z M30.5,29.5v-2h-5v2H30.5z M22.5,29.5v-2h-5v2H22.5z M30.5,24.5v-2h-5v2H30.5z M22.5,24.5v-2h-5v2	H22.5z" opacity=".07"></path><path fill="#fff" d="M32,20H16c-0.553,0-1,0.448-1,1v10c0,0.552,0.447,1,1,1h16c0.553,0,1-0.448,1-1V21	C33,20.448,32.553,20,32,20z M31,25h-6v-3h6V25z M23,22v3h-6v-3H23z M17,27h6v3h-6V27z M25,30v-3h6v3H25z"></path></svg>',
					'is_configured' => $google_is_configured,
					'is_active'     => $google_is_active,
				],
				'googlecalendar' => [
					'slug'          => 'googlecalendar',
					'name'          => 'Google Calendar',
					'category'      => 'scheduling-events',
					'category_label'=> 'Scheduling & Events',
					'program_name'  => 'GoogleCalendarAPI',
					'modal_id'      => 'GoogleCalendarAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/google-calendar-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path fill="#1a73e8" d="M37 6H11a4 4 0 0 0-4 4v28a4 4 0 0 0 4 4h26a4 4 0 0 0 4-4V10a4 4 0 0 0-4-4z"/><path fill="#fff" d="M14 4h4v8h-4zm16 0h4v8h-4z"/><path fill="#e8f0fe" d="M11 16h26v22a4 4 0 0 1-4 4H11a4 4 0 0 1-4-4V16z"/><path fill="#1a73e8" d="M18 22h5v5h-5zm7 0h5v5h-5zm-7 7h5v5h-5zm7 0h5v5h-5z"/></svg>',
					'is_configured' => $googlecalendar_is_configured,
					'is_active'     => $googlecalendar_is_active,
				],
				'zapier'       => [
					'slug'          => 'zapier',
					'name'          => 'Zapier',
					'category'      => 'automation-webhooks',
					'category_label'=> 'Automation & Webhooks',
					'program_name'  => 'ZapierAPI',
					'modal_id'      => 'ZapierAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/zapier-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#FF4A00" d="M508.5 300.3l-150-45.7 97.6-116.6-54.7-54.7-116.6 97.6-45.7-150h-77.9l-45.7 150-116.6-97.6-54.7 54.7 97.6 116.6-150 45.7v77.9l150 45.7-97.6 116.6 54.7 54.7 116.6-97.6 45.7 150h77.9l45.7-150 116.6 97.6 54.7-54.7-97.6-116.6 150-45.7v-77.9z"/></svg>',
					'is_configured' => $zapier_is_configured,
					'is_active'     => $zapier_is_active,
				],
				'customwebhook' => [
					'slug'          => 'customwebhook',
					'name'          => 'Custom Webhook',
					'category'      => 'automation-webhooks',
					'category_label'=> 'Automation & Webhooks',
					'program_name'  => 'CustomWebhookAPI',
					'modal_id'      => 'CustomWebhookAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/custom-webhook-modal.php',
					'icon_html'     => '<span class="dashicons dashicons-rest-api wordform-connect-card-main-icon" aria-hidden="true"></span>',
					'is_configured' => $custom_webhook_is_configured,
					'is_active'     => $custom_webhook_is_active,
				],
				'slack'         => [
					'slug'          => 'slack',
					'name'          => 'Slack',
					'category'      => 'automation-webhooks',
					'category_label'=> 'Automation & Webhooks',
					'program_name'  => 'SlackAPI',
					'modal_id'      => 'SlackAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/slack-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.8 122.8"><path fill="#e01e5a" d="M30.3 77.7c0 8.4-6.8 15.2-15.2 15.2S0 86.1 0 77.7s6.8-15.2 15.2-15.2h15.2v15.2z"/><path fill="#e01e5a" d="M37.9 77.7c0-8.4 6.8-15.2 15.2-15.2s15.2 6.8 15.2 15.2v38c0 8.4-6.8 15.2-15.2 15.2s-15.2-6.8-15.2-15.2v-38z"/><path fill="#36c5f0" d="M45.1 30.3c-8.4 0-15.2-6.8-15.2-15.2S36.7 0 45.1 0s15.2 6.8 15.2 15.2v15.2H45.1z"/><path fill="#36c5f0" d="M45.1 37.9c8.4 0 15.2 6.8 15.2 15.2s-6.8 15.2-15.2 15.2H7.6C-0.8 68.3-7.6 61.5-7.6 53.1S-.8 37.9 7.6 37.9h37.5z" transform="translate(7.6)"/><path fill="#2eb67d" d="M92.5 45.1c0-8.4 6.8-15.2 15.2-15.2s15.2 6.8 15.2 15.2-6.8 15.2-15.2 15.2H92.5V45.1z"/><path fill="#2eb67d" d="M84.9 45.1c0 8.4-6.8 15.2-15.2 15.2s-15.2-6.8-15.2-15.2V7.6c0-8.4 6.8-15.2 15.2-15.2S84.9-.8 84.9 7.6v37.5z" transform="translate(0 7.6)"/><path fill="#ecb22e" d="M77.7 92.5c8.4 0 15.2 6.8 15.2 15.2s-6.8 15.2-15.2 15.2-15.2-6.8-15.2-15.2V92.5h15.2z"/><path fill="#ecb22e" d="M77.7 84.9c-8.4 0-15.2-6.8-15.2-15.2s6.8-15.2 15.2-15.2h37.5c8.4 0 15.2 6.8 15.2 15.2s-6.8 15.2-15.2 15.2H77.7z"/></svg>',
					'is_configured' => $slack_is_configured,
					'is_active'     => $slack_is_active,
				],
				'mailchimp'     => [
					'slug'          => 'mailchimp',
					'name'          => 'Mailchimp',
					'category'      => 'email-marketing',
					'category_label'=> 'Email Marketing',
					'program_name'  => 'MailchimpAPI',
					'modal_id'      => 'MailchimpAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/mailchimp-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#ffe01b" d="M511.92 262.28c-4.64 91.44-79.62 165.44-171.18 168.8-39.12 1.44-75.38-10.14-105.12-31.06-11.66-8.18-27.76-4.46-34.6 8.02l-20.62 37.58c-7.18 13.08-3.2 29.54 9.22 37.8 43.08 28.66 95.06 44.92 150.86 44.92 146.16 0 265.14-118.98 265.14-265.14 0-7.08-.28-14.1-.82-21.04-.76-9.94-9.32-17.36-19.28-16.84l-56.9 3.16c-9.98 .56-17.38 9.4-16.7 19.8z"/><path fill="#231f20" d="M227.34 266.88c19.52 14.42 42.98 22.74 67.72 22.74 64.86 0 117.64-52.78 117.64-117.64S359.92 54.34 295.06 54.34 177.42 107.12 177.42 171.98c0 10.52 1.4 20.7 4 30.38 2.66 9.88 13.16 15.02 22.56 11.02l53.54-22.76c14.14-6 28.96-8.94 45.34-8.94 37.72 0 68.4 30.68 68.4 68.4s-30.68 68.4-68.4 68.4c-22.74 0-44.12-11.36-56.9-30.36-5.82-8.66-17.26-11.62-26.54-6.78l-47.52 24.8c-9.06 4.72-12.56 16.08-8.1 25.28 11.08 22.74 28.6 42.36 50.64 56.66 10.3 6.68 23.92 3.18 29.5-7.76l18.96-37.16c5.28-10.34 1.8-23.06-8.04-29.88-9.98-6.92-18.78-15.48-26.12-25.38z"/><path fill="#231f20" d="M141.1 158.32c-34.64-6.12-68.14-2.46-97.62 9.58-6.98 2.84-11.36 9.9-10.84 17.42l5.22 74.34c.58 8.2 6.8 14.94 14.96 16.14 17.38 2.56 34.74 8.68 50.2 18.16 8.24 5.04 18.94 2.4 24.02-5.82l28.3-45.94c4.96-8.06 2.86-18.58-4.76-24.22-9.34-6.9-19.7-12.02-30.52-15.66 9.36-4.38 19.58-7.14 30.28-8.06 9.9-.84 17.28-9.48 16.56-19.38l-4.2-57.94c-.68-9.56-8.4-17.08-17.6-17.62-1.32-.08-2.66-.1-4-.1z"/></svg>',
					'is_configured' => $mailchimp_is_configured,
					'is_active'     => $mailchimp_is_active,
				],
				'mailerlite'    => [
					'slug'          => 'mailerlite',
					'name'          => 'MailerLite',
					'category'      => 'email-marketing',
					'category_label'=> 'Email Marketing',
					'program_name'  => 'MailerLiteAPI',
					'modal_id'      => 'MailerLiteAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/mailerlite-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" aria-hidden="true"><rect width="96" height="96" rx="22" fill="#1a6cff"></rect><path fill="#fff" d="M24 64V32h10.4l13.1 21.2L60.6 32H71v32H60.6V48.7l-8.4 13.5h-9.2l-8.6-13.6V64z"/></svg>',
					'is_configured' => $mailerlite_is_configured,
					'is_active'     => $mailerlite_is_active,
				],
				'airtable'      => [
					'slug'          => 'airtable',
					'name'          => 'Airtable',
					'category'      => 'data-storage',
					'category_label'=> 'Data & Storage',
					'program_name'  => 'AirtableAPI',
					'modal_id'      => 'AirtableAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/airtable-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 420"><path fill="#fcb400" d="M188.2 27.4 33.8 90.4c-14.4 5.9-14.1 26.4.5 31.9l154.8 58.7c13.5 5.1 28.4 5.1 41.9 0l154.8-58.7c14.6-5.5 14.9-26 .5-31.9L231.8 27.4a58.5 58.5 0 0 0-43.6 0Z"/><path fill="#18bfff" d="m224.7 213.6 0 164.7c0 11.4 11.5 19.2 22.1 14.8l173.1-72.9c6.3-2.6 10.4-8.8 10.4-15.6V139.9c0-11.4-11.5-19.2-22.1-14.8l-173.1 72.9a17 17 0 0 0-10.4 15.6Z"/><path fill="#f82b60" d="m183.3 221.7-50.9 24.6-7.3 3.5L.9 309.3c-10.6 5.1-10.6 20.1 0 25.2L155 408.7c17.2 8.3 37-4.2 37-23.4V221.7c0-12.5-13.5-20.4-24.7-15Z"/><path fill="#ba1e45" d="m183.3 221.7-50.9 24.6L5.5 181.9c-10.9-5.5-10.4-21.2.8-26.1l154-68.9c10.5-4.7 22.4 3 22.4 14.5v120.3c0 6.1-3.5 11.7-8.9 14.3Z"/></svg>',
					'is_configured' => $airtable_is_configured,
					'is_active'     => $airtable_is_active,
				],
				'brevo'         => [
					'slug'          => 'brevo',
					'name'          => 'Brevo',
					'category'      => 'email-marketing',
					'category_label'=> 'Email Marketing',
					'program_name'  => 'BrevoAPI',
					'modal_id'      => 'BrevoAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/brevo-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#0b996f" d="M78.8 32h354.4C476.7 32 512 67.3 512 110.8v290.4C512 444.7 476.7 480 433.2 480H78.8C35.3 480 0 444.7 0 401.2V110.8C0 67.3 35.3 32 78.8 32z"/><path fill="#fff" d="M150.5 129.6h137.9c61 0 99.9 32.1 99.9 83.2 0 34.4-17 58.3-48.6 68.4v1.3c40.1 8 61.6 33.7 61.6 73.5 0 58.3-42.7 95.5-109 95.5H150.5V129.6zm132.2 123.2c24.6 0 39.8-11.2 39.8-30.5 0-18.2-13.7-28.7-38.6-28.7h-62.7v59.2h61.5zm9.3 133.3c27.8 0 44.8-12.4 44.8-34.7 0-21.5-16.1-33.4-45.4-33.4h-70.2v68.1H292z"/></svg>',
					'is_configured' => $brevo_is_configured,
					'is_active'     => $brevo_is_active,
				],
				'hubspot'      => [
					'slug'          => 'hubspot',
					'name'          => 'HubSpot',
					'category'      => 'crm-sales',
					'category_label'=> 'CRM & Sales',
					'program_name'  => 'HubspotAPI',
					'modal_id'      => 'HubspotAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/hubspot-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#ff7a59" d="M512 257.3c0-31.8-25.8-57.6-57.6-57.6-8.3 0-16.2 1.8-23.3 5V110.9c13.5-5.8 23-19.2 23-34.8 0-20.9-16.9-37.8-37.8-37.8s-37.8 16.9-37.8 37.8c0 15.6 9.5 29 23 34.8v93.8c-6.6-3.2-13.9-5-21.7-5-31.8 0-57.6 25.8-57.6 57.6 0 27.3 19 50.1 44.6 56v58.4h-58.5c-5.8-25.6-28.7-44.8-56.1-44.8-31.8 0-57.6 25.8-57.6 57.6S223.5 442 255.3 442c27.4 0 50.3-19.2 56.1-44.8h58.5v38.4c-13.5 5.8-23 19.2-23 34.8 0 20.9 16.9 37.8 37.8 37.8s37.8-16.9 37.8-37.8c0-15.6-9.5-29-23-34.8v-38.4h15.9c31.8 0 57.6-25.8 57.6-57.6 0-22.2-12.6-41.4-31.1-51v-31.1c25.6-5.8 44.9-28.7 44.9-56.2zM255.3 391.4c-17.7 0-32.1-14.4-32.1-32.1s14.4-32.1 32.1-32.1 32.1 14.4 32.1 32.1-14.4 32.1-32.1 32.1zm124.5-102c-17.7 0-32.1-14.4-32.1-32.1s14.4-32.1 32.1-32.1 32.1 14.4 32.1 32.1-14.4 32.1-32.1 32.1z"/></svg>',
					'is_configured' => $hubspot_is_configured,
					'is_active'     => $hubspot_is_active,
				],
				'make'         => [
					'slug'          => 'make',
					'name'          => 'Make',
					'category'      => 'automation-webhooks',
					'category_label'=> 'Automation & Webhooks',
					'program_name'  => 'MakeAPI',
					'modal_id'      => 'MakeAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/make-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#6d5dfc" d="M116.3 409.6c-55.5 0-100.5-45-100.5-100.5s45-100.5 100.5-100.5h76.8c17.7 0 32 14.3 32 32v137c0 17.7-14.3 32-32 32h-76.8zm102.7-216.7c-17.7 0-32-14.3-32-32V84c0-55.5 45-100.5 100.5-100.5S388 28.5 388 84v76.8c0 17.7-14.3 32-32 32H219zm176.7 0c-55.5 0-100.5-45-100.5-100.5S340.2-8 395.7-8s100.5 45 100.5 100.5S451.2 192.9 395.7 192.9zm0 224.7c-55.5 0-100.5-45-100.5-100.5s45-100.5 100.5-100.5 100.5 45 100.5 100.5-45 100.5-100.5 100.5zM219 519.9c-17.7 0-32-14.3-32-32v-76.8c0-17.7 14.3-32 32-32h137c17.7 0 32 14.3 32 32v76.8c0 55.5-45 100.5-100.5 100.5S219 575.4 219 519.9z"/></svg>',
					'is_configured' => $make_is_configured,
					'is_active'     => $make_is_active,
				],
				'activecampaign' => [
					'slug'          => 'activecampaign',
					'name'          => 'ActiveCampaign',
					'category'      => 'email-marketing',
					'category_label'=> 'Email Marketing',
					'program_name'  => 'ActivecampaignAPI',
					'modal_id'      => 'ActivecampaignAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/activecampaign-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#356ae6" d="M256 32C132.3 32 32 132.3 32 256s100.3 224 224 224 224-100.3 224-224S379.7 32 256 32zm101.8 143.9L245 334.6c-7.9 11-24.2 13.6-35.3 5.5l-55.1-39.9c-11.2-8.1-13.6-23.8-5.5-35s23.8-13.6 35-5.5l34.7 25.1 98.2-138.1c8-11.2 23.7-13.8 35-5.8 11.2 8 13.8 23.7 5.8 35z"/></svg>',
					'is_configured' => $activecampaign_is_configured,
					'is_active'     => $activecampaign_is_active,
				],
				'salesforce'    => [
					'slug'          => 'salesforce',
					'name'          => 'Salesforce',
					'category'      => 'crm-sales',
					'category_label'=> 'CRM & Sales',
					'program_name'  => 'SalesforceAPI',
					'modal_id'      => 'SalesforceAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/salesforce-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#00a1e0" d="M379.5 213.5c-13.7 0-26.5 3.5-37.8 9.7-8.3-39.5-43.4-69.2-85.3-69.2-28.3 0-53.5 13.5-69.4 34.4-11.4-6.4-24.6-10-38.7-10-43.5 0-78.8 35.2-78.8 78.7s35.3 78.8 78.8 78.8c5.9 0 11.6-.7 17.1-1.9C182.2 364 216.3 384 255 384c35.8 0 68.3-17 88.8-43.7 10.7 5.5 22.9 8.7 35.8 8.7 43.5 0 78.8-35.3 78.8-78.8s-35.3-78.7-78.9-78.7z"/></svg>',
					'is_configured' => $salesforce_is_configured,
					'is_active'     => $salesforce_is_active,
				],
				'zohocrm'       => [
					'slug'          => 'zohocrm',
					'name'          => 'Zoho CRM',
					'category'      => 'crm-sales',
					'category_label'=> 'CRM & Sales',
					'program_name'  => 'ZohocrmAPI',
					'modal_id'      => 'ZohocrmAPIModal',
					'modal_view'    => SFTCY_WORDFORM_PLUGIN_DIR . 'admin/views/connect-modals/zohocrm-modal.php',
					'icon_html'     => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#e42527" d="M64 96h128v128H64z"/><path fill="#f89c1c" d="M224 96h128v128H224z"/><path fill="#0467b1" d="M384 96h64c35.3 0 64 28.7 64 64v64H384z"/><path fill="#1aa34a" d="M64 256h448v96c0 35.3-28.7 64-64 64H64z"/></svg>',
					'is_configured' => $zohocrm_is_configured,
					'is_active'     => $zohocrm_is_active,
				],
			];

			if ( class_exists( 'SftcyWordformFeatures' ) ) {
				foreach ( $applications as $application_key => $application ) {
					$application_slug = isset( $application['slug'] ) ? sanitize_key( $application['slug'] ) : '';
					$applications[ $application_key ]['is_available'] = ! empty( $application_slug ) ? SftcyWordformFeatures::wordform_is_connect_application_available( $application_slug ) : true;
				}
			}

			return $applications;
		}

		/**
		 * Save connected application information into DB.
		 * Table: scwordform_connects_data
		 *
		 * @param array $data Connection data to insert or update.
		 * @return int|false
		 */
		public static function wordform_save_connected_application_info( $data = [] ) {
			if ( ! array_filter( $data ) ) {
				return false;
			}

			global $wpdb;
			$table          = $wpdb->prefix . SftcyWordformBase::$sc_wordform_connects_tbl;
			$wordform_id    = isset( $data['wordform_id'] ) ? $data['wordform_id'] : '';
			$application_id = isset( $data['configured_application_tbl_id'] ) ? $data['configured_application_tbl_id'] : 0;

			$query_results = $wpdb->get_results(
				$wpdb->prepare(
					'SELECT * FROM %i WHERE wordform_id = %s AND configured_application_tbl_id = %d LIMIT 1',
					array( $table, $wordform_id, $application_id )
				),
				ARRAY_A
			);

			// If same WordForm and application exist then update, else insert.
			if ( $query_results ) {
				$where = [ 'id' => $query_results[0]['id'] ];
				return $wpdb->update( $table, $data, $where );
			}

			return $wpdb->insert( $table, $data );
		}

		/**
		 * Check whether selected WordForm is already connected with the same application.
		 *
		 * @param int    $configured_application_tbl_id Configured application table ID.
		 * @param string $wordform_id WordForm ID.
		 * @return bool
		 */
		public static function is_wordform_with_application_connected( $configured_application_tbl_id = 0, $wordform_id = '' ) {
			if ( $configured_application_tbl_id <= 0 || empty( $wordform_id ) ) {
				return false;
			}

			global $wpdb;
			$table = $wpdb->prefix . SftcyWordformBase::$sc_wordform_connects_tbl;

			$query_results = $wpdb->get_results(
				$wpdb->prepare(
					'SELECT * FROM %i WHERE wordform_id = %s AND configured_application_tbl_id = %d LIMIT 1',
					array( $table, $wordform_id, $configured_application_tbl_id )
				),
				ARRAY_A
			);

			return ! empty( $query_results );
		}

		/**
		 * Get application slug value based on configured application ID.
		 *
		 * @param int $configured_application_tbl_id Configured application table ID.
		 * @return string
		 */
		public static function wordform_get_application_slug_by_configured_application_id( $configured_application_tbl_id = 0 ) {
			if ( $configured_application_tbl_id <= 0 ) {
				return '';
			}

			global $wpdb;
			$table             = $wpdb->prefix . SftcyWordformBase::$sc_wordform_configured_application_tbl;
			$configured_status = 'active';

			$query_results = $wpdb->get_results(
				$wpdb->prepare(
					'SELECT * FROM %i WHERE id = %d AND configured_status = %s LIMIT 1',
					array( $table, $configured_application_tbl_id, $configured_status )
				),
				ARRAY_A
			);

			if ( $query_results ) {
				return $query_results[0]['application_slug'];
			}

			return '';
		}

		/**
		 * Get configured application row by application slug.
		 *
		 * @param string $application_slug Application slug.
		 * @return array
		 */
		public static function get_configured_application_by_slug( $application_slug = '' ) {
			if ( empty( $application_slug ) ) {
				return [];
			}

			global $wpdb;
			$table         = $wpdb->prefix . SftcyWordformBase::$sc_wordform_configured_application_tbl;
			$query_results = $wpdb->get_results(
				$wpdb->prepare(
					'SELECT * FROM %i WHERE application_slug = %s LIMIT 1',
					array( $table, $application_slug )
				),
				ARRAY_A
			);

			if ( $query_results ) {
				return $query_results[0];
			}

			return [];
		}

		/**
		 * Get configured application option payload for UI handoff.
		 *
		 * @param string $application_slug Application slug.
		 * @return array
		 */
		public static function get_configured_application_option_payload( $application_slug = '' ) {
			if ( class_exists( 'SftcyWordformFeatures' ) && ! SftcyWordformFeatures::wordform_is_connect_application_available( $application_slug ) ) {
				return array();
			}

			$configured_application = self::get_configured_application_by_slug( $application_slug );
			if ( empty( $configured_application ) ) {
				return array();
			}

			return array(
				'id'              => isset( $configured_application['id'] ) ? absint( $configured_application['id'] ) : 0,
				'applicationSlug' => isset( $configured_application['application_slug'] ) ? sanitize_key( $configured_application['application_slug'] ) : '',
				'applicationName' => isset( $configured_application['application_name'] ) ? sanitize_text_field( $configured_application['application_name'] ) : '',
			);
		}

		/**
		 * Get connected application row by configured application ID and WordForm ID.
		 *
		 * @param int    $configured_application_tbl_id Configured application table ID.
		 * @param string $wordform_id WordForm ID.
		 * @return array
		 */
		public static function get_connected_application_row( $configured_application_tbl_id = 0, $wordform_id = '' ) {
			if ( $configured_application_tbl_id <= 0 || empty( $wordform_id ) ) {
				return [];
			}

			global $wpdb;
			$table         = $wpdb->prefix . SftcyWordformBase::$sc_wordform_connects_tbl;
			$query_results = $wpdb->get_results(
				$wpdb->prepare(
					'SELECT * FROM %i WHERE wordform_id = %s AND configured_application_tbl_id = %d LIMIT 1',
					array( $table, $wordform_id, $configured_application_tbl_id )
				),
				ARRAY_A
			);

			if ( $query_results ) {
				return $query_results[0];
			}

			return [];
		}

		/**
		 * Return whether the current WordPress host looks like a local/private development environment.
		 *
		 * @return bool
		 */
		public static function is_wordform_connect_local_environment() {
			$host = isset( $_SERVER['SERVER_NAME'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_NAME'] ) ) : '';
			if ( empty( $host ) && isset( $_SERVER['HTTP_HOST'] ) ) {
				$host = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) );
			}

			$host = strtolower( trim( preg_replace( '/:\d+$/', '', (string) $host ) ) );
			if ( empty( $host ) ) {
				return false;
			}

			if ( in_array( $host, [ 'localhost', '127.0.0.1', '::1' ], true ) ) {
				return true;
			}

			if ( preg_match( '/\.(local|test|invalid)$/', $host ) ) {
				return true;
			}

			if ( preg_match( '/^(10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3})$/', $host ) ) {
				return true;
			}

			return false;
		}

		/**
		 * Get shared OAuth redirect URL used by connection providers.
		 * Uses the site callback directly by default and allows explicit local-dev overrides.
		 *
		 * @return string
		 */
		public static function get_wordform_connect_oauth_redirect_url() {
			$default_redirect_url = admin_url( 'admin.php?page=wordform-connects' );
			$redirect_url         = $default_redirect_url;

			if ( defined( 'WORDFORM_CONNECT_OAUTH_REDIRECT_URL' ) && is_string( WORDFORM_CONNECT_OAUTH_REDIRECT_URL ) ) {
				$constant_redirect_url = trim( WORDFORM_CONNECT_OAUTH_REDIRECT_URL );
				if ( ! empty( $constant_redirect_url ) ) {
					$redirect_url = $constant_redirect_url;
				}
			}

			$redirect_url = apply_filters( 'wordform_connect_oauth_redirect_url', $redirect_url, $default_redirect_url );
			$redirect_url = esc_url_raw( trim( (string) $redirect_url ) );

			if ( empty( $redirect_url ) ) {
				return esc_url_raw( $default_redirect_url );
			}

			return $redirect_url;
		}

		/**
		 * Extract the first valid email value from processed submission fields.
		 *
		 * @param array $forms_data Processed form submission fields.
		 * @return string
		 */
		public static function extract_first_valid_email_from_submission_fields( $forms_data = [] ) {
			if ( ! is_array( $forms_data ) || ! array_filter( $forms_data ) ) {
				return '';
			}

			foreach ( $forms_data as $field_info ) {
				$field_value = isset( $field_info['formFieldValues'] ) ? sanitize_email( (string) $field_info['formFieldValues'] ) : '';
				if ( ! empty( $field_value ) && is_email( $field_value ) ) {
					return $field_value;
				}
			}

			return '';
		}

		/**
		 * Extract likely first and last name values from processed submission fields.
		 * This is a best-effort helper for CRM and email marketing apps.
		 *
		 * @param array $forms_data Processed form submission fields.
		 * @return array
		 */
		public static function extract_name_parts_from_submission_fields( $forms_data = [] ) {
			$name_parts = [
				'firstName' => '',
				'lastName'  => '',
			];

			if ( ! is_array( $forms_data ) || ! array_filter( $forms_data ) ) {
				return $name_parts;
			}

			foreach ( $forms_data as $field_info ) {
				$field_label = isset( $field_info['formLabelName'] ) ? sanitize_text_field( $field_info['formLabelName'] ) : '';
				$field_value = isset( $field_info['formFieldValues'] ) ? sanitize_text_field( (string) $field_info['formFieldValues'] ) : '';
				$label_key   = strtolower( $field_label );

				if ( empty( $name_parts['firstName'] ) && false !== strpos( $label_key, 'first' ) ) {
					$name_parts['firstName'] = $field_value;
				}

				if ( empty( $name_parts['lastName'] ) && false !== strpos( $label_key, 'last' ) ) {
					$name_parts['lastName'] = $field_value;
				}
			}

			return $name_parts;
		}

		/**
		 * Extract common CRM/contact properties from processed submission fields.
		 * Best effort only. Intended for apps like HubSpot.
		 *
		 * @param array $forms_data Processed form submission fields.
		 * @return array
		 */
		public static function extract_common_contact_properties_from_submission_fields( $forms_data = [] ) {
			$properties = [
				'email'     => self::extract_first_valid_email_from_submission_fields( $forms_data ),
				'firstName' => '',
				'lastName'  => '',
				'phone'     => '',
				'company'   => '',
			];

			$name_parts = self::extract_name_parts_from_submission_fields( $forms_data );
			if ( ! empty( $name_parts['firstName'] ) ) {
				$properties['firstName'] = $name_parts['firstName'];
			}
			if ( ! empty( $name_parts['lastName'] ) ) {
				$properties['lastName'] = $name_parts['lastName'];
			}

			if ( ! is_array( $forms_data ) || ! array_filter( $forms_data ) ) {
				return $properties;
			}

			foreach ( $forms_data as $field_info ) {
				$field_label = isset( $field_info['formLabelName'] ) ? sanitize_text_field( $field_info['formLabelName'] ) : '';
				$field_value = isset( $field_info['formFieldValues'] ) ? sanitize_text_field( (string) $field_info['formFieldValues'] ) : '';
				$label_key   = strtolower( $field_label );

				if ( empty( $properties['phone'] ) && ( false !== strpos( $label_key, 'phone' ) || false !== strpos( $label_key, 'mobile' ) || false !== strpos( $label_key, 'tel' ) ) ) {
					$properties['phone'] = $field_value;
				}

				if ( empty( $properties['company'] ) && ( false !== strpos( $label_key, 'company' ) || false !== strpos( $label_key, 'business' ) || false !== strpos( $label_key, 'organization' ) ) ) {
					$properties['company'] = $field_value;
				}
			}

			return $properties;
		}

		/**
		 * Build associative field map from processed submission fields.
		 * Keeps original labels so integrations like Airtable can match table columns.
		 *
		 * @param array $forms_data Processed form submission fields.
		 * @return array
		 */
		public static function extract_submission_fields_map( $forms_data = [] ) {
			$fields_map = [];

			if ( ! is_array( $forms_data ) || ! array_filter( $forms_data ) ) {
				return $fields_map;
			}

			foreach ( $forms_data as $index => $field_info ) {
				$field_label = isset( $field_info['formLabelName'] ) && ! empty( $field_info['formLabelName'] ) ? sanitize_text_field( $field_info['formLabelName'] ) : 'Field ' . ( $index + 1 );
				$field_value = isset( $field_info['formFieldValues'] ) ? sanitize_textarea_field( (string) $field_info['formFieldValues'] ) : '';
				$unique_key  = $field_label;
				$duplicate_i = 2;

				while ( isset( $fields_map[ $unique_key ] ) ) {
					$unique_key = $field_label . ' (' . $duplicate_i . ')';
					$duplicate_i++;
				}

				$fields_map[ $unique_key ] = $field_value;
			}

			return $fields_map;
		}

		/**
		 * Get connection status report help meta by application slug.
		 * Used in the Connection Status tab and failure detail modal.
		 *
		 * @param string $application_slug Application slug.
		 * @return array
		 */
		public static function get_connection_status_help_meta( $application_slug = '' ) {
			$meta = [
				'googlesheet' => [
					'docsUrl'        => 'https://developers.google.com/sheets/api/quickstart/js',
					'docsLabel'      => 'Google Sheets setup guide',
					'suggestion'     => 'Reconfigure the Google account if access was revoked and confirm the spreadsheet still exists.',
				],
				'googlecalendar' => [
					'docsUrl'        => 'https://developers.google.com/workspace/calendar/api/guides/create-events',
					'docsLabel'      => 'Google Calendar event creation guide',
					'suggestion'     => 'Reconnect Google Calendar if access was revoked, confirm the selected calendar still exists, and make sure the form includes a valid Date or Datetime field.',
				],
				'zapier' => [
					'docsUrl'        => 'https://help.zapier.com/hc/en-us/articles/8496288690317-Trigger-Zaps-from-webhooks',
					'docsLabel'      => 'Zapier Catch Hook guide',
					'suggestion'     => 'Check that the Catch Hook URL is still active and the Zap is published.',
				],
				'customwebhook' => [
					'docsUrl'        => 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST',
					'docsLabel'      => 'Webhook POST guide',
					'suggestion'     => 'Confirm the endpoint URL is correct and the receiver accepts JSON POST requests.',
				],
				'slack' => [
					'docsUrl'        => 'https://api.slack.com/messaging/webhooks',
					'docsLabel'      => 'Slack Incoming Webhooks docs',
					'suggestion'     => 'Verify the webhook still belongs to the target channel and was not revoked in Slack.',
				],
				'mailchimp' => [
					'docsUrl'        => 'https://mailchimp.com/developer/marketing/api/list-members/',
					'docsLabel'      => 'Mailchimp audience API docs',
					'suggestion'     => 'Check the API key, server suffix, audience ID, and that the form submission includes a valid email field.',
				],
				'mailerlite' => [
					'docsUrl'        => 'https://developers.mailerlite.com/docs/subscribers',
					'docsLabel'      => 'MailerLite subscribers API docs',
					'suggestion'     => 'Check the API token, selected group, and confirm the connected form includes at least one valid email field.',
				],
				'airtable' => [
					'docsUrl'        => 'https://airtable.com/developers/web/api/introduction',
					'docsLabel'      => 'Airtable API docs',
					'suggestion'     => 'Confirm the base ID, table name, access token scopes, and that form labels match Airtable column names.',
				],
				'brevo' => [
					'docsUrl'        => 'https://developers.brevo.com/reference/createcontact',
					'docsLabel'      => 'Brevo contacts API docs',
					'suggestion'     => 'Check the Brevo API key, list ID, and confirm the form has at least one valid email field.',
				],
				'hubspot' => [
					'docsUrl'        => 'https://developers.hubspot.com/docs/api-reference/crm-contacts-v3/guide',
					'docsLabel'      => 'HubSpot contacts guide',
					'suggestion'     => 'Verify the private app token still has contact read/write scopes and the form includes a valid email.',
				],
				'make' => [
					'docsUrl'        => 'https://help.make.com/custom-webhooks',
					'docsLabel'      => 'Make custom webhook guide',
					'suggestion'     => 'Confirm the Make webhook URL still belongs to an active scenario and the scenario is turned on.',
				],
				'activecampaign' => [
					'docsUrl'        => 'https://developers.activecampaign.com/reference/sync-a-contacts-data',
					'docsLabel'      => 'ActiveCampaign contact sync docs',
					'suggestion'     => 'Check the API URL, API key, list ID, and make sure the connected form sends a valid email address.',
				],
				'salesforce' => [
					'docsUrl'        => 'https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_web_server_oauth_flow.htm',
					'docsLabel'      => 'Salesforce OAuth flow docs',
					'suggestion'     => 'Reconnect Salesforce if refresh access was lost and confirm the connected user can create or update Contacts.',
				],
				'zohocrm' => [
					'docsUrl'        => 'https://www.zoho.com/accounts/protocol/oauth/web-server-applications.html',
					'docsLabel'      => 'Zoho CRM OAuth guide',
					'suggestion'     => 'Reconnect Zoho CRM if tokens were revoked and confirm the connected user can upsert Contacts.',
				],
			];

			if ( isset( $meta[ $application_slug ] ) ) {
				return $meta[ $application_slug ];
			}

			return [
				'docsUrl'    => '',
				'docsLabel'  => '',
				'suggestion' => 'Recheck the application configuration and reconnect it if needed.',
			];
		}

		/**
		 * Get connection send log detail page URL for a specific form.
		 *
		 * @param string $form_id WordForm ID.
		 * @return string
		 */
		public static function get_connection_status_send_log_page_url( $form_id = '' ) {
			$form_id = sanitize_text_field( $form_id );
			if ( empty( $form_id ) ) {
				return admin_url( 'admin.php?page=wordform-connects#scWordFormConnectionStatus' );
			}

			return add_query_arg(
				'form_id',
				$form_id,
				admin_url( 'admin.php?page=sc-wordform-connection-status-send-log' )
			);
		}

		/**
		 * Format a submission datetime for connection reporting views.
		 *
		 * @param string $datetime MySQL datetime value.
		 * @return string
		 */
		public static function format_connection_status_datetime( $datetime = '' ) {
			if ( empty( $datetime ) ) {
				return '';
			}

			$timestamp = strtotime( $datetime );
			if ( false === $timestamp ) {
				return '';
			}

			return date_i18n( 'j M Y, g:i a', $timestamp );
		}

		/**
		 * Convert stored submission JSON into a modal-friendly HTML table.
		 *
		 * @param string $submission_data_json Raw submission JSON.
		 * @return string
		 */
		public static function get_connection_submission_data_modal_html( $submission_data_json = '' ) {
			if ( empty( $submission_data_json ) ) {
				return '<p>' . esc_html__( 'No submitted field data found.', 'wordform-pro' ) . '</p>';
			}

			$decoded_submission_data = json_decode( $submission_data_json, true );
			if ( ! is_array( $decoded_submission_data ) || ! array_filter( $decoded_submission_data ) ) {
				return '<p>' . esc_html__( 'Submitted field data could not be read.', 'wordform-pro' ) . '</p>';
			}

			SftcyWordformFormSubmission::$sc_wordform_return_processed_raw_data = true;
			SftcyWordformFormSubmission::$sc_wordform_submission_array_data     = $decoded_submission_data;
			SftcyWordformFormSubmission::$sc_wordform_processed_forms_raw_data  = [];
			$processed_submission_fields = SftcyWordformFormSubmission::sc_wordform_process_submission_data();
			SftcyWordformFormSubmission::$sc_wordform_return_processed_raw_data = false;
			SftcyWordformFormSubmission::$sc_wordform_submission_array_data     = [];
			SftcyWordformFormSubmission::$sc_wordform_processed_forms_raw_data  = [];

			if ( ! is_array( $processed_submission_fields ) || ! array_filter( $processed_submission_fields ) ) {
				return '<p>' . esc_html__( 'No submitted field data found.', 'wordform-pro' ) . '</p>';
			}

			ob_start();
			?>
			<div class="wordform-connection-send-log-submission-data-wrapper">
				<table class="widefat striped wordform-connection-send-log-submission-data-table">
					<thead>
						<tr>
							<th><?php esc_html_e( 'Field Name', 'wordform-pro' ); ?></th>
							<th><?php esc_html_e( 'Submitted Value', 'wordform-pro' ); ?></th>
						</tr>
					</thead>
					<tbody>
						<?php foreach ( $processed_submission_fields as $submission_field ) { ?>
							<tr>
								<td>
									<?php
									echo esc_html(
										isset( $submission_field['formLabelName'] ) && '' !== $submission_field['formLabelName']
											? $submission_field['formLabelName']
											: __( 'Field', 'wordform-pro' )
									);
									?>
								</td>
								<td>
									<?php
									$field_value = isset( $submission_field['formFieldValues'] ) ? (string) $submission_field['formFieldValues'] : '';
									if ( '' === $field_value ) {
										echo '<span class="description">' . esc_html__( 'No value', 'wordform-pro' ) . '</span>';
									} else {
										echo nl2br( esc_html( $field_value ) );
									}
									?>
								</td>
							</tr>
						<?php } ?>
					</tbody>
				</table>
			</div>
			<?php

			return ob_get_clean();
		}

		/**
		 * Build DataTable rows for a form-specific connection send log page.
		 * One row represents one submission and one application send attempt.
		 *
		 * @param array $post_data DataTable request payload.
		 * @return array
		 */
		public static function get_connection_status_send_log_table_data( $post_data = [] ) {
			global $wpdb;

			$form_id = isset( $post_data['form_id'] ) ? sanitize_text_field( wp_unslash( $post_data['form_id'] ) ) : '';
			$draw    = isset( $post_data['draw'] ) ? absint( $post_data['draw'] ) : 1;
			$start   = isset( $post_data['start'] ) ? absint( $post_data['start'] ) : 0;
			$length  = isset( $post_data['length'] ) ? absint( $post_data['length'] ) : 10;

			if ( empty( $form_id ) ) {
				return [
					'draw'            => $draw,
					'recordsTotal'    => 0,
					'recordsFiltered' => 0,
					'data'            => [],
				];
			}

			$created_forms_table = $wpdb->prefix . SftcyWordformBase::$sc_wordform_tbl;
			$submission_table    = $wpdb->prefix . SftcyWordformBase::$sc_wordform_submission_tbl;
			$applications        = self::get_connects_page_applications_registry();
			$form_row            = SftcyWordformBase::sc_wordform_db_query( $form_id );
			$form_name           = '';

			if ( is_array( $form_row ) && ! empty( $form_row[0]['form_name'] ) ) {
				$form_name = sanitize_text_field( $form_row[0]['form_name'] );
			}

			$submission_rows = $wpdb->get_results(
				$wpdb->prepare(
					"SELECT wcf.form_name, wst.id, wst.form_id, wst.submission_data, wst.data_send_info, wst.created_at
					FROM {$submission_table} AS wst
					INNER JOIN {$created_forms_table} AS wcf ON wcf.form_id = wst.form_id
					WHERE wst.form_id = %s
					ORDER BY wst.id DESC",
					$form_id
				),
				ARRAY_A
			);

			$expanded_rows = [];
			if ( $submission_rows ) {
				foreach ( $submission_rows as $submission_row ) {
					$submission_id    = isset( $submission_row['id'] ) ? absint( $submission_row['id'] ) : 0;
					$submission_date  = isset( $submission_row['created_at'] ) ? sanitize_text_field( $submission_row['created_at'] ) : '';
					$submission_stamp = $submission_date ? strtotime( $submission_date ) : 0;
					$submission_html  = self::get_connection_submission_data_modal_html(
						isset( $submission_row['submission_data'] ) ? (string) $submission_row['submission_data'] : ''
					);
					$send_info        = [];

					if ( ! empty( $submission_row['data_send_info'] ) ) {
						$decoded_send_info = json_decode( $submission_row['data_send_info'], true );
						$send_info         = is_array( $decoded_send_info ) ? $decoded_send_info : [];
					}

					if ( ! $send_info ) {
						continue;
					}

					foreach ( $send_info as $application_slug => $application_send_info ) {
						$application_slug = sanitize_key( $application_slug );
						if ( 'dbstoredstatus' === strtolower( $application_slug ) || ! is_array( $application_send_info ) ) {
							continue;
						}

						$application_name = isset( $applications[ $application_slug ]['name'] )
							? sanitize_text_field( $applications[ $application_slug ]['name'] )
							: ucwords( str_replace( [ '-', '_' ], ' ', $application_slug ) );
						$help_meta        = self::get_connection_status_help_meta( $application_slug );
						$raw_status       = isset( $application_send_info['status'] ) ? sanitize_key( $application_send_info['status'] ) : '';
						$status_key       = 'fail';
						$status_label     = __( 'Fail', 'wordform-pro' );

						if ( 'success' === $raw_status ) {
							$status_key   = 'success';
							$status_label = __( 'Success', 'wordform-pro' );
						} elseif ( 'fail' !== $raw_status ) {
							$status_key   = 'unknown';
							$status_label = __( 'Unknown', 'wordform-pro' );
						}

						$failure_detail = [
							'applicationName' => $application_name,
							'formName'        => $form_name,
							'formId'          => $form_id,
							'reason'          => isset( $application_send_info['reason'] ) ? sanitize_textarea_field( $application_send_info['reason'] ) : '',
							'comment'         => isset( $application_send_info['comment'] ) ? sanitize_textarea_field( $application_send_info['comment'] ) : '',
							'exceptionType'   => isset( $application_send_info['exceptionType'] ) ? sanitize_text_field( $application_send_info['exceptionType'] ) : '',
							'exceptionMsg'    => isset( $application_send_info['exceptionMsg'] ) ? sanitize_textarea_field( $application_send_info['exceptionMsg'] ) : '',
							'docsUrl'         => isset( $help_meta['docsUrl'] ) ? esc_url_raw( $help_meta['docsUrl'] ) : '',
							'docsLabel'       => isset( $help_meta['docsLabel'] ) ? sanitize_text_field( $help_meta['docsLabel'] ) : '',
							'suggestion'      => isset( $help_meta['suggestion'] ) ? sanitize_textarea_field( $help_meta['suggestion'] ) : '',
							'submissionId'    => $submission_id,
							'createdAt'       => self::format_connection_status_datetime( $submission_date ),
						];

						$success_detail = [
							'applicationName'    => $application_name,
							'formName'           => $form_name,
							'formId'             => $form_id,
							'submissionId'       => $submission_id,
							'createdAt'          => self::format_connection_status_datetime( $submission_date ),
							'submissionDataHtml' => $submission_html,
						];

						$expanded_rows[] = [
							'formNamePlain'         => $form_name,
							'applicationNamePlain'  => $application_name,
							'sendStatusPlain'       => $status_label,
							'sendStatusKey'         => $status_key,
							'sendingDatePlain'      => self::format_connection_status_datetime( $submission_date ),
							'sendingDateTimestamp'  => $submission_stamp ? (int) $submission_stamp : 0,
							'failureDetail'         => $failure_detail,
							'successDetail'         => $success_detail,
						];
					}
				}
			}

			$records_total  = count( $expanded_rows );
			$search_value   = isset( $post_data['search']['value'] ) ? sanitize_text_field( wp_unslash( $post_data['search']['value'] ) ) : '';
			$filtered_rows  = $expanded_rows;

			if ( '' !== $search_value ) {
				$search_value = strtolower( $search_value );
				$filtered_rows = array_values(
					array_filter(
						$expanded_rows,
						static function( $row ) use ( $search_value ) {
							$search_haystack = strtolower(
								implode(
									' ',
									[
										isset( $row['formNamePlain'] ) ? $row['formNamePlain'] : '',
										isset( $row['applicationNamePlain'] ) ? $row['applicationNamePlain'] : '',
										isset( $row['sendStatusPlain'] ) ? $row['sendStatusPlain'] : '',
										isset( $row['sendingDatePlain'] ) ? $row['sendingDatePlain'] : '',
										isset( $row['failureDetail']['reason'] ) ? $row['failureDetail']['reason'] : '',
										isset( $row['failureDetail']['comment'] ) ? $row['failureDetail']['comment'] : '',
									]
								)
							);

							return false !== strpos( $search_haystack, $search_value );
						}
					)
				);
			}

			$records_filtered = count( $filtered_rows );
			$order_col_index  = isset( $post_data['order'][0]['column'] ) ? absint( $post_data['order'][0]['column'] ) : 3;
			$order_dir        = isset( $post_data['order'][0]['dir'] ) && 'asc' === strtolower( sanitize_text_field( wp_unslash( $post_data['order'][0]['dir'] ) ) ) ? 'asc' : 'desc';

			usort(
				$filtered_rows,
				static function( $left, $right ) use ( $order_col_index, $order_dir ) {
					$column_map = [
						0 => 'formNamePlain',
						1 => 'applicationNamePlain',
						2 => 'sendStatusPlain',
						3 => 'sendingDateTimestamp',
					];
					$column_key = isset( $column_map[ $order_col_index ] ) ? $column_map[ $order_col_index ] : 'sendingDateTimestamp';
					$left_value = isset( $left[ $column_key ] ) ? $left[ $column_key ] : '';
					$right_value = isset( $right[ $column_key ] ) ? $right[ $column_key ] : '';

					if ( $left_value === $right_value ) {
						return 0;
					}

					$is_numeric_sort = 'sendingDateTimestamp' === $column_key;
					if ( $is_numeric_sort ) {
						$comparison = (int) $left_value <=> (int) $right_value;
					} else {
						$comparison = strcasecmp( (string) $left_value, (string) $right_value );
					}

					return 'asc' === $order_dir ? $comparison : -1 * $comparison;
				}
			);

			$paged_rows = array_slice( $filtered_rows, $start, $length );
			$data       = [];

			foreach ( $paged_rows as $row ) {
				$send_status_badge = '<span class="wordform-connection-status-pill wordform-connection-status-pill-' . sanitize_html_class( $row['sendStatusKey'] ) . '">' . esc_html( $row['sendStatusPlain'] ) . '</span>';

				if ( 'fail' === $row['sendStatusKey'] ) {
					$send_status_badge .= ' <button type="button" class="button button-link wordform-open-connection-send-log-fail-detail-modal" data-failure-detail="' . esc_attr( wp_json_encode( $row['failureDetail'] ) ) . '"><span class="dashicons dashicons-warning" aria-hidden="true"></span></button>';
				}

				$data[] = [
					'formName'      => esc_html( $row['formNamePlain'] ),
					'application'   => esc_html( $row['applicationNamePlain'] ),
					'sendStatus'    => $send_status_badge,
					'sendingDate'   => esc_html( $row['sendingDatePlain'] ),
					'details'       => '<button type="button" class="button button-secondary wordform-open-connection-send-log-success-detail-modal" data-success-detail="' . esc_attr( wp_json_encode( $row['successDetail'] ) ) . '">' . esc_html__( 'View Data', 'wordform-pro' ) . '</button>',
				];
			}

			return [
				'draw'            => $draw,
				'recordsTotal'    => $records_total,
				'recordsFiltered' => $records_filtered,
				'data'            => $data,
			];
		}

		/**
		 * Build status rows for the Connection Status report tab.
		 * One row represents one form and one supported application.
		 *
		 * @param string $selected_form_id Optional selected WordForm ID.
		 * @param string $selected_application_slug Optional application slug filter.
		 * @return array
		 */
		public static function get_connection_status_report_rows( $selected_form_id = '', $selected_application_slug = '' ) {
			$all_forms = SftcyWordformBase::sc_wordform_get_all_created_forms_data();
			if ( ! $all_forms || ! is_array( $all_forms ) ) {
				return [];
			}

			$selected_form_id          = sanitize_text_field( $selected_form_id );
			$selected_application_slug = sanitize_key( $selected_application_slug );
			$forms                     = [];
			foreach ( $all_forms as $form_row ) {
				if ( empty( $form_row['form_id'] ) ) {
					continue;
				}

				if ( ! empty( $selected_form_id ) && $form_row['form_id'] !== $selected_form_id ) {
					continue;
				}

				$forms[] = $form_row;
			}

			if ( ! $forms ) {
				return [];
			}

			$form_ids             = array_values( array_unique( array_filter( array_map( static function( $form_row ) {
				return isset( $form_row['form_id'] ) ? sanitize_text_field( $form_row['form_id'] ) : '';
			}, $forms ) ) ) );
			$applications_registry = self::get_connects_page_applications_registry();
			if ( ! empty( $selected_application_slug ) && isset( $applications_registry[ $selected_application_slug ] ) ) {
				$applications_registry = [
					$selected_application_slug => $applications_registry[ $selected_application_slug ],
				];
			}
			$configured_by_slug    = [];
			$connected_by_form     = [];
			$latest_submission_map = [];

			global $wpdb;
			$configured_table = $wpdb->prefix . SftcyWordformBase::$sc_wordform_configured_application_tbl;
			$connect_table    = $wpdb->prefix . SftcyWordformBase::$sc_wordform_connects_tbl;
			$submission_table = $wpdb->prefix . SftcyWordformBase::$sc_wordform_submission_tbl;

			$configured_rows = $wpdb->get_results( "SELECT * FROM {$configured_table} ORDER BY id DESC", ARRAY_A );
			if ( $configured_rows ) {
				foreach ( $configured_rows as $configured_row ) {
					if ( isset( $configured_row['application_slug'] ) && ! isset( $configured_by_slug[ $configured_row['application_slug'] ] ) ) {
						$configured_by_slug[ $configured_row['application_slug'] ] = $configured_row;
					}
				}
			}

			if ( $form_ids ) {
				$form_placeholders = implode( ', ', array_fill( 0, count( $form_ids ), '%s' ) );

				$connected_rows = $wpdb->get_results(
					$wpdb->prepare(
						"SELECT cd.*, ca.application_slug, ca.application_name, ca.configured_status
						FROM {$connect_table} AS cd
						INNER JOIN {$configured_table} AS ca ON ca.id = cd.configured_application_tbl_id
						WHERE cd.wordform_id IN ({$form_placeholders})
						ORDER BY cd.id DESC",
						$form_ids
					),
					ARRAY_A
				);

				if ( $connected_rows ) {
					foreach ( $connected_rows as $connected_row ) {
						$form_id          = isset( $connected_row['wordform_id'] ) ? sanitize_text_field( $connected_row['wordform_id'] ) : '';
						$application_slug = isset( $connected_row['application_slug'] ) ? sanitize_key( $connected_row['application_slug'] ) : '';
						if ( empty( $form_id ) || empty( $application_slug ) ) {
							continue;
						}

						if ( ! isset( $connected_by_form[ $form_id ] ) ) {
							$connected_by_form[ $form_id ] = [];
						}

						if ( ! isset( $connected_by_form[ $form_id ][ $application_slug ] ) ) {
							$connected_by_form[ $form_id ][ $application_slug ] = $connected_row;
						}
					}
				}

				$latest_submission_rows = $wpdb->get_results(
					$wpdb->prepare(
						"SELECT ws.id, ws.form_id, ws.data_send_info, ws.created_at
						FROM {$submission_table} AS ws
						INNER JOIN (
							SELECT form_id, MAX(id) AS latest_submission_id
							FROM {$submission_table}
							WHERE form_id IN ({$form_placeholders})
							GROUP BY form_id
						) AS latest_rows ON latest_rows.latest_submission_id = ws.id",
						$form_ids
					),
					ARRAY_A
				);

				if ( $latest_submission_rows ) {
					foreach ( $latest_submission_rows as $submission_row ) {
						$form_id = isset( $submission_row['form_id'] ) ? sanitize_text_field( $submission_row['form_id'] ) : '';
						if ( empty( $form_id ) ) {
							continue;
						}

						$decoded_send_info = [];
						if ( ! empty( $submission_row['data_send_info'] ) ) {
							$decoded_send_info = json_decode( $submission_row['data_send_info'], true );
							$decoded_send_info = is_array( $decoded_send_info ) ? $decoded_send_info : [];
						}

						$latest_submission_map[ $form_id ] = [
							'submissionId' => isset( $submission_row['id'] ) ? absint( $submission_row['id'] ) : 0,
							'createdAt'    => isset( $submission_row['created_at'] ) ? sanitize_text_field( $submission_row['created_at'] ) : '',
							'sendInfo'     => $decoded_send_info,
						];
					}
				}
			}

			$status_rows = [];
			foreach ( $forms as $form_row ) {
				$form_id   = isset( $form_row['form_id'] ) ? sanitize_text_field( $form_row['form_id'] ) : '';
				$form_name = isset( $form_row['form_name'] ) ? sanitize_text_field( $form_row['form_name'] ) : '';
				if ( empty( $form_id ) ) {
					continue;
				}

				foreach ( $applications_registry as $application_slug => $application ) {
					$configured_row    = isset( $configured_by_slug[ $application_slug ] ) ? $configured_by_slug[ $application_slug ] : [];
					$connected_row     = isset( $connected_by_form[ $form_id ][ $application_slug ] ) ? $connected_by_form[ $form_id ][ $application_slug ] : [];
					$latest_submission = isset( $latest_submission_map[ $form_id ] ) ? $latest_submission_map[ $form_id ] : [];
					$latest_send_info  = isset( $latest_submission['sendInfo'][ $application_slug ] ) && is_array( $latest_submission['sendInfo'][ $application_slug ] ) ? $latest_submission['sendInfo'][ $application_slug ] : [];
					$help_meta         = self::get_connection_status_help_meta( $application_slug );

					$configured_status_label = 'Not Configured';
					$configured_status_key   = 'not-configured';
					if ( ! empty( $configured_row ) ) {
						$is_configured_active = isset( $configured_row['configured_status'] ) && 'active' === $configured_row['configured_status'];
						$configured_status_label = $is_configured_active ? 'Configured [Active]' : 'Configured [Inactive]';
						$configured_status_key   = $is_configured_active ? 'active' : 'inactive';
					}

					$connection_status_label = 'Not Connected';
					$connection_status_key   = 'not-connected';
					if ( ! empty( $connected_row ) ) {
						$is_connection_active = isset( $connected_row['connection_status'] ) && 'active' === $connected_row['connection_status'];
						$connection_status_label = $is_connection_active ? 'Active' : 'Inactive';
						$connection_status_key   = $is_connection_active ? 'active' : 'inactive';
					}

					$data_send_status_label = 'Not Connected';
					$data_send_status_key   = 'not-connected';
					if ( ! empty( $connected_row ) ) {
						if ( empty( $latest_submission ) ) {
							$data_send_status_label = 'No Submission Yet';
							$data_send_status_key   = 'no-submission';
						} elseif ( empty( $latest_send_info ) ) {
							$data_send_status_label = 'Not Sent Yet';
							$data_send_status_key   = 'not-sent';
						} else {
							$send_status = isset( $latest_send_info['status'] ) ? sanitize_key( $latest_send_info['status'] ) : '';
							if ( 'success' === $send_status ) {
								$data_send_status_label = 'Success';
								$data_send_status_key   = 'success';
							} elseif ( 'fail' === $send_status ) {
								$data_send_status_label = 'Fail';
								$data_send_status_key   = 'fail';
							} else {
								$data_send_status_label = 'Unknown';
								$data_send_status_key   = 'unknown';
							}
						}
					}

					$failure_detail = [];
					if ( 'fail' === $data_send_status_key ) {
						$failure_detail = [
							'applicationName' => isset( $application['name'] ) ? sanitize_text_field( $application['name'] ) : '',
							'formName'        => $form_name,
							'formId'          => $form_id,
							'reason'          => isset( $latest_send_info['reason'] ) ? sanitize_textarea_field( $latest_send_info['reason'] ) : '',
							'comment'         => isset( $latest_send_info['comment'] ) ? sanitize_textarea_field( $latest_send_info['comment'] ) : '',
							'exceptionType'   => isset( $latest_send_info['exceptionType'] ) ? sanitize_text_field( $latest_send_info['exceptionType'] ) : '',
							'exceptionMsg'    => isset( $latest_send_info['exceptionMsg'] ) ? sanitize_textarea_field( $latest_send_info['exceptionMsg'] ) : '',
							'docsUrl'         => isset( $help_meta['docsUrl'] ) ? esc_url_raw( $help_meta['docsUrl'] ) : '',
							'docsLabel'       => isset( $help_meta['docsLabel'] ) ? sanitize_text_field( $help_meta['docsLabel'] ) : '',
							'suggestion'      => isset( $help_meta['suggestion'] ) ? sanitize_textarea_field( $help_meta['suggestion'] ) : '',
							'submissionId'    => isset( $latest_submission['submissionId'] ) ? absint( $latest_submission['submissionId'] ) : 0,
							'createdAt'       => isset( $latest_submission['createdAt'] ) ? sanitize_text_field( $latest_submission['createdAt'] ) : '',
						];
					}

					$status_rows[] = [
						'formId'                   => $form_id,
						'formName'                 => $form_name,
						'formSendLogUrl'           => self::get_connection_status_send_log_page_url( $form_id ),
						'applicationSlug'          => $application_slug,
						'applicationName'          => isset( $application['name'] ) ? sanitize_text_field( $application['name'] ) : '',
						'configuredStatusLabel'    => $configured_status_label,
						'configuredStatusKey'      => $configured_status_key,
						'connectionStatusLabel'    => $connection_status_label,
						'connectionStatusKey'      => $connection_status_key,
						'dataSendStatusLabel'      => $data_send_status_label,
						'dataSendStatusKey'        => $data_send_status_key,
						'latestSubmissionId'       => isset( $latest_submission['submissionId'] ) ? absint( $latest_submission['submissionId'] ) : 0,
						'latestSubmissionDate'     => isset( $latest_submission['createdAt'] ) ? sanitize_text_field( $latest_submission['createdAt'] ) : '',
						'failureDetail'            => $failure_detail,
					];
				}
			}

			return $status_rows;
		}
	} // End class
}
