<?php
/**
 * ActiveTrail User Registration Handler
 *
 * @package ActiveTrail_WooCommerce
 * @since 1.0.0
 */

// phpcs:disable WordPress.WP.I18n.TextDomainMismatch
// Text domain 'activetrail-for-woocommerce' is correct per WordPress review requirements.

// Prevent direct access.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * ActiveTrail User Registration Handler Class
 */
class ActiveTrail_User_Registration_Handler {


	/**
	 * API Client instance
	 *
	 * @var ActiveTrail_API_Client
	 */
	private $api_client;

	/**
	 * Settings instance
	 *
	 * @var ActiveTrail_Settings
	 */
	private $settings;

	/**
	 * Constructor
	 *
	 * @param ActiveTrail_API_Client $api_client API client instance.
	 * @param ActiveTrail_Settings   $settings Settings instance.
	 */
	public function __construct( $api_client, $settings ) {
		$this->api_client = $api_client;
		$this->settings   = $settings;

		$this->init_hooks();
	}

	/**
	 * Initialize WordPress hooks
	 */
	private function init_hooks() {
		// Add consent field to registration form (only once).
		add_action( 'woocommerce_register_form', array( $this, 'add_registration_consent_field' ) );

		// Add consent field to my-account page.
		add_action( 'woocommerce_edit_account_form', array( $this, 'add_account_consent_field' ) );

		// Validate consent field.
		add_action( 'woocommerce_register_post', array( $this, 'validate_registration_consent' ), 10, 3 );

		// Save consent when user is created.
		add_action( 'woocommerce_created_customer', array( $this, 'save_registration_consent' ), 10, 3 );

		// Save consent when account is updated.
		add_action( 'woocommerce_save_account_details', array( $this, 'save_account_consent' ), 10, 1 );

		// Handle user registration to ActiveTrail.
		add_action( 'woocommerce_created_customer', array( $this, 'handle_user_registration' ), 15, 3 );

		// AJAX handler for updating consent status.
		add_action( 'wp_ajax_activetrail_update_consent', array( $this, 'ajax_update_consent' ) );
		add_action( 'wp_ajax_nopriv_activetrail_update_consent', array( $this, 'ajax_update_consent' ) );
	}

	/**
	 * Add consent field to registration form
	 */
	public function add_registration_consent_field() {
		$settings = ActiveTrail_Settings::get_all();
		if ( ! isset( $settings['enable_registration_consent'] ) || ! $settings['enable_registration_consent'] ) {
			return;
		}
		// Prevent duplicate fields.
		static $field_added = false;
		if ( $field_added ) {
			return;
		}
		$field_added = true;

		// Use custom consent text from settings, or fall back to translated default.
		$consent_text = ! empty( $settings['consent_text'] )
			? $settings['consent_text']
			: esc_html__( 'I agree to receive marketing emails', 'activetrail-for-woocommerce' );

		// When "Marketing consent checked by default" is enabled, render the checkbox as checked.
		$checked_by_default = ! empty( $settings['consent_checked_by_default'] );
		?>
		<p class="woocommerce-form-row form-row">
			<label class="woocommerce-form__label woocommerce-form__label-for-checkbox woocommerce-form-login__rememberme">
				<input class="woocommerce-form__input woocommerce-form__input-checkbox" name="activetrail_registration_consent"
					type="checkbox" id="activetrail_registration_consent" value="1" <?php checked( $checked_by_default, true ); ?> />
				<?php echo esc_html( $consent_text ); ?>
			</label>
		</p>
		<?php
	}

	/**
	 * Add consent field to my-account page
	 */
	public function add_account_consent_field() {
		$settings = ActiveTrail_Settings::get_all();
		if ( ! isset( $settings['enable_registration_consent'] ) || ! $settings['enable_registration_consent'] ) {
			return;
		}

		// Get current user's consent status.
		$user_id    = get_current_user_id();
		$consent    = get_user_meta( $user_id, '_activetrail_registration_consent', true );
		$is_checked = $consent === 'yes';

		// Use custom consent text from settings, or fall back to translated default.
		$consent_text = ! empty( $settings['consent_text'] )
			? $settings['consent_text']
			: esc_html__( 'I agree to receive marketing emails', 'activetrail-for-woocommerce' );
		?>
		<fieldset>
			<legend><?php esc_html_e( 'Newsletter Preferences', 'activetrail-for-woocommerce' ); ?></legend>
			<p class="woocommerce-form-row form-row">
				<label class="woocommerce-form__label woocommerce-form__label-for-checkbox">
					<input class="woocommerce-form__input woocommerce-form__input-checkbox"
						name="activetrail_registration_consent" type="checkbox" id="activetrail_registration_consent" value="1"
						<?php checked( $is_checked, true ); ?> />
					<?php echo esc_html( $consent_text ); ?>
				</label>
			</p>
		</fieldset>
		<?php
	}

