<?php
/**
 * Intex Global App
 *
 * @category   WordPress_Plugin
 * @package    Common
 * @subpackage Suppliers
 * @author     miniOrange <info@miniorange.com>
 * @license    MIT/Expat
 * @link       https://plugins.miniorange.com/woocommerce-api-product-sync-with-woocommerce-rest-apis
 */

namespace MOWCPS\Common\Suppliers;

use WP_Error;
use MOWCPS\Common\Abstracts\Base_Supplier_App;
use MOWCPS\Common\Interfaces\Supplier_App_Interface;
use MOWCPS\Common\Constants\Constants;
use MOWCPS\Common\Services\API\API_Service;
use MOWCPS\Common\Services\Authorization\Authorization_Service;
use MOWCPS\Common\Utils\Utils;
use MOWCPS\Common\Constants\Plugin_Filters;

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

/**
 * Class Intex_Global
 *
 * Handles Intex Global supplier app operations.
 */
class Intex_Global extends Base_Supplier_App implements Supplier_App_Interface {

	/**
	 * Constructor
	 */
	public function __construct() {
		parent::__construct( Constants::SUPPLIER_APP_TYPE_INTEX_GLOBAL );
	}

	/**
	 * Ensure app_type is in the request payload so Supplier_Request::to_array() persists it on insert.
	 *
	 * @param array $data Supplier data from API request.
	 * @return array|WP_Error
	 */
	public function create_supplier( $data ) {
		if ( empty( $data['app_type'] ) ) {
			$data['app_type'] = Constants::SUPPLIER_APP_TYPE_INTEX_GLOBAL;
		}
		return parent::create_supplier( $data );
	}

	/**
	 * Perform Intex Global connection test (token + primary API).
	 *
	 * @param array $supplier_data Supplier details from credentials form.
	 * @return array Test result.
	 */
	public function perform_connection_test( $supplier_data ) {
		$validation_result = $this->validate_supplier_specific_configuration( $supplier_data );
		if ( is_wp_error( $validation_result ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, $validation_result->get_error_message() ),
			);
		}

		$processed_config = $this->load_and_process_configuration( $supplier_data );
		if ( is_wp_error( $processed_config ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_CONFIG_LOADING_FAILED, $this->supplier_name, $processed_config->get_error_message() ),
			);
		}

		$authorization = $processed_config[ Constants::AUTHORIZATION ] ?? array();

		$auth_service = new Authorization_Service();
		$headers      = $auth_service->generate_headers( $authorization, 0 );

		if ( is_wp_error( $headers ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, $headers->get_error_message() ),
			);
		}

		$connections     = $processed_config['connections'] ?? array();
		$test_connection = $this->find_test_connection( $connections );

		if ( empty( $test_connection ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_NO_TEST_ENDPOINT, $this->supplier_name ),
			);
		}

		$config         = $test_connection['configuration'];
		$endpoint       = $config['endpoint'];
		$method         = strtoupper( (string) ( $config['method'] ?? 'GET' ) );
		$headers        = array_merge( $headers, $config['headers'] ?? array() );
		$body           = $config['body'] ?? array();

		if ( empty( $endpoint ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_NO_TEST_ENDPOINT_AVAILABLE, $this->supplier_name ),
			);
		}

		// Intex (and some other APIs) reject GET requests that include a body. wp_remote_request
		// may still forward a body key; omit it entirely for GET (matches execute_api_call behaviour).
		$wp_request_args = array(
			'method'  => $method,
			'headers' => $headers,
			'timeout' => 600,
		);
		if ( Constants::GET_REQUEST !== $method && ! empty( $body ) ) {
			$wp_request_args['body'] = $body;
		}

		$response = API_Service::make_api_call( $endpoint, $wp_request_args );

		$response_code    = wp_remote_retrieve_response_code( $response );
		$response_message = wp_remote_retrieve_response_message( $response );
		$response_body    = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( is_wp_error( $response ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, $response->get_error_message() ),
				$response_code,
				$response_body,
			);
		}

		if ( ! Utils::is_status_success( $response ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, $response_message ),
				$response_code,
				$response_body,
			);
		}

		return $this->get_test_result(
			true,
			sprintf( Constants::SUPPLIER_AUTH_SUCCESSFUL, $this->supplier_name ),
			$response_code,
			$response_body,
		);
	}

	/**
	 * Validate Intex Global credentials (stored in supplier details).
	 *
	 * @param array $supplier_data Supplier details.
	 * @return bool|WP_Error
	 */
	public function validate_supplier_specific_configuration( $supplier_data ) {
		if ( empty( $supplier_data['client_id'] ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_SUPPLIER_CONFIG,
				sprintf( Constants::MSG_MISSING_REQUIRED_FIELD, 'Client ID' ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		if ( empty( $supplier_data['refresh_token'] ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_SUPPLIER_CONFIG,
				sprintf( Constants::MSG_MISSING_REQUIRED_FIELD, 'Refresh token' ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		return true;
	}

	/**
	 * Map per-colour images from the parent product onto each variation (same hook flow as Amrod).
	 *
	 * Expects parent payloads to expose a list such as `colourImages` with entries shaped like
	 * `array( 'code' => '<colour>', 'images' => ... )`. Also accepts `colorImages` / snake_case keys.
	 * Variations are matched on `stock_colour` (Intex inventories) with fallbacks for other keys.
	 *
	 * @param array $data Filter payload with event_specifier, variation_array, parent_data.
	 * @return array
	 */
	public static function transform_product_data( $data ) {
	if ( Plugin_Filters::EVENT_ALTER_VARIATION_PRODUCT_DATA === $data['event_specifier'] ) {
		$current_variation_color_code = $data['variation_array']['stock_colour'];
		if ( ! empty( $data['parent_data']['images'][0] ) ) {
			foreach ( $data['parent_data']['images'] as $value ) {
				if ( strtolower( $current_variation_color_code ) === strtolower( $value['colour'] ) ) {
					$data['variation_array']['images'] = $value['url'];
					break;
				}
			}
		}
	}
		return $data;
	}

}
