<?php

/**
 * TrackSharp Settings
 *
 * Handles settings page rendering and registration.
 *
 * @package TrackSharp
 */
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
class TrackSharp_Settings {
    const OPT_GROUP = 'tracksharp_tracker';

    private const PAGE_MAIN = 'tracksharp_tracker_page_main';

    private const PAGE_REPORTING = 'tracksharp_tracker_page_reporting';

    private const PAGE_ADVANCED = 'tracksharp_tracker_page_advanced';

    const CORE_OPTS = ['tracksharp_ga4_measurement_id', 'tracksharp_ga4_api_secret', 'tracksharp_consent_fallback'];

    const PREMIUM_OPTS = ['tracksharp_meta_pixel_id', 'tracksharp_meta_access_token', 'tracksharp_meta_test_event_code'];

    /** @var TrackSharp_GA4 */
    private $ga4;

    /** @var TrackSharp_Meta|null */
    private $meta;

    /** @var TrackSharp_Events_Log */
    private $events_log;

    /**
     * @param TrackSharp_GA4        $ga4        GA4 client.
     * @param TrackSharp_Meta|null  $meta       Meta client (premium build only).
     * @param TrackSharp_Events_Log $events_log Events logger.
     */
    public function __construct( TrackSharp_GA4 $ga4, ?object $meta, TrackSharp_Events_Log $events_log ) {
        $this->ga4 = $ga4;
        $this->meta = $meta;
        $this->events_log = $events_log;
    }

