<?php
/**
 * Class WooCommerceDHLPolskaSettingsPage
 *
 * @package DhlPolska\WooCommerceSettings
 */

namespace DhlPolska\WooCommerceSettings;

use DhlPolskaVendor\WPDesk\PluginBuilder\Plugin\Hookable;

/**
 * Register DHL Polska Settings Page.
 */
class WooCommerceDHLPolskaSettingsPage implements Hookable {
	public const SECTION_ID    = 'dhl_polska';
	private const TIME_PATTERN = '/^([01][0-9]|2[0-3]):[0-5][0-9]$/';

	/**
	 * @var WooCommerceDHLPolskaSettingsFields
	 */
	private WooCommerceDHLPolskaSettingsFields $settings_fields;

	/**
	 * WooCommerceDHLPolskaSettingsPage constructor.
	 *
	 * @param WooCommerceDHLPolskaSettingsFields $settings_fields .
	 */
	public function __construct( WooCommerceDHLPolskaSettingsFields $settings_fields ) {
		$this->settings_fields = $settings_fields;
	}

	/**
	 * Hooks.
	 */
	public function hooks() {
		add_filter( 'woocommerce_get_sections_shipping', [ $this, 'add_section_to_array' ] );
		add_filter( 'woocommerce_get_settings_shipping', [ $this, 'get_section_settings_fields' ], 10, 2 );
		add_action( 'woocommerce_settings_tabs_shipping', [ $this, 'add_mode_switch' ] );
		add_filter(
			'woocommerce_admin_settings_sanitize_option_' . WooCommerceDHLPolskaSettingsFields::OPTION_COURIER_PICKUP_START,
			[ $this, 'sanitize_courier_pickup_time' ],
			10,
			3
		);
		add_filter(
			'woocommerce_admin_settings_sanitize_option_' . WooCommerceDHLPolskaSettingsFields::OPTION_COURIER_PICKUP_END,
			[ $this, 'sanitize_courier_pickup_time' ],
			10,
			3
		);
		add_filter(
			'woocommerce_admin_settings_sanitize_option_' . WooCommerceDHLPolskaSettingsFields::OPTION_SHIPMENT_DATE_CUTOFF,
			[ $this, 'sanitize_optional_time' ],
			10,
			3
		);
		add_filter(
			'woocommerce_admin_settings_sanitize_option_' . WooCommerceDHLPolskaSettingsFields::OPTION_COURIER_DATE_CUTOFF,
			[ $this, 'sanitize_optional_time' ],
			10,
			3
		);
	}

	/**
	 * @param array<string, string> $sections .
	 *
	 * @return array<string, string>
	 */
	public function add_section_to_array( $sections ) {
		$sections[ self::SECTION_ID ] = __( 'DHL Polska', 'dhl-polska' );

		return $sections;
	}

	/**
	 * @param array<string, array> $settings        .
	 * @param string               $current_section .
	 *
	 * @return array<string, array>
	 */
	public function get_section_settings_fields( $settings, $current_section ) {
		if ( self::SECTION_ID !== $current_section ) {
			return $settings;
		}

		return $this->settings_fields->get_settings_fields();
	}

	/**
	 * @return void
	 */
	public function add_mode_switch() {
		if ( ! $this->is_settings_page() ) {
			return;
		}

		include __DIR__ . '/views/html-mode-switch.php';
	}

	/**
	 * @return bool
	 */
	private function is_settings_page(): bool {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		return isset( $_GET['page'], $_GET['tab'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'shipping' === $_GET['tab'] && self::SECTION_ID === $_GET['section'];
	}

	/**
	 * @param string              $value .
	 * @param array<string, mixed> $option .
	 * @param mixed               $raw_value .
	 *
	 * @return string
	 */
	public function sanitize_courier_pickup_time( $value, array $option, $raw_value ): string {
		$raw_value = is_string( $raw_value ) ? trim( $raw_value ) : '';
		if ( $this->is_valid_time_format( $raw_value ) ) {
			return $raw_value;
		}

		$option_id   = $option['id'] ?? '';
		$default     = $option['default'] ?? '';
		$saved_value = '' !== $option_id ? get_option( $option_id, $default ) : $default;

		return is_string( $saved_value ) ? $saved_value : (string) $default;
	}

	/**
	 * @param string              $value .
	 * @param array<string, mixed> $option .
	 * @param mixed               $raw_value .
	 *
	 * @return string
	 */
	public function sanitize_optional_time( $value, array $option, $raw_value ): string {
		$raw_value = is_string( $raw_value ) ? trim( $raw_value ) : '';
		if ( '' === $raw_value ) {
			return '';
		}

		if ( $this->is_valid_time_format( $raw_value ) ) {
			return $raw_value;
		}

		$option_id   = $option['id'] ?? '';
		$default     = $option['default'] ?? '';
		$saved_value = '' !== $option_id ? get_option( $option_id, $default ) : $default;

		return is_string( $saved_value ) ? $saved_value : (string) $default;
	}

	private function is_valid_time_format( string $value ): bool {
		return 1 === preg_match( self::TIME_PATTERN, $value );
	}
}
