<?php
/**
 * Sanitiser and validator for country routing form input.
 *
 * @since   1.0.0
 * @package DonationRouter
 */

declare( strict_types=1 );
namespace DonationRouter;

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

/**
 * Validates and sanitises raw POST data for a country routing rule.
 *
 * Call {@see validate()} with the raw POST array; it returns a clean,
 * type-correct array on success or throws \InvalidArgumentException on
 * validation failure so that callers can surface an error notice.
 *
 * @since 1.0.0
 */
class Routing_Validator {
	/**
	 * Sanitise and validate raw form input for a country routing rule.
	 *
	 * Applies WordPress sanitisation functions appropriate to each field
	 * and enforces domain constraints. Allowed HTML in display_label and
	 * display_description uses wp_kses_post() so basic formatting tags are
	 * preserved.
	 *
	 * @since 1.0.0
	 *
	 * @param array<string,mixed> $input Raw POST fields.
	 *
	 * @return array{
	 *   country_code: string,
	 *   form_id: int,
	 *   account_id: int,
	 *   display_label: string,
	 *   display_description: string,
	 *   sort_order: int,
	 *   is_active: bool,
	 * }
	 *
	 * @throws \InvalidArgumentException  When required fields are missing or fail validation.
	 */
	public function validate( array $input ): array {
		$country_code        = strtoupper( sanitize_key( (string) ( $input['country_code'] ?? '' ) ) );
		$form_id             = absint( $input['form_id'] ?? 0 );
		$account_id          = absint( $input['account_id'] ?? 0 );
		$display_label       = wp_kses_post( (string) ( $input['display_label'] ?? '' ) );
		$display_description = wp_kses_post( (string) ( $input['display_description'] ?? '' ) );
		$sort_order          = absint( $input['sort_order'] ?? 0 );
		$is_active           = ! empty( $input['is_active'] );

		if ( '' === $country_code ) {
			throw new \InvalidArgumentException( 'Country code is required.' );
		}

		if ( 1 !== preg_match( '/^[A-Z]{2}$/', $country_code ) ) {
			throw new \InvalidArgumentException( 'Country code must be two uppercase letters (ISO 3166-1 alpha-2).' );
		}

		$allowed = array_keys( Account_Form::get_paypal_countries() );
		if ( ! in_array( $country_code, $allowed, true ) ) {
			throw new \InvalidArgumentException(
				sprintf( 'Country code "%s" is not a supported PayPal Business country.', esc_html( $country_code ) )
			);
		}

		if ( $form_id <= 0 ) {
			throw new \InvalidArgumentException( 'A valid donation form must be selected.' );
		}

		if ( $account_id <= 0 ) {
			throw new \InvalidArgumentException( 'A valid PayPal account must be selected.' );
		}

		$display_label = trim( $display_label );
		if ( '' === $display_label ) {
			throw new \InvalidArgumentException( 'Display label is required.' );
		}

		if ( mb_strlen( $display_label ) > 191 ) {
			throw new \InvalidArgumentException( 'Display label must be 191 characters or fewer.' );
		}

		return array(
			'country_code'        => $country_code,
			'form_id'             => $form_id,
			'account_id'          => $account_id,
			'display_label'       => $display_label,
			'display_description' => $display_description,
			'sort_order'          => $sort_order,
			'is_active'           => $is_active,
		);
	}
}
