<?php

namespace UltraguardPro\modules\woo_security;

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

use UltraguardPro\Plugin;
use UltraguardPro\core\Utils;
use UltraguardPro\modules\core\AbstractModule;

class WooSecurityModule extends AbstractModule {

    private const OPT_BOT_ORDERS_BLOCKED = 'ultraguard_woo_security_bot_orders_blocked';

    public function __construct( Plugin $plugin ) {
        parent::__construct( $plugin );
        $this->plugin->settings->register_module_prefix( 'woo_security_', 'woo_security' );
    }

    public function get_id(): string {
        return 'woo_security';
    }

    protected function requires_pro(): bool {
        return true;
    }

    protected function allow_preview_mode(): bool {
        return true;
    }

    public function is_enabled(): bool {
        if ( ! class_exists( 'WooCommerce' ) ) {
            return false;
        }

        return parent::is_enabled();
    }

    public function boot(): void {
        if ( ! class_exists( 'WooCommerce' ) ) {
            return;
        }

        $_db_tables = $this->plugin->modules->get_db_tables();
        if ( $_db_tables ) {
            $_db_tables->register_schema( new schema\WooSecuritySchema() );
        }

        if ( method_exists( $this->plugin->settings, 'register_settings_schema' ) ) {
            $this->plugin->settings->register_settings_schema( 'woo_security', 'woo_security_', [
                'woo_security_enabled'                    => [ 'type' => 'bool', 'default' => true ],
                'woo_security_skimmer_detection'          => [ 'type' => 'bool', 'default' => true ],
                'woo_security_strict_csp'                 => [ 'type' => 'bool', 'default' => true ],
                'woo_security_allowed_script_domains'     => [ 'type' => 'textarea', 'default' => '' ],
                'woo_security_checkout_honeypot'          => [ 'type' => 'bool', 'default' => true ],
                'woo_security_block_honeypot_order'       => [ 'type' => 'bool', 'default' => true ],
                'woo_security_secure_headers'             => [ 'type' => 'bool', 'default' => true ],
                'woo_security_alert_on_skimmer'           => [ 'type' => 'bool', 'default' => true ],
                'woo_security_block_suspicious_orders'    => [ 'type' => 'bool', 'default' => false ],
            ] );
        }

        ( new ajax\WooSecurityAjax( $this->plugin ) )->register();
        add_action( 'ultraguard_register_admin_pages', [ $this, 'register_pages' ], 130, 1 );
        ( new WooSecurityDashboardContributor( $this->plugin ) )->register();
        add_action( 'ultraguard_after_enqueue_assets', [ $this, 'enqueue_assets' ] );

        if ( ! $this->is_preview_mode() ) {
            add_action( 'wp_head', [ $this, 'output_store_headers' ], 1 );
            add_filter( 'woocommerce_checkout_fields', [ $this, 'inject_honeypot_field' ] );
            add_action( 'woocommerce_process_checkout', [ $this, 'validate_honeypot' ] );
            add_action( 'woocommerce_before_checkout_form', [ $this, 'render_checkout_verification' ], 1 );
            add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_checkout_script' ] );
            add_action( 'wp_loaded', [ $this, 'maybe_setup_schedule' ] );
            add_action( 'ultraguard_woo_security_skimmer_scan', [ $this, 'run_daily_skimmer_scan' ] );
            ( new WooSecurityNotifications( $this->plugin ) )->register();
        }

        do_action( 'ultraguard_pro/woo_security/booted', $this );
    }

    public function register_pages( $admin ): void {
        $admin->register_page( [
            'id'              => 'woo-security',
            'page_title'      => __( 'WooCommerce Security Mode', 'ultraguard-security-suite' ),
            'menu_title'      => __( 'Woo Security', 'ultraguard-security-suite' ),
            'capability'      => 'manage_options',
            'scheme_callback' => [ new pages\WooSecurityDashboard( $this->plugin ), 'get_scheme' ],
            'parent_id'       => '',
            'priority'        => 130,
            'group'           => 'Commerce',
            'icon'            => 'dashicons-cart',
        ] );

        $admin->register_page( [
            'id'              => 'woo-security-settings',
            'page_title'      => __( 'WooCommerce Security Settings', 'ultraguard-security-suite' ),
            'menu_title'      => __( 'Settings', 'ultraguard-security-suite' ),
            'capability'      => 'manage_options',
            'scheme_callback' => [ new pages\WooSecuritySettings( $this->plugin ), 'get_scheme' ],
            'parent_id'       => 'woo-security',
            'priority'        => 131,
            'group'           => 'Commerce',
            'icon'            => 'dashicons-admin-settings',
        ] );
    }

