<?php
/**
 * This file is for performing the connect external supplier handler functionality.
 *
 * @package    ProductSync
 * @subpackage ConnectExternalSupplierHandler
 * @author     miniOrange <info@miniorange.com>
 * @link       https://miniorange.com
 */

namespace MOWCPS\Common\Handlers\ConnectExternalSupplierHandler;

use MOWCPS\Common\Models\Setting_Model;
use MOWCPS\Common\Models\Authorization_Model;
use MOWCPS\Common\Services\API\API_Service;
use MOWCPS\Common\Constants\Constants;
use MOWCPS\Common\Models\Sync_Details_DAO;
use MOWCPS\Common\Services\Pagination\Pagination_Service;
use MOWCPS\Common\Services\Authorization\Authorization_Service;

/**
 * Connect External Supplier Handler.
 */
class Connect_External_Supplier_Handler {

	/**
	 * Connection ID.
	 *
	 * @var int
	 */
	public $connection_id;

	/**
	 * Supplier ID.
	 *
	 * @var int
	 */
	public $supplier_id;

	/**
	 * Supplier details.
	 *
	 * @var array
	 */
	public $supplier_details;

	/**
	 * Connection details.
	 *
	 * @var array
	 */
	public $connection_details;

	/**
	 * Page number for the sync process.
	 *
	 * @var int
	 */
	public $page_number;

	/**
	 * Constructor.
	 *
	 * @param int $connection_id The connection ID.
	 * @param int $supplier_id   The supplier ID.
	 * @param int $page_number   The page number for the sync. Default 1.
	 */
	public function __construct( $connection_id, $supplier_id, $page_number = 1 ) {
		$this->connection_id = $connection_id;
		$this->supplier_id   = $supplier_id;
		$this->page_number   = $page_number;
	}

	/**
	 * Connect to the API handler.
	 *
	 * @param string $mode    The request mode (e.g., GET, POST).
	 * @param mixed  $body    The request body. Default empty string.
	 * @param string $url     The API endpoint URL. Default empty string.
	 * @param array  $headers The request headers. Default empty array.
	 * @return mixed The API response.
	 */
	public function connect_api_handler( $mode, $body = '', $url = '', $headers = array() ) {

		$details = $this->retrieve_api_details( $mode, $body, $url, $headers );

		// Check if API details retrieval failed.
		if ( is_wp_error( $details ) ) {
			return $details;
		}

		$api_service = new API_Service( $this->supplier_id, $this->connection_id );
		$response    = $api_service->execute_api_call( $details );
		return $response;
	}

	/**
	 * Retrieve API details based on the given mode.
	 *
	 * @param string $mode    Mode of the request ('outbound', 'order_sync', 'inbound').
	 * @param string $body    Request body (optional).
	 * @param string $url     Request URL (optional).
	 * @param array  $header  Request header (optional).
	 *
	 * @return array API details including headers, body, URL, request type, and time delay.
	 */
	public function retrieve_api_details( $mode, $body = '', $url = '', $header = array() ) {
		// TODO auth details also be pass from here.
		$api_details  = Sync_Details_DAO::get_instance()->get_api_details( $this->connection_id );
		$page_details = Setting_Model::get_by_connection_and_operation( $this->connection_id, 'page', array( 'configuration' => true ) );
		$auth_config  = Authorization_Model::get_by_supplier_id( $this->supplier_id );
		switch ( $mode ) {

			case Constants::INBOUND_SYNC:
				return self::get_inbound_api_details( $api_details, $header, $body, $url, $page_details, $auth_config, $this->supplier_id, $this->connection_id, $this->page_number );

			default:
				return array(
					'headers'    => $header,
					'body'       => $body,
					'endpoint'   => $url,
					'method'     => '',
					'time_delay' => 0,
				);
		}
	}

	/**
	 * Get API details for inbound sync.
	 *
	 * @param array  $api_details API details from the connection model.
	 * @param array  $headers     Request headers.
	 * @param string $body        Request body.
	 * @param string $url         Request URL.
	 * @param string $page_details Page details configuration.
	 * @param array  $auth_config Authentication configuration for generating headers.
	 * @param int    $supplier_id Supplier ID.
	 * @param int    $connection_id Connection ID.
	 * @param int    $page_number Page number for pagination.
	 *
	 * @return array API details.
	 */
	public static function get_inbound_api_details( $api_details, $headers, $body, $url, $page_details, $auth_config, $supplier_id, $connection_id, $page_number = 1 ) {
		$page_flag = ! empty( $page_details['is_active'] ) && (string) $page_details['is_active'] === '1';
		Sync_Details_DAO::get_instance()->set_page_flag( $page_flag );

		$header = array();
		if ( isset( $api_details['auth_enabled'] ) && true === $api_details['auth_enabled'] ) {
			$auth_services = new Authorization_Service();
			$header        = $auth_services->generate_headers( $auth_config, $supplier_id );

			// If auth header generation failed (e.g. OAuth token call error), propagate the error.
			if ( is_wp_error( $header ) ) {
				return $header;
			}
		}

		$header       = array_merge( $headers, $api_details['headers'], $header );
		$body         = $api_details['body'] ?? '';
		$url          = $api_details['endpoint'] ?? '';
		$request_type = $api_details['method'] ?? '';
		$time_delay   = $api_details['advanced_configuration']['time_delay'] ?? 0;

		if ( Constants::CONFIGURATION_ACTIVE === $page_flag ) {
			$pagination_details = new Pagination_Service( $supplier_id, $connection_id, $page_number, $page_details['configuration'] );
			$new_details        = $pagination_details->get_page_details( $header, $body, $url, $page_details );

			$header = $new_details['headers'];
			$header = array_merge( $headers, $api_details['headers'] ?? array(), $header );
			$body   = $new_details['body'];
			$url    = $new_details['url'];
		}

		return array(
			'headers'    => $header,
			'body'       => $body,
			'endpoint'   => $url,
			'method'     => $request_type,
			'time_delay' => $time_delay,
		);
	}
}
