<?php

namespace Devikit\Infakt\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' ] );
        add_filter( 'woocommerce_email_order_meta_fields', [ $this, 'add_nip_to_emails' ], 10, 3 );
        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-infakt-checkout', DEVIKIT_INFAKT_URL . 'assets/js/checkout.js', [ 'jquery' ], DEVIKIT_INFAKT_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_infakt_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', '.infakt-nip-hidden-initially { display: none !important; }' );
        }
    }

    /**
     * Add NIP to formatted address (HTML)
     */
    public function add_nip_to_formatted_address( $address, $raw_address, $order ) {
        $nip = $order->get_meta( '_billing_nip' ) ?: $order->get_meta( 'vat_number' );
        
        // Check if NIP is already in the address to prevent duplication
        if ( ! empty( $nip ) && strpos( $address, 'NIP: ' . $nip ) === false ) {
            // Try to insert before company
            if ( ! empty( $raw_address['company'] ) ) {
                $address = str_replace( 
                    $raw_address['company'], 
                    __( 'VAT Number', 'invoicing-integration-for-infakt-and-woocommerce' ) . ': ' . esc_html( $nip ) . '<br>' . $raw_address['company'], 
                    $address 
                );
            } else {
                // Prepend to beginning of address
                $address = __( 'VAT Number', 'invoicing-integration-for-infakt-and-woocommerce' ) . ': ' . esc_html( $nip ) . '<br>' . $address;
            }
        }
        return $address;
    }

    /**
     * Add NIP field if not exists
     */
    public function add_nip_field( $fields ) {
        $settings = get_option( 'devikit_infakt_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-infakt-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;
            }
        }

        // Common keys used by different plugins:
        // - billing_company_nip: other inFakt plugins
        // - billing_nip: most other plugins
        // - billing_tax_number, billing_vat, vat_number: other variations
        $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'       => __( 'VAT Number', 'invoicing-integration-for-infakt-and-woocommerce' ),
            'placeholder' => __( 'Enter NIP', 'invoicing-integration-for-infakt-and-woocommerce' ),
            'required'    => $nip_required,
            'class'       => [ 'form-row-wide', 'infakt-nip-field' ], // Added class for JS
            'clear'       => true,
            'priority'    => 25, // Before Company (30)
        ];
        
        // Add class to hide NIP field initially if checkbox mode is enabled
        if ( $nip_display_mode === 'checkbox' ) {
            $nip_field_config['class'][] = 'infakt-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 {
            // Fallback
            $fields['billing']['billing_nip'] = $nip_field_config;
        }

        return $fields;
    }

    /**
     * Validate NIP field during checkout
     *
     * @param array $data Posted data
     * @param \WP_Error $errors WP_Error object
     */
    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_infakt_settings', [] );
        
        // Check if NIP field is required
        $nip_required = isset( $settings['nip_required'] ) && $settings['nip_required'] === 'yes';
        $validate_format = isset( $settings['validate_nip_format'] ) && $settings['validate_nip_format'] === 'yes';
        
        // Get NIP value from POST
        $nip = isset( $_POST['billing_nip'] ) ? sanitize_text_field( wp_unslash( $_POST['billing_nip'] ) ) : '';
        
        // If field is required and empty
        if ( $nip_required && empty( $nip ) ) {
            $errors->add( 'billing_nip_required', __( 'Pole NIP jest wymagane.', 'invoicing-integration-for-infakt-and-woocommerce' ) );
            return;
        }
        
        // If format validation is enabled and NIP is not empty
        if ( $validate_format && ! empty( $nip ) ) {
            // Remove only spaces and dashes (allowed separators)
            $nip_clean = preg_replace( '/[\s\-]/', '', $nip );
            
            // Check if contains ONLY digits and has exactly 10
            if ( ! preg_match( '/^[0-9]{10}$/', $nip_clean ) ) {
                $errors->add( 'billing_nip_invalid', __( 'VAT number must contain exactly 10 digits.', 'invoicing-integration-for-infakt-and-woocommerce' ) );
            }
        }
    }
    
    /**
     * Check if another NIP plugin is active
     *
     * @return bool
     */
    private function is_other_nip_plugin_active() {
        // Include plugin.php if not already loaded
        if ( ! function_exists( 'is_plugin_active' ) ) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        
        // Check for common NIP plugins
        $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',
            'flexible-invoices-for-woocommerce-infakt/flexible-invoices-for-woocommerce-infakt.php',
        ];
        
        foreach ( $nip_plugins as $plugin ) {
            if ( is_plugin_active( $plugin ) ) {
                return true;
            }
        }
        
        // Also check if NIP field was added by another plugin
        // by checking if woocommerce_checkout_fields hook has callbacks from other plugins
        global $wp_filter;
        if ( isset( $wp_filter['woocommerce_checkout_fields'] ) ) {
            foreach ( $wp_filter['woocommerce_checkout_fields']->callbacks as $priority => $callbacks ) {
                if ( $priority < 20 ) { // Our priority is 20, check lower priorities (those run first)
                    foreach ( $callbacks as $callback ) {
                        // Check if callback is from another plugin (not our class)
                        if ( isset( $callback['function'] ) && is_array( $callback['function'] ) ) {
                            $class = is_object( $callback['function'][0] ) ? get_class( $callback['function'][0] ) : $callback['function'][0];
                            // Check if it's not our class and contains NIP/VAT/invoice related keywords
                            if ( strpos( $class, 'Devikit\Infakt' ) === false && 
                                 ( stripos( $class, 'nip' ) !== false || 
                                   stripos( $class, 'vat' ) !== false ||
                                   stripos( $class, 'invoice' ) !== false ||
                                   stripos( $class, 'tax' ) !== false ) ) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
        
        return false;
    }

    /**
     * Save checkout fields to order meta
     *
     * @param int $order_id Order ID
     */
    public function save_checkout_fields( $order_id ) {
        // Check if NIP was already saved by another plugin
        $existing_nip = get_post_meta( $order_id, '_billing_nip', true );
        
        // Save NIP field only if not already saved
        if ( empty( $existing_nip ) && ! empty( $_POST['billing_nip'] ) ) {
            $nip = sanitize_text_field( wp_unslash( $_POST['billing_nip'] ) );
            update_post_meta( $order_id, '_billing_nip', $nip );
        }
        
        // Save "want invoice" checkbox state
        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 admin order extras (e.g. "I want an invoice").
     * NIP is shown only in the editable billing form via woocommerce_admin_billing_fields.
     */
    public function display_nip_in_admin_order( $order ) {
        // Display "Want Invoice" checkbox status (if checkbox mode was used)
        $want_invoice = $order->get_meta( '_billing_want_invoice' );
        if ( $want_invoice !== '' ) {
            $status = ( $want_invoice === '1' ) ? __( 'Yes', 'invoicing-integration-for-infakt-and-woocommerce' ) : __( 'No', 'invoicing-integration-for-infakt-and-woocommerce' );
            echo '<p><strong>' . esc_html__( 'I want an invoice', 'invoicing-integration-for-infakt-and-woocommerce' ) . ':</strong> ' . esc_html( $status ) . '</p>';
        }
    }

    /**
     * Add NIP to emails
     */
    public function add_nip_to_emails( $keys, $sent_to_admin, $order ) {
        $keys['NIP'] = [
            'label' => __( 'VAT Number', 'invoicing-integration-for-infakt-and-woocommerce' ),
            'value' => $order->get_meta( '_billing_nip' ) ?: $order->get_meta( 'vat_number' ),
        ];
        return $keys;
    }

    /**
     * Display NIP field in billing address (My Account)
     *
     * @param array $address Address fields
     * @param int $customer_id Customer ID
     * @param string $name Address name (billing/shipping)
     * @return array Modified address fields
     */
    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
     *
     * @param array $fields Billing fields
     * @return array Modified billing fields
     */
    public function add_nip_to_my_account_billing_fields( $fields ) {
        // Check if billing_nip field already exists (added by another plugin)
        if ( isset( $fields['billing_nip'] ) ) {
            return $fields;
        }

        // Allow other plugins to disable our NIP field
        if ( ! apply_filters( 'devikit_infakt_add_nip_field_my_account', true ) ) {
            return $fields;
        }

        // Get settings
        $settings = get_option( 'devikit_infakt_settings', [] );
        $nip_required = isset( $settings['nip_required'] ) && $settings['nip_required'] === 'yes';

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

    /**
     * Validate NIP field in My Account address form
     *
     * @param int $user_id User ID
     * @param string $load_address Address type (billing/shipping)
     */
    public function validate_my_account_billing_nip( $user_id, $load_address ) {
        // Check only billing address
        if ( $load_address !== 'billing' ) {
            return;
        }
        
        // Verify nonce
        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 another NIP plugin is active, let it handle validation
        if ( $this->is_other_nip_plugin_active() ) {
            return;
        }
        
        // Get settings
        $settings = get_option( 'devikit_infakt_settings', [] );
        $nip_required = isset( $settings['nip_required'] ) && $settings['nip_required'] === 'yes';
        $validate_format = isset( $settings['validate_nip_format'] ) && $settings['validate_nip_format'] === 'yes';
        
        // Get NIP field value
        $nip = isset( $_POST['billing_nip'] ) ? sanitize_text_field( wp_unslash( $_POST['billing_nip'] ) ) : '';
        
        // If field is required and empty
        if ( $nip_required && empty( $nip ) ) {
            wc_add_notice( __( 'Pole NIP jest wymagane.', 'invoicing-integration-for-infakt-and-woocommerce' ), 'error' );
            return;
        }
        
        // If format validation is enabled and NIP is not empty
        if ( $validate_format && ! empty( $nip ) ) {
            // Remove only spaces and dashes (allowed separators)
            $nip_clean = preg_replace( '/[\s\-]/', '', $nip );
            
            // Check if contains ONLY digits and has exactly 10
            if ( ! preg_match( '/^[0-9]{10}$/', $nip_clean ) ) {
                wc_add_notice( __( 'VAT number must contain exactly 10 digits.', 'invoicing-integration-for-infakt-and-woocommerce' ), 'error' );
            }
        }
    }

    /**
     * Save NIP field in My Account address form
     *
     * @param int $user_id User ID
     * @param string $load_address Address type (billing/shipping)
     */
    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;
        }

        // Check if NIP was already saved by another plugin
        // We use priority 10, other plugins might use priority 5 or 15
        $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'] ) );
            
            // Only save if empty or different value
            if ( empty( $existing_nip ) || $existing_nip !== $new_nip ) {
                update_user_meta( $user_id, 'billing_nip', $new_nip );
            }
        }
    }
}