    /**
     * Register settings.
     */
    public function register_settings() {
        foreach ( self::CORE_OPTS as $key ) {
            register_setting( self::OPT_GROUP, $key, [
                'type'              => 'string',
                'sanitize_callback' => 'sanitize_text_field',
            ] );
        }
        register_setting( self::OPT_GROUP, 'tracksharp_ga4_attribution_mode', [
            'type'              => 'string',
            'sanitize_callback' => function ( $value ) {
                $value = sanitize_text_field( $value );
                return ( in_array( $value, ['ads_first', 'reporting_first'], true ) ? $value : 'ads_first' );
            },
            'default'           => 'ads_first',
        ] );
        register_setting( self::OPT_GROUP, 'tracksharp_revenue_excl_tax', [
            'type'              => 'boolean',
            'sanitize_callback' => 'rest_sanitize_boolean',
            'default'           => false,
        ] );
        register_setting( self::OPT_GROUP, 'tracksharp_ga4_use_purchase_sst', [
            'type'              => 'boolean',
            'sanitize_callback' => 'rest_sanitize_boolean',
            'default'           => false,
        ] );
        // Premium-only options (stripped from the free build by Freemius).
        if ( function_exists( 'tracksharp_fs' ) ) {
        }
        add_settings_section(
            'ws_main',
            __( 'Destinations & Consent', 'tracksharp' ),
            function () {
                $allowed_html = [
                    'a' => [
                        'href'   => [],
                        'target' => [],
                        'rel'    => [],
                    ],
                ];
                echo '<p>' . wp_kses( sprintf( 
                    /* translators: %s: link to WP Consent API plugin */
                    __( 'Configure GA4 and Meta CAPI. When no %s compatible Consent Management plugin is found, we apply the configured fallback behavior.', 'tracksharp' ),
                    '<a href="https://wordpress.org/plugins/wp-consent-api">WP Consent API</a>'
                 ), $allowed_html ) . '</p>';
            },
            self::PAGE_MAIN
        );
        // Advanced/debug settings are rendered in a separate (collapsed) card.
        add_settings_section(
            'ws_advanced',
            '',
            '__return_false',
            self::PAGE_ADVANCED
        );
        $this->add_text_field( 'tracksharp_ga4_measurement_id', __( 'GA4 Measurement ID', 'tracksharp' ), [
            'placeholder' => 'G-XXXXXXX',
            'help'        => __( 'Your GA4 stream ID (starts with "G-").', 'tracksharp' ),
            'doc'         => 'https://support.google.com/analytics/answer/12270356?hl=en',
            'howto'       => __( 'Google Analytics -> Admin -> Data Streams -> select your web stream -> copy the "Measurement ID".', 'tracksharp' ),
        ] );
        $this->add_text_field( 'tracksharp_ga4_api_secret', __( 'GA4 API Secret', 'tracksharp' ), [
            'help'  => __( 'Secret for Measurement Protocol (server-to-server).', 'tracksharp' ),
            'doc'   => 'https://developers.google.com/analytics/devguides/collection/protocol/ga4',
            'howto' => __( 'Google Analytics -> Admin -> Data Streams -> select your web stream -> "Measurement Protocol API secrets" -> Create -> Copy the secret.', 'tracksharp' ),
        ] );
        add_settings_field(
            'tracksharp_ga4_attribution_mode',
            __( 'GA4 Purchase Mode', 'tracksharp' ),
            [$this, 'field_select'],
            self::PAGE_ADVANCED,
            'ws_advanced',
            [
                'key'     => 'tracksharp_ga4_attribution_mode',
                'default' => 'ads_first',
                'choices' => [
                    'ads_first'       => __( 'Server-side only (default)', 'tracksharp' ),
                    'reporting_first' => __( 'Browser-first + server fallback (requires Google tag)', 'tracksharp' ),
                ],
                'help'    => __( 'Server-side only sends the GA4 purchase via Measurement Protocol from your server. Browser-first + server fallback sends a browser-side purchase for better GA4 session attribution (Source/Medium) and only sends the server purchase as a fallback when the browser could not send. This mode requires a working Google tag that fires page_view/session_start (and consent for analytics). If you import GA4 conversions into Google Ads, make sure auto-tagging is enabled in Google Ads.', 'tracksharp' ),
            ]
        );
        add_settings_field(
            'tracksharp_ga4_use_purchase_sst',
            __( 'GA4 Comparison Mode', 'tracksharp' ),
            [$this, 'field_checkbox'],
            self::PAGE_ADVANCED,
            'ws_advanced',
            [
                'key'   => 'tracksharp_ga4_use_purchase_sst',
                'label' => __( 'Send server purchases as purchase_sst (advanced)', 'tracksharp' ),
                'help'  => __( 'When enabled, TrackSharp will send server-side purchases to GA4 as "purchase_sst" instead of "purchase" so you can compare against an existing GTM/gtag purchase event. TrackSharp will also suppress its own browser-side purchase while this mode is enabled to reduce the risk of double counting. Note: "purchase_sst" is a custom event and won\'t show in standard GA4 ecommerce reports.', 'tracksharp' ),
            ]
        );
        // Meta fields: real inputs exist only in the premium build; free build shows a non-interactive preview.
        if ( !TrackSharp_Features::is_meta_available() ) {
            add_settings_field(
                'tracksharp_meta_pro_preview',
                __( 'Meta (Conversions API)', 'tracksharp' ) . ' ' . TrackSharp_Features::render_pro_badge(),
                [$this, 'field_meta_pro_preview'],
                self::PAGE_MAIN,
                'ws_main'
            );
        }
        if ( function_exists( 'tracksharp_fs' ) ) {
        }
        add_settings_field(
            'tracksharp_consent_fallback',
            __( 'Consent Fallback (no CMP found)', 'tracksharp' ),
            [$this, 'field_select'],
            self::PAGE_MAIN,
            'ws_main',
            [
                'key'     => 'tracksharp_consent_fallback',
                'choices' => [
                    'deny'              => __( 'Deny: only load tracking after a CMP grants consent', 'tracksharp' ),
                    'grant_immediately' => __( 'Grant immediately (default): treat consent as granted when no CMP/WP Consent API is available.', 'tracksharp' ),
                ],
            ]
        );
        add_settings_section(
            'ws_reporting',
            '',
            '__return_false',
            self::PAGE_REPORTING
        );
        add_settings_field(
            'tracksharp_revenue_excl_tax',
            __( 'Revenue (VAT)', 'tracksharp' ),
            [$this, 'field_checkbox'],
            self::PAGE_REPORTING,
            'ws_reporting',
            [
                'key'   => 'tracksharp_revenue_excl_tax',
                'label' => __( 'Track revenue excluding VAT (excl. tax)', 'tracksharp' ),
                'help'  => __( 'When enabled, TrackSharp will send and display revenue values excluding VAT/tax. Shipping is still included (excluding shipping tax).', 'tracksharp' ),
            ]
        );
        register_setting( self::OPT_GROUP, 'tracksharp_log_retention_days', [
            'type'              => 'integer',
            'sanitize_callback' => function ( $value ) {
                $value = (int) $value;
                if ( $value < 7 ) {
                    $value = 7;
                }
                if ( $value > 3650 ) {
                    $value = 3650;
                }
                return $value;
            },
            'default'           => 180,
        ] );
        add_settings_field(
            'tracksharp_log_retention_days',
            __( 'Log Retention (days)', 'tracksharp' ),
            function () {
                $val = (int) get_option( 'tracksharp_log_retention_days', 180 );
                $table = $this->events_log->table_name();
                echo '<input type="number" name="tracksharp_log_retention_days" min="7" max="3650" step="1" value="' . esc_attr( $val ) . '" class="small-text" />';
                echo '<p class="description">' . sprintf( 
                    /* translators: %s: database table name */
                    esc_html__( 'Older rows in %s are automatically deleted. Default 180 days.', 'tracksharp' ),
                    '<code>' . esc_html( $table ) . '</code>'
                 ) . '</p>';
            },
            self::PAGE_REPORTING,
            'ws_reporting'
        );
    }

