<?php
/**
 * Barron 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\DTO\Authorization_Request;
use MOWCPS\Common\Constants\Plugin_Filters;
use MOWCPS\Common\Constants\Suppliers\Barron as Barron_Constants;
use MOWCPS\Common\Utils\Utils;

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

/**
 * Class Barron
 *
 * Handles Barron supplier app operations
 */
class Barron extends Base_Supplier_App implements Supplier_App_Interface {
	/**
	 * Constructor
	 */
	public function __construct() {
		parent::__construct( Constants::SUPPLIER_APP_TYPE_BARRON );
	}

	/**
	 * Perform Barron-specific connection test
	 *
	 * @param array $supplier_data Supplier data.
	 * @return array Test result.
	 */
	public function perform_connection_test( $supplier_data ) {
		// Validate supplier-specific configuration using existing validation method.
		$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() ),
			);
		}

		// Load and process configuration with dynamic parameters.
		$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() ),
			);
		}

		// Get authorization configuration.
		$authorization = $processed_config[ Constants::AUTHORIZATION ] ?? array();
		if ( empty( $authorization ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_NO_AUTH_CONFIG, $this->supplier_name ),
			);
		}

		$authorization_request = Authorization_Request::from_request_parameters( $authorization );
		if ( is_wp_error( $authorization_request ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_INVALID_AUTH_CONFIG, $this->supplier_name, $authorization_request->get_error_message() ),
			);
		}

		$request_settings = $authorization['auth_settings']['request_settings'];

		$url    = $request_settings['url'];
		$method = strtoupper( $request_settings['method'] );

		// Prepare API request.
		$api_request = array(
			'endpoint' => $url,
			'method'   => $method,
			'headers'  => $request_settings['headers'],
			'body'     => $request_settings['body'],
		);

		// Make the authentication request.
		$response = API_Service::make_api_call( $api_request['endpoint'], $api_request );

		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    = wp_remote_retrieve_response_code( $response );
		$response_message = wp_remote_retrieve_response_message( $response );

		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,
				wp_remote_retrieve_body( $response ),
			);
		}

		$response_body = API_Service::parse_xml( wp_remote_retrieve_body( $response ) );
		$response_body = json_decode( $response_body, true );

		if ( 'false' === strtolower( $response_body['Callresult'] ) ) {
			$response_code = Constants::HTTP_UNAUTHORIZED;
		}

		if ( ! Utils::is_status_success( $response ) || 'false' === strtolower( $response_body['Callresult'] ) ) {
			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 Barron-specific configuration
	 *
	 * @param array $supplier_data Supplier data to validate.
	 * @return bool|WP_Error True if valid, WP_Error if invalid.
	 */
	public function validate_supplier_specific_configuration( $supplier_data ) {
		// Validate required fields for Barron.
		if ( empty( $supplier_data['token_key'] ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_SUPPLIER_CONFIG,
				sprintf( Constants::SUPPLIER_MISSING_TOKEN_KEY, $this->supplier_name ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		if ( empty( $supplier_data['username'] ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_SUPPLIER_CONFIG,
				sprintf( Constants::SUPPLIER_MISSING_USERNAME, $this->supplier_name ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		if ( empty( $supplier_data['password'] ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_SUPPLIER_CONFIG,
				sprintf( Constants::SUPPLIER_MISSING_PASSWORD, $this->supplier_name ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		if ( empty( $supplier_data['entity_name'] ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_SUPPLIER_CONFIG,
				sprintf( Constants::SUPPLIER_MISSING_ENTITY_NAME, $this->supplier_name ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		if ( empty( $supplier_data['entity_id'] ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_SUPPLIER_CONFIG,
				sprintf( Constants::SUPPLIER_MISSING_ENTITY_ID, $this->supplier_name ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		return true;
	}

	/**
	 * Function to modify the data coming from Barron into suitable structure which is accepted by the plugin.
	 *
	 * @param array $arguments API data coming from Barron.
	 *
	 * @return array
	 */
	public static function transform_product_data( $arguments ) {
		if ( Plugin_Filters::EVENT_ALTER_PRE_API_CALL_DATA === $arguments['event_specifier'] ) {
			$cookies       = $arguments['api_arguments']['headers']['set-cookie'];
			$cookie_string = '';

			foreach ( $cookies as $cookie ) {
				if ( preg_match( '/^(.*?;)(.*)$/', $cookie, $matches ) ) {
					$cookie_string = $cookie_string . $matches[1] . ' ';
				}
			}

			$cookie_string     = rtrim( $cookie_string, '; ' );
			$headers['Cookie'] = $cookie_string;

			$arguments['api_arguments']['headers'] = $headers;
		}

		if ( 'alter_api_data' === $arguments['event_specifier'] ) {
			$arguments['products_data'] = is_array( $arguments['products_data'] ) ? $arguments['products_data'] : json_decode( $arguments['products_data'], true );
		}

		return $arguments;
	}
}
