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

if ( ! class_exists( 'SftcyWordformConnectMailchimp' ) ) {
	class SftcyWordformConnectMailchimp {
		private static $initiated = false;
		public static $output     = [];

		public function __construct() {
			if ( ! self::$initiated ) {
				self::initiate_hooks();
			}
		}

		/**
		 * Init hooks.
		 *
		 * @return void
		 */
		private static function initiate_hooks() {
			add_action( 'wp_ajax_wordform_connect_save_mailchimp_data_as_wp_option_data', [ __CLASS__, 'wordform_connect_save_mailchimp_data_as_wp_option_data' ] );
			add_action( 'wp_ajax_wordform_connect_create_mailchimp_with_form_fields', [ __CLASS__, 'wordform_connect_create_mailchimp_with_form_fields' ] );
			add_action( 'wp_ajax_wordform_connect_fetch_mailchimp_audiences', [ __CLASS__, 'wordform_connect_fetch_mailchimp_audiences' ] );

			self::$initiated = true;
		}

		/**
		 * Get Mailchimp configured information from option table.
		 *
		 * @return array
		 */
		public static function get_mailchimp_configured_info() {
			$mailchimp_info = get_option( 'wordform_connect_mailchimp_info', [] );
			if ( isset( $mailchimp_info['apiKey'], $mailchimp_info['audienceId'] ) && ! empty( $mailchimp_info['apiKey'] ) && ! empty( $mailchimp_info['audienceId'] ) ) {
				return [
					'apiKey'        => $mailchimp_info['apiKey'],
					'audienceId'    => $mailchimp_info['audienceId'],
					'audienceLabel' => isset( $mailchimp_info['audienceLabel'] ) ? $mailchimp_info['audienceLabel'] : '',
					'apiServer'     => self::get_mailchimp_api_server_from_api_key( $mailchimp_info['apiKey'] ),
				];
			}

			return [];
		}

		/**
		 * Get Mailchimp API server prefix from API key suffix.
		 * Example: abc-us21 => us21.
		 *
		 * @param string $mailchimp_api_key Mailchimp API key.
		 * @return string
		 */
		public static function get_mailchimp_api_server_from_api_key( $mailchimp_api_key = '' ) {
			$mailchimp_api_key = trim( (string) $mailchimp_api_key );
			if ( empty( $mailchimp_api_key ) || false === strpos( $mailchimp_api_key, '-' ) ) {
				return '';
			}

			$key_parts = explode( '-', $mailchimp_api_key );
			$api_server = end( $key_parts );

			return sanitize_text_field( $api_server );
		}

		/**
		 * Ajax request.
		 * Store Mailchimp API key and Audience ID as option data.
		 *
		 * @return void
		 */
		public static function wordform_connect_save_mailchimp_data_as_wp_option_data() {
			check_ajax_referer( 'scwordform_wpnonce', 'security' );

			$mailchimp_api_key     = isset( $_POST['params']['mailchimpApiKey'] ) ? sanitize_text_field( trim( $_POST['params']['mailchimpApiKey'] ) ) : '';
			$mailchimp_audience_id = isset( $_POST['params']['mailchimpAudienceId'] ) ? sanitize_text_field( trim( $_POST['params']['mailchimpAudienceId'] ) ) : '';
			$mailchimp_audience_label = isset( $_POST['params']['mailchimpAudienceLabel'] ) ? sanitize_text_field( trim( $_POST['params']['mailchimpAudienceLabel'] ) ) : '';
			$mailchimp_api_server  = self::get_mailchimp_api_server_from_api_key( $mailchimp_api_key );
			self::$output          = [];

			if ( empty( $mailchimp_api_key ) || empty( $mailchimp_audience_id ) ) {
				self::$output['status']  = 'fail';
				self::$output['reason']  = 'Mailchimp API key or Audience ID missing.';
				self::$output['comment'] = 'Mailchimp API key and Audience ID are required.';
			} elseif ( empty( $mailchimp_api_server ) ) {
				self::$output['status']  = 'fail';
				self::$output['reason']  = 'Mailchimp API key format invalid.';
				self::$output['comment'] = 'Valid Mailchimp API key required.';
			} else {
				$mailchimp_info = [
					'apiKey'        => $mailchimp_api_key,
					'audienceId'    => $mailchimp_audience_id,
					'audienceLabel' => $mailchimp_audience_label,
					'apiServer'     => $mailchimp_api_server,
				];

				if ( update_option( 'wordform_connect_mailchimp_info', $mailchimp_info ) ) {
					self::$output['status']  = 'success';
					self::$output['reason']  = 'Mailchimp data saved as option value.';
					self::$output['comment'] = 'Mailchimp configuration saved successfully.';
				} else {
					self::$output['status']  = 'warning';
					self::$output['reason']  = 'Mailchimp configuration did not change.';
					self::$output['comment'] = 'Mailchimp configuration saved successfully.';
				}

				self::$output['mailchimpConfiguredInfoStatus'] = self::save_configured_mailchimp_application( $mailchimp_info );
				self::$output['configuredApplication'] = SftcyWordformConnectBase::get_configured_application_option_payload( 'mailchimp' );
			}

			echo wp_json_encode( self::$output, JSON_HEX_APOS );
			wp_die();
		}

		/**
		 * Save configured Mailchimp application into configured applications table.
		 *
		 * @param array $mailchimp_info Mailchimp configuration.
		 * @return bool
		 */
		public static function save_configured_mailchimp_application( $mailchimp_info = [] ) {
			if ( ! is_array( $mailchimp_info ) || ! isset( $mailchimp_info['apiKey'], $mailchimp_info['audienceId'] ) ) {
				return false;
			}

			$application_slug = 'mailchimp';
			$application_name = 'Mailchimp';
			$data             = [
				'application_slug' => $application_slug,
				'application_name' => $application_name,
			];

			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 );

			$data['configured_info'] = wp_json_encode(
				[
					'reconfigured'  => $query_results ? 'yes' : 'no',
					'payloadFormat' => 'mailchimp-audience-member',
					'apiKey'        => $mailchimp_info['apiKey'],
					'audienceId'    => $mailchimp_info['audienceId'],
					'audienceLabel' => isset( $mailchimp_info['audienceLabel'] ) ? $mailchimp_info['audienceLabel'] : '',
					'apiServer'     => isset( $mailchimp_info['apiServer'] ) ? $mailchimp_info['apiServer'] : self::get_mailchimp_api_server_from_api_key( $mailchimp_info['apiKey'] ),
				]
			);

			if ( $query_results ) {
				$where                     = [ 'id' => $query_results[0]['id'] ];
				$data['configured_status'] = 'active';
				$update_result             = $wpdb->update( $table, $data, $where );
				return false !== $update_result;
			}

			$insert_result = $wpdb->insert( $table, $data );
			return false !== $insert_result;
		}

		/**
		 * Ajax call.
		 * Store Mailchimp connection record against selected WordForm.
		 *
		 * @return void
		 */
		public static function wordform_connect_create_mailchimp_with_form_fields() {
			check_ajax_referer( 'scwordform_wpnonce', 'security' );

			self::$output = [];
			if ( isset( $_POST['params'] ) && array_filter( $_POST['params'] ) ) {
				$wordform_id                 = isset( $_POST['params']['wordFormID'] ) ? sanitize_text_field( $_POST['params']['wordFormID'] ) : '';
				$wordform_name               = isset( $_POST['params']['wordFormName'] ) ? sanitize_text_field( $_POST['params']['wordFormName'] ) : '';
				$configured_application_id   = isset( $_POST['params']['applicationID'] ) ? absint( $_POST['params']['applicationID'] ) : 0;
				$configured_application_name = isset( $_POST['params']['applicationName'] ) ? sanitize_text_field( $_POST['params']['applicationName'] ) : '';

				if ( ! empty( $wordform_id ) && ! empty( $configured_application_id ) ) {
					$form_fields = SftcyWordformBuildForm::wordform_get_field_names( $wordform_id );
					if ( $form_fields && array_filter( $form_fields ) ) {
						$mailchimp_info = self::get_mailchimp_configured_info();
						if ( isset( $mailchimp_info['apiKey'], $mailchimp_info['audienceId'] ) && ! empty( $mailchimp_info['apiKey'] ) && ! empty( $mailchimp_info['audienceId'] ) ) {
							$connection_info = [
								'applicationName'     => $configured_application_name,
								'formName'            => $wordform_name,
								'formFields'          => $form_fields,
								'payloadFormat'       => 'mailchimp-audience-member',
								'apiKey'              => $mailchimp_info['apiKey'],
								'audienceId'          => $mailchimp_info['audienceId'],
								'apiServer'           => isset( $mailchimp_info['apiServer'] ) ? $mailchimp_info['apiServer'] : self::get_mailchimp_api_server_from_api_key( $mailchimp_info['apiKey'] ),
								'connectionUpdatedAt' => current_time( 'mysql' ),
							];

							$insertdata = [
								'configured_application_tbl_id' => $configured_application_id,
								'wordform_id'                   => $wordform_id,
								'connection_info'               => wp_json_encode( $connection_info ),
							];

							$db_result = SftcyWordformConnectBase::wordform_save_connected_application_info( $insertdata );
							if ( false !== $db_result ) {
								self::$output['status']              = 'success';
								self::$output['formFields']          = $form_fields;
								self::$output['formName']            = $wordform_name;
								self::$output['reason']              = 'Mailchimp connected successfully.';
								self::$output['comment']             = 'Mailchimp connected successfully.';
								self::$output['connectedInfoStored'] = $db_result;
							} else {
								self::$output['status']  = 'fail';
								self::$output['reason']  = 'Connection info storing failed.';
								self::$output['comment'] = 'Could not create Mailchimp connection record.';
							}
						} else {
							self::$output['status']  = 'fail';
							self::$output['reason']  = 'Mailchimp configuration missing.';
							self::$output['comment'] = 'Mailchimp API key or Audience ID not found. Please save Mailchimp configuration first.';
						}
					} else {
						self::$output['status']  = 'fail';
						self::$output['reason']  = 'WordForm form fields are not available.';
						self::$output['comment'] = 'WordForm fields not found for selected form.';
					}
				} else {
					self::$output['status']  = 'fail';
					self::$output['reason']  = 'WordForm ID or configured application ID missing.';
					self::$output['comment'] = 'Required connection fields are missing.';
				}
			} else {
				self::$output['status']  = 'fail';
				self::$output['reason']  = 'Post parameters are missing.';
				self::$output['comment'] = 'Required post parameters are missing.';
			}

			echo wp_json_encode( self::$output, JSON_HEX_AMP );
			wp_die();
		}

		/**
		 * Ajax request.
		 * Fetch Mailchimp audiences using the provided API key.
		 *
		 * @return void
		 */
		public static function wordform_connect_fetch_mailchimp_audiences() {
			check_ajax_referer( 'scwordform_wpnonce', 'security' );

			$mailchimp_api_key = isset( $_POST['params']['mailchimpApiKey'] ) ? sanitize_text_field( trim( $_POST['params']['mailchimpApiKey'] ) ) : '';
			$response          = self::get_mailchimp_audiences( $mailchimp_api_key );

			echo wp_json_encode( $response, JSON_HEX_APOS );
			wp_die();
		}

		/**
		 * Fetch Mailchimp audiences.
		 *
		 * @param string $mailchimp_api_key
		 * @return array
		 */
		private static function get_mailchimp_audiences( $mailchimp_api_key = '' ) {
			$mailchimp_api_key = sanitize_text_field( trim( (string) $mailchimp_api_key ) );
			$mailchimp_api_server = self::get_mailchimp_api_server_from_api_key( $mailchimp_api_key );

			if ( empty( $mailchimp_api_key ) || empty( $mailchimp_api_server ) ) {
				return SftcyWordformConnectBase::build_connect_feedback_payload(
					'fail',
					'Please enter a valid Mailchimp API key first.',
					'mailchimp',
					[
					'fixTip' => 'Mailchimp API keys include a server suffix like us21. Copy the full key exactly as shown in Mailchimp.',
						'logStage' => 'verify_load',
					]
				);
			}

			$response = wp_remote_get(
				'https://' . $mailchimp_api_server . '.api.mailchimp.com/3.0/lists?count=1000',
				[
					'timeout' => 20,
					'headers' => [
						'Authorization' => 'Basic ' . base64_encode( 'wordform:' . $mailchimp_api_key ),
					],
				]
			);

			if ( is_wp_error( $response ) ) {
				return SftcyWordformConnectBase::build_connect_feedback_payload(
					'fail',
					'Mailchimp audiences could not be loaded right now: ' . $response->get_error_message(),
					'mailchimp',
					[
					'fixTip' => 'Check outbound HTTPS access from this site, then verify the API key and try again.',
						'logStage' => 'verify_load',
					]
				);
			}

			$status_code = (int) wp_remote_retrieve_response_code( $response );
			$body        = wp_remote_retrieve_body( $response );
			$json        = json_decode( $body, true );

			if ( $status_code < 200 || $status_code >= 300 || ! is_array( $json ) ) {
				$remote_error = SftcyWordformConnectBase::extract_connect_remote_error_message( $body );
				$comment      = 'Mailchimp API key could not be verified.';
				if ( ! empty( $remote_error ) ) {
					$comment .= ' ' . $remote_error;
				}

				return SftcyWordformConnectBase::build_connect_feedback_payload(
					'fail',
					$comment,
					'mailchimp',
					[
						'fixTip'            => 'Check the API key, confirm its server suffix is intact, and make sure the key can access audiences in this account.',
						'responseStatusCode'=> $status_code,
						'logStage'          => 'verify_load',
					]
				);
			}

			$resources = [];
			if ( ! empty( $json['lists'] ) && is_array( $json['lists'] ) ) {
				foreach ( $json['lists'] as $list ) {
					if ( empty( $list['id'] ) ) {
						continue;
					}
					$label = isset( $list['name'] ) && '' !== trim( (string) $list['name'] ) ? $list['name'] : $list['id'];
					$resources[] = [
						'value' => sanitize_text_field( $list['id'] ),
						'label' => sanitize_text_field( $label ),
					];
				}
			}

			if ( empty( $resources ) ) {
				return SftcyWordformConnectBase::build_connect_feedback_payload(
					'fail',
					'No Mailchimp audiences were found for this API key.',
					'mailchimp',
					[
						'fixTip' => 'Create at least one audience in Mailchimp, or confirm the key belongs to the expected account.',
						'logStage' => 'verify_load',
					]
				);
			}

			return SftcyWordformConnectBase::build_connect_feedback_payload(
				'success',
				'Mailchimp audiences loaded successfully.',
				'mailchimp',
				[
					'resources' => $resources,
				]
			);
		}

		/**
		 * Send form submission data into Mailchimp audience.
		 * Uses PUT to create or update a list member by subscriber hash.
		 *
		 * @param array $forms_data Processed form fields.
		 * @param array $mailchimp_info Mailchimp configuration.
		 * @return array
		 */
		public static function wordform_send_forms_data_into_mailchimp_audience( $forms_data = [], $mailchimp_info = [] ) {
			$send_info                    = [];
			$send_info['applicationSlug'] = 'mailchimp';

			if ( ! is_array( $forms_data ) || ! array_filter( $forms_data ) ) {
				$send_info['status']  = 'fail';
				$send_info['reason']  = 'Processed submission fields are empty.';
				$send_info['comment'] = 'No WordForm submission fields found for Mailchimp.';
				return $send_info;
			}

			$mailchimp_api_key    = isset( $mailchimp_info['apiKey'] ) ? sanitize_text_field( (string) $mailchimp_info['apiKey'] ) : '';
			$mailchimp_audience_id = isset( $mailchimp_info['audienceId'] ) ? sanitize_text_field( (string) $mailchimp_info['audienceId'] ) : '';
			$mailchimp_api_server = isset( $mailchimp_info['apiServer'] ) ? sanitize_text_field( (string) $mailchimp_info['apiServer'] ) : self::get_mailchimp_api_server_from_api_key( $mailchimp_api_key );

			if ( empty( $mailchimp_api_key ) || empty( $mailchimp_audience_id ) || empty( $mailchimp_api_server ) ) {
				$send_info['status']  = 'fail';
				$send_info['reason']  = 'Mailchimp configuration incomplete.';
				$send_info['comment'] = 'Mailchimp API key, Audience ID, or API server missing.';
				return $send_info;
			}

			$email_address = SftcyWordformConnectBase::extract_first_valid_email_from_submission_fields( $forms_data );
			if ( empty( $email_address ) ) {
				$send_info['status']  = 'fail';
				$send_info['reason']  = 'Email field value not found in this form submission.';
				$send_info['comment'] = 'Mailchimp requires at least one valid email field in the connected form.';
				return $send_info;
			}

			$name_parts   = SftcyWordformConnectBase::extract_name_parts_from_submission_fields( $forms_data );
			$merge_fields = [];
			if ( ! empty( $name_parts['firstName'] ) ) {
				$merge_fields['FNAME'] = $name_parts['firstName'];
			}
			if ( ! empty( $name_parts['lastName'] ) ) {
				$merge_fields['LNAME'] = $name_parts['lastName'];
			}

			$subscriber_hash = md5( strtolower( $email_address ) );
			$endpoint_url    = sprintf(
				'https://%1$s.api.mailchimp.com/3.0/lists/%2$s/members/%3$s',
				rawurlencode( $mailchimp_api_server ),
				rawurlencode( $mailchimp_audience_id ),
				rawurlencode( $subscriber_hash )
			);

			$request_body = [
				'email_address' => $email_address,
				'status_if_new' => 'subscribed',
			];
			if ( $merge_fields ) {
				$request_body['merge_fields'] = $merge_fields;
			}

			$response = wp_remote_request(
				$endpoint_url,
				[
					'method'  => 'PUT',
					'timeout' => 20,
					'headers' => [
						'Content-Type'  => 'application/json; charset=utf-8',
						'Authorization' => 'Basic ' . base64_encode( 'wordform:' . $mailchimp_api_key ),
					],
					'body'    => wp_json_encode( $request_body ),
				]
			);

			if ( is_wp_error( $response ) ) {
				$send_info['status']       = 'fail';
				$send_info['reason']       = 'Mailchimp request failed.';
				$send_info['requestError'] = $response->get_error_message();
				$send_info['comment']      = 'Mailchimp API request could not be completed.';
				return $send_info;
			}

			$status_code = (int) wp_remote_retrieve_response_code( $response );
			$response_body = wp_remote_retrieve_body( $response );
			$response_json = json_decode( $response_body, true );
			$send_info['responseStatusCode'] = $status_code;

			if ( $status_code >= 200 && $status_code < 300 ) {
				$send_info['status']  = 'success';
				$send_info['reason']  = 'Form submission data sent to Mailchimp.';
				$send_info['comment'] = 'Mailchimp audience member synced successfully.';
				if ( isset( $response_json['status'] ) ) {
					$send_info['mailchimpMemberStatus'] = sanitize_text_field( $response_json['status'] );
				}
			} else {
				$send_info['status']  = 'fail';
				$send_info['reason']  = 'Mailchimp response status indicates failure.';
				$send_info['comment'] = 'Mailchimp API returned non-success HTTP status.';
				if ( is_array( $response_json ) ) {
					if ( isset( $response_json['title'] ) ) {
						$send_info['responseTitle'] = sanitize_text_field( $response_json['title'] );
					}
					if ( isset( $response_json['detail'] ) ) {
						$send_info['responseDetail'] = substr( sanitize_textarea_field( (string) $response_json['detail'] ), 0, 500 );
					}
				} else {
					$send_info['responseBody'] = substr( sanitize_textarea_field( (string) $response_body ), 0, 500 );
				}
			}

			return $send_info;
		}

		/**
		 * Check whether Mailchimp configured app status is active.
		 *
		 * @return bool
		 */
		public static function is_mailchimp_configured_status_active() {
			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 AND configured_status = %s LIMIT 1',
					[
						$table,
						'mailchimp',
						'active',
					]
				),
				ARRAY_A
			);

			return ! empty( $query_results );
		}
	} // End class
}
