<?php
/**
 * Attribute Mapping Handler
 *
 * @category   WordPress_Plugin
 * @package    Common
 * @subpackage Handlers\Rest_API
 * @author     miniOrange <info@miniorange.com>
 * @license    MIT/Expat
 * @link       https://plugins.miniorange.com/woocommerce-api-product-sync-with-woocommerce-rest-apis
 */

namespace MOWCPS\Common\Handlers\Rest_API;

use WP_Error;
use MOWCPS\Common\Models\Attribute_Mapping_Model;
use MOWCPS\Common\Models\Supplier_Model;
use MOWCPS\Common\Models\Connection_Model;
use MOWCPS\Common\DTO\Attribute_Mapping_Request;
use MOWCPS\Common\Constants\Constants;
use MOWCPS\Common\Utils\Model_Utils;

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

/**
 * Class Attribute_Mapping_Handler
 *
 * Handles attribute mapping REST API operations
 */
class Attribute_Mapping_Handler {

	/**
	 * Constructor
	 */
	public function __construct() {
	}

	/**
	 * Get all attribute mappings for a supplier
	 *
	 * @param string $supplier_uuid Supplier UUID.
	 * @param array  $params Query parameters.
	 * @return array|WP_Error
	 */
	public function get_all_by_supplier_uuid( $supplier_uuid, $params = array() ) {
		$supplier = Supplier_Model::get_by_uuid( $supplier_uuid );
		if ( ! $supplier ) {
			return new WP_Error(
				Constants::ERROR_SUPPLIER_NOT_FOUND,
				Constants::MSG_SUPPLIER_NOT_FOUND,
				array( 'status' => Constants::HTTP_NOT_FOUND )
			);
		}

		$params['supplier_id'] = $supplier['id'];

		// Convert connection_id from UUID to integer ID if provided.
		if ( isset( $params['connection_id'] ) ) {
			$connection = Connection_Model::get_by_uuid( $params['connection_id'] );
			if ( ! $connection ) {
				return new WP_Error(
					Constants::ERROR_CONNECTION_NOT_FOUND,
					Constants::MSG_CONNECTION_NOT_FOUND,
					array( 'status' => Constants::HTTP_NOT_FOUND )
				);
			}
			$params['connection_id'] = $connection['id'];
		}

		$mappings = Attribute_Mapping_Model::get_all( $params );

		// Add connection names to mappings.
		$mappings = Model_Utils::add_connection_names( $mappings );

		// Convert connection IDs to UUIDs in advanced_configuration.
		$mappings = Model_Utils::convert_advanced_config_connection_ids_to_uuids( $mappings );

		// Remove ID fields from API response and format data types.
		return Model_Utils::sanitize_for_api_response( $mappings );
	}

	/**
	 * Get attribute mapping by UUID
	 *
	 * @param string $mapping_uuid Mapping UUID.
	 * @return array|WP_Error
	 */
	public function get_by_uuid( $mapping_uuid ) {
		// Validate UUID parameter using DTO.
		$validation = Attribute_Mapping_Request::validate_uuid( $mapping_uuid, 'mapping_uuid' );
		if ( is_wp_error( $validation ) ) {
			return $validation;
		}

		$mapping = Attribute_Mapping_Model::get_by_uuid( $mapping_uuid );
		if ( ! $mapping ) {
			return new WP_Error(
				Constants::ERROR_RECORD_NOT_FOUND,
				Constants::MSG_RECORD_NOT_FOUND,
				array( 'status' => Constants::HTTP_NOT_FOUND )
			);
		}

		// Add connection name to mapping.
		$mapping = Model_Utils::add_connection_names( array( $mapping ) )[0];

		// Convert connection IDs to UUIDs in advanced_configuration.
		$mapping = Model_Utils::convert_advanced_config_connection_ids_to_uuids( $mapping );

		// Remove ID fields from API response and format data types.
		return Model_Utils::sanitize_for_api_response( $mapping );
	}

