<?php
/**
 * Class CheckoutPointValidator
 *
 * @package DhlPolska\Point
 */

namespace DhlPolska\Point;

use DhlPolska\Shipment\ShipmentData;
use DhlPolskaVendor\WPDesk\PluginBuilder\Plugin\Hookable;
use WP_Error;

/**
 * Validating point field.
 */
class CheckoutPointValidator implements Hookable {
	use ServicePointTrait;

	/**
	 * Hooks.
	 */
	public function hooks() {
		add_action( 'woocommerce_after_checkout_validation', [ $this, 'validate_point' ], 10, 2 );
	}

	/**
	 * Validates that the checkout has enough info to proceed.
	 *
	 * @param array<string, string> $data   An array of posted data.
	 * @param WP_Error              $errors Validation errors.
	 *
	 * @return void
	 */
	public function validate_point( $data, $errors ): void {
		$api_error_status = (string) ( $data[ CheckoutChoosePointField::FIELD_API_ERROR ] ?? 'no' );

		if ( ! $this->is_required_field( $api_error_status ) ) {
			return;
		}

		if ( empty( $data[ CheckoutChoosePointField::FIELD_PARCELSHOP_ID ] ) ) {
			$errors->add(
				'dhl-polska-point-required',
				sprintf(
					// Translators: open strong tag, close strong tag.
					__( '%1$sPunkt odbioru DHL%2$s jest wymagany. Wybierz punkt odbioru z mapy i spróbuj ponownie.', 'dhl-polska' ),
					'<strong>',
					'</strong>'
				)
			);
		}

		if ( $this->is_postnummer_required( $data ) ) {
			$postnummer = trim( (string) ( $data[ CheckoutChoosePointField::FIELD_PARCELSHOP_POSTNUMMER ] ?? '' ) );
			if ( '' === $postnummer ) {
				$errors->add(
					'dhl-polska-postnummer-required',
					__( 'Postnummer jest wymagany dla odbioru w automacie paczkowym (Packstation) w Niemczech.', 'dhl-polska' )
				);
			}
		}
	}

	/**
	 * @param string $api_error_status .
	 *
	 * @return bool
	 */
	private function is_required_field( string $api_error_status ): bool {
		if ( 'yes' === $api_error_status ) {
			return false;
		}

		return $this->is_service_point_option();
	}

	/**
	 * @param array<string, string> $data .
	 *
	 * @return bool
	 */
	private function is_postnummer_required( array $data ): bool {
		if ( ShipmentData::POINT_TYPE_PACKSTATION !== $this->get_point_type_for_chosen_rate() ) {
			return false;
		}

		$shipping_country = strtoupper( (string) ( $data['shipping_country'] ?? '' ) );
		if ( '' === $shipping_country ) {
			$shipping_country = strtoupper( (string) ( $data['billing_country'] ?? '' ) );
		}

		return 'DE' === $shipping_country;
	}

	/**
	 * @return string
	 */
	private function get_point_type_for_chosen_rate(): string {
		$session = WC()->session;
		if ( null === $session ) { /** @phpstan-ignore-line */
			return '';
		}

		$point_types = $session->get( CheckoutChoosePointField::SESSION_SERVICE_POINT_TYPES, [] );
		if ( ! is_array( $point_types ) ) {
			return '';
		}

		$chosen_methods = wp_parse_list( $session->get( 'chosen_shipping_methods' ) );
		foreach ( $chosen_methods as $method ) {
			if ( isset( $point_types[ $method ] ) ) {
				return (string) $point_types[ $method ];
			}
		}

		return '';
	}
}
