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

namespace MOWCPS\Common\DTO;

use WP_Error;
use MOWCPS\Common\Constants\Constants;
use MOWCPS\Common\Abstracts\Base_DTO;
use MOWCPS\Common\Utils\Utils;

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

/**
 * Class Supplier_Request
 *
 * Handles supplier request data transformation and validation
 */
class Supplier_Request extends Base_DTO {
	/**
	 * Supplier name
	 *
	 * @var string
	 */
	private $name;

	/**
	 * Supplier app type
	 *
	 * @var string
	 */
	private $app_type;

	/**
	 * Supplier sync type
	 *
	 * @var string
	 */
	private $sync_type;

	/**
	 * Supplier is_active status
	 *
	 * @var bool
	 */
	private $is_active;

	/**
	 * Supplier debug_mode status
	 *
	 * @var bool
	 */
	private $debug_mode;

	/**
	 * Supplier audit_mode status (detailed sync audit PDF logging)
	 *
	 * @var bool
	 */
	private $audit_mode;

	/**
	 * Supplier unique product identifier
	 *
	 * @var string
	 */
	private $unique_product_identifier;

	/**
	 * Supplier unique product variation identifier
	 *
	 * @var string
	 */
	private $unique_product_variation_identifier;

	/**
	 * Supplier details
	 *
	 * @var array|null
	 */
	private $details;

	/**
	 * Original parameters provided in request
	 *
	 * @var array
	 */
	private $original_params;

	/**
	 * Valid app types
	 *
	 * @var array
	 */
	private static $valid_app_types = array(
		Constants::SUPPLIER_APP_TYPE_AMROD,
		Constants::SUPPLIER_APP_TYPE_BARRON,
		Constants::SUPPLIER_APP_TYPE_SNS_ACTIVEWEAR,
		Constants::SUPPLIER_APP_TYPE_SHOPIFY,
		Constants::SUPPLIER_APP_TYPE_WOOCOMMERCE,
		Constants::SUPPLIER_APP_TYPE_MIDOCEAN,
		Constants::SUPPLIER_APP_TYPE_SANMAR,
		Constants::SUPPLIER_APP_TYPE_PARTS_UNLIMITED,
		Constants::SUPPLIER_APP_TYPE_TURN14,
		Constants::SUPPLIER_APP_TYPE_PARTS_EUROPE,
		Constants::SUPPLIER_APP_TYPE_UTTEAM,
		Constants::SUPPLIER_APP_TYPE_TRENDS,
		Constants::SUPPLIER_APP_TYPE_INTEX_GLOBAL,
		Constants::SUPPLIER_APP_TYPE_TOPTEX,
		Constants::SUPPLIER_APP_TYPE_KMQ,
		Constants::SUPPLIER_APP_TYPE_SYSCOM,
		Constants::SUPPLIER_APP_TYPE_JASANI,
		Constants::SUPPLIER_APP_TYPE_CUSTOM,
		Constants::SUPPLIER_APP_TYPE_PROMOSTANDARDS,
		Constants::SUPPLIER_APP_TYPE_PROMOSTANDARDS_SANMAR,
		Constants::SUPPLIER_APP_TYPE_PROMOSTANDARDS_SANMAR_CA,
		Constants::SUPPLIER_APP_TYPE_PROMOSTANDARDS_SAINTREGIS,
		Constants::SUPPLIER_APP_TYPE_INGRAM_MICRO,
		Constants::SUPPLIER_APP_TYPE_MALFINI,
	);

	/**
	 * Valid sync types
	 *
	 * @var array
	 */
	private static $valid_sync_types = array(
		Constants::SYNC_TYPE_API,
		Constants::SYNC_TYPE_FTP,
		Constants::SYNC_TYPE_FILE,
	);

	/**
	 * List of valid columns that can be selected in API responses.
	 *
	 * @var array
	 */
	private static $valid_columns = array(
		'uuid',
		'name',
		'is_active',
		'app_type',
		'sync_type',
		'debug_mode',
		'audit_mode',
		'unique_product_identifier',
		'unique_product_variation_identifier',
		'details',
	);