	/**
	 * Save account consent
	 *
	 * @param int $user_id User ID.
	 */
	public function save_account_consent( $user_id ) {
		try {
			// Save consent information.
            // phpcs:ignore WordPress.Security.NonceVerification.Missing -- WordPress registration form handles nonce verification
			if ( isset( $_POST['activetrail_registration_consent'] ) && sanitize_text_field( wp_unslash( $_POST['activetrail_registration_consent'] ) ) ) {
				update_user_meta( $user_id, '_activetrail_registration_consent', 'yes' );
				update_user_meta( $user_id, '_activetrail_consent_date', current_time( 'mysql' ) );
				// Add standard meta keys for compatibility with other plugins.
				update_user_meta( $user_id, 'activetrail_optin', 'yes' );
				update_user_meta( $user_id, 'activetrail_subscribe', '1' );

				// Sync user to ActiveTrail if consent is given.
				$user = get_user_by( 'id', $user_id );
				if ( $user ) {
					// Prepare user data for ActiveTrail.
					$user_data = $this->prepare_user_data( $user );

					// Always set subscriptionStatus explicitly based on consent.
					$user_data['subscriptionStatus'] = true; // Since we know consent is given here

					// Make sure API client has the correct API key.
					$api_key = ActiveTrail_Settings::get( 'api_key' );
					if ( ! empty( $api_key ) ) {
						$this->api_client->set_api_key( $api_key );
					}

					// Send to ActiveTrail - wrap in try/catch to prevent form submission errors.
					try {
						$result = $this->api_client->import_customer_from_user( $user_data );

						if ( $result['success'] ) {
							// Mark user as synced.
							update_user_meta( $user_id, '_activetrail_synced', 'yes' );
							update_user_meta( $user_id, '_activetrail_sync_date', current_time( 'mysql' ) );

							$this->log( 'User consent updated and synced successfully: ' . $user->user_email );
						} else {
							$this->log( 'Failed to sync user after consent update ' . $user->user_email . ': ' . $result['message'], 'error' );
						}
					} catch ( Exception $api_e ) {
						// Log the API error but don't fail the form submission.
						$this->log( 'API error during consent update: ' . $api_e->getMessage(), 'error' );
					}
				}
			} else {
				update_user_meta( $user_id, '_activetrail_registration_consent', 'no' );
				// Add standard meta keys for compatibility with other plugins.
				update_user_meta( $user_id, 'activetrail_optin', 'no' );
				update_user_meta( $user_id, 'activetrail_subscribe', '0' );
			}
		} catch ( Exception $e ) {
			// Log the error but don't fail the form submission.
			$this->log( 'Error during account consent update: ' . $e->getMessage(), 'error' );
		}
	}

	/**
	 * Validate registration consent
	 *
	 * @param string   $username Username.
	 * @param string   $email Email.
	 * @param WP_Error $errors Errors object.
	 */
	public function validate_registration_consent( $username, $email, $errors ) {
		$settings = ActiveTrail_Settings::get_all();
		if ( ! isset( $settings['enable_registration_consent'] ) || ! $settings['enable_registration_consent'] ) {
			return;
		}
		if ( empty( $settings['consent_required'] ) ) {
			return;
		}
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Registration form context
		$consent = isset( $_POST['activetrail_registration_consent'] ) ? sanitize_text_field( wp_unslash( $_POST['activetrail_registration_consent'] ) ) : '';
		if ( empty( $consent ) ) {
			$errors->add(
				'activetrail_consent_required',
				__( 'You must approve marketing emails in order to continue.', 'activetrail-for-woocommerce' )
			);
		}
	}