    private function add_text_field( string $key, string $label, array $args ) {
        $args['key'] = $key;
        add_settings_field(
            $key,
            $label,
            [$this, 'field_text'],
            self::PAGE_MAIN,
            'ws_main',
            $args
        );
    }

    public function field_text( array $args ) {
        $key = esc_attr( $args['key'] );
        $val = esc_attr( get_option( $key, '' ) );
        $ph = ( isset( $args['placeholder'] ) ? esc_attr( $args['placeholder'] ) : '' );
        $help = ( isset( $args['help'] ) ? wp_kses_post( $args['help'] ) : '' );
        $doc = ( isset( $args['doc'] ) ? esc_url( $args['doc'] ) : '' );
        echo '<div class="ws-field">';
        echo '<input type="text" name="' . esc_attr( $key ) . '" value="' . esc_attr( $val ) . '" placeholder="' . esc_attr( $ph ) . '" class="regular-text" />';
        if ( $help ) {
            echo '<span class="ws-help" aria-label="' . esc_attr__( 'Help', 'tracksharp' ) . '"><span class="dashicons dashicons-editor-help"></span><span class="ws-tip">' . wp_kses_post( $help ) . (( $doc ? '<br><br><a href="' . esc_url( $doc ) . '" target="_blank" rel="noreferrer">' . esc_html__( 'Open documentation ->', 'tracksharp' ) . '</a>' : '' )) . '</span></span>';
        }
        echo '</div>';
        if ( !empty( $args['howto'] ) ) {
            $id = 'ws-howto-' . esc_attr( $key );
            echo '<a href="#" class="ws-more" data-ws-toggle="' . esc_attr( $id ) . '">' . esc_html__( 'How to find this', 'tracksharp' ) . '</a>';
            echo '<div id="' . esc_attr( $id ) . '" class="ws-hint ws-hidden">' . wp_kses_post( $args['howto'] ) . '</div>';
        }
    }

    public function field_meta_pro_preview() {
        $upgrade_url = TrackSharp_Features::get_upgrade_url();
        echo '<div style="background:#f6f7f7;border:1px solid #dcdcde;border-radius:8px;padding:14px;">';
        echo '<p style="margin:0 0 10px;">' . esc_html__( 'Meta Conversions API settings are available in TrackSharp Pro.', 'tracksharp' ) . '</p>';
        echo '<a class="button button-secondary" href="' . esc_url( $upgrade_url ) . '">' . esc_html__( 'View Pro Plans', 'tracksharp' ) . '</a>';
        echo '</div>';
    }

    public function field_select( array $args ) {
        $key = esc_attr( $args['key'] );
        $default = ( isset( $args['default'] ) ? (string) $args['default'] : 'grant_immediately' );
        $val = esc_attr( get_option( $key, $default ) );
        $choices = $args['choices'] ?? [];
        echo '<select name="' . esc_attr( $key ) . '">';
        foreach ( $choices as $k => $label ) {
            $selected_attr = selected( $val, $k, false );
            echo '<option value="' . esc_attr( $k ) . '"' . esc_attr( $selected_attr ) . '>' . esc_html( $label ) . '</option>';
        }
        echo '</select>';
        if ( !empty( $args['help'] ) ) {
            echo '<p class="description">' . esc_html( $args['help'] ) . '</p>';
        }
    }

    public function field_checkbox( array $args ) {
        $key = esc_attr( $args['key'] );
        $label = ( isset( $args['label'] ) ? (string) $args['label'] : '' );
        $help = ( isset( $args['help'] ) ? (string) $args['help'] : '' );
        $val = (bool) get_option( $key, false );
        echo '<label style="display:inline-flex;gap:8px;align-items:center;">';
        echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="0" />';
        echo '<input type="checkbox" name="' . esc_attr( $key ) . '" value="1" ' . checked( $val, true, false ) . ' />';
        echo '<span>' . esc_html( $label ) . '</span>';
        echo '</label>';
        if ( $help !== '' ) {
            echo '<p class="description">' . esc_html( $help ) . '</p>';
        }
    }

