<?php

namespace Devikit\Ifirma\Frontend;

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

class Checkout {

	/**
	 * Constructor
	 */
	public function __construct() {
		// Use higher priority (20+) to run after other plugins that might add NIP field
		add_filter( 'woocommerce_checkout_fields', [ $this, 'add_nip_field' ], 20 );
		add_action( 'woocommerce_checkout_update_order_meta', [ $this, 'save_checkout_fields' ], 20 );
		add_action( 'woocommerce_admin_order_data_after_billing_address', [ $this, 'display_nip_in_admin_order' ] );
		// Editable NIP in order admin (same as address fields)
		add_filter( 'woocommerce_admin_billing_fields', [ $this, 'add_editable_nip_to_admin_billing' ], 20 );
		add_action( 'woocommerce_process_shop_order_meta', [ $this, 'save_admin_order_nip' ], 10, 2 );
		// NIP is already shown in formatted billing address, no need to add it to email order meta fields
		add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
		add_action( 'wp_head', [ $this, 'add_inline_css' ], 999 );
		
		// NIP validation
		add_action( 'woocommerce_after_checkout_validation', [ $this, 'validate_nip_field' ], 10, 2 );
		
		// Formatted address
		add_filter( 'woocommerce_order_get_formatted_billing_address', [ $this, 'add_nip_to_formatted_address' ], 10, 3 );
		
		// My Account - billing address display
		add_filter( 'woocommerce_my_account_my_address_formatted_address', [ $this, 'my_account_my_address_formatted_address' ], 10, 3 );
		
		// My Account - billing address form (priority 20 to run after other plugins)
		add_filter( 'woocommerce_billing_fields', [ $this, 'add_nip_to_my_account_billing_fields' ], 20, 1 );
		add_action( 'woocommerce_after_save_address_validation', [ $this, 'validate_my_account_billing_nip' ], 10, 2 );
		add_action( 'woocommerce_customer_save_address', [ $this, 'save_my_account_billing_nip' ], 20, 2 );
	}

	/**
	 * Enqueue scripts
	 */
	public function enqueue_scripts() {
		if ( is_checkout() ) {
			wp_enqueue_script( 'devikit-ifirma-checkout', DEVIKIT_IFIRMA_URL . 'assets/js/checkout.js', [ 'jquery' ], DEVIKIT_IFIRMA_VERSION, true );
		}
	}

	/**
	 * Add inline CSS to hide NIP field initially if checkbox mode
	 */
	public function add_inline_css() {
		if ( ! is_checkout() ) {
			return;
		}
		
		$settings = get_option( 'devikit_ifirma_settings', [] );
		$nip_display_mode = isset( $settings['nip_display_mode'] ) ? $settings['nip_display_mode'] : 'always';
		
		if ( $nip_display_mode === 'checkbox' ) {
			wp_add_inline_style( 'woocommerce-inline', '.ifirma-nip-hidden-initially { display: none !important; }' );
		}
	}

	/**
	 * Add NIP to formatted address (HTML)
	 * NIP is also added by NipField.php via address_formats, but this ensures it's shown in contexts
	 * where NipField might not be active (e.g., other NIP plugins are active)
	 */
	public function add_nip_to_formatted_address( $address, $raw_address, $order ) {
		$nip = \Devikit\Ifirma\InvoiceManager::get_order_tax_id( $order );
		
		// Check if NIP is already in the address to prevent duplication
		if ( ! empty( $nip ) && strpos( $address, 'NIP: ' . $nip ) === false && strpos( $address, 'NIP:' ) === false ) {
			$company = '';
			if ( is_array( $raw_address ) && ! empty( $raw_address['company'] ) ) {
				$company = (string) $raw_address['company'];
			}

			$address = $this->insert_nip_into_formatted_address( $address, $company, $nip );
		}
		return $address;
	}