	/**
	 * Save registration consent
	 *
	 * @param int    $customer_id Customer ID.
	 * @param array  $new_customer_data Customer data.
	 * @param string $password_generated Whether password was generated.
	 */
	public function save_registration_consent( $customer_id, $new_customer_data, $password_generated ) {
		try {
			// Save consent information.
			// Check registration form consent first.
			$has_consent = false;
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WordPress registration form handles nonce verification
			if ( isset( $_POST['activetrail_registration_consent'] ) && sanitize_text_field( wp_unslash( $_POST['activetrail_registration_consent'] ) ) ) {
				$has_consent = true;
			}
			// Registration during checkout: consent may come from checkout checkbox (billing_activetrail_consent / activetrail_consent).
			if ( ! $has_consent && ! empty( $_POST ) && class_exists( 'ActiveTrail_Consent_Helper' ) ) {
				// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Checkout form context
				$has_consent = ActiveTrail_Consent_Helper::has_consent_from_data( $_POST );
			}
			if ( $has_consent ) {
				update_user_meta( $customer_id, '_activetrail_registration_consent', 'yes' );
				update_user_meta( $customer_id, '_activetrail_consent', 'yes' );
				update_user_meta( $customer_id, '_activetrail_consent_date', current_time( 'mysql' ) );
				// Add standard meta keys for compatibility with other plugins.
				update_user_meta( $customer_id, 'activetrail_optin', 'yes' );
				update_user_meta( $customer_id, 'activetrail_subscribe', '1' );

				// Note: We don't need to sync here as handle_user_registration will do it.
				// This is just to record the consent status.
			} else {
				update_user_meta( $customer_id, '_activetrail_registration_consent', 'no' );
				update_user_meta( $customer_id, '_activetrail_consent', 'no' );
				// Add standard meta keys for compatibility with other plugins.
				update_user_meta( $customer_id, 'activetrail_optin', 'no' );
				update_user_meta( $customer_id, 'activetrail_subscribe', '0' );
			}

			// Registration during checkout: copy billing fields from POST to user meta
			// so that prepare_user_data (in handle_user_registration) can send phone, street, zip to ActiveTrail.
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Checkout form context
			if ( ! empty( $_POST['billing_phone'] ) ) {
				update_user_meta( $customer_id, 'billing_phone', sanitize_text_field( wp_unslash( $_POST['billing_phone'] ) ) );
			}
			if ( ! empty( $_POST['billing_address_1'] ) ) {
				update_user_meta( $customer_id, 'billing_address_1', sanitize_text_field( wp_unslash( $_POST['billing_address_1'] ) ) );
			}
			if ( isset( $_POST['billing_address_2'] ) ) {
				update_user_meta( $customer_id, 'billing_address_2', sanitize_text_field( wp_unslash( $_POST['billing_address_2'] ) ) );
			}
			if ( ! empty( $_POST['billing_city'] ) ) {
				update_user_meta( $customer_id, 'billing_city', sanitize_text_field( wp_unslash( $_POST['billing_city'] ) ) );
			}
			if ( ! empty( $_POST['billing_postcode'] ) ) {
				update_user_meta( $customer_id, 'billing_postcode', sanitize_text_field( wp_unslash( $_POST['billing_postcode'] ) ) );
			}
		} catch ( Exception $e ) {
			// Log the error but don't fail the registration.
			$this->log( 'Error during registration consent save: ' . $e->getMessage(), 'error' );
		}
	}