    /**
     * Render settings page.
     */
    public function render() {
        $test_results = null;
        if ( !empty( $_POST['ws_test_console'] ) && check_admin_referer( 'ws_test_console' ) ) {
            if ( !current_user_can( 'manage_options' ) ) {
                $test_results = [
                    'error' => 'Insufficient permissions.',
                ];
            } else {
                $test_results = $this->run_tests();
            }
        }
        ?>
        <div class="wrap tracksharp-admin tracksharp-admin--wide">
            <?php 
        if ( !function_exists( 'wp_has_consent' ) ) {
            ?>
                <?php 
            $fallback = (string) get_option( 'tracksharp_consent_fallback', 'grant_immediately' );
            $fallback_is_deny = $fallback === 'deny';
            $notice_class = ( $fallback_is_deny ? 'notice notice-error is-dismissible' : 'notice notice-warning is-dismissible' );
            $message = ( $fallback_is_deny ? esc_html__( 'The WP Consent API plugin is not active. Your current fallback is set to deny, so TrackSharp will not send events until consent can be determined. Install a CMP that supports WP Consent API or change the fallback below if you understand the implications.', 'tracksharp' ) : esc_html__( 'The WP Consent API plugin is not active. TrackSharp will use your configured fallback to decide whether events can be sent. For stricter compliance, install a CMP that supports WP Consent API or change the fallback below.', 'tracksharp' ) );
            ?>
                <div class="<?php 
            echo esc_attr( $notice_class );
            ?>" style="margin-top:12px">
                    <p><strong><?php 
            esc_html_e( 'TrackSharp:', 'tracksharp' );
            ?></strong> <?php 
            echo esc_html( $message );
            ?></p>
                </div>
            <?php 
        }
        ?>

            <form method="post" action="options.php">
                <?php 
        settings_fields( self::OPT_GROUP );
        ?>

                <div class="ws-card">
                    <h1>TrackSharp Tracker</h1>
                    <?php 
        do_settings_sections( self::PAGE_MAIN );
        ?>
                </div>

                <div class="ws-card">
                    <h2><?php 
        esc_html_e( 'Reporting & Revenue', 'tracksharp' );
        ?></h2>
                    <p><?php 
        esc_html_e( 'Control how TrackSharp calculates revenue values and how long event logs are stored.', 'tracksharp' );
        ?></p>
                    <table class="form-table" role="presentation">
                        <?php 
        do_settings_fields( self::PAGE_REPORTING, 'ws_reporting' );
        ?>
                    </table>
                </div>

                <div class="ws-card">
                    <details>
                        <summary><strong><?php 
        esc_html_e( 'Advanced (Optional)', 'tracksharp' );
        ?></strong></summary>
                        <p style="margin-top:12px">
                            <?php 
        esc_html_e( 'Use these settings only for debugging or comparisons. Most stores should leave them disabled.', 'tracksharp' );
        ?>
                        </p>
                        <p style="margin-top:8px">
                            <?php 
        esc_html_e( 'If you enable purchase_sst comparison mode, server purchases will no longer be sent as the standard GA4 "purchase" event. This can affect standard ecommerce reporting. If you import GA4 conversions into Google Ads, make sure you import "purchase_sst" (not "purchase") while this mode is enabled.', 'tracksharp' );
        ?>
                        </p>
                        <table class="form-table" role="presentation">
                            <?php 
        do_settings_fields( self::PAGE_ADVANCED, 'ws_advanced' );
        ?>
                        </table>
                    </details>
                </div>

                <?php 
        submit_button();
        ?>
            </form>

            <div class="ws-card">
                <h2><?php 
        esc_html_e( 'Test Console', 'tracksharp' );
        ?></h2>
                <p><?php 
        esc_html_e( 'Send sample events to test your credentials and network connection.', 'tracksharp' );
        ?></p>
                <?php 
        if ( !TrackSharp_Features::is_meta_available() ) {
            ?>
                    <p><?php 
            esc_html_e( 'Meta test events are available in TrackSharp Pro.', 'tracksharp' );
            ?></p>
                <?php 
        }
        ?>
                <form method="post">
                    <?php 
        wp_nonce_field( 'ws_test_console' );
        ?>
                    <input type="hidden" name="ws_test_console" value="1">
                    <?php 
        $label = ( TrackSharp_Features::is_meta_available() ? __( 'Run Test (GA4 + Meta)', 'tracksharp' ) : __( 'Run Test (GA4)', 'tracksharp' ) );
        submit_button(
            $label,
            'secondary',
            'submit',
            false
        );
        ?>
                </form>

                <?php 
        if ( $test_results !== null ) {
            ?>
                    <h3><?php 
            esc_html_e( 'Results', 'tracksharp' );
            ?></h3>
                    <div class="ws-test-pills">
                        <?php 
            echo wp_kses_post( $this->render_test_badge( 'GA4', $test_results['ga4'] ?? null ) );
            ?>
                        <?php 
            if ( TrackSharp_Features::is_meta_available() ) {
                ?>
                            <?php 
                echo wp_kses_post( $this->render_test_badge( 'Meta', $test_results['meta'] ?? null ) );
                ?>
                        <?php 
            }
            ?>
                    </div>
                <?php 
        }
        ?>
            </div>
        </div>
        <?php 
    }

