<?php
/**
 * Parts Europe Supplier Implementation
 *
 * @package    Common
 * @subpackage Suppliers
 */

namespace MOWCPS\Common\Suppliers;

use MOWCPS\Common\Abstracts\Base_Supplier_App;
use MOWCPS\Common\Constants\Constants;
use MOWCPS\Common\Services\API\API_Service;
use MOWCPS\Common\Services\Authorization\Authorization_Service;
use WP_Error;

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

/**
 * Class Parts_Europe
 */
class Parts_Europe extends Base_Supplier_App {

	/**
	 * Authorization Service instance
	 *
	 * @var Authorization_Service
	 */
	private $auth_service;

	/**
	 * Constructor
	 */
	public function __construct() {
		parent::__construct( Constants::SUPPLIER_APP_TYPE_PARTS_EUROPE );
		$this->auth_service = new Authorization_Service();
	}

	/**
	 * Create supplier with domain set for URL replacement.
	 *
	 * Ensures <domain> placeholder is replaced in stored config (authorization + connections)
	 * by adding domain to details before processing, matching Turn14 behaviour.
	 *
	 * @param array $data Supplier data from API request.
	 * @return array|WP_Error Created supplier with configurations or error.
	 */
	public function create_supplier( $data ) {
		$details = $data['details'] ?? array();
		// Set domain from environment_type so Configuration_Loader replaces <domain> in URLs.
		$environment_type = isset( $details['environment_type'] ) ? (bool) $details['environment_type'] : true;
		$data['details']  = array_merge( $details, array( 'domain' => $environment_type ? '-docs' : '-sandbox' ) );
		return parent::create_supplier( $data );
	}

	/**
	 * Perform connection test for Parts Europe
	 *
	 * @param array $authorization_config Authorization configuration.
	 * @return array|WP_Error Success response or error.
	 */
	public function perform_connection_test( $authorization_config ) {
		// Validate user credentials.
		if ( empty( $authorization_config['user_id'] ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, 'User ID is required for Parts Europe.' ),
			);
		}

		if ( empty( $authorization_config['user_secret'] ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, 'Secret is required for Parts Europe.' ),
			);
		}

		// Set domain based on production/sandbox.
		$authorization_config['domain'] = $authorization_config['environment_type'] ? '-docs' : '-sandbox';

		// Load and process configuration with dynamic parameters.
		$processed_config = $this->load_and_process_configuration( $authorization_config );
		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 from processed config.
		$authorization = $processed_config[ Constants::AUTHORIZATION ] ?? array();

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

		// Get token endpoint configuration from processed config.
		$auth_settings     = $authorization['auth_settings'] ?? array();
		$request_settings  = $auth_settings['request_settings'] ?? array();
		$response_settings = $auth_settings['response_settings'] ?? array();

		$auth_url = $request_settings['url'] ?? '';
		$user_id  = $authorization_config['user_id'] ?? '';
		$secret   = $authorization_config['user_secret'] ?? '';

		if ( empty( $auth_url ) || empty( $user_id ) || empty( $secret ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, 'Missing required authentication configuration (url, user_id, secret)' ),
			);
		}

		// Prepare authentication request.
		$request_data = array(
			'user_id' => $user_id,
			'secret'  => $secret,
		);

		$auth_headers = array(
			'Content-Type' => 'application/json',
		);

		// Make authentication request using API Service.
		$auth_response = API_Service::make_api_call(
			$auth_url,
			array(
				'method'  => Constants::HTTP_REQUEST_METHOD_POST,
				'headers' => $auth_headers,
				'body'    => wp_json_encode( $request_data ),
				'timeout' => 30,
			)
		);

		if ( is_wp_error( $auth_response ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, 'Authentication failed: ' . $auth_response->get_error_message() ),
			);
		}

		$status_code = wp_remote_retrieve_response_code( $auth_response );
		if ( 200 !== $status_code ) {
			$response_body = wp_remote_retrieve_body( $auth_response );
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, 'Authentication failed with status ' . $status_code . ': ' . $response_body ),
			);
		}

		$auth_body = wp_remote_retrieve_body( $auth_response );
		$auth_data = json_decode( $auth_body, true );
		$token_key = $response_settings['token_key'] ?? 'access_token';

		if ( ! $auth_data || empty( $auth_data[ $token_key ] ) ) {
			return $this->get_test_result(
				false,
				sprintf( Constants::SUPPLIER_AUTH_FAILED, $this->supplier_name, 'Failed to get access token. Response: ' . $auth_body ),
			);
		}

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

	/**
	 * Validate supplier-specific configuration
	 *
	 * @param array $configuration Supplier configuration.
	 * @return true|WP_Error True on success, WP_Error on failure.
	 */
	public function validate_supplier_specific_configuration( $configuration ) {
		// Validate user credentials.
		if ( empty( $configuration['user_id'] ) ) {
			return new WP_Error(
				'missing_user_id',
				'User ID is required for Parts Europe.'
			);
		}

		if ( empty( $configuration['secret'] ) ) {
			return new WP_Error(
				'missing_secret',
				'Secret is required for Parts Europe.'
			);
		}

		return true;
	}

	/**
	 * Transform part_numbers array from simple values to key-value pairs
	 *
	 * Transforms the part_numbers array in API response from simple string values
	 * to objects with 'id' key for Parts Europe supplier.
	 *
	 * @param array $data Filter data from API service.
	 * @return array Modified data.
	 */
	public static function transform_part_numbers_to_objects( $data ) {
		// Check if this is the event we want to handle
		if ( ! isset( $data['event_specifier'] ) || 'alter_curated_api_response_data' !== $data['event_specifier'] ) {
			return $data;
		}

		// Get the response body
		$response_body = $data['response_body'] ?? array();

		// Check if part_numbers exists and is an array
		if ( ! isset( $response_body['part_numbers'] ) || ! is_array( $response_body['part_numbers'] ) ) {
			return $data;
		}

		// Transform the part_numbers array
		$transformed_part_numbers = array();
		
		foreach ( $response_body['part_numbers'] as $part_number ) {
			// Check if it's already an object/array (to avoid double transformation)
			if ( is_array( $part_number ) && isset( $part_number['id'] ) ) {
				$transformed_part_numbers[] = $part_number;
			} else {
				// Transform string to object with 'id' key
				$transformed_part_numbers[] = array( 'id' => $part_number );
			}
		}

		// Replace the part_numbers with transformed version
		$response_body['part_numbers'] = $transformed_part_numbers;

		// Update the data array
		$data['response_body'] = $response_body;

		return $data;
	}
}