	/**
	 * Handle user registration to ActiveTrail
	 *
	 * @param int    $customer_id Customer ID.
	 * @param array  $new_customer_data Customer data.
	 * @param string $password_generated Whether password was generated.
	 */
	public function handle_user_registration( $customer_id, $new_customer_data, $password_generated ) {
		try {
			// Get settings.
			$settings = ActiveTrail_Settings::get_all();

			// Check if we should sync this user.
			if ( ! $this->should_sync_user( $customer_id ) ) {
				return;
			}

			// Get user data.
			$user = get_user_by( 'id', $customer_id );
			if ( ! $user ) {
				return;
			}

			// CRITICAL: Check if there's already a guest contact with this email.
			// If user registered during checkout, a guest contact might already exist.
			// We should not create a duplicate - the existing guest contact will be used.
			// and the order will link to it via the registered external ID when synced.
			try {
				$api_key = ActiveTrail_Settings::get( 'api_key' );
				if ( ! empty( $api_key ) ) {
					$this->api_client->set_api_key( $api_key );
				}

				// Check if contact already exists (could be guest contact created during cart/checkout).
				$existing_contact_check = $this->api_client->get_customer_by_email( $user->user_email );

				if ( ! is_wp_error( $existing_contact_check ) && ! empty( $existing_contact_check['exists'] ) ) {
					// Contact already exists (likely a guest contact from checkout). data may be array of contacts.
					$data   = $existing_contact_check['data'];
					$first  = ( is_array( $data ) && isset( $data[0] ) ) ? $data[0] : $data;
					$existing_external_id = isset( $first['externalId'] ) ? $first['externalId'] : 'unknown';

					$this->log( 'User registered but contact already exists in ActiveTrail (likely from checkout): ' . $existing_external_id . ' - skipping duplicate creation', 'info' );

					// Mark user as synced even though we didn't create new contact.
					// The existing guest contact will be used for orders.
					update_user_meta( $customer_id, '_activetrail_synced', 'yes' );
					update_user_meta( $customer_id, '_activetrail_sync_date', current_time( 'mysql' ) );
					update_user_meta( $customer_id, '_activetrail_existing_contact_id', $existing_external_id );

					return; // Exit early - don't create duplicate
				}
			} catch ( Exception $check_e ) {
				// If check fails, continue with normal registration process.
				$this->log( 'Could not check for existing contact during registration: ' . $check_e->getMessage(), 'debug' );
			}

			// Prepare user data for ActiveTrail.
			$user_data = $this->prepare_user_data( $user );

			// Make sure API client has the correct API key.
			$api_key = ActiveTrail_Settings::get( 'api_key' );
			if ( ! empty( $api_key ) ) {
				$this->api_client->set_api_key( $api_key );
			}

			// Send to ActiveTrail - wrap in try/catch to prevent registration errors.
			try {
				$result = $this->api_client->import_customer_from_user( $user_data );

				if ( $result['success'] ) {
					// Mark user as synced.
					update_user_meta( $customer_id, '_activetrail_synced', 'yes' );
					update_user_meta( $customer_id, '_activetrail_sync_date', current_time( 'mysql' ) );

					$this->log( 'User synced successfully: ' . $user->user_email );
				} else {
					$this->log( 'Failed to sync user ' . $user->user_email . ': ' . $result['message'], 'error' );
				}
			} catch ( Exception $api_e ) {
				// Log the API error but don't fail the registration.
				$this->log( 'API error during user registration sync: ' . $api_e->getMessage(), 'error' );
			}
		} catch ( Exception $e ) {
			// Log the error but don't let it bubble up to the user interface.
			$this->log( 'Error during user registration sync: ' . $e->getMessage(), 'error' );
		}
	}

	/**
	 * Check if user should be synced to ActiveTrail
	 *
	 * @param int $customer_id Customer ID.
	 * @return bool
	 */
	private function should_sync_user( $customer_id ) {
		// Always sync users to ActiveTrail.
		// The subscriptionStatus will be set based on consent in prepare_user_data.
		return true;
	}

	/**
	 * Prepare user data for ActiveTrail API
	 *
	 * @param WP_User $user User object.
	 * @return array
	 */
	private function prepare_user_data( $user ) {
		// Get settings.
		$settings = ActiveTrail_Settings::get_all();

		// Get user meta data.
		$first_name = get_user_meta( $user->ID, 'first_name', true );
		$last_name  = get_user_meta( $user->ID, 'last_name', true );
		$phone      = get_user_meta( $user->ID, 'billing_phone', true );
		
		// Get address data from user meta.
		$address_1 = get_user_meta( $user->ID, 'billing_address_1', true );
		$address_2 = get_user_meta( $user->ID, 'billing_address_2', true );
		$city      = get_user_meta( $user->ID, 'billing_city', true );
		$postcode  = get_user_meta( $user->ID, 'billing_postcode', true );
		
		// Combine address lines.
		$address = trim( $address_1 . ' ' . $address_2 );

		// Get consent information from both registration and checkout consent.
		$reg_consent     = get_user_meta( $user->ID, '_activetrail_registration_consent', true );
		$checkout_consent = get_user_meta( $user->ID, '_activetrail_consent', true );
		$has_consent     = ( $reg_consent === 'yes' || $checkout_consent === 'yes' );
		$subscriber_status = $has_consent;

		// Format data according to what the API client expects.
		$user_data = array(
			'email'              => $user->user_email,
			'first_name'         => $first_name ? $first_name : '',
			'last_name'          => $last_name ? $last_name : '',
			'phone'              => $phone ? $phone : '',
			'address'            => $address ? $address : '',
			'street'             => $address ? $address : '', // Map to street for API
			'city'               => $city ? $city : '',
			'zip_code'           => $postcode ? $postcode : '',
			'postcode'           => $postcode ? $postcode : '', // Also include as postcode for compatibility
			'consent'            => $has_consent,
			'subscriptionStatus' => $subscriber_status, // Always set explicitly
			'registration_date'  => $user->user_registered,
			'source'             => 'woocommerce_registration',
			'group_id'           => isset( $settings['group_id'] ) ? $settings['group_id'] : '',
			// Add required fields for the API client.
			'externalId'         => activetrail_external_id_for_contact( $user->ID, $user->user_email ),
			'externalName'       => ACTIVETRAIL_EXTERNAL_NAME,
		);

		$this->log( 'Prepared user data: ' . wp_json_encode( $user_data ), 'debug' );

		return $user_data;
	}

