<?php
/**
 * Scripts Module — Global code injection (header/footer/checkout).
 *
 * Allows injecting custom code snippets into specific locations.
 * Use for: GTM container, custom analytics, chatbots, popups.
 *
 * @package CapiFlow
 */

namespace CapiFlow\Core\Modules\Scripts;

defined( 'ABSPATH' ) || exit;

class Code_Injector {

    /**
     * Boot the module.
     */
    public static function init() {
        $instance = new self();

        // Inject code at configured locations.
        add_action( 'wp_head', array( $instance, 'inject_header' ), 1 );
        add_action( 'wp_footer', array( $instance, 'inject_footer' ), 99 );
        add_action( 'woocommerce_before_checkout_form', array( $instance, 'inject_checkout_before' ) );
        add_action( 'woocommerce_thankyou', array( $instance, 'inject_thankyou' ), 1 );

        // Save-side guard: sanitize code options when the saving user
        // lacks unfiltered_html (e.g. shop managers on multisite).
        foreach ( array( 'capiflow_header_code', 'capiflow_footer_code', 'capiflow_checkout_code', 'capiflow_thankyou_code' ) as $opt ) {
            add_filter( "pre_update_option_{$opt}", array( __CLASS__, 'sanitize_code_option' ), 10, 2 );
        }
    }

    /**
     * Sanitize code injection option on save.
     *
     * If the current user lacks unfiltered_html, strip dangerous tags.
     * On single-site all admins have this cap; on multisite only Super Admins do.
     *
     * @param mixed $value     New value.
     * @param mixed $old_value Old value.
     * @return string Sanitized value.
     */
    public static function sanitize_code_option( $value, $old_value ) {
        if ( ! current_user_can( 'unfiltered_html' ) ) {
            return wp_kses_post( $value );
        }
        return $value;
    }

    /**
     * Inject header code.
     *
     * Raw output is intentional: stored values contain <script>, <style>,
     * and <noscript> tags (GTM, analytics, chat widgets). These options
     * are saved via the CapiFlow settings page with manage_woocommerce
     * capability. Save-side sanitization (sanitize_code_option) applies
     * wp_kses_post() for users without unfiltered_html capability.
     * This pattern matches WPCode, Insert Headers and Footers, etc.
     */
    public function inject_header() {
        $code = get_option( 'capiflow_header_code', '' );
        if ( empty( $code ) ) {
            return;
        }
        echo "\n<!-- CapiFlow: Header Code -->\n";
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Intentional: admin-stored custom code injection (GTM/analytics scripts). Sanitized on save via sanitize_code_option().
        echo wp_unslash( $code );
        echo "\n<!-- End Header Code -->\n";
    }

    /**
     * Inject footer code.
     *
     * Raw output is intentional: admin-stored custom code injection.
     * Sanitized on save via sanitize_code_option().
     */
    public function inject_footer() {
        $code = get_option( 'capiflow_footer_code', '' );
        if ( empty( $code ) ) {
            return;
        }
        echo "\n<!-- CapiFlow: Footer Code -->\n";
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Intentional: admin-stored custom code injection. Sanitized on save via sanitize_code_option().
        echo wp_unslash( $code );
        echo "\n<!-- End Footer Code -->\n";
    }

    /**
     * Inject code before checkout form.
     *
     * Raw output is intentional: admin-stored custom code injection.
     * Sanitized on save via sanitize_code_option().
     */
    public function inject_checkout_before() {
        $code = get_option( 'capiflow_checkout_code', '' );
        if ( empty( $code ) ) {
            return;
        }
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Intentional: admin-stored custom code injection. Sanitized on save via sanitize_code_option().
        echo wp_unslash( $code );
    }

    /**
     * Inject code on Thank You page.
     *
     * Raw output is intentional: admin-stored custom code injection.
     * Sanitized on save via sanitize_code_option().
     * Placeholders are replaced with WooCommerce order data (sanitized at source).
     *
     * @param int $order_id Order ID.
     */
    public function inject_thankyou( $order_id ) {
        $code = get_option( 'capiflow_thankyou_code', '' );
        if ( empty( $code ) ) {
            return;
        }
        // Replace placeholders with WooCommerce order data (sanitized at source).
        $order = wc_get_order( $order_id );
        if ( $order ) {
            $replacements = array(
                '{{order_id}}'    => $order->get_order_number(),
                '{{order_total}}' => $order->get_total(),
                '{{currency}}'    => $order->get_currency(),
                '{{email}}'       => $order->get_billing_email(),
            );
            $code = str_replace( array_keys( $replacements ), array_values( $replacements ), $code );
        }

        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Intentional: admin-stored custom code injection. See inject_header() docblock.
        echo wp_unslash( $code );
    }
}

// Auto-init when module loads via Plugin_Loader::load_module('scripts').
add_action( 'capiflow_module_loaded_scripts', array( 'CapiFlow\Core\Modules\Scripts\Code_Injector', 'init' ) );
