<?php

namespace Devikit\Wfirma;

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

/**
 * NIP Field Handler
 * Adds NIP field to checkout if not provided by another plugin
 */
class NipField {

	/**
	 * Constructor
	 */
	public function __construct() {
		add_action( 'wp', [ $this, 'maybe_add_nip_field' ] );
		add_filter( 'woocommerce_customer_meta_fields', [ $this, 'add_nip_to_user_profile' ] );
		add_action( 'woocommerce_admin_order_data_after_billing_address', [ $this, 'display_nip_in_admin_order' ] );
		add_filter( 'woocommerce_admin_billing_fields', [ $this, 'admin_billing_fields' ] );
		add_action( 'woocommerce_process_shop_order_meta', [ $this, 'save_admin_order_nip' ], 10, 2 );

		// Direct WP admin user profile NIP save.
		add_action( 'personal_options_update', [ $this, 'save_user_profile_nip' ] );
		add_action( 'edit_user_profile_update', [ $this, 'save_user_profile_nip' ] );

		// Sync NIP before admin profile is rendered.
		add_action( 'load-profile.php', [ $this, 'sync_nip_before_profile_display' ] );
		add_action( 'load-user-edit.php', [ $this, 'sync_nip_before_profile_display' ] );

		// Include NIP in the AJAX response when admin selects a customer on the order edit screen.
		add_filter( 'woocommerce_found_customer_details', [ $this, 'add_nip_to_customer_details' ], 10, 2 );

		// Admin scripts: populate NIP field when a customer is loaded on the order edit screen.
		add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_order_scripts' ] );

		// Own AJAX action to get customer NIP.
		add_action( 'wp_ajax_devikit_wfirma_get_customer_nip', [ $this, 'ajax_get_customer_nip' ] );
	}

	/**
	 * Maybe add NIP field if not exists from other plugin
	 */
	public function maybe_add_nip_field() {
		$settings = get_option( 'devikit_wfirma_settings', [] );
		$add_nip = isset( $settings['add_nip_field'] ) ? $settings['add_nip_field'] : 'yes';
		
		if ( $add_nip !== 'yes' ) {
			return;
		}

		if ( $this->is_nip_field_available() ) {
			return;
		}

		add_filter( 'woocommerce_billing_fields', [ $this, 'add_nip_field' ], 20 );
		add_action( 'woocommerce_checkout_update_order_meta', [ $this, 'save_nip_field' ] );
		add_filter( 'woocommerce_order_formatted_billing_address', [ $this, 'display_nip_in_address' ], 10, 2 );
		
		// Only add {nip} placeholder system if NOT using blocks checkout
		// Blocks checkout uses direct HTML modification instead (see CheckoutBlocks.php)
		if ( ! $this->site_uses_block_checkout() ) {
			add_filter( 'woocommerce_formatted_address_replacements', [ $this, 'address_replacements' ], 10, 2 );
			add_filter( 'woocommerce_localisation_address_formats', [ $this, 'address_formats' ] );
		}
		
		add_filter( 'woocommerce_admin_billing_fields', [ $this, 'admin_billing_fields' ] );
	}

	/**
	 * Check if NIP field is already available from another plugin
	 */
	private function is_nip_field_available() {
		$nip_plugins = [
			'nip-field-for-woocommerce/nip-field-for-woocommerce.php',
			'nip-field-for-woocommerce-pro/nip-field-for-woocommerce-pro.php',
			'nip-field-woocommerce/nip-field-woocommerce.php',
			'nip-field-woocommerce-pro/nip-field-woocommerce-pro.php',
			'flexible-invoices/flexible-invoices.php',
			'woocommerce-eu-vat-number/woocommerce-eu-vat-number.php',
		];

		foreach ( $nip_plugins as $plugin ) {
			if ( is_plugin_active( $plugin ) ) {
				return true;
			}
		}

		return apply_filters( 'devikit_wfirma_nip_field_available', false );
	}

	/**
	 * Add NIP field to billing fields
	 */
	public function add_nip_field( $fields ) {
		if ( isset( $fields['billing_nip'] ) ) {
			return $fields;
		}

		$settings = get_option( 'devikit_wfirma_settings', [] );
		$nip_required = isset( $settings['nip_required'] ) && $settings['nip_required'] === 'yes';

		$fields['billing_nip'] = [
			'type'        => 'text',
			'label'       => __( 'NIP', 'invoicing-integration-for-wfirma-and-woocommerce' ),
			'placeholder' => __( 'Enter NIP if you need an invoice', 'invoicing-integration-for-wfirma-and-woocommerce' ),
			'required'    => $nip_required,
			'class'       => [ 'form-row-wide' ],
			'priority'    => 35,
			'maxlength'   => 13,
		];

		return $fields;
	}