	/**
	 * Insert NIP line into already-formatted HTML address safely.
	 *
	 * Avoids naive str_replace() on company string (can duplicate when company is a short substring).
	 *
	 * @param string $address Formatted address HTML.
	 * @param string $company Company name from raw address.
	 * @param string $nip     NIP value.
	 * @return string
	 */
	private function insert_nip_into_formatted_address( $address, $company, $nip ) {
		$nip_line = __( 'NIP', 'invoicing-integration-for-ifirma-and-woocommerce' ) . ': ' . esc_html( $nip );

		// Normalize common <br> variants and split into lines.
		$normalized = str_replace( [ '<br/>', '<br />' ], '<br>', (string) $address );
		$parts = preg_split( '/<br\s*\/?>|\r\n|\r|\n/', $normalized );
		if ( ! is_array( $parts ) || empty( $parts ) ) {
			return $nip_line . '<br>' . $address;
		}

		$company = trim( wp_strip_all_tags( (string) $company ) );
		$inserted = false;
		$out = [];

		foreach ( $parts as $part ) {
			$part = trim( (string) $part );
			if ( $part === '' ) {
				continue;
			}

			$part_text = trim( wp_strip_all_tags( $part ) );
			if ( ! $inserted && $company !== '' && $part_text === $company ) {
				$out[] = $nip_line;
				$inserted = true;
			}

			$out[] = $part;
		}

		if ( ! $inserted ) {
			array_unshift( $out, $nip_line );
		}

		return implode( '<br>', $out );
	}

	/**
	 * Add NIP field if not exists
	 */
	public function add_nip_field( $fields ) {
		$settings = get_option( 'devikit_ifirma_settings', [] );
		$nip_display_mode = isset( $settings['nip_display_mode'] ) ? $settings['nip_display_mode'] : 'always';
		$checkbox_label = isset( $settings['invoice_checkbox_label'] ) && ! empty( $settings['invoice_checkbox_label'] ) 
			? $settings['invoice_checkbox_label'] 
			: __( 'I want an invoice', 'invoicing-integration-for-ifirma-and-woocommerce' );
		
		// Add checkbox if mode is 'checkbox'
		if ( $nip_display_mode === 'checkbox' ) {
			$checkbox_field = [
				'type'    => 'checkbox',
				'label'   => $checkbox_label,
				'class'   => [ 'form-row-wide', 'create-invoice-checkbox' ],
				'priority' => 24, // Before NIP (25)
			];

			if ( isset( $fields['billing']['billing_company'] ) ) {
				$new_billing_fields = [];
				foreach ( $fields['billing'] as $key => $field ) {
					if ( $key === 'billing_company' ) {
						$new_billing_fields['billing_want_invoice'] = $checkbox_field;
					}
					$new_billing_fields[ $key ] = $field;
				}
				$fields['billing'] = $new_billing_fields;
			} else {
				$fields['billing']['billing_want_invoice'] = $checkbox_field;
			}
		}

		// Check if NIP field is already added by another plugin
		$common_keys = [ 'billing_company_nip', 'billing_nip', 'billing_tax_number', 'billing_vat', 'vat_number' ];
		
		$nip_exists = false;
		foreach ( $common_keys as $key ) {
			if ( isset( $fields['billing'][ $key ] ) ) {
				$nip_exists = $key;
				break;
			}
		}

		// If NIP field already exists, don't add our own
		if ( $nip_exists ) {
			return $fields;
		}

		// Check if NIP is required
		$nip_required = isset( $settings['nip_required'] ) && $settings['nip_required'] === 'yes';
		
		$nip_field_config = [
			'type'        => 'text',
			'label'       => __( 'NIP', 'invoicing-integration-for-ifirma-and-woocommerce' ),
			'placeholder' => __( 'Enter NIP', 'invoicing-integration-for-ifirma-and-woocommerce' ),
			'required'    => $nip_required,
			'class'       => [ 'form-row-wide', 'ifirma-nip-field' ],
			'clear'       => true,
			'priority'    => 25,
		];
		
		// Add class to hide NIP field initially if checkbox mode is enabled
		if ( $nip_display_mode === 'checkbox' ) {
			$nip_field_config['class'][] = 'ifirma-nip-hidden-initially';
		}

		// Insert before Company Name if exists
		if ( isset( $fields['billing']['billing_company'] ) ) {
			$new_billing_fields = [];
			foreach ( $fields['billing'] as $key => $field ) {
				if ( $key === 'billing_company' ) {
					$new_billing_fields['billing_nip'] = $nip_field_config;
				}
				$new_billing_fields[ $key ] = $field;
			}
			$fields['billing'] = $new_billing_fields;
		} else {
			$fields['billing']['billing_nip'] = $nip_field_config;
		}

		return $fields;
	}