    public function maybe_setup_schedule(): void {
        if ( ! $this->option_enabled( 'woo_security_enabled' ) || ! $this->option_enabled( 'woo_security_skimmer_detection' ) ) {
            wp_clear_scheduled_hook( 'ultraguard_woo_security_skimmer_scan' );
            return;
        }

        if ( ! wp_next_scheduled( 'ultraguard_woo_security_skimmer_scan' ) ) {
            wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'ultraguard_woo_security_skimmer_scan' );
        }
    }

    public function run_daily_skimmer_scan(): void {
        if ( ! class_exists( 'WooCommerce' ) || ! $this->option_enabled( 'woo_security_skimmer_detection' ) ) {
            return;
        }

        $results = ( new SkimmerDetectionEngine( $this->plugin ) )->scan_for_skimmers();
        do_action( 'ultraguard_pro/woo_security/skimmer_scan_complete', $results );
    }

    public function output_store_headers(): void {
        if ( ! $this->is_store_sensitive_page() ) {
            return;
        }

        if ( $this->option_enabled( 'woo_security_strict_csp' ) && ! headers_sent() ) {
            header( 'Content-Security-Policy: ' . $this->build_checkout_csp() );
        }

        if ( $this->option_enabled( 'woo_security_secure_headers' ) && ! headers_sent() ) {
            header( 'X-Content-Type-Options: nosniff' );
            header( 'Referrer-Policy: strict-origin-when-cross-origin' );
            header( 'X-Frame-Options: SAMEORIGIN' );
            if ( is_ssl() ) {
                header( 'Strict-Transport-Security: max-age=31536000; includeSubDomains' );
            }
        }
    }

    public function inject_honeypot_field( array $fields ): array {
        if ( ! $this->option_enabled( 'woo_security_checkout_honeypot' ) ) {
            return $fields;
        }

        $fields['billing']['woo_security_honey_field'] = [
            'type'        => 'text',
            'label'       => __( 'Leave this field empty', 'ultraguard-security-suite' ),
            'required'    => false,
            'class'       => [ 'woo-security-honeypot-field' ],
            'input_class' => [ 'woo-security-honeypot-input' ],
            'priority'    => 999,
        ];

        return $fields;
    }

    public function render_checkout_verification(): void {
        if ( ! $this->option_enabled( 'woo_security_checkout_honeypot' ) ) {
            return;
        }

        echo '<input type="hidden" name="woo_security_checkout_token" value="' . esc_attr( wp_create_nonce( 'woo_security_checkout' ) ) . '" />';
        echo '<input type="hidden" name="woo_security_checkout_started" value="' . esc_attr( (string) time() ) . '" />';
    }

    public function validate_honeypot(): void {
        if ( ! $this->option_enabled( 'woo_security_checkout_honeypot' ) ) {
            return;
        }

        $trap    = sanitize_text_field( wp_unslash( $_POST['woo_security_honey_field'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Checkout token verification happens immediately below in this guarded flow.
        $token   = sanitize_text_field( wp_unslash( $_POST['woo_security_checkout_token'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Checkout token verification happens immediately below in this guarded flow.
        $started = absint( wp_unslash( $_POST['woo_security_checkout_started'] ?? 0 ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Timestamp is read in the same guarded checkout verification flow.

        if ( ! wp_verify_nonce( $token, 'woo_security_checkout' ) ) {
            wc_add_notice( __( 'Checkout verification failed. Please refresh and try again.', 'ultraguard-security-suite' ), 'error' );
            return;
        }

        if ( '' !== $trap || ( $started > 0 && ( time() - $started ) < 2 ) ) {
            $this->logSecurityEvent( 'WooHoneypot', 'Checkout honeypot triggered.', [ 'ip' => $this->get_request_ip() ] );
            do_action( 'ultraguard_pro/woo_security/honeypot_triggered', [ 'ip' => $this->get_request_ip() ] );

            if ( $this->option_enabled( 'woo_security_block_suspicious_orders' ) ) {
                do_action( 'ultraguard_pro/firewall/block_ip', $this->get_request_ip(), 'woo_security', 'Checkout honeypot triggered' );
            }

            if ( $this->option_enabled( 'woo_security_block_honeypot_order' ) ) {
                $this->increment_honeypot_block_counter();
                wc_add_notice( __( 'Your order could not be processed. Please contact support.', 'ultraguard-security-suite' ), 'error' );
            }
        }
    }

    public function enqueue_checkout_script(): void {
        if ( ! function_exists( 'is_checkout' ) || ! is_checkout() ) {
            return;
        }

        $module_url = plugin_dir_url( __FILE__ );
        $version    = defined( 'ULTRAGUARD_PRO_VERSION' ) ? ULTRAGUARD_PRO_VERSION : '1.0.0';

        wp_enqueue_script(
            'ultraguard-woo-security-checkout',
            $module_url . 'assets/js/woo-security-page.js',
            [ 'jquery' ],
            $version,
            true
        );
    }

    public function enqueue_assets(): void {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin screen detection.
        $ug_page = sanitize_key( wp_unslash( $_GET['ug_page'] ?? ''  ) );
        if ( ! in_array( $ug_page, [ 'woo-security', 'woo-security-settings' ], true ) ) {
            return;
        }

        $module_url = plugin_dir_url( __FILE__ );
        $version    = defined( 'ULTRAGUARD_PRO_VERSION' ) ? ULTRAGUARD_PRO_VERSION : '1.0.0';

        wp_enqueue_style(
            'ultraguard-woo-security-page',
            $module_url . 'assets/css/woo-security-page.css',
            [ 'admin-base', 'admin-components' ],
            $version
        );

        wp_enqueue_script(
            'ultraguard-woo-security-admin',
            $module_url . 'assets/js/woo-security-page.js',
            [ 'jquery', 'ultraguard-core', 'ultraguard-managers' ],
            $version,
            true
        );

        wp_localize_script( 'ultraguard-woo-security-admin', 'ultraguardWooSecurity', [
            'nonce'   => wp_create_nonce( 'ultraguard_admin_nonce' ),
            'ajaxUrl' => self_admin_url( 'admin-ajax.php' ),
            'i18n'    => [
                'scanning' => __( 'Scanning checkout scripts...', 'ultraguard-security-suite' ),
                'failed'   => __( 'Unable to complete the requested WooCommerce security action.', 'ultraguard-security-suite' ),
            ],
        ] );
    }

    public function build_checkout_csp(): string {
        $domains = preg_split( '/\r\n|\r|\n/', (string) $this->option( 'woo_security_allowed_script_domains', '' ) );
        $domains = array_values( array_filter( array_map( static function ( $domain ) {
            $domain = trim( (string) $domain );
            return '' !== $domain ? $domain : null;
        }, (array) $domains ) ) );

        $script_sources = array_merge( [ "'self'", "'unsafe-inline'" ], $domains );

        return sprintf(
            "default-src 'self'; script-src %s; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https:; frame-ancestors 'self'; form-action 'self'; base-uri 'self';",
            implode( ' ', array_unique( $script_sources ) )
        );
    }

    private function is_store_sensitive_page(): bool {
        if ( ! function_exists( 'is_cart' ) || ! function_exists( 'is_checkout' ) || ! function_exists( 'is_account_page' ) ) {
            return false;
        }

        return is_cart() || is_checkout() || is_account_page();
    }

    private function get_request_ip(): string {
        return Utils::get_client_ip();
    }

    public static function get_bot_orders_blocked_count(): int {
        return max( 0, (int) get_option( self::OPT_BOT_ORDERS_BLOCKED, 0 ) );
    }

    private function increment_honeypot_block_counter(): void {
        update_option( self::OPT_BOT_ORDERS_BLOCKED, self::get_bot_orders_blocked_count() + 1, false );
    }
}