	/**
	 * Save NIP field to order meta
	 */
	public function save_nip_field( $order_id ) {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called by WooCommerce checkout hook which handles nonce
		if ( ! empty( $_POST['billing_nip'] ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called by WooCommerce checkout hook which handles nonce
			$nip = sanitize_text_field( wp_unslash( $_POST['billing_nip'] ) );
			// Keep original NIP with country prefix (e.g., "DE123456789")
			// Only remove spaces and dashes, keep letters for country prefix
			
			$order = wc_get_order( $order_id );
			$order->update_meta_data( '_billing_nip', $nip );
			$order->save();
		}
	}

	/**
	 * Display NIP in formatted address
	 */
	public function display_nip_in_address( $address, $order ) {
		$nip = $order->get_meta( '_billing_nip' );
		if ( $nip ) {
			$address['nip'] = $nip;
		}
		return $address;
	}

	/**
	 * Address replacements
	 */
	public function address_replacements( $replacements, $args ) {
		$replacements['{nip}'] = isset( $args['nip'] ) ? __( 'NIP: ', 'invoicing-integration-for-wfirma-and-woocommerce' ) . $args['nip'] : '';
		return $replacements;
	}

	/**
	 * Address formats
	 */
	public function address_formats( $formats ) {
		foreach ( $formats as $country => $format ) {
			$formats[ $country ] = $format . "\n{nip}";
		}
		return $formats;
	}

	/**
	 * Admin billing fields
	 */
	public function admin_billing_fields( $fields ) {
		if ( isset( $fields['nip'] ) ) {
			return $fields;
		}
		$fields['nip'] = [
			'label' => __( 'NIP', 'invoicing-integration-for-wfirma-and-woocommerce' ),
			'show'  => true,
		];
		return $fields;
	}

	/**
	 * Add NIP field to user profile in admin
	 */
	public function add_nip_to_user_profile( $fields ) {
		if ( isset( $fields['billing']['fields']['billing_nip'] ) ) {
			return $fields;
		}
		
		$settings = get_option( 'devikit_wfirma_settings', [] );
		$add_nip = isset( $settings['add_nip_field'] ) ? $settings['add_nip_field'] : 'yes';
		
		if ( $add_nip !== 'yes' ) {
			return $fields;
		}
		
		if ( isset( $fields['billing']['fields'] ) ) {
			if ( isset( $fields['billing']['fields']['billing_company'] ) ) {
				$new_fields = [];
				
				foreach ( $fields['billing']['fields'] as $key => $field ) {
					$new_fields[ $key ] = $field;
					
					if ( $key === 'billing_company' ) {
						$new_fields['billing_nip'] = [
							'label'       => __( 'NIP', 'invoicing-integration-for-wfirma-and-woocommerce' ),
							'description' => '',
						];
					}
				}
				
				$fields['billing']['fields'] = $new_fields;
			} else {
				$fields['billing']['fields'] = array_merge(
					[
						'billing_nip' => [
							'label'       => __( 'NIP', 'invoicing-integration-for-wfirma-and-woocommerce' ),
							'description' => '',
						],
					],
					$fields['billing']['fields']
				);
			}
		}
		
		return $fields;
	}

	/**
	 * Check if site uses block checkout
	 */
	private function site_uses_block_checkout() {
		$checkout_page_id = wc_get_page_id( 'checkout' );
		if ( ! $checkout_page_id ) {
			return false;
		}
		
		// Check if checkout page has blocks
		return has_block( 'woocommerce/checkout', $checkout_page_id );
	}

	/**
	 * Display NIP in admin order screen (want_invoice checkbox info).
	 */
	public function display_nip_in_admin_order( $order ) {
		// wfirma does not have want_invoice checkbox - nothing to display here
	}

	/**
	 * Save NIP from admin order edit screen.
	 *
	 * @param int           $order_id Order ID.
	 * @param \WC_Order|null $order    Order object.
	 */
	public function save_admin_order_nip( $order_id, $order = null ) {
		if ( ! $order instanceof \WC_Order ) {
			$order = wc_get_order( $order_id );
		}
		if ( ! $order ) {
			return;
		}
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called by WooCommerce save hook which verifies nonce
		if ( isset( $_POST['_billing_nip'] ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing
			$nip = sanitize_text_field( wp_unslash( $_POST['_billing_nip'] ) );
			$order->update_meta_data( '_billing_nip', $nip );
			$order->save();
		}
	}

	/**
	 * Save NIP directly from the WP admin user profile form.
	 *
	 * @param int $user_id User ID being saved.
	 */
	public function save_user_profile_nip( $user_id ) {
		if ( ! current_user_can( 'edit_user', $user_id ) ) {
			return;
		}
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- WP core verifies nonce for profile/user-edit forms
		if ( ! isset( $_POST['billing_nip'] ) ) {
			return;
		}
		// phpcs:ignore WordPress.Security.NonceVerification.Missing
		$nip = sanitize_text_field( wp_unslash( $_POST['billing_nip'] ) );

		update_user_meta( $user_id, 'billing_nip', $nip );
		update_user_meta( $user_id, 'devikit-wfirma/billing_nip', $nip );
		update_user_meta( $user_id, '_wc_billing/devikit-wfirma/billing_nip', $nip );
	}

	/**
	 * Sync NIP meta keys before the WP admin user profile page is rendered.
	 */
	public function sync_nip_before_profile_display() {
		$user_id = isset( $_REQUEST['user_id'] ) ? absint( $_REQUEST['user_id'] ) : get_current_user_id();
		if ( ! $user_id ) {
			return;
		}

		$billing_nip = (string) get_user_meta( $user_id, 'billing_nip', true );
		$wc_nip      = (string) get_user_meta( $user_id, 'devikit-wfirma/billing_nip', true );
		$wc_nip_pref = (string) get_user_meta( $user_id, '_wc_billing/devikit-wfirma/billing_nip', true );

		$latest = ! empty( $wc_nip_pref ) ? $wc_nip_pref : ( ! empty( $wc_nip ) ? $wc_nip : $billing_nip );

		if ( $billing_nip === $latest && $wc_nip === $latest ) {
			return;
		}

		update_user_meta( $user_id, 'billing_nip', $latest );
		update_user_meta( $user_id, 'devikit-wfirma/billing_nip', $latest );
		update_user_meta( $user_id, '_wc_billing/devikit-wfirma/billing_nip', $latest );
	}

	/**
	 * Inject billing NIP into the WooCommerce AJAX customer-details response.
	 *
	 * @param array $data    Customer data array.
	 * @param int   $user_id Customer user ID.
	 * @return array
	 */
	public function add_nip_to_customer_details( $data, $user_id ) {
		$nip = get_user_meta( $user_id, 'billing_nip', true );

		if ( empty( $nip ) ) {
			foreach ( $this->get_external_nip_user_meta_keys() as $key ) {
				$nip = get_user_meta( $user_id, $key, true );
				if ( ! empty( $nip ) ) {
					break;
				}
			}
		}

		if ( ! empty( $nip ) ) {
			$data['billing']['nip'] = esc_attr( $nip );
		}

		return $data;
	}

	/**
	 * Enqueue admin JavaScript for the order edit screen.
	 *
	 * @param string $hook Current admin page hook.
	 */
	public function enqueue_admin_order_scripts( $hook ) {
		$order_hooks = [ 'post.php', 'post-new.php', 'woocommerce_page_wc-orders' ];
		if ( ! in_array( $hook, $order_hooks, true ) ) {
			return;
		}

		$screen = get_current_screen();
		if ( ! $screen ) {
			return;
		}

		$is_order_screen = in_array( $screen->id, [ 'shop_order', 'woocommerce_page_wc-orders' ], true );
		if ( ! $is_order_screen ) {
			return;
		}

		wp_enqueue_script(
			'devikit-wfirma-admin-order-nip',
			DEVIKIT_WFIRMA_URL . 'assets/js/admin-order-nip.js',
			[ 'jquery', 'wc-admin-order-meta-boxes' ],
			DEVIKIT_WFIRMA_VERSION,
			true
		);

		wp_localize_script(
			'devikit-wfirma-admin-order-nip',
			'devikit_wfirma_admin_nip',
			[
				'ajax_url' => admin_url( 'admin-ajax.php' ),
				'nonce'    => wp_create_nonce( 'devikit_wfirma_admin_nip' ),
			]
		);
	}

	/**
	 * AJAX handler: return the NIP for a given customer.
	 */
	public function ajax_get_customer_nip() {
		check_ajax_referer( 'devikit_wfirma_admin_nip', 'nonce' );

		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_send_json_error( 'Unauthorized', 403 );
		}

		$user_id = isset( $_POST['user_id'] ) ? absint( $_POST['user_id'] ) : 0;
		if ( ! $user_id ) {
			wp_send_json_error( 'Invalid user ID', 400 );
		}

		$nip = '';
		foreach ( $this->get_external_nip_user_meta_keys() as $key ) {
			$nip = (string) get_user_meta( $user_id, $key, true );
			if ( ! empty( $nip ) ) {
				break;
			}
		}

		if ( empty( $nip ) ) {
			$nip = (string) get_user_meta( $user_id, 'billing_nip', true );
		}

		wp_send_json_success( [ 'nip' => $nip ] );
	}

	/**
	 * Returns user meta keys used by known external NIP plugins.
	 *
	 * @return string[]
	 */
	private function get_external_nip_user_meta_keys() {
		return [
			'_wc_billing/devikit-wfirma/billing_nip',
			'devikit-wfirma/billing_nip',
			'nip-field-wc/billing_nip',
			'_wc_billing/nip-field-wc/billing_nip',
			'nip-field-woocommerce/billing_nip',
			'_wc_billing/nip-field-woocommerce/billing_nip',
		];
	}
}

