<?php

namespace Devikit\Sellsy\Frontend;

use Devikit\Sellsy\Admin\Settings;
use Devikit\Sellsy\VatIdField;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class CheckoutBlocks {

	/**
	 * @var string[]
	 */
	private $siret_meta_keys = [
		'billing_siret',
		'devikit-sellsy/billing_siret',
		'_wc_billing/devikit-sellsy/billing_siret',
	];

	/**
	 * @var string[]
	 */
	private $vat_meta_keys = [
		'billing_vat_id',
		'devikit-sellsy/billing_vat_id',
		'_wc_billing/devikit-sellsy/billing_vat_id',
	];

	public function __construct() {
		add_action( 'woocommerce_blocks_loaded', [ $this, 'init_blocks_integration' ] );
		add_action( 'added_user_meta', [ $this, 'on_field_meta_changed' ], 10, 4 );
		add_action( 'updated_user_meta', [ $this, 'on_field_meta_changed' ], 10, 4 );
		add_action( 'template_redirect', [ $this, 'sync_fields_before_my_account_display' ] );
	}

	public function init_blocks_integration() {
		if ( ! class_exists( 'Automattic\WooCommerce\Blocks\Package' ) ) {
			return;
		}

		if ( function_exists( 'woocommerce_register_additional_checkout_field' )
			&& defined( 'WC_VERSION' )
			&& version_compare( WC_VERSION, '8.8.0', '>=' )
			&& $this->site_uses_block_checkout()
		) {
			add_action( 'woocommerce_init', [ $this, 'register_additional_checkout_fields' ], 20 );
			add_filter(
				'woocommerce_get_default_value_for_devikit-sellsy/billing_siret',
				[ $this, 'provide_default_siret_for_blocks_checkout' ],
				10,
				3
			);
			if ( ! VatIdField::is_external_vat_field_available() ) {
				add_filter(
					'woocommerce_get_default_value_for_devikit-sellsy/billing_vat_id',
					[ $this, 'provide_default_vat_for_blocks_checkout' ],
					10,
					3
				);
			}
		}

		add_action( 'woocommerce_store_api_checkout_update_order_from_request', [ $this, 'save_fields_from_blocks' ] );
		add_action( 'woocommerce_store_api_checkout_order_processed', [ $this, 'save_fields_from_blocks' ] );
		add_action( 'woocommerce_checkout_order_processed', [ $this, 'copy_fields_to_standard_meta' ], 20 );
		add_action( 'woocommerce_store_api_checkout_order_processed', [ $this, 'copy_fields_to_standard_meta' ], 20 );

		if ( $this->site_uses_block_checkout() ) {
			add_filter( 'woocommerce_billing_fields', [ $this, 'remove_classic_fields_from_my_account' ], 999 );
			add_action( 'woocommerce_customer_save_address', [ $this, 'save_fields_my_account_blocks' ], 10, 2 );
			add_action( 'woocommerce_customer_save_address', [ $this, 'sync_fields_my_account_late' ], 50, 2 );
		}
	}

	public function register_additional_checkout_fields() {
		if ( ! function_exists( 'woocommerce_register_additional_checkout_field' ) ) {
			return;
		}

		$opts             = get_option( Settings::OPTION_NAME, [] );
		$siret_required   = isset( $opts['siret_required'] ) && $opts['siret_required'] === 'yes';
		$validate_siret   = ! isset( $opts['validate_siret_format'] ) || $opts['validate_siret_format'] === 'yes';
		$vat_display_mode = isset( $opts['vat_id_display_mode'] ) ? $opts['vat_id_display_mode'] : 'always';
		$vat_required     = isset( $opts['vat_id_required'] ) && $opts['vat_id_required'] === 'yes';
		$validate_vat     = ! isset( $opts['validate_vat_id_format'] ) || $opts['validate_vat_id_format'] === 'yes';

		$siret_attributes = [];
		if ( $validate_siret ) {
			$siret_attributes['pattern']   = '[0-9]{14}';
			$siret_attributes['maxlength'] = '14';
		}

		try {
			woocommerce_register_additional_checkout_field(
				[
					'id'                => 'devikit-sellsy/billing_siret',
					'label'             => __( 'SIRET', 'invoicing-integration-for-sellsy-and-woocommerce' ),
					'location'          => 'address',
					'type'              => 'text',
					'required'          => $siret_required,
					'index'             => 25,
					'attributes'        => $siret_attributes,
					'sanitize_callback' => [ $this, 'sanitize_siret_field' ],
					'validate_callback' => [ $this, 'validate_siret_field' ],
				]
			);

			if ( $vat_display_mode !== 'hidden' && ! VatIdField::is_external_vat_field_available() ) {
				$vat_attributes = [];
				if ( $validate_vat ) {
					$vat_attributes['pattern'] = '[A-Za-z]{2}[0-9]{2,13}';
				}

				woocommerce_register_additional_checkout_field(
					[
						'id'                => 'devikit-sellsy/billing_vat_id',
						'label'             => __( 'VAT Number (TVA)', 'invoicing-integration-for-sellsy-and-woocommerce' ),
						'location'          => 'address',
						'type'              => 'text',
						'required'          => $vat_required,
						'index'             => 26,
						'attributes'        => $vat_attributes,
						'sanitize_callback' => [ $this, 'sanitize_vat_field' ],
						'validate_callback' => [ $this, 'validate_vat_field' ],
					]
				);
			}
		} catch ( \Exception $e ) {
			if ( function_exists( 'wc_get_logger' ) ) {
				wc_get_logger()->error(
					'sellsy: Failed to register checkout fields: ' . $e->getMessage(),
					[ 'source' => 'invoicing-integration-for-sellsy-and-woocommerce' ]
				);
			}
		}
	}

	/**
	 * @param string $value
	 * @return string
	 */
	public function sanitize_siret_field( $value ) {
		return sanitize_text_field( $value );
	}

	/**
	 * @param string    $value
	 * @param \WP_Error $errors
	 */
	public function validate_siret_field( $value, $errors ) {
		$opts            = get_option( Settings::OPTION_NAME, [] );
		$siret_required  = isset( $opts['siret_required'] ) && $opts['siret_required'] === 'yes';
		$validate_format = ! isset( $opts['validate_siret_format'] ) || $opts['validate_siret_format'] === 'yes';

		if ( $siret_required && empty( $value ) ) {
			$errors->add(
				'billing_siret_required',
				__( 'SIRET number is required.', 'invoicing-integration-for-sellsy-and-woocommerce' )
			);
			return;
		}

		if ( ! empty( $value ) && $validate_format ) {
			$clean = preg_replace( '/[^0-9]/', '', $value );
			if ( strlen( $clean ) !== 14 ) {
				$errors->add(
					'billing_siret_invalid',
					__( 'SIRET must contain exactly 14 digits.', 'invoicing-integration-for-sellsy-and-woocommerce' )
				);
			}
		}
	}

	/**
	 * @param string $value
	 * @return string
	 */
	public function sanitize_vat_field( $value ) {
		return sanitize_text_field( $value );
	}

	/**
	 * @param string    $value
	 * @param \WP_Error $errors
	 */
	public function validate_vat_field( $value, $errors ) {
		$opts         = get_option( Settings::OPTION_NAME, [] );
		$vat_required = isset( $opts['vat_id_required'] ) && $opts['vat_id_required'] === 'yes';
		$validate_vat = ! isset( $opts['validate_vat_id_format'] ) || $opts['validate_vat_id_format'] === 'yes';

		if ( $vat_required && empty( $value ) ) {
			$errors->add(
				'billing_vat_id_required',
				__( 'VAT number is required.', 'invoicing-integration-for-sellsy-and-woocommerce' )
			);
			return;
		}

		if ( ! empty( $value ) && $validate_vat && ! preg_match( '/^[A-Z]{2}\d{2,13}$/i', $value ) ) {
			$errors->add(
				'billing_vat_id_invalid',
				__( 'VAT number must start with a 2-letter country code followed by 2-13 digits (e.g. FR12345678901).', 'invoicing-integration-for-sellsy-and-woocommerce' )
			);
		}
	}

	/**
	 * @param \WC_Order $order
	 */
	public function save_fields_from_blocks( $order ) {
		if ( ! $order || ! $this->is_valid_store_api_or_checkout_request() ) {
			return;
		}

		$siret = $this->get_field_value_from_request( 'billing_siret' );
		if ( $siret !== '' && empty( $order->get_meta( '_billing_siret' ) ) ) {
			$order->update_meta_data( '_billing_siret', $siret );
		}

		if ( ! VatIdField::is_external_vat_field_available() ) {
			$vat = $this->get_field_value_from_request( 'billing_vat_id' );
			if ( $vat !== '' && empty( $order->get_meta( '_billing_vat_id' ) ) ) {
				$order->update_meta_data( '_billing_vat_id', $vat );
			}
		}

		$order->save();
	}

	/**
	 * @param \WC_Order|int $order
	 */
	public function copy_fields_to_standard_meta( $order ) {
		if ( is_numeric( $order ) ) {
			$order = wc_get_order( $order );
		}
		if ( ! $order ) {
			return;
		}

		$changed = false;

		if ( empty( $order->get_meta( '_billing_siret' ) ) ) {
			$wc_siret = $order->get_meta( '_wc_billing/devikit-sellsy/billing_siret' );
			if ( ! empty( $wc_siret ) ) {
				$order->update_meta_data( '_billing_siret', sanitize_text_field( $wc_siret ) );
				$changed = true;
			}
		}

		if ( empty( $order->get_meta( '_billing_vat_id' ) ) ) {
			$wc_vat = $order->get_meta( '_wc_billing/devikit-sellsy/billing_vat_id' );
			if ( ! empty( $wc_vat ) ) {
				$order->update_meta_data( '_billing_vat_id', sanitize_text_field( $wc_vat ) );
				$changed = true;
			}
		}

		if ( $changed ) {
			$order->save();
		}
	}

	/**
	 * @param array $fields
	 * @return array
	 */
	public function remove_classic_fields_from_my_account( $fields ) {
		if ( is_account_page() && ! is_admin() ) {
			unset( $fields['billing_siret'], $fields['billing_vat_id'], $fields['billing_want_invoice'] );
		}
		return $fields;
	}

	/**
	 * @param int    $user_id
	 * @param string $load_address
	 */
	public function save_fields_my_account_blocks( $user_id, $load_address ) {
		if ( 'billing' !== $load_address || ! $this->is_valid_edit_address_request( $user_id ) ) {
			return;
		}

		foreach ( [ '_wc_billing/devikit-sellsy/billing_siret', 'devikit-sellsy/billing_siret' ] as $post_key ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified in is_valid_edit_address_request().
			if ( isset( $_POST[ $post_key ] ) ) {
				// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified in is_valid_edit_address_request().
				$siret = sanitize_text_field( wp_unslash( $_POST[ $post_key ] ) );
				if ( $siret !== '' ) {
					update_user_meta( $user_id, 'billing_siret', $siret );
				}
				break;
			}
		}

		if ( VatIdField::is_external_vat_field_available() ) {
			return;
		}

		foreach ( [ '_wc_billing/devikit-sellsy/billing_vat_id', 'devikit-sellsy/billing_vat_id' ] as $post_key ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified in is_valid_edit_address_request().
			if ( isset( $_POST[ $post_key ] ) ) {
				// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified in is_valid_edit_address_request().
				$vat = sanitize_text_field( wp_unslash( $_POST[ $post_key ] ) );
				if ( $vat !== '' ) {
					update_user_meta( $user_id, 'billing_vat_id', $vat );
				}
				break;
			}
		}
	}

	/**
	 * @param int    $meta_id
	 * @param int    $user_id
	 * @param string $meta_key
	 * @param mixed  $meta_value
	 */
	public function on_field_meta_changed( $meta_id, $user_id, $meta_key, $meta_value ) {
		unset( $meta_id );

		$is_siret = in_array( $meta_key, $this->siret_meta_keys, true );
		$is_vat   = in_array( $meta_key, $this->vat_meta_keys, true );

		if ( ! $is_siret && ! $is_vat ) {
			return;
		}

		remove_action( 'added_user_meta', [ $this, 'on_field_meta_changed' ], 10 );
		remove_action( 'updated_user_meta', [ $this, 'on_field_meta_changed' ], 10 );

		$value = sanitize_text_field( (string) $meta_value );

		if ( $value !== '' ) {
			if ( $is_siret ) {
				update_user_meta( $user_id, 'billing_siret', $value );
				update_user_meta( $user_id, 'devikit-sellsy/billing_siret', $value );
				update_user_meta( $user_id, '_wc_billing/devikit-sellsy/billing_siret', $value );
			} elseif ( $is_vat ) {
				update_user_meta( $user_id, 'billing_vat_id', $value );
				update_user_meta( $user_id, 'devikit-sellsy/billing_vat_id', $value );
				update_user_meta( $user_id, '_wc_billing/devikit-sellsy/billing_vat_id', $value );
			}
		}

		add_action( 'added_user_meta', [ $this, 'on_field_meta_changed' ], 10, 4 );
		add_action( 'updated_user_meta', [ $this, 'on_field_meta_changed' ], 10, 4 );
	}

	/**
	 * @param mixed  $value
	 * @param string $group
	 * @param mixed  $wc_object
	 * @return mixed
	 */
	public function provide_default_siret_for_blocks_checkout( $value, $group, $wc_object ) {
		if ( 'billing' !== $group || ! ( $wc_object instanceof \WC_Customer ) ) {
			return $value;
		}
		$user_id = $wc_object->get_id();
		if ( ! $user_id ) {
			return $value;
		}
		foreach ( [ 'billing_siret', 'devikit-sellsy/billing_siret' ] as $key ) {
			$val = (string) get_user_meta( $user_id, $key, true );
			if ( $val !== '' ) {
				update_user_meta( $user_id, '_wc_billing/devikit-sellsy/billing_siret', $val );
				return $val;
			}
		}
		return $value;
	}

	/**
	 * @param mixed  $value
	 * @param string $group
	 * @param mixed  $wc_object
	 * @return mixed
	 */
	public function provide_default_vat_for_blocks_checkout( $value, $group, $wc_object ) {
		if ( 'billing' !== $group || ! ( $wc_object instanceof \WC_Customer ) ) {
			return $value;
		}
		$user_id = $wc_object->get_id();
		if ( ! $user_id ) {
			return $value;
		}
		foreach ( [ 'billing_vat_id', 'devikit-sellsy/billing_vat_id' ] as $key ) {
			$val = (string) get_user_meta( $user_id, $key, true );
			if ( $val !== '' ) {
				update_user_meta( $user_id, '_wc_billing/devikit-sellsy/billing_vat_id', $val );
				return $val;
			}
		}
		return $value;
	}

	public function sync_fields_before_my_account_display() {
		if ( ! is_account_page() || ! is_user_logged_in() ) {
			return;
		}

		$user_id = get_current_user_id();

		remove_action( 'added_user_meta', [ $this, 'on_field_meta_changed' ], 10 );
		remove_action( 'updated_user_meta', [ $this, 'on_field_meta_changed' ], 10 );

		$siret        = (string) get_user_meta( $user_id, 'billing_siret', true );
		$wc_siret     = (string) get_user_meta( $user_id, 'devikit-sellsy/billing_siret', true );
		$wc_siret_p   = (string) get_user_meta( $user_id, '_wc_billing/devikit-sellsy/billing_siret', true );
		$latest_siret = $wc_siret_p !== '' ? $wc_siret_p : ( $wc_siret !== '' ? $wc_siret : $siret );
		if ( $siret !== $latest_siret || $wc_siret !== $latest_siret ) {
			update_user_meta( $user_id, 'billing_siret', $latest_siret );
			update_user_meta( $user_id, 'devikit-sellsy/billing_siret', $latest_siret );
			update_user_meta( $user_id, '_wc_billing/devikit-sellsy/billing_siret', $latest_siret );
		}

		$vat        = (string) get_user_meta( $user_id, 'billing_vat_id', true );
		$wc_vat     = (string) get_user_meta( $user_id, 'devikit-sellsy/billing_vat_id', true );
		$wc_vat_p   = (string) get_user_meta( $user_id, '_wc_billing/devikit-sellsy/billing_vat_id', true );
		$latest_vat = $wc_vat_p !== '' ? $wc_vat_p : ( $wc_vat !== '' ? $wc_vat : $vat );
		if ( $vat !== $latest_vat || $wc_vat !== $latest_vat ) {
			update_user_meta( $user_id, 'billing_vat_id', $latest_vat );
			update_user_meta( $user_id, 'devikit-sellsy/billing_vat_id', $latest_vat );
			update_user_meta( $user_id, '_wc_billing/devikit-sellsy/billing_vat_id', $latest_vat );
		}

		add_action( 'added_user_meta', [ $this, 'on_field_meta_changed' ], 10, 4 );
		add_action( 'updated_user_meta', [ $this, 'on_field_meta_changed' ], 10, 4 );
	}

	/**
	 * @param int    $user_id
	 * @param string $load_address
	 */
	public function sync_fields_my_account_late( $user_id, $load_address ) {
		if ( 'billing' !== $load_address || ! $this->is_valid_edit_address_request( $user_id ) ) {
			return;
		}

		$siret = '';
		foreach ( [ '_wc_billing/devikit-sellsy/billing_siret', 'devikit-sellsy/billing_siret', 'billing_siret' ] as $key ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified in is_valid_edit_address_request().
			if ( isset( $_POST[ $key ] ) && '' !== $_POST[ $key ] ) {
				// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified in is_valid_edit_address_request().
				$siret = sanitize_text_field( wp_unslash( $_POST[ $key ] ) );
				break;
			}
		}
		if ( $siret === '' ) {
			foreach ( $this->siret_meta_keys as $key ) {
				$val = (string) get_user_meta( $user_id, $key, true );
				if ( $val !== '' ) {
					$siret = $val;
					break;
				}
			}
		}
		if ( $siret !== '' ) {
			update_user_meta( $user_id, 'billing_siret', $siret );
			update_user_meta( $user_id, 'devikit-sellsy/billing_siret', $siret );
			update_user_meta( $user_id, '_wc_billing/devikit-sellsy/billing_siret', $siret );
		}

		if ( VatIdField::is_external_vat_field_available() ) {
			return;
		}

		$vat = '';
		foreach ( [ '_wc_billing/devikit-sellsy/billing_vat_id', 'devikit-sellsy/billing_vat_id', 'billing_vat_id' ] as $key ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified in is_valid_edit_address_request().
			if ( isset( $_POST[ $key ] ) && '' !== $_POST[ $key ] ) {
				// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified in is_valid_edit_address_request().
				$vat = sanitize_text_field( wp_unslash( $_POST[ $key ] ) );
				break;
			}
		}
		if ( $vat === '' ) {
			foreach ( $this->vat_meta_keys as $key ) {
				$val = (string) get_user_meta( $user_id, $key, true );
				if ( $val !== '' ) {
					$vat = $val;
					break;
				}
			}
		}
		if ( $vat !== '' ) {
			update_user_meta( $user_id, 'billing_vat_id', $vat );
			update_user_meta( $user_id, 'devikit-sellsy/billing_vat_id', $vat );
			update_user_meta( $user_id, '_wc_billing/devikit-sellsy/billing_vat_id', $vat );
		}
	}

	/**
	 * @param string $field_name
	 * @return string
	 */
	private function get_field_value_from_request( $field_name ) {
		if ( ! $this->is_valid_store_api_or_checkout_request() ) {
			return '';
		}

		// phpcs:disable WordPress.Security.NonceVerification.Missing -- Verified in is_valid_store_api_or_checkout_request().
		if (
			isset( $_POST['extensions'] )
			&& is_array( $_POST['extensions'] )
			&& isset( $_POST['extensions']['devikit-sellsy'] )
			&& is_array( $_POST['extensions']['devikit-sellsy'] )
			&& isset( $_POST['extensions']['devikit-sellsy'][ $field_name ] )
		) {
			return sanitize_text_field( wp_unslash( $_POST['extensions']['devikit-sellsy'][ $field_name ] ) );
		}
		if ( isset( $_POST[ $field_name ] ) ) {
			return sanitize_text_field( wp_unslash( $_POST[ $field_name ] ) );
		}
		if ( isset( $_POST[ 'devikit-sellsy/' . $field_name ] ) ) {
			return sanitize_text_field( wp_unslash( $_POST[ 'devikit-sellsy/' . $field_name ] ) );
		}
		// phpcs:enable WordPress.Security.NonceVerification.Missing

		return '';
	}

	/**
	 * @param int $user_id
	 * @return bool
	 */
	private function is_valid_edit_address_request( $user_id ) {
		$user_id = absint( $user_id );
		if ( ! $user_id || ! is_user_logged_in() || get_current_user_id() !== $user_id ) {
			return false;
		}

		$nonce = '';
		if ( isset( $_REQUEST['woocommerce-edit-address-nonce'] ) ) {
			$nonce = sanitize_text_field( wp_unslash( $_REQUEST['woocommerce-edit-address-nonce'] ) );
		} elseif ( isset( $_REQUEST['_wpnonce'] ) ) {
			$nonce = sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) );
		}

		return $nonce !== '' && (bool) wp_verify_nonce( $nonce, 'woocommerce-edit_address' );
	}

	/**
	 * @return bool
	 */
	private function is_valid_store_api_or_checkout_request() {
		if ( isset( $_POST['woocommerce-process-checkout-nonce'] ) ) {
			$valid = wp_verify_nonce(
				sanitize_text_field( wp_unslash( $_POST['woocommerce-process-checkout-nonce'] ) ),
				'woocommerce-process_checkout'
			);
			if ( $valid ) {
				return true;
			}
			return did_action( 'woocommerce_checkout_process' ) > 0
				|| did_action( 'woocommerce_before_checkout_process' ) > 0;
		}

		return ( defined( 'REST_REQUEST' ) && REST_REQUEST )
			|| did_action( 'woocommerce_store_api_checkout_update_order_from_request' ) > 0;
	}

	/**
	 * @return bool
	 */
	private function site_uses_block_checkout() {
		$page_id = wc_get_page_id( 'checkout' );
		return $page_id && has_block( 'woocommerce/checkout', $page_id );
	}
}