	/**
	 * Log message
	 *
	 * @param string $message Message to log.
	 * @param string $level Log level.
	 */
	private function log( $message, $level = 'info' ) {
		if ( class_exists( 'ActiveTrail_Logger' ) ) {
			ActiveTrail_Logger::get_instance()->log( $message, $level );
		}
	}

	/**
	 * AJAX handler for updating consent status
	 */
	public function ajax_update_consent() {
		try {
			// Verify nonce.
			$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
			if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'activetrail_nonce' ) ) {
				wp_send_json_error(
					array(
						'message' => esc_html__( 'Security check failed', 'activetrail-for-woocommerce' ),
					)
				);
				return;
			}

			// Check if user is logged in.
			if ( ! is_user_logged_in() ) {
				wp_send_json_error(
					array(
						'message' => esc_html__( 'You must be logged in to update consent status', 'activetrail-for-woocommerce' ),
					)
				);
				return;
			}

			// Get current user.
			$user_id = get_current_user_id();
			if ( ! $user_id ) {
				wp_send_json_error(
					array(
						'message' => esc_html__( 'Invalid user', 'activetrail-for-woocommerce' ),
					)
				);
				return;
			}

			// Get consent status from request.
			$consent = isset( $_POST['consent'] ) ? (bool) sanitize_text_field( wp_unslash( $_POST['consent'] ) ) : false;

			// Update user meta.
			update_user_meta( $user_id, '_activetrail_registration_consent', $consent ? 'yes' : 'no' );
			// Add standard meta keys for compatibility with other plugins.
			update_user_meta( $user_id, 'activetrail_optin', $consent ? 'yes' : 'no' );
			update_user_meta( $user_id, 'activetrail_subscribe', $consent ? '1' : '0' );
			if ( $consent ) {
				update_user_meta( $user_id, '_activetrail_consent_date', current_time( 'mysql' ) );
			}

			// If consent is given, sync user to ActiveTrail.
			if ( $consent ) {
				$user = get_user_by( 'id', $user_id );
				if ( $user ) {
					// Prepare user data for ActiveTrail.
					$user_data = $this->prepare_user_data( $user );

					// Make sure API client has the correct API key.
					$api_key = ActiveTrail_Settings::get( 'api_key' );
					if ( ! empty( $api_key ) ) {
						$this->api_client->set_api_key( $api_key );
					}

					// Send to ActiveTrail - wrap in try/catch to prevent AJAX errors.
					try {
						$result = $this->api_client->import_customer_from_user( $user_data );

						if ( $result['success'] ) {
							// Mark user as synced.
							update_user_meta( $user_id, '_activetrail_synced', 'yes' );
							update_user_meta( $user_id, '_activetrail_sync_date', current_time( 'mysql' ) );

							$this->log( 'User consent updated and synced successfully: ' . $user->user_email );

							wp_send_json_success(
								array(
									'message' => esc_html__( 'Consent updated and synced successfully', 'activetrail-for-woocommerce' ),
									'synced'  => true,
								)
							);
							return;
						} else {
							$this->log( 'Failed to sync user after consent update ' . $user->user_email . ': ' . $result['message'], 'error' );

							wp_send_json_success(
								array(
									'message' => esc_html__( 'Consent updated but sync failed', 'activetrail-for-woocommerce' ),
									'synced'  => false,
									'error'   => $result['message'],
								)
							);
							return;
						}
					} catch ( Exception $api_e ) {
						// Log the API error but still return success for the consent update.
						$this->log( 'API error during AJAX consent update: ' . $api_e->getMessage(), 'error' );

						wp_send_json_success(
							array(
								'message' => esc_html__( 'Consent updated but sync failed', 'activetrail-for-woocommerce' ),
								'synced'  => false,
								'error'   => $api_e->getMessage(),
							)
						);
						return;
					}
				}
			}

			// If we got here, consent was updated but no sync was needed.
			wp_send_json_success(
				array(
					'message' => esc_html__( 'Consent updated successfully', 'activetrail-for-woocommerce' ),
					'synced'  => false,
				)
			);

		} catch ( Exception $e ) {
			// Log the error.
			$this->log( 'Error during consent update: ' . $e->getMessage(), 'error' );

			wp_send_json_error(
				array(
					'message' => esc_html__( 'An error occurred while updating consent', 'activetrail-for-woocommerce' ),
					'error'   => $e->getMessage(),
				)
			);
		}
	}
}
