<?php
/**
 * Notification and contact settings AJAX handlers for SiteStaffr admin.
 *
 * @package    SiteStaffr
 * @subpackage SiteStaffr/admin/traits
 * @since      0.14.263
 */

if ( ! defined( 'WPINC' ) ) {
	die;
}

/**
 * Encapsulates notification and business contact AJAX actions.
 */
trait SiteStaffr_Admin_Notification_Ajax_Trait {

	/**
	 * AJAX handler to send a test email notification.
	 *
	 * Sends a test email to verify that email notification settings
	 * are configured correctly and working.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function ajax_send_test_email() {

		// Verify nonce
		if ( ! check_ajax_referer( 'sitestaffr_admin_nonce', 'nonce', false ) ) {
			SiteStaffr_Logger::legacy( 'SiteStaffr Admin: Test email nonce verification failed' );
			wp_send_json_error( array( 'message' => __( 'Security check failed. Please refresh the page and try again.', 'sitestaffr' ) ) );
			return;
		}

		// Verify capability
		if ( ! current_user_can( 'manage_options' ) ) {
			SiteStaffr_Logger::legacy( 'SiteStaffr Admin: Test email permission denied' );
			wp_send_json_error( array( 'message' => __( 'You do not have permission to do this.', 'sitestaffr' ) ) );
			return;
		}

		// Get optional custom email address from request
		$custom_email = isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : null;

		// Which agent the test is for, so the email itself says which one arrived.
		$source = isset( $_POST['source'] ) ? sanitize_key( wp_unslash( $_POST['source'] ) ) : '';
		if ( 'blog' === $source ) {
			$agent_label = __( 'Blog Agent', 'sitestaffr' );
		} elseif ( 'voice' === $source ) {
			$agent_label = __( 'Voice & Text Agent', 'sitestaffr' );
		} else {
			$agent_label = '';
		}

		// Load the email notifications class if not already loaded
		if ( ! class_exists( 'SiteStaffr_Email_Notifications' ) ) {
			require_once SITESTAFFR_PLUGIN_DIR . 'includes/class-sitestaffr-email-notifications.php';
		}

		// Send test email
		$email_handler = new SiteStaffr_Email_Notifications();
		$sent          = $email_handler->send_test_email( $custom_email, $agent_label );

		if ( $sent ) {
			$settings  = get_option( 'sitestaffr_settings', array() );
			$recipient = $custom_email ? $custom_email : ( ! empty( $settings['notification_email'] ) ? $settings['notification_email'] : get_option( 'admin_email' ) );
			$message   = sprintf(
				/* translators: %s: Email address */
				__( 'Test email sent successfully to %s!', 'sitestaffr' ),
				$recipient
			);

			if ( ! $custom_email ) {
				$cc_emails = $this->parse_notification_email_list(
					isset( $settings['notification_cc_emails'] ) ? $settings['notification_cc_emails'] : ''
				);
				$all_recipients = $this->merge_unique_email_recipients( array_merge( array( $recipient ), $cc_emails ) );
				if ( count( $all_recipients ) > 1 ) {
					$message = sprintf(
						/* translators: %d: Number of recipients */
						__( 'Test emails sent successfully to %d recipients.', 'sitestaffr' ),
						count( $all_recipients )
					);
				}
			}

			wp_send_json_success(
				array(
					'message' => $message,
				)
			);
		} else {
			$error_detail = $email_handler->get_last_mail_error();
			$message      = __( 'Failed to send test email.', 'sitestaffr' );
			if ( ! empty( $error_detail ) ) {
				$message .= ' ' . $error_detail;
			}
			wp_send_json_error(
				array(
					'message' => $message,
				)
			);
		}
	}

	/**
	 * AJAX handler to update email notification enabled setting.
	 *
	 * Updates the email_notifications_enabled setting via AJAX
	 * to allow real-time toggle on the settings page.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function ajax_update_email_setting() {
		// Verify nonce
		if ( ! check_ajax_referer( 'sitestaffr_admin_nonce', 'nonce', false ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'sitestaffr' ) ) );
			return;
		}

		// Verify capability
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to do this.', 'sitestaffr' ) ) );
			return;
		}

		// Get the enabled value from request
		$enabled = isset( $_POST['enabled'] ) ? (bool) absint( wp_unslash( $_POST['enabled'] ) ) : true;

		// Update settings
		$settings                                 = get_option( 'sitestaffr_settings', array() );
		$settings['email_notifications_enabled'] = $enabled;
		$updated                                  = update_option( 'sitestaffr_settings', $settings );

		if ( $updated || get_option( 'sitestaffr_settings' ) === $settings ) {
			wp_send_json_success(
				array(
					'message' => $enabled
						? __( 'Email notifications enabled.', 'sitestaffr' )
						: __( 'Email notifications disabled.', 'sitestaffr' ),
					'enabled' => $enabled,
				)
			);
		} else {
			wp_send_json_error( array( 'message' => __( 'Failed to update setting.', 'sitestaffr' ) ) );
		}
	}

	/**
	 * AJAX handler to save both notification enabled state and email address.
	 *
	 * @since 0.14.206
	 * @return void
	 */
	public function ajax_save_notification_settings() {
		if ( ! check_ajax_referer( 'sitestaffr_admin_nonce', 'nonce', false ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'sitestaffr' ) ) );
			return;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to do this.', 'sitestaffr' ) ) );
			return;
		}

		$enabled = isset( $_POST['enabled'] ) ? (bool) absint( wp_unslash( $_POST['enabled'] ) ) : true;
		$email   = isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : '';
		// An absent or empty value means "not supplied" — keep what is stored rather
		// than resetting the owner's choice to the default.
		$scope_raw = isset( $_POST['notification_scope'] ) ? sanitize_text_field( wp_unslash( $_POST['notification_scope'] ) ) : '';
		$cc_raw  = isset( $_POST['cc_emails'] )
			? sanitize_textarea_field( wp_unslash( $_POST['cc_emails'] ) )
			: '';
		$max_cc_recipients = 5;
		$invalid_cc_emails = array();
		$cc_emails = $this->parse_notification_email_list( $cc_raw, $invalid_cc_emails );

		$email_input = isset( $_POST['email'] ) ? sanitize_text_field( wp_unslash( $_POST['email'] ) ) : '';
		if ( ! empty( $email_input ) && empty( $email ) ) {
			wp_send_json_error( array( 'message' => __( 'Please enter a valid email address.', 'sitestaffr' ) ) );
			return;
		}

		if ( ! empty( $invalid_cc_emails ) ) {
			$invalid_list = implode( ', ', array_slice( $invalid_cc_emails, 0, 3 ) );
			wp_send_json_error(
				array(
					/* translators: %s: Comma-separated invalid email values */
					'message' => sprintf( __( 'Please enter valid CC email address(es): %s', 'sitestaffr' ), $invalid_list ),
				)
			);
			return;
		}
		if ( count( $cc_emails ) > $max_cc_recipients ) {
			wp_send_json_error(
				array(
					/* translators: %d: Maximum CC recipients */
					'message' => sprintf( __( 'You can add up to %d CC email addresses.', 'sitestaffr' ), $max_cc_recipients ),
				)
			);
			return;
		}

		$settings = get_option( 'sitestaffr_settings', array() );
		if ( ! is_array( $settings ) ) {
			$settings = array();
		}

		$settings['email_notifications_enabled'] = $enabled;
		if ( '' !== $scope_raw ) {
			$settings[ SiteStaffr_Notification_Scope::SETTING_KEY ] = SiteStaffr_Notification_Scope::sanitize( $scope_raw );
		}
		$scope = SiteStaffr_Notification_Scope::from_settings( $settings );
		if ( ! empty( $email ) ) {
			$settings['notification_email'] = $email;
		}
		$effective_primary = ! empty( $email )
			? $email
			: ( isset( $settings['notification_email'] ) ? sanitize_email( $settings['notification_email'] ) : '' );

		if ( ! empty( $effective_primary ) ) {
			$primary_normalized = strtolower( $effective_primary );
			$cc_emails = array_values(
				array_filter(
					$cc_emails,
					function ( $cc_email ) use ( $primary_normalized ) {
						return strtolower( $cc_email ) !== $primary_normalized;
					}
				)
			);
		}
		$settings['notification_cc_emails'] = ! empty( $cc_emails ) ? implode( ', ', $cc_emails ) : '';

		update_option( 'sitestaffr_settings', $settings );

		wp_send_json_success(
			array(
				'message'   => __( 'Notification settings saved.', 'sitestaffr' ),
				'enabled'   => $enabled,
				'scope'     => $scope,
				'email'     => ! empty( $email ) ? $email : ( isset( $settings['notification_email'] ) ? $settings['notification_email'] : '' ),
				'cc_emails' => $settings['notification_cc_emails'],
			)
		);
	}

	/**
	 * AJAX handler to update business phone number.
	 *
	 * Updates the business phone number setting via AJAX from the Settings page.
	 * This is the business's main contact number (not the AI phone number).
	 *
	 * @since 1.2.7
	 * @return void
	 */
	public function ajax_update_business_phone() {
		// Verify nonce
		if ( ! check_ajax_referer( 'sitestaffr_admin_nonce', 'nonce', false ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'sitestaffr' ) ) );
			return;
		}

		// Verify capability
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to do this.', 'sitestaffr' ) ) );
			return;
		}

		// Get and sanitize phone number
		$phone = isset( $_POST['phone'] ) ? sanitize_text_field( wp_unslash( $_POST['phone'] ) ) : '';

		// Update option
		update_option( 'sitestaffr_business_phone', $phone );

		// Also update in settings array for backward compatibility
		$settings                   = get_option( 'sitestaffr_settings', array() );
		$settings['business_phone'] = $phone;
		update_option( 'sitestaffr_settings', $settings );

		if ( ! empty( $phone ) ) {
			wp_send_json_success(
				array(
					'message' => __( 'Business phone number saved successfully!', 'sitestaffr' ),
					'phone'   => $phone,
				)
			);
		} else {
			wp_send_json_success(
				array(
					'message' => __( 'Business phone number cleared.', 'sitestaffr' ),
					'phone'   => '',
				)
			);
		}
	}

	/**
	 * AJAX handler for updating notification email.
	 *
	 * Updates the notification email address that receives call notifications.
	 * Validates email format and saves to settings.
	 *
	 * @since 0.5.10
	 * @return void
	 */
	public function ajax_update_notification_email() {
		// Verify nonce
		if ( ! check_ajax_referer( 'sitestaffr_admin_nonce', 'nonce', false ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'sitestaffr' ) ) );
			return;
		}

		// Verify capability
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient permissions.', 'sitestaffr' ) ) );
			return;
		}

		// Get and sanitize email
		$email = isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : '';

		if ( empty( $email ) || ! is_email( $email ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid email address.', 'sitestaffr' ) ) );
			return;
		}

		// Update settings
		$settings                       = get_option( 'sitestaffr_settings', array() );
		$settings['notification_email'] = $email;
		update_option( 'sitestaffr_settings', $settings );

		wp_send_json_success(
			array(
				'message' => __( 'Email updated successfully.', 'sitestaffr' ),
				'email'   => $email,
			)
		);
	}

	/**
	 * Parse a comma/semicolon/newline-separated email list into unique valid emails.
	 *
	 * @since 0.14.269
	 *
	 * @param string $raw_emails Raw email list.
	 * @param array  $invalid_emails Invalid values found during parsing.
	 * @return array
	 */
	private function parse_notification_email_list( $raw_emails, &$invalid_emails = array() ) {
		$invalid_emails = array();
		if ( ! is_string( $raw_emails ) || '' === trim( $raw_emails ) ) {
			return array();
		}

		$parts = preg_split( '/[,;\r\n]+/', $raw_emails );
		if ( false === $parts || empty( $parts ) ) {
			return array();
		}

		$valid_emails = array();
		$seen         = array();

		foreach ( $parts as $part ) {
			$candidate = trim( (string) $part );
			if ( '' === $candidate ) {
				continue;
			}

			$email = sanitize_email( $candidate );
			if ( empty( $email ) || ! is_email( $email ) ) {
				$invalid_emails[] = $candidate;
				continue;
			}

			$key = strtolower( $email );
			if ( isset( $seen[ $key ] ) ) {
				continue;
			}

			$seen[ $key ] = true;
			$valid_emails[] = $email;
		}

		return $valid_emails;
	}

	/**
	 * The configured notification recipient set (primary + CC), deduped.
	 *
	 * Source of truth for the "Email Conversation" / "Email Review Link" pickers,
	 * so those actions can only ever target addresses the owner already trusts.
	 *
	 * @since 1.28.0
	 * @return array<int,string>
	 */
	public function get_configured_recipients() {
		$settings = get_option( 'sitestaffr_settings', array() );
		$primary  = ! empty( $settings['notification_email'] )
			? sanitize_email( $settings['notification_email'] )
			: sanitize_email( get_option( 'admin_email' ) );

		$list = array();
		if ( $primary && is_email( $primary ) ) {
			$list[] = $primary;
		}
		$cc = $this->parse_notification_email_list(
			isset( $settings['notification_cc_emails'] ) ? $settings['notification_cc_emails'] : ''
		);
		foreach ( $cc as $cc_email ) {
			$list[] = $cc_email;
		}
		return $this->merge_unique_email_recipients( $list );
	}

	/**
	 * The Blog agent's own recipient set (primary + CC), deduped. Blog emails go
	 * here ONLY — fully separate from conversation recipients, with NO fallback.
	 * Empty when no blog email is configured (then no blog emails are sent).
	 *
	 * @since 1.28.0
	 * @return array<int,string>
	 */
	public function get_blog_recipients() {
		$blog    = get_option( 'sitestaffr_blog_notifications', array() );
		$primary = ! empty( $blog['email'] ) ? sanitize_email( $blog['email'] ) : '';

		$list = array();
		if ( $primary && is_email( $primary ) ) {
			$list[] = $primary;
		}
		$cc = $this->parse_notification_email_list( isset( $blog['cc'] ) ? $blog['cc'] : '' );
		foreach ( $cc as $cc_email ) {
			$list[] = $cc_email;
		}
		return $this->merge_unique_email_recipients( $list );
	}

	/**
	 * Keep only requested addresses that are in a given allowed recipient set.
	 *
	 * The Email actions are not an open relay: a request can only resolve to
	 * addresses the owner already configured (conversation set or blog set).
	 *
	 * @since 1.28.0
	 * @param array $requested Raw requested emails from the picker.
	 * @param array $allowed   The allowed recipient set to validate against.
	 * @return array<int,string>
	 */
	private function filter_requested_recipients( $requested, $allowed ) {
		$allowed_lc = array_map( 'strtolower', (array) $allowed );
		$out        = array();
		foreach ( (array) $requested as $candidate ) {
			$email = sanitize_email( (string) $candidate );
			if ( $email && is_email( $email ) && in_array( strtolower( $email ), $allowed_lc, true ) ) {
				$out[] = $email;
			}
		}
		return $this->merge_unique_email_recipients( $out );
	}

	/**
	 * AJAX: save the Blog agent's own notification recipients (separate from the
	 * conversation recipients).
	 *
	 * @since 1.28.0
	 * @return void
	 */
	public function ajax_save_blog_notification_settings() {
		if ( ! check_ajax_referer( 'sitestaffr_admin_nonce', 'nonce', false ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'sitestaffr' ) ) );
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to do this.', 'sitestaffr' ) ) );
			return;
		}

		$enabled = isset( $_POST['enabled'] ) ? (bool) absint( wp_unslash( $_POST['enabled'] ) ) : true;
		$email   = isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : '';
		$cc_raw  = isset( $_POST['cc_emails'] ) ? sanitize_textarea_field( wp_unslash( $_POST['cc_emails'] ) ) : '';

		$email_input = isset( $_POST['email'] ) ? sanitize_text_field( wp_unslash( $_POST['email'] ) ) : '';
		if ( ! empty( $email_input ) && empty( $email ) ) {
			wp_send_json_error( array( 'message' => __( 'Please enter a valid email address.', 'sitestaffr' ) ) );
			return;
		}

		$invalid_cc = array();
		$cc_emails  = $this->parse_notification_email_list( $cc_raw, $invalid_cc );
		if ( ! empty( $invalid_cc ) ) {
			wp_send_json_error( array(
				/* translators: %s: invalid email values */
				'message' => sprintf( __( 'Please enter valid CC email address(es): %s', 'sitestaffr' ), implode( ', ', array_slice( $invalid_cc, 0, 3 ) ) ),
			) );
			return;
		}
		if ( count( $cc_emails ) > 5 ) {
			wp_send_json_error( array( 'message' => __( 'You can add up to 5 CC email addresses.', 'sitestaffr' ) ) );
			return;
		}

		// Drop a CC that duplicates the primary.
		$primary_norm = strtolower( $email );
		if ( '' !== $primary_norm ) {
			$cc_emails = array_values( array_filter( $cc_emails, function ( $e ) use ( $primary_norm ) {
				return strtolower( $e ) !== $primary_norm;
			} ) );
		}
		$cc_string = ! empty( $cc_emails ) ? implode( ', ', $cc_emails ) : '';

		// Stored in a DEDICATED option (not the shared sitestaffr_settings array) so
		// the blog recipients can never be clobbered by another settings writer.
		update_option( 'sitestaffr_blog_notifications', array(
			'enabled' => $enabled,
			'email'   => $email,
			'cc'      => $cc_string,
		), false );

		wp_send_json_success( array(
			'message'   => __( 'Notification settings saved.', 'sitestaffr' ),
			'enabled'   => $enabled,
			'email'     => $email,
			'cc_emails' => $cc_string,
		) );
	}

	/**
	 * AJAX: manually email a conversation's notification to selected recipients.
	 *
	 * @since 1.28.0
	 * @return void
	 */
	public function ajax_email_conversation() {
		if ( ! check_ajax_referer( 'sitestaffr_admin_nonce', 'nonce', false ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'sitestaffr' ) ) );
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to do this.', 'sitestaffr' ) ) );
			return;
		}

		$call_id    = isset( $_POST['call_id'] ) ? absint( wp_unslash( $_POST['call_id'] ) ) : 0;
		$requested  = isset( $_POST['recipients'] ) ? (array) wp_unslash( $_POST['recipients'] ) : array();
		$recipients = $this->filter_requested_recipients( $requested, $this->get_configured_recipients() );

		if ( ! $call_id ) {
			wp_send_json_error( array( 'message' => __( 'Missing conversation.', 'sitestaffr' ) ) );
			return;
		}
		if ( empty( $recipients ) ) {
			wp_send_json_error( array( 'message' => __( 'Choose at least one recipient.', 'sitestaffr' ) ) );
			return;
		}

		if ( ! class_exists( 'SiteStaffr_Email_Notifications' ) ) {
			require_once SITESTAFFR_PLUGIN_DIR . 'includes/class-sitestaffr-email-notifications.php';
		}
		$handler = new SiteStaffr_Email_Notifications();
		$sent    = $handler->send_call_notification( $call_id, '', $recipients );

		if ( $sent ) {
			wp_send_json_success(
				array(
					/* translators: %d: number of recipients */
					'message' => sprintf( _n( 'Conversation emailed to %d recipient.', 'Conversation emailed to %d recipients.', count( $recipients ), 'sitestaffr' ), count( $recipients ) ),
				)
			);
		} else {
			$detail = $handler->get_last_mail_error();
			wp_send_json_error( array( 'message' => __( 'Failed to email the conversation.', 'sitestaffr' ) . ( $detail ? ' ' . $detail : '' ) ) );
		}
	}

	/**
	 * AJAX: manually email a draft's review link to selected recipients.
	 *
	 * @since 1.28.0
	 * @return void
	 */
	public function ajax_email_review_link() {
		if ( ! check_ajax_referer( 'sitestaffr_admin_nonce', 'nonce', false ) ) {
			wp_send_json_error( array( 'message' => __( 'Security check failed.', 'sitestaffr' ) ) );
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to do this.', 'sitestaffr' ) ) );
			return;
		}

		$post_id    = isset( $_POST['post_id'] ) ? absint( wp_unslash( $_POST['post_id'] ) ) : 0;
		$requested  = isset( $_POST['recipients'] ) ? (array) wp_unslash( $_POST['recipients'] ) : array();
		$recipients = $this->filter_requested_recipients( $requested, $this->get_blog_recipients() );

		if ( ! $post_id || ! class_exists( 'SiteStaffr_Blog_Review' ) || ! SiteStaffr_Blog_Review::is_blog_agent_post( $post_id ) ) {
			wp_send_json_error( array( 'message' => __( 'Not a Blog Agent post.', 'sitestaffr' ) ) );
			return;
		}
		if ( empty( $recipients ) ) {
			wp_send_json_error( array( 'message' => __( 'Choose at least one recipient.', 'sitestaffr' ) ) );
			return;
		}

		if ( ! class_exists( 'SiteStaffr_Email_Notifications' ) ) {
			require_once SITESTAFFR_PLUGIN_DIR . 'includes/class-sitestaffr-email-notifications.php';
		}
		$handler = new SiteStaffr_Email_Notifications();
		$sent    = $handler->send_blog_ready_notification( $post_id, $recipients, true );

		if ( $sent ) {
			wp_send_json_success(
				array(
					/* translators: %d: number of recipients */
					'message' => sprintf( _n( 'Review link emailed to %d recipient.', 'Review link emailed to %d recipients.', count( $recipients ), 'sitestaffr' ), count( $recipients ) ),
				)
			);
		} else {
			$detail = $handler->get_last_mail_error();
			wp_send_json_error( array( 'message' => __( 'Failed to email the review link.', 'sitestaffr' ) . ( $detail ? ' ' . $detail : '' ) ) );
		}
	}

	/**
	 * Merge a list of emails into a unique set.
	 *
	 * @since 0.14.269
	 *
	 * @param array $emails Raw email list.
	 * @return array
	 */
	private function merge_unique_email_recipients( $emails ) {
		if ( ! is_array( $emails ) || empty( $emails ) ) {
			return array();
		}

		$merged = array();
		$seen   = array();

		foreach ( $emails as $email ) {
			$sanitized_email = sanitize_email( (string) $email );
			if ( empty( $sanitized_email ) || ! is_email( $sanitized_email ) ) {
				continue;
			}

			$key = strtolower( $sanitized_email );
			if ( isset( $seen[ $key ] ) ) {
				continue;
			}

			$seen[ $key ] = true;
			$merged[] = $sanitized_email;
		}

		return $merged;
	}
}