	/**
	 * Validate NIP field during checkout
	 */
	public function validate_nip_field( $data, $errors ) {
		// If another NIP plugin is active, let it handle validation
		if ( $this->is_other_nip_plugin_active() ) {
			return;
		}
		
		$settings = get_option( 'devikit_ifirma_settings', [] );
		
		$nip_required = isset( $settings['nip_required'] ) && $settings['nip_required'] === 'yes';
		$validate_format = isset( $settings['validate_nip_format'] ) && $settings['validate_nip_format'] === 'yes';
		
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called by WooCommerce checkout validation hook which handles nonce
		$nip = isset( $_POST['billing_nip'] ) ? sanitize_text_field( wp_unslash( $_POST['billing_nip'] ) ) : '';
		
		if ( $nip_required && empty( $nip ) ) {
			$errors->add( 'billing_nip_required', __( 'Pole NIP jest wymagane.', 'invoicing-integration-for-ifirma-and-woocommerce' ) );
			return;
		}
		
		if ( $validate_format && ! empty( $nip ) ) {
			$nip_clean = preg_replace( '/[\s\-]/', '', $nip );
			
			if ( ! preg_match( '/^[0-9]{10}$/', $nip_clean ) ) {
				$errors->add( 'billing_nip_invalid', __( 'NIP must contain exactly 10 digits.', 'invoicing-integration-for-ifirma-and-woocommerce' ) );
			}
		}
	}

