<?php
/**
 * Class to handle VAT number validation.
 *
 * @package     EDD\Pro\Taxes\VAT
 * @copyright   Copyright (c) 2025, Sandhills Development, LLC
 * @license     https://opensource.org/licenses/gpl-2.0.php GNU Public License
 * @since       3.5.0
 */

namespace EDD\Pro\Taxes\VAT;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore

use EDD\Utils\Countries;

/**
 * Class Validator
 *
 * @since 3.5.0
 */
class Validator {

	/**
	 * Check a VAT number against the supplied country code.
	 *
	 * @param   string $vat_number The VAT number to check.
	 * @param   string $country_code The country code.
	 * @return  Result
	 */
	public static function check_vat( $vat_number, $country_code ) {
		$result = new Result( $vat_number, $country_code );

		if ( ! $vat_number ) {
			$result->error = Result::NO_VAT_NUMBER;

			return $result;
		}

		if ( ! $country_code ) {
			$result->error = Result::NO_COUNTRY_CODE;

			return $result;
		}

		// Check country is in the EU.
		if ( ! in_array( $country_code, Countries::get_eu_countries(), true ) ) {
			$result->error = Result::INVALID_COUNTRY_CODE;

			return $result;
		}

		if ( ! self::is_valid_for_country( $country_code, $vat_number ) ) {
			$result->error = Result::VAT_NUMBER_INVALID_FOR_COUNTRY;

			return $result;
		}

		$result = self::get_result( $result );

		// Catch all for invalid VAT number if no error set.
		if ( ! $result->is_valid() && empty( $result->error ) ) {
			$result->error = Result::INVALID_VAT_NUMBER;
		}

		edd_debug_log( 'Checked VAT for VAT Number: ' . $result->vat_number );
		edd_debug_log( 'Checked VAT with country code: ' . $country_code );
		edd_debug_log( 'Checked VAT result: ' . print_r( $result, true ) );

		return apply_filters( 'edd_vat_number_check', $result, $result->vat_number, $country_code );
	}

	/**
	 * Retrieves the result of the VAT check.
	 *
	 * @param Result $result The result object to populate.
	 * @return Result
	 */
	private static function get_result( $result ) {
		foreach ( self::get_services( $result ) as $service ) {
			if ( $service->requirements_met() ) {
				return $service->get_result();
			}
		}

		return $result;
	}

	/**
	 * Gets the services for VAT validation.
	 *
	 * Services are tried in the order they appear in the array until one meets
	 * all requirements and successfully validates the VAT number.
	 *
	 * @since 3.5.0
	 * @param Result $result The result object to populate.
	 * @return array
	 */
	private static function get_services( $result ): array {
		return apply_filters(
			'edd_vat_validation_services',
			array(
				'custom' => new \EDD\Pro\Taxes\Services\Custom( $result ),
				'edd'    => new \EDD\Pro\Taxes\Services\EDD( $result ),
			),
			$result
		);
	}

	/**
	 * Checks if the country code matches the VAT number prefix.
	 *
	 * @since 3.5.0
	 * @param string $country_code The country code.
	 * @param string $vat_number   The VAT number.
	 * @return bool
	 */
	private static function is_valid_for_country( $country_code, $vat_number ): bool {
		$eu_vat_prefixes   = Utility::get_eu_vat_number_prefixes();
		$vat_number_prefix = substr( $vat_number, 0, 2 );
		if ( ! in_array( $vat_number_prefix, $eu_vat_prefixes, true ) ) {
			return false;
		}

		return $eu_vat_prefixes[ $country_code ] === $vat_number_prefix;
	}
}