    /**
     * Run test events.
     *
     * @return array Test results.
     */
    private function run_tests() : array {
        $items = [[
            'item_id'   => '123',
            'item_name' => 'Test Product',
            'price'     => 19.99,
            'quantity'  => 1,
        ]];
        $currency = ( function_exists( 'get_woocommerce_currency' ) ? get_woocommerce_currency() : 'EUR' );
        $value = 19.99;
        $ga4 = $this->ga4->send( [
            'client_id' => time() . '.' . wp_rand( 100000, 999999 ),
            'events'    => [[
                'name'   => 'purchase',
                'params' => [
                    'transaction_id' => 'ws_test_' . time(),
                    'currency'       => $currency,
                    'value'          => $value,
                    'items'          => $items,
                    'event_id'       => 'ws_test_' . wp_generate_uuid4(),
                ],
            ]],
        ] );
        $meta = null;
        if ( $this->meta && method_exists( $this->meta, 'send' ) ) {
            $meta = $this->meta->send( [
                'event_name'       => 'InitiateCheckout',
                'event_id'         => 'ws_test_' . wp_generate_uuid4(),
                'event_time'       => time(),
                'action_source'    => 'website',
                'event_source_url' => admin_url( 'admin.php?page=tracksharp-settings' ),
                'user_data'        => array_filter( [
                    'client_user_agent' => ( isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '' ),
                    'client_ip_address' => $this->get_client_ip(),
                ] ),
                'custom_data'      => [
                    'currency'     => $currency,
                    'value'        => $value,
                    'contents'     => array_map( function ( $i ) {
                        return [
                            'id'         => sanitize_text_field( $i['item_id'] ),
                            'quantity'   => (int) $i['quantity'],
                            'item_price' => (float) $i['price'],
                        ];
                    }, $items ),
                    'content_type' => 'product',
                ],
            ] );
        }
        return [
            'ga4'  => $ga4,
            'meta' => $meta,
        ];
    }

    private function render_test_badge( string $label, ?array $result ) : string {
        [$ok, $message] = $this->summarize_test_result( $result );
        $class = ( $ok ? 'ws-ok' : 'ws-fail' );
        $icon = ( $ok ? 'dashicons-yes-alt' : 'dashicons-no-alt' );
        $details = '';
        if ( $result ) {
            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- Used for debug output in admin settings
            $details = '<details><summary>Details</summary><pre>' . esc_html( print_r( $result, true ) ) . '</pre></details>';
        }
        return '<div class="ws-test-pill ' . esc_attr( $class ) . '"><span class="dashicons ' . esc_attr( $icon ) . '"></span><div><strong>' . esc_html( $label ) . '</strong><br>' . esc_html( $message ) . '</div>' . $details . '</div>';
    }

    private function summarize_test_result( ?array $result ) : array {
        if ( !$result || !is_array( $result ) ) {
            return [false, 'No response received.'];
        }
        if ( !empty( $result['ok'] ) ) {
            $status = ( isset( $result['status'] ) ? 'HTTP ' . intval( $result['status'] ) : 'HTTP 200' );
            return [true, 'Success (' . $status . ')'];
        }
        foreach ( ['reason', 'error', 'body'] as $key ) {
            if ( !empty( $result[$key] ) && is_scalar( $result[$key] ) ) {
                $message = (string) $result[$key];
                if ( $key === 'body' ) {
                    $message = wp_strip_all_tags( $message );
                    $message = wp_trim_words( $message, 25, '…' );
                }
                return [false, $message];
            }
        }
        return [false, 'Unknown error'];
    }

    private function get_client_ip() : string {
        foreach ( [
            'HTTP_CF_CONNECTING_IP',
            'HTTP_X_FORWARDED_FOR',
            'HTTP_CLIENT_IP',
            'REMOTE_ADDR'
        ] as $k ) {
            if ( !empty( $_SERVER[$k] ) ) {
                $iplist = explode( ',', sanitize_text_field( wp_unslash( $_SERVER[$k] ) ) );
                return trim( $iplist[0] );
            }
        }
        return '';
    }

}