	/**
	 * Check if another NIP plugin is active
	 */
	private function is_other_nip_plugin_active() {
		if ( ! function_exists( 'is_plugin_active' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}
		
		$nip_plugins = [
			'woocommerce-nip-field/woocommerce-nip-field.php',
			'nip-field-woocommerce/nip-field-woocommerce.php',
			'nip-field-for-woocommerce/nip-field-for-woocommerce.php',
			'flexible-invoices-woocommerce/flexible-invoices-woocommerce.php',
			'woocommerce-ifirma/woocommerce-ifirma.php',
			'woocommerce-fakturownia/woocommerce-fakturownia.php',
			'woocommerce-infakt/woocommerce-infakt.php',
		];
		
		foreach ( $nip_plugins as $plugin ) {
			if ( is_plugin_active( $plugin ) ) {
				return true;
			}
		}
		
		return false;
	}

	/**
	 * Save checkout fields to order meta
	 */
	public function save_checkout_fields( $order_id ) {
		$existing_nip = get_post_meta( $order_id, '_billing_nip', true );
		
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called by WooCommerce checkout hook which handles nonce
		if ( empty( $existing_nip ) && ! 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'] ) );
			update_post_meta( $order_id, '_billing_nip', $nip );
		}
		
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called by WooCommerce checkout hook which handles nonce
		if ( isset( $_POST['billing_want_invoice'] ) ) {
			update_post_meta( $order_id, '_billing_want_invoice', '1' );
		} else {
			update_post_meta( $order_id, '_billing_want_invoice', '0' );
		}
	}

	/**
	 * Display NIP in Admin Order
	 */
	public function display_nip_in_admin_order( $order ) {
		$want_invoice = $order->get_meta( '_billing_want_invoice' );
		if ( $want_invoice !== '' ) {
			$status = ( $want_invoice === '1' ) ? __( 'Yes', 'invoicing-integration-for-ifirma-and-woocommerce' ) : __( 'No', 'invoicing-integration-for-ifirma-and-woocommerce' );
			echo '<p><strong>' . esc_html__( 'I want an invoice', 'invoicing-integration-for-ifirma-and-woocommerce' ) . ':</strong> ' . esc_html( $status ) . '</p>';
		}
	}

	/**
	 * Add editable NIP field to admin order billing section (same as address fields)
	 */
	public function add_editable_nip_to_admin_billing( $fields ) {
		if ( isset( $fields['nip'] ) ) {
			return $fields;
		}
		$fields['nip'] = [
			'label' => __( 'NIP', 'invoicing-integration-for-ifirma-and-woocommerce' ),
			'show'  => true,
		];
		return $fields;
	}

	/**
	 * Save NIP when order is updated in admin
	 *
	 * @param int       $order_id Order ID.
	 * @param \WC_Order $order    Order object (optional, for HPOS compatibility).
	 */
	public function save_admin_order_nip( $order_id, $order = null ) {
		// Hook may pass WP_Post in some WooCommerce versions - always use WC_Order
		if ( ! $order instanceof \WC_Order ) {
			$order = wc_get_order( $order_id );
		}
		if ( ! $order instanceof \WC_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 -- Called by WooCommerce save hook which verifies nonce
			$nip = sanitize_text_field( wp_unslash( $_POST['_billing_nip'] ) );
			$order->update_meta_data( '_billing_nip', $nip );
			$order->save();
		}
	}

	/**
	 * Display NIP field in billing address (My Account)
	 */
	public function my_account_my_address_formatted_address( $address, $customer_id, $name ) {
		if ( $name === 'billing' ) {
			$nip = get_user_meta( $customer_id, 'billing_nip', true );
			
			if ( ! empty( $nip ) ) {
				$address['nip'] = $nip;
			}
		}
		
		return $address;
	}

	/**
	 * Add NIP field to billing address form in My Account
	 */
	public function add_nip_to_my_account_billing_fields( $fields ) {
		if ( isset( $fields['billing_nip'] ) ) {
			return $fields;
		}

		if ( ! apply_filters( 'devikit_ifirma_add_nip_field_my_account', true ) ) {
			return $fields;
		}

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

		if ( isset( $fields['billing_company'] ) ) {
			$company_field = $fields['billing_company'];
			$company_priority = isset( $company_field['priority'] ) ? $company_field['priority'] : 30;
			
			$fields['billing_nip'] = [
				'type'        => 'text',
				'label'       => __( 'NIP', 'invoicing-integration-for-ifirma-and-woocommerce' ),
				'placeholder' => __( 'Enter NIP', 'invoicing-integration-for-ifirma-and-woocommerce' ),
				'required'    => $nip_required,
				'class'       => [ 'form-row-wide' ],
				'clear'       => true,
				'priority'    => $company_priority - 1,
			];
		}
		
		return $fields;
	}

	/**
	 * Validate NIP field in My Account address form
	 */
	public function validate_my_account_billing_nip( $user_id, $load_address ) {
		if ( $load_address !== 'billing' ) {
			return;
		}
		
		if ( ! isset( $_POST['woocommerce-edit-address-nonce'] ) || 
			 ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['woocommerce-edit-address-nonce'] ) ), 'woocommerce-edit_address' ) ) {
			return;
		}
		
		if ( $this->is_other_nip_plugin_active() ) {
			return;
		}
		
		$settings = get_option( 'devikit_ifirma_settings', [] );
		$nip_required = isset( $settings['nip_required'] ) && $settings['nip_required'] === 'yes';
		$validate_format = isset( $settings['validate_nip_format'] ) && $settings['validate_nip_format'] === 'yes';
		
		$nip = isset( $_POST['billing_nip'] ) ? sanitize_text_field( wp_unslash( $_POST['billing_nip'] ) ) : '';
		
		if ( $nip_required && empty( $nip ) ) {
			wc_add_notice( __( 'Pole NIP jest wymagane.', 'invoicing-integration-for-ifirma-and-woocommerce' ), 'error' );
			return;
		}
		
		if ( $validate_format && ! empty( $nip ) ) {
			$nip_clean = preg_replace( '/[\s\-]/', '', $nip );
			
			if ( ! preg_match( '/^[0-9]{10}$/', $nip_clean ) ) {
				wc_add_notice( __( 'NIP must contain exactly 10 digits.', 'invoicing-integration-for-ifirma-and-woocommerce' ), 'error' );
			}
		}
	}

	/**
	 * Save NIP field in My Account address form
	 */
	public function save_my_account_billing_nip( $user_id, $load_address ) {
		if ( $load_address !== 'billing' ) {
			return;
		}

		if ( ! isset( $_POST['woocommerce-edit-address-nonce'] ) || 
			 ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['woocommerce-edit-address-nonce'] ) ), 'woocommerce-edit_address' ) ) {
			return;
					}

		$existing_nip = get_user_meta( $user_id, 'billing_nip', true );
		
		if ( isset( $_POST['billing_nip'] ) ) {
			$new_nip = sanitize_text_field( wp_unslash( $_POST['billing_nip'] ) );
			
			if ( empty( $existing_nip ) || $existing_nip !== $new_nip ) {
				update_user_meta( $user_id, 'billing_nip', $new_nip );
			}
		}
	}
}
