<?php
/**
 * Connection Tester Service
 *
 * Handles connection testing for native integrations.
 *
 * @package SureForms
 * @since 1.13.0
 */

namespace SRFM_Pro\Inc\Pro\Native_Integrations\Services;

use SRFM\Inc\Helper;
use SRFM_Pro\Inc\Pro\Native_Integrations\Integration_Provider;
use SRFM_Pro\Inc\Pro\Native_Integrations\OAuth_Handler;
use SRFM_Pro\Inc\Pro\Native_Integrations\Provider_Factory;
use SRFM_Pro\Inc\Pro\Native_Integrations\Utils\Integration_Utils;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Connection Tester Service class.
 *
 * @since 1.13.0
 */
class Connection_Tester {
	/**
	 * OAuth Handler instance
	 *
	 * @var OAuth_Handler
	 */
	private $oauth_handler;

	/**
	 * Constructor
	 *
	 * @param OAuth_Handler $oauth_handler OAuth handler instance.
	 * @since 2.1.0
	 */
	public function __construct( OAuth_Handler $oauth_handler ) {
		$this->oauth_handler = $oauth_handler;
	}

	/**
	 * Test integration connection
	 *
	 * @param string $integration_name Integration name.
	 * @param array  $credentials User credentials.
	 * @param array  $auth_config Authentication configuration.
	 * @return \WP_REST_Response
	 * @since 1.13.0
	 */
	public function test_connection( $integration_name, $credentials, $auth_config ) {
		if ( empty( $integration_name ) || empty( $credentials ) || empty( $auth_config ) ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => __( 'Please provide valid credentials before testing the connection.', 'sureforms-pro' ),
				],
				400
			);
		}

		try {
			// Handle OAuth token refresh via middleware if needed.
			if ( OAuth_Handler::is_oauth_credentials( $credentials ) ) {
				$credentials = $this->oauth_handler->ensure_fresh_oauth_tokens( $integration_name, $credentials, $auth_config );
				if ( is_wp_error( $credentials ) ) {
					return new \WP_REST_Response(
						[
							'success' => false,
							'message' => $credentials->get_error_message(),
						],
						400
					);
				}
			}

			// Use provider system for all integrations (generic or specific).
			$provider_type = Provider_Factory::get_provider_type( $integration_name );
			$provider      = Provider_Factory::create( $provider_type );

			if ( $provider instanceof Integration_Provider ) {
				$result = $provider->test_connection( $credentials, $auth_config );

				return new \WP_REST_Response(
					[
						'success' => $result['success'],
						'message' => $result['message'],
					],
					$result['success'] ? 200 : 400
				);
			}

			// Fallback to legacy method for unsupported integrations.
			return $this->legacy_test_connection( $credentials, $auth_config );

		} catch ( \Exception $e ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => sprintf(
						/* translators: %s: Exception message */
						__( 'Connection test error: %s', 'sureforms-pro' ),
						$e->getMessage()
					),
				],
				500
			);
		}
	}

	/**
	 * Legacy test integration connection method
	 *
	 * @param array $credentials User credentials.
	 * @param array $auth_config Authentication configuration.
	 * @return \WP_REST_Response
	 * @since 1.13.0
	 */
	private function legacy_test_connection( $credentials, $auth_config ) {
		// Validate test endpoint structure.
		$test_endpoint = $auth_config['test_endpoint'] ?? [];
		if ( empty( $test_endpoint['url'] ) ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => __( 'Test endpoint URL is required.', 'sureforms-pro' ),
				],
				400
			);
		}

		// Build authentication headers using auth config.
		// Since connection-tester only gets auth_config, we need to wrap it as integration_config.
		$integration_config = [
			'auth' => $auth_config,
		];
		$headers            = Integration_Utils::build_auth_headers(
			Helper::get_array_value( $credentials ),
			$integration_config,
			[
				'default_headers' => [
					'User-Agent' => 'SureForms Pro/' . SRFM_PRO_VER,
				],
			]
		);

		// Prepare request arguments.
		$request_args = [
			'method'     => $test_endpoint['method'] ?? 'GET',
			'headers'    => $headers,
			'timeout'    => 30,
			'sslverify'  => true,
			'user-agent' => 'SureForms Pro/' . SRFM_PRO_VER,
		];

		// Make HTTP request to the integration's test endpoint.
		$response = wp_remote_request( $test_endpoint['url'], $request_args );

		// Check for WordPress HTTP errors.
		if ( is_wp_error( $response ) ) {
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => sprintf(
						/* translators: %s: Error message */
						__( 'Connection test failed: %s', 'sureforms-pro' ),
						$response->get_error_message()
					),
				],
				500
			);
		}

		// Get response details.
		$status_code      = wp_remote_retrieve_response_code( $response );
		$response_body    = wp_remote_retrieve_body( $response );
		$success_criteria = $test_endpoint['success_criteria'] ?? [];

		// Validate response against success criteria.
		$is_successful = $this->validate_test_response(
			Helper::get_integer_value( $status_code ),
			$response_body,
			$success_criteria
		);

		if ( $is_successful ) {
			return new \WP_REST_Response(
				[
					'success' => true,
					'message' => __( 'Connection test successful! Integration is properly configured.', 'sureforms-pro' ),
				],
				200
			);
		}
			return new \WP_REST_Response(
				[
					'success' => false,
					'message' => sprintf(
						/* translators: %s: HTTP status code */
						__( 'Connection test failed. HTTP Status: %d', 'sureforms-pro' ),
						$status_code
					),
				],
				400
			);
	}

	/**
	 * Validate test response against success criteria
	 *
	 * @param int    $status_code HTTP status code.
	 * @param string $response_body Response body.
	 * @param array  $success_criteria Success criteria.
	 * @return bool
	 * @since 1.13.0
	 */
	private function validate_test_response( $status_code, $response_body, $success_criteria ) {
		// Default success criteria: 200 status code.
		if ( empty( $success_criteria ) ) {
			return 200 === $status_code;
		}

		// Check status code criteria.
		if ( isset( $success_criteria['status_code'] ) ) {
			$expected_codes = (array) $success_criteria['status_code'];
			if ( ! in_array( $status_code, $expected_codes, true ) ) {
				return false;
			}
		}

		// Check response body criteria.
		if ( isset( $success_criteria['response_contains'] ) ) {
			$required_strings = (array) $success_criteria['response_contains'];
			foreach ( $required_strings as $required_string ) {
				if ( strpos( $response_body, $required_string ) === false ) {
					return false;
				}
			}
		}

		// Check response body exclusion criteria.
		if ( isset( $success_criteria['response_not_contains'] ) ) {
			$forbidden_strings = (array) $success_criteria['response_not_contains'];
			foreach ( $forbidden_strings as $forbidden_string ) {
				if ( strpos( $response_body, $forbidden_string ) !== false ) {
					return false;
				}
			}
		}

		return true;
	}
}