	/**
	 * Create attribute mapping for a supplier
	 *
	 * @param string|int $supplier_identifier Supplier UUID or ID.
	 * @param array      $data Mapping data.
	 * @return array|WP_Error
	 */
	public function create( $supplier_identifier, $data ) {
		$identifier_info = Model_Utils::identify_identifier( $supplier_identifier );
		if ( is_wp_error( $identifier_info ) ) {
			return $identifier_info;
		}

		if ( 'id' === $identifier_info['type'] ) {
			$supplier_id = $identifier_info['value'];
		} else {
			$supplier = Supplier_Model::get_by_uuid( $identifier_info['value'] );
			if ( ! $supplier ) {
				return new WP_Error(
					Constants::ERROR_SUPPLIER_NOT_FOUND,
					Constants::MSG_SUPPLIER_NOT_FOUND,
					array( 'status' => Constants::HTTP_NOT_FOUND )
				);
			}
			$supplier_id = $supplier['id'];
		}

		// Transform and validate data using DTO.
		$mapping_request = Attribute_Mapping_Request::from_request_parameters( $data );
		if ( is_wp_error( $mapping_request ) ) {
			return $mapping_request;
		}

		// Add supplier_id to the validated data.
		$validated_data                = $mapping_request->to_array();
		$validated_data['supplier_id'] = $supplier_id;

		// Convert connection_id from UUID to integer ID if provided.
		if ( isset( $validated_data['connection_id'] ) ) {
			$connection = Connection_Model::get_by_uuid( $validated_data['connection_id'] );
			if ( ! $connection ) {
				return new WP_Error(
					Constants::ERROR_CONNECTION_NOT_FOUND,
					Constants::MSG_CONNECTION_NOT_FOUND,
					array( 'status' => Constants::HTTP_NOT_FOUND )
				);
			}
			$validated_data['connection_id'] = $connection['id'];
		}

		// Convert fetch_from_other_api connection UUID to integer ID if provided.
		if ( ! empty( $validated_data['advanced_configuration']['fetch_from_other_api']['connection'] ) ) {
			$fetch_connection_uuid = $validated_data['advanced_configuration']['fetch_from_other_api']['connection'];
			$fetch_connection      = Connection_Model::get_by_uuid( $fetch_connection_uuid );
			if ( ! $fetch_connection ) {
				return new WP_Error(
					Constants::ERROR_CONNECTION_NOT_FOUND,
					sprintf( 'Fetch from other API connection not found: %s', $fetch_connection_uuid ),
					array( 'status' => Constants::HTTP_NOT_FOUND )
				);
			}
			$validated_data['advanced_configuration']['fetch_from_other_api']['connection'] = $fetch_connection['id'];
		}

		$result = Attribute_Mapping_Model::create( $validated_data );
		if ( is_wp_error( $result ) ) {
			return $result;
		}

		// Add connection name to result.
		$result = Model_Utils::add_connection_names( array( $result ) )[0];

		// Convert connection IDs to UUIDs in advanced_configuration.
		$result = Model_Utils::convert_advanced_config_connection_ids_to_uuids( $result );

		// Remove ID fields from API response and format data types.
		return Model_Utils::sanitize_for_api_response( $result );
	}

	/**
	 * Update attribute mapping
	 *
	 * @param string $mapping_uuid Mapping UUID.
	 * @param array  $data Mapping data.
	 * @return array|WP_Error
	 */
	public function update( $mapping_uuid, $data ) {
		// Validate UUID parameter using DTO.
		$validation = Attribute_Mapping_Request::validate_uuid( $mapping_uuid, 'mapping_uuid' );
		if ( is_wp_error( $validation ) ) {
			return $validation;
		}

		// Transform and validate data using DTO for partial updates.
		if ( ! empty( $data ) ) {
			$mapping_request = Attribute_Mapping_Request::from_request_parameters( $data );
			if ( is_wp_error( $mapping_request ) ) {
				return $mapping_request;
			}
			$data = $mapping_request->to_array();
		}

		// Convert connection_id from UUID to integer ID if provided.
		if ( isset( $data['connection_id'] ) ) {
			$connection = Connection_Model::get_by_uuid( $data['connection_id'] );
			if ( ! $connection ) {
				return new WP_Error(
					Constants::ERROR_CONNECTION_NOT_FOUND,
					Constants::MSG_CONNECTION_NOT_FOUND,
					array( 'status' => Constants::HTTP_NOT_FOUND )
				);
			}
			$data['connection_id'] = $connection['id'];
		}

		// Convert fetch_from_other_api connection UUID to integer ID if provided.
		if ( ! empty( $data['advanced_configuration']['fetch_from_other_api']['connection'] ) ) {
			$fetch_connection_uuid = $data['advanced_configuration']['fetch_from_other_api']['connection'];
			$fetch_connection      = Connection_Model::get_by_uuid( $fetch_connection_uuid );
			if ( ! $fetch_connection ) {
				return new WP_Error(
					Constants::ERROR_CONNECTION_NOT_FOUND,
					sprintf( 'Fetch from other API connection not found: %s', $fetch_connection_uuid ),
					array( 'status' => Constants::HTTP_NOT_FOUND )
				);
			}
			$data['advanced_configuration']['fetch_from_other_api']['connection'] = $fetch_connection['id'];
		}

		$result = Attribute_Mapping_Model::update( $mapping_uuid, $data );
		if ( is_wp_error( $result ) ) {
			return $result;
		}

		// Add connection name to result.
		$result = Model_Utils::add_connection_names( array( $result ) )[0];

		// Convert connection IDs to UUIDs in advanced_configuration.
		$result = Model_Utils::convert_advanced_config_connection_ids_to_uuids( $result );

		// Remove ID fields from API response and format data types.
		return Model_Utils::sanitize_for_api_response( $result );
	}

	/**
	 * Delete attribute mapping
	 *
	 * @param string $mapping_uuid Mapping UUID.
	 * @return bool|WP_Error
	 */
	public function delete( $mapping_uuid ) {
		// Validate UUID parameter using DTO.
		$validation = Attribute_Mapping_Request::validate_uuid( $mapping_uuid, 'mapping_uuid' );
		if ( is_wp_error( $validation ) ) {
			return $validation;
		}

		return Attribute_Mapping_Model::delete( $mapping_uuid );
	}
}
