<?php
/**
 * Resolves Tax ID (NIP) from POST and order meta.
 *
 * Handles classic and block checkout flows.
 *
 * @package Simplyin\Simplyin_W_Plugin\Service\Order
 */

declare(strict_types=1);

namespace Simplyin\Simplyin_W_Plugin\Service\Order;

use WC_Order;

class Tax_Id_Resolver {

	private const TAX_FIELD_NAME = 'billing_tax_id_simply';

	private const ORDER_META_KEYS = [
		'_billing_tax_id_simply',
		'billing_tax_id_simply',
	];

	/**
	 * Known NIP/VAT field names from third-party checkout field plugins.
	 * Used for rendering suppression and POST data fallback.
	 * Extensible via the `simplyin_tax_id_field_candidates` filter.
	 */
	public const EXTERNAL_FIELD_CANDIDATES = [
		'billing_nip',            // Flexible Checkout Fields (FCF).
		'billing_tax_no',         // Themehigh Checkout Field Designer (THWCFD).
		'billing_vat',
		'billing_vat_number',
		'billing_tax_id',
		'billing_vat_id',
		'billing_company_tax_id',
	];

	/**
	 * Resolve tax ID from POST or order meta.
	 *
	 * @param WC_Order $order
	 *
	 * @return string
	 */
	public function resolve( WC_Order $order ): string {
		$from_post = $this->resolve_from_post();
		if ( $from_post !== '' ) {
			return $from_post;
		}

		return $this->resolve_from_order_meta( $order );
	}

	private function resolve_from_post(): string {
		// Build the validated allowlist once. Includes our own field + externals + filter additions.
		$candidates     = array_values(
			array_filter(
				(array) apply_filters( 'simplyin_tax_id_field_candidates', self::EXTERNAL_FIELD_CANDIDATES ),
				static fn( $c ) => is_string( $c ) && (bool) preg_match( '/^[a-z0-9_]+$/i', $c )
			)
		);
		$allowed_fields = array_merge( [ self::TAX_FIELD_NAME ], $candidates );

		// simply_tax_label_id is a pointer to the actual NIP field.
		// Only follow it if the target is within the allowlist — prevents indirect field injection.
		$pointer = $this->get_sanitized_post( 'simply_tax_label_id' );
		if ( '' !== $pointer && in_array( $pointer, $allowed_fields, true ) ) {
			$value = $this->get_sanitized_post( $pointer );
			if ( $value !== '' ) {
				return $value;
			}
		}
		// Invalid or missing pointer: do not short-circuit — fall through to normal chain.

		$direct_value = $this->get_sanitized_post( self::TAX_FIELD_NAME );
		if ( $direct_value !== '' ) {
			return $direct_value;
		}

		foreach ( $candidates as $field_name ) {
			$value = $this->get_sanitized_post( $field_name );
			if ( '' !== $value ) {
				return $value;
			}
		}

		return '';
	}

	private function resolve_from_order_meta( WC_Order $order ): string {
		foreach ( self::ORDER_META_KEYS as $meta_key ) {
			$value = $order->get_meta( $meta_key, true );
			if ( is_string( $value ) && trim( $value ) !== '' ) {
				return trim( $value );
			}
		}

		return '';
	}

	private function get_sanitized_post( string $key ): string {
		// phpcs:disable WordPress.Security.NonceVerification.Missing
		if ( ! isset( $_POST[ $key ] ) || ! is_string( $_POST[ $key ] ) ) {
			// phpcs:enable WordPress.Security.NonceVerification.Missing
			return '';
		}

		return trim( sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
	}
}
