<?php
/**
 * Compatibility Utils Service
 *
 * Handles compatibility issues between different integration APIs and data formats.
 *
 * @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\Utils\Integration_Utils;

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

/**
 * Compatibility Utils class.
 *
 * @since 1.13.0
 */
class Compatibility_Utils {
	/**
	 * Apply field lookup to fetch field value from API
	 *
	 * This method handles compatibility issues where APIs require different field formats.
	 * For example, converting email addresses to subscriber IDs for APIs that only accept IDs.
	 *
	 * @param string $url URL template.
	 * @param array  $data Data containing source field.
	 * @param array  $config Field lookup configuration.
	 * @return string URL with field value replaced.
	 * @since 1.13.0
	 */
	public static function apply_field_lookup( $url, $data, $config ) {
		$source_field      = $config['source_field'] ?? '';
		$lookup_endpoint   = $config['lookup_endpoint'] ?? '';
		$lookup_method     = $config['lookup_method'] ?? 'GET';
		$lookup_params     = $config['lookup_params'] ?? [];
		$field_path        = $config['field_path'] ?? 'id';
		$replacement_token = $config['replacement_token'] ?? '';
		$headers_config    = $config['headers'] ?? [];

		if ( empty( $source_field ) || empty( $lookup_endpoint ) || empty( $replacement_token ) ) {
			return $url;
		}

		$source_value = $data[ $source_field ] ?? '';
		if ( empty( $source_value ) ) {
			return $url;
		}

		try {
			// Build lookup URL with template variable processing.
			$lookup_url = Integration_Utils::replace_placeholders( $lookup_endpoint, $data );

			// Prepare headers for lookup request.
			$headers = [];
			foreach ( $headers_config as $key => $value ) {
				$headers[ sanitize_key( Helper::get_string_value( $key ) ) ] = sanitize_text_field( Integration_Utils::replace_placeholders( $value, $data ) );
			}

			// Build unified request args.
			$request_args = [
				'method'  => $lookup_method,
				'headers' => $headers,
				'timeout' => 30,
			];

			// Handle lookup parameters based on method.
			if ( ! empty( $lookup_params ) ) {
				$processed_params = [];
				foreach ( $lookup_params as $param_key => $param_value ) {
					$processed_params[ $param_key ] = Integration_Utils::replace_placeholders( $param_value, $data );
				}

				if ( 'GET' === strtoupper( $lookup_method ) ) {
					// Add as query parameters for GET requests.
					$lookup_url = add_query_arg( $processed_params, $lookup_url );
				} else {
					// Add as request body for non-GET methods.
					$json_body = wp_json_encode( $processed_params );
					if ( false === $json_body ) {
						return $url; // Return original URL if JSON encoding fails.
					}
					$request_args['body'] = $json_body;
					if ( ! isset( $headers['Content-Type'] ) ) {
						$request_args['headers']['Content-Type'] = 'application/json';
					}
				}
			}

			// Make lookup API request.
			$response = wp_remote_request( $lookup_url, $request_args );

			if ( is_wp_error( $response ) ) {
				return $url;
			}

			$status_code = wp_remote_retrieve_response_code( $response );
			// Check if status code is not 2xx.
			if ( $status_code < 200 || $status_code >= 300 ) {
				return $url;
			}

			$body          = wp_remote_retrieve_body( $response );
			$response_data = json_decode( $body, true );

			if ( json_last_error() !== JSON_ERROR_NONE ) {
				return $url;
			}

			// Extract field value using path notation.
			$field_value = Integration_Utils::get_nested_value( Helper::get_array_value( $response_data ), $field_path );

			if ( ! empty( $field_value ) ) {
				$url = str_replace( $replacement_token, Helper::get_string_value( $field_value ), $url );
			}
		} catch ( \Exception $e ) {
			// Log error but don't break the flow.
			_doing_it_wrong( __METHOD__, 'SureForms Field Lookup Error: ' . esc_html( $e->getMessage() ), '1.13.0' );
		}

		return $url;
	}

	/**
	 * Transform dynamic field conversion
	 *
	 * Generic transformation that can convert form fields to various API formats
	 * including GetResponse customFieldValues, Mailchimp merge_fields, etc.
	 *
	 * @param array $payload Payload data.
	 * @param array $config Transformation configuration.
	 * @return array Transformed payload.
	 * @since 1.13.0
	 */
	public static function transform_dynamic_field_conversion( $payload, $config ) {
		$format           = $config['format'] ?? 'object_array';
		$source_pattern   = $config['source_pattern'] ?? '*';
		$exclude_fields   = $config['exclude_fields'] ?? [];
		$target_field     = $config['target_field'] ?? 'customFieldValues';
		$replace_source   = $config['replace_source_fields'] ?? true;
		$object_structure = $config['object_structure'] ?? [];

		// Collect matching fields.
		$matching_fields = [];
		foreach ( $payload as $key => $value ) {
			// Skip if in exclude list.
			if ( in_array( $key, $exclude_fields, true ) ) {
				continue;
			}

			// Check if field matches pattern.
			if ( fnmatch( $source_pattern, $key ) ) {
				$matching_fields[ $key ] = $value;
			}
		}

		if ( empty( $matching_fields ) ) {
			return $payload;
		}

		// Convert to target format.
		$converted_data = self::convert_to_target_format( $matching_fields, $format, $object_structure );

		// Add to payload and optionally remove source fields.
		if ( ! empty( $converted_data ) ) {
			$payload[ $target_field ] = $converted_data;
		}

		if ( $replace_source ) {
			foreach ( array_keys( $matching_fields ) as $key ) {
				unset( $payload[ $key ] );
			}
		}

		return $payload;
	}

	/**
	 * Convert fields to target format
	 *
	 * @param array  $fields Fields to convert.
	 * @param string $format Target format.
	 * @param array  $object_structure Object structure configuration.
	 * @return mixed Converted data.
	 * @since 1.13.0
	 */
	public static function convert_to_target_format( $fields, $format, $object_structure ) {
		// Only support object_array format for GetResponse-style APIs.
		if ( 'object_array' === $format ) {
			return self::convert_to_object_array( $fields, $object_structure );
		}

		// Default fallback.
		return $fields;
	}

	/**
	 * Convert fields to object array format
	 *
	 * @param array $fields Fields to convert.
	 * @param array $structure Object structure configuration.
	 * @return array Object array.
	 * @since 1.13.0
	 */
	public static function convert_to_object_array( $fields, $structure ) {
		$id_field     = $structure['id_field'] ?? 'customFieldId';
		$value_field  = $structure['value_field'] ?? 'value';
		$value_format = $structure['value_format'] ?? 'array';

		$result = [];
		foreach ( $fields as $field_key => $field_value ) {
			$obj = [
				$id_field => $field_key,
			];

			// Format value according to configuration.
			switch ( $value_format ) {
				case 'array':
					$obj[ $value_field ] = is_array( $field_value ) ? $field_value : [ $field_value ];
					break;
				case 'string':
					$obj[ $value_field ] = is_array( $field_value ) ? implode( ',', $field_value ) : (string) $field_value;
					break;
				case 'preserve_array':
					$obj[ $value_field ] = $field_value;
					break;
				default:
					$obj[ $value_field ] = $field_value;
			}

			$result[] = $obj;
		}

		return $result;
	}

}