	/**
	 * Validate and sanitize column selection for API responses.
	 *
	 * Ensures that only valid columns are requested and that required columns
	 * (uuid and name) are always included.
	 *
	 * @param string $columns_param Comma-separated list of column names to validate.
	 * @return array|WP_Error Array of validated column names or WP_Error if validation fails.
	 */
	public static function validate_columns( $columns_param ) {
		if ( ! is_string( $columns_param ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_DATA_TYPE,
				'Columns parameter must be a comma-separated string.',
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		// Sanitize and split columns.
		$sanitized_param = sanitize_text_field( wp_unslash( $columns_param ) );
		$raw_columns     = explode( ',', $sanitized_param );
		$columns         = array_map( 'sanitize_key', $raw_columns );

		// Validate each column.
		$invalid_columns = array_diff( $columns, self::$valid_columns );
		if ( ! empty( $invalid_columns ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_FIELD_VALUE,
				sprintf(
					'Invalid columns: %s. Valid columns are: %s.',
					implode( ', ', $invalid_columns ),
					implode( ', ', self::$valid_columns )
				),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		// Always include required columns.
		$required_columns = array( 'uuid', 'name' );
		return array_unique( array_merge( $required_columns, $columns ) );
	}

	/**
	 * Create instance from request parameters
	 *
	 * @param array $params Request parameters.
	 * @return self|WP_Error Instance or error if validation fails
	 */
	public static function from_request_parameters( $params ) {
		$instance = new self();

		// Store original parameters for selective updates.
		$instance->original_params = $params;

		// Transform data.
		$instance->name                                = sanitize_text_field( wp_unslash( $params['name'] ?? '' ) );
		$instance->app_type                            = sanitize_text_field( wp_unslash( $params['app_type'] ?? Constants::SUPPLIER_APP_TYPE_CUSTOM ) );
		$instance->sync_type                           = strtoupper( sanitize_text_field( wp_unslash( $params['sync_type'] ?? Constants::SYNC_TYPE_API ) ) );
		$instance->is_active                           = isset( $params['is_active'] ) ? (bool) sanitize_text_field( wp_unslash( $params['is_active'] ) ) : true;
		$instance->debug_mode                          = isset( $params['debug_mode'] ) ? (bool) sanitize_text_field( wp_unslash( $params['debug_mode'] ) ) : false;
		$instance->audit_mode                          = isset( $params['audit_mode'] ) ? (bool) sanitize_text_field( wp_unslash( $params['audit_mode'] ) ) : false;
		$instance->unique_product_identifier           = isset( $params['unique_product_identifier'] ) ? sanitize_text_field( wp_unslash( $params['unique_product_identifier'] ) ) : null;
		$instance->unique_product_variation_identifier = isset( $params['unique_product_variation_identifier'] ) ? sanitize_text_field( wp_unslash( $params['unique_product_variation_identifier'] ) ) : null;
		$instance->details                             = isset( $params['details'] ) ? Utils::sanitize_json_field( wp_unslash( $params['details'] ) ) : null;

		return $instance->validate();
	}

	/**
	 * Create instance from test request parameters
	 * Skips name validation since it's not needed for testing
	 *
	 * @param array $params Request parameters.
	 * @return self|WP_Error Instance or error if validation fails
	 */
	public static function from_test_parameters( $params ) {
		$instance = new self();

		// Store original parameters.
		$instance->original_params = $params;

		// Transform data - only app_type and details are required for testing.
		$instance->app_type = sanitize_text_field( wp_unslash( $params['app_type'] ?? Constants::SUPPLIER_APP_TYPE_CUSTOM ) );
		$instance->details  = isset( $params['details'] ) ? Utils::sanitize_json_field( wp_unslash( $params['details'] ) ) : null;

		// Skip name validation for test requests.
		return $instance->validate_test_request();
	}

	/**
	 * Validate test request
	 * Only validates app_type and details
	 *
	 * @return self|WP_Error
	 */
	private function validate_test_request() {
		// Validate app type.
		if ( ! in_array( $this->app_type, self::$valid_app_types, true ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_APP_TYPE,
				sprintf( Constants::MSG_INVALID_APP_TYPE, $this->app_type ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		// Validate details.
		if ( empty( $this->details ) ) {
			return new WP_Error(
				Constants::ERROR_MISSING_REQUIRED_FIELD,
				sprintf( Constants::MSG_MISSING_REQUIRED_FIELD, 'details' ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		return $this;
	}

	/**
	 * Create instance from update request parameters (for partial updates)
	 *
	 * @param array $params Request parameters.
	 * @return self|WP_Error Instance or error if validation fails
	 */
	public static function from_update_parameters( $params ) {
		$instance = new self();

		// Store original parameters for selective updates.
		$instance->original_params = $params;

		// Transform data - only set values if they were provided.
		$instance->name                                = isset( $params['name'] ) ? sanitize_text_field( wp_unslash( $params['name'] ) ) : '';
		$instance->app_type                            = isset( $params['app_type'] ) ? sanitize_text_field( wp_unslash( $params['app_type'] ) ) : Constants::SUPPLIER_APP_TYPE_CUSTOM;
		$instance->sync_type                           = isset( $params['sync_type'] ) ? strtoupper( sanitize_text_field( wp_unslash( $params['sync_type'] ) ) ) : Constants::SYNC_TYPE_API;
		$instance->is_active                           = isset( $params['is_active'] ) ? (bool) sanitize_text_field( wp_unslash( $params['is_active'] ) ) : true;
		$instance->debug_mode                          = isset( $params['debug_mode'] ) ? (bool) sanitize_text_field( wp_unslash( $params['debug_mode'] ) ) : false;
		$instance->audit_mode                          = isset( $params['audit_mode'] ) ? (bool) sanitize_text_field( wp_unslash( $params['audit_mode'] ) ) : false;
		$instance->unique_product_identifier           = isset( $params['unique_product_identifier'] ) ? sanitize_text_field( wp_unslash( $params['unique_product_identifier'] ) ) : null;
		$instance->unique_product_variation_identifier = isset( $params['unique_product_variation_identifier'] ) ? sanitize_text_field( wp_unslash( $params['unique_product_variation_identifier'] ) ) : null;
		$instance->details                             = isset( $params['details'] ) ? Utils::sanitize_json_field( wp_unslash( $params['details'] ) ) : null;

		return $instance->validate_update();
	}

	/**
	 * Validate the request data
	 *
	 * @return self|WP_Error Instance if valid, WP_Error if invalid
	 */
	protected function validate() {
		// Validate name.
		if ( empty( $this->name ) ) {
			return new WP_Error(
				Constants::ERROR_MISSING_REQUIRED_FIELD,
				sprintf( Constants::MSG_MISSING_REQUIRED_FIELD, 'name' ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		// Validate app_type.
		if ( ! in_array( $this->app_type, self::$valid_app_types, true ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_APP_TYPE,
				Constants::MSG_INVALID_APP_TYPE,
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		// Validate sync_type.
		if ( ! in_array( $this->sync_type, self::$valid_sync_types, true ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_SYNC_TYPE,
				Constants::MSG_INVALID_SYNC_TYPE,
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		// Validate details if provided.
		if ( isset( $this->details ) && ! is_array( $this->details ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_DATA_TYPE,
				sprintf( Constants::MSG_INVALID_DATA_TYPE, 'details' ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		return $this;
	}

	/**
	 * Validate the request data for updates (allows partial data)
	 *
	 * @return self|WP_Error Instance if valid, WP_Error if invalid
	 */
	protected function validate_update() {
		// Validate name if provided.
		if ( isset( $this->original_params['name'] ) && empty( $this->name ) ) {
			return new WP_Error(
				Constants::ERROR_MISSING_REQUIRED_FIELD,
				sprintf( Constants::MSG_MISSING_REQUIRED_FIELD, 'name' ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		// Validate app_type if provided.
		if ( isset( $this->original_params['app_type'] ) && ! in_array( $this->app_type, self::$valid_app_types, true ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_APP_TYPE,
				Constants::MSG_INVALID_APP_TYPE,
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		// Validate sync_type if provided.
		if ( isset( $this->original_params['sync_type'] ) && ! in_array( $this->sync_type, self::$valid_sync_types, true ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_SYNC_TYPE,
				Constants::MSG_INVALID_SYNC_TYPE,
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		// Validate details if provided.
		if ( isset( $this->original_params['details'] ) && isset( $this->details ) && ! is_array( $this->details ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_DATA_TYPE,
				sprintf( Constants::MSG_INVALID_DATA_TYPE, 'details' ),
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		return $this;
	}

	/**
	 * Convert to array for database
	 *
	 * @return array Data ready for database
	 */
	public function to_array() {
		$data = array();

		// Only include fields that were actually provided in the request.
		if ( isset( $this->original_params['name'] ) ) {
			$data['name'] = $this->name;
		}

		if ( isset( $this->original_params['app_type'] ) ) {
			$data['app_type'] = $this->app_type;
		}

		if ( isset( $this->original_params['sync_type'] ) ) {
			$data['sync_type'] = $this->sync_type;
		}

		if ( isset( $this->original_params['is_active'] ) ) {
			$data['is_active'] = $this->is_active;
		}

		if ( isset( $this->original_params['debug_mode'] ) ) {
			$data['debug_mode'] = $this->debug_mode;
		}

		if ( isset( $this->original_params['audit_mode'] ) ) {
			$data['audit_mode'] = $this->audit_mode;
		}

		if ( isset( $this->original_params['unique_product_identifier'] ) ) {
			$data['unique_product_identifier'] = $this->unique_product_identifier;
		}

		if ( isset( $this->original_params['unique_product_variation_identifier'] ) ) {
			$data['unique_product_variation_identifier'] = $this->unique_product_variation_identifier;
		}

		if ( isset( $this->original_params['details'] ) ) {
			$data['details'] = $this->details;
		}

		return $data;
	}
}
