<?php
/**
 * CheckoutController class.
 *
 * Controller class for checkout-related hooks.
 *
 * @package Automattic/WCShipping
 */

namespace Automattic\WCShipping\Checkout;

use Automattic\WCShipping\Connect\WC_Connect_Logger;
use Automattic\WCShipping\Connect\WC_Connect_Service_Settings_Store;
use Automattic\WCShipping\LabelPurchase\AddressNormalizationService;
use Automattic\WCShipping\Utils;
use WC_Order;

defined( 'ABSPATH' ) || exit;

/**
 * Class CheckoutController
 */
class CheckoutController {

	/**
	 * Checkout service.
	 *
	 * @var CheckoutService
	 */
	private CheckoutService $checkout_service;

	/**
	 * Notifier instance.
	 *
	 * @var CheckoutNotifier
	 */
	private CheckoutNotifier $notifier;

	/**
	 * The settings store.
	 *
	 * @var WC_Connect_Service_Settings_Store
	 */
	private WC_Connect_Service_Settings_Store $settings_store;

	/**
	 * Address normalization service.
	 *
	 * @var AddressNormalizationService
	 */
	private AddressNormalizationService $address_normalization_service;

	/**
	 * CheckoutController constructor.
	 *
	 * @param WC_Connect_Logger                 $wc_connect_logger The WC_Connect_Logger instance.
	 * @param CheckoutService                   $checkout_service Checkout service.
	 * @param WC_Connect_Service_Settings_Store $settings_store The settings store.
	 * @param AddressNormalizationService       $address_normalization_service Address normalization service.
	 */
	public function __construct(
		WC_Connect_Logger $wc_connect_logger,
		CheckoutService $checkout_service,
		WC_Connect_Service_Settings_Store $settings_store,
		AddressNormalizationService $address_normalization_service
	) {
		$this->checkout_service              = $checkout_service;
		$this->notifier                      = new CheckoutNotifier( $wc_connect_logger->is_debug_enabled() );
		$this->settings_store                = $settings_store;
		$this->address_normalization_service = $address_normalization_service;

		add_action( 'wp_enqueue_scripts', array( $this, 'load_assets' ) );
		add_action( 'woocommerce_after_calculate_totals', array( $this, 'maybe_display_address_validation_notices' ) );
		add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'maybe_set_destination_normalized_order_meta' ) );
		add_action( 'woocommerce_store_api_checkout_update_order_meta', array( $this, 'maybe_set_destination_normalized_order_meta' ) );
		add_filter( 'woocommerce_shipping_packages', array( $this, 'maybe_add_address_validation_notices' ) );
	}

	/**
	 * Load assets.
	 */
	public function load_assets() {
		if ( ! CheckoutService::is_address_validation_enabled() || ! CheckoutService::is_checkout_page() ) {
			return;
		}

		wp_enqueue_style(
			'wcshipping-checkout',
			Utils::get_enqueue_base_url() . 'woocommerce-shipping-checkout-address-validation.css',
			array(),
			Utils::get_file_version( WCSHIPPING_PLUGIN_DIST_DIR . 'woocommerce-shipping-checkout-address-validation.css' )
		);

		$handle = 'wcshipping-checkout';

		wp_register_script(
			$handle,
			WCSHIPPING_JAVASCRIPT_URL . 'checkout.js',
			array( 'wp-i18n' ),
			Utils::get_file_version( WCSHIPPING_JAVASCRIPT_DIR . 'checkout.js' ),
			true
		);

		wp_localize_script(
			$handle,
			'wcShippingSettings',
			array_merge(
				Utils::get_settings_object(),
				array(
					'checkout' => CheckoutService::get_checkout_script_data(),
				)
			)
		);

		wp_enqueue_script( $handle );
	}

	/**
	 * Maybe display address validation notices.
	 */
	public function maybe_display_address_validation_notices() {
		if ( ! CheckoutService::is_address_validation_enabled() || ! CheckoutService::is_checkout_page() ) {
			return;
		}

		$this->notifier->print_notices();
		$this->notifier->clear_notices();
	}

	/**
	 * Maybe set destination normalized order meta.
	 *
	 * @param int|WC_Order $order_id_or_object The order ID or WC_Order instance depending on the context.
	 */
	public function maybe_set_destination_normalized_order_meta( $order_id_or_object ) {
		if ( ! CheckoutService::is_address_validation_enabled() ) {
			return;
		}

		if ( ! $this->checkout_service->get_destination_normalized_session_value() ) {
			return;
		}

		$order = wc_get_order( $order_id_or_object );
		if ( ! $order instanceof WC_Order ) {
			return;
		}

		$this->address_normalization_service->set_is_destination_address_normalized( $order->get_id(), true );
	}

	/**
	 * If the right conditions are met, add address validation notices for entered shipping address.
	 *
	 * @param array $packages Shipping packages.
	 *
	 * @return array
	 */
	public function maybe_add_address_validation_notices( array $packages ): array {
		if (
			CheckoutService::is_address_validation_enabled()
			&& CheckoutService::is_classic_checkout()
		) {
			$this->add_address_validation_notices();
		}

		return $packages;
	}


	/**
	 * Add address validation notices for entered shipping address.
	 */
	private function add_address_validation_notices() {
		static $has_run = false;

		if ( $has_run ) {
			return;
		}

		$has_run = true;

		// Validate the shipping address.
		$response = $this->checkout_service->validate_shipping_address();
		if ( ! $response['success'] || empty( $response['notices'] ) ) {
			return;
		}

		foreach ( $response['notices'] as $notice ) {
			$this->notifier->info( $notice->get_message(), $notice->get_data() ?? array(), 'address-validation' );
		}
	}
}