<?php
/**
 * Admin Settings — Main settings page, tabs, AJAX handlers.
 *
 * Tabs: General, Pixel Config, Events, License, Debug Console, System Health.
 *
 * @package CapiFlow
 */

namespace CapiFlow\Core;

defined( 'ABSPATH' ) || exit;

class Admin_Settings {

    /**
     * Register hooks.
     */
    public function register_hooks(): void {
        add_action( 'admin_menu', array( $this, 'add_menu_page' ) );
        add_action( 'admin_init', array( $this, 'register_settings' ) );
        add_action( 'admin_init', array( $this, 'maybe_redirect_to_wizard' ) );
        add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );

        // Clear Dataset Quality failure flags when access token is updated.
        // Safety net for when Pro is deactivated while 403 flag is set.
        add_action( 'update_option_capiflow_access_token', function () {
            delete_option( 'capiflow_dataset_quality_403' );
            delete_option( 'capiflow_dataset_quality_failed_at' );
        } );

        // Fix: hidden pages (null parent) don't get $title set by WordPress.
        // This causes strip_tags(null) in admin-header.php on PHP 8.1+.
        add_action( 'load-admin_page_capiflow-setup', function () {
            global $title;
            if ( empty( $title ) ) {
                $title = __( 'CapiFlow Setup', 'capiflow' );
            }
        } );

        // AJAX handlers — all with capiflow_ prefix and nonce + capability checks.
        add_action( 'wp_ajax_capiflow_test_connection', array( $this, 'ajax_test_connection' ) );
        add_action( 'wp_ajax_capiflow_send_purchase', array( $this, 'ajax_send_purchase' ) );
        add_action( 'wp_ajax_capiflow_get_queue_data', array( $this, 'ajax_get_queue_data' ) );
        add_action( 'wp_ajax_capiflow_get_log_data', array( $this, 'ajax_get_log_data' ) );

        // Widget CTA dismiss — saves user_meta per-user.
        add_action( 'wp_ajax_capiflow_dismiss_widget_cta', array( $this, 'ajax_dismiss_widget_cta' ) );

        // Dashboard AJAX handlers (GAP 10).
        add_action( 'wp_ajax_capiflow_get_kpi_data',    array( $this, 'ajax_get_kpi_data' ) );
        add_action( 'wp_ajax_capiflow_get_funnel_data', array( $this, 'ajax_get_funnel_data' ) );
        add_action( 'wp_ajax_capiflow_get_table_data',  array( $this, 'ajax_get_table_data' ) );
        add_action( 'wp_ajax_capiflow_get_live_events', array( $this, 'ajax_get_live_events' ) );
    }

    /**
     * Add admin menu page.
     */
    public function add_menu_page(): void {
        // Main menu: Dashboard.
        add_menu_page(
            __( 'CapiFlow', 'capiflow' ),
            __( 'CapiFlow', 'capiflow' ),
            'manage_woocommerce',
            'capiflow-dashboard',
            array( $this, 'render_dashboard_page' ),
            'dashicons-chart-area',
            58
        );

        // Submenu: Dashboard (rename to avoid duplication).
        add_submenu_page(
            'capiflow-dashboard',
            __( 'Dashboard', 'capiflow' ),
            '📊 ' . __( 'Dashboard', 'capiflow' ),
            'manage_woocommerce',
            'capiflow-dashboard',
            array( $this, 'render_dashboard_page' )
        );

        // Submenu: Settings.
        add_submenu_page(
            'capiflow-dashboard',
            __( 'CapiFlow Settings', 'capiflow' ),
            '⚙️ ' . __( 'Settings', 'capiflow' ),
            'manage_woocommerce',
            'capiflow-settings',
            array( $this, 'render_settings_page' )
        );

        // Submenu: Setup Wizard (hidden — only linked from activation redirect).
        add_submenu_page(
            null,
            __( 'CapiFlow Setup', 'capiflow' ),
            __( 'Setup', 'capiflow' ),
            'manage_woocommerce',
            'capiflow-setup',
            array( $this, 'render_wizard_page' )
        );
    }

    /**
     * Register settings.
     */
    public function register_settings(): void {
        // General.
        register_setting( 'capiflow_general', 'capiflow_pixel_id', array( 'sanitize_callback' => 'sanitize_text_field' ) );
        register_setting( 'capiflow_general', 'capiflow_access_token', array( 'sanitize_callback' => array( $this, 'encrypt_token' ) ) );
        register_setting( 'capiflow_general', 'capiflow_graph_api_version', array( 'sanitize_callback' => 'sanitize_text_field' ) );
        register_setting( 'capiflow_general', 'capiflow_test_event_code', array( 'sanitize_callback' => 'sanitize_text_field' ) );
        register_setting( 'capiflow_general', 'capiflow_environment_mode', array( 'sanitize_callback' => 'sanitize_text_field' ) );
        register_setting( 'capiflow_general', 'capiflow_debug_mode', array( 'sanitize_callback' => array( $this, 'sanitize_bool' ) ) );
        register_setting( 'capiflow_general', 'capiflow_keep_data_on_uninstall', array( 'sanitize_callback' => array( $this, 'sanitize_bool' ) ) );

        // Consent enforcement (Finding #3 — Option A: default OFF, events fire normally).
        register_setting( 'capiflow_general', 'capiflow_consent_enforcement', array( 'sanitize_callback' => array( $this, 'sanitize_bool' ) ) );

        // Events (Core only — no negative events, those are Pro).
        $events = array( 'pageview', 'viewcontent', 'search', 'addtocart', 'initiatecheckout', 'addpaymentinfo', 'purchase' );
        foreach ( $events as $event ) {
            register_setting( 'capiflow_events', 'capiflow_send_' . $event, array( 'sanitize_callback' => array( $this, 'sanitize_bool' ) ) );
        }

        // Purchase trigger is now hardcoded (dual-hook: processing + wc-confirmed).
        // Legacy option 'capiflow_purchase_trigger' is no longer used.

        // Performance.
        register_setting( 'capiflow_general', 'capiflow_queue_interval', array( 'sanitize_callback' => 'absint' ) );
        register_setting( 'capiflow_general', 'capiflow_batch_size', array( 'sanitize_callback' => 'absint' ) );
        register_setting( 'capiflow_general', 'capiflow_api_timeout', array( 'sanitize_callback' => 'absint' ) );
        register_setting( 'capiflow_general', 'capiflow_hourly_rate_limit', array( 'sanitize_callback' => 'absint' ) );
        register_setting( 'capiflow_general', 'capiflow_global_hourly_limit', array( 'sanitize_callback' => 'absint' ) );

        // Inbound IP rate limiting (proxy security).
        register_setting( 'capiflow_general', 'capiflow_ip_trusted_limit', array( 'sanitize_callback' => 'absint' ) );
        register_setting( 'capiflow_general', 'capiflow_ip_suspicious_limit', array( 'sanitize_callback' => 'absint' ) );

        // Catalog & Content ID Strategy (v1.1.0) — General group (affects all events).
        register_setting( 'capiflow_general', 'capiflow_content_id_strategy', array( 'sanitize_callback' => array( $this, 'sanitize_content_id_strategy' ) ) );

        // Order Source Filter options (v1.1.0) — Events group.
        register_setting( 'capiflow_events', 'capiflow_track_admin_orders', array( 'sanitize_callback' => array( $this, 'sanitize_bool' ) ) );
        register_setting( 'capiflow_events', 'capiflow_track_marketplace_orders', array( 'sanitize_callback' => array( $this, 'sanitize_bool' ) ) );

        // OpenGraph product tags (v1.1.0) — Events group.
        register_setting( 'capiflow_events', 'capiflow_enable_og_product_tags', array( 'sanitize_callback' => array( $this, 'sanitize_bool' ) ) );
    }

    /**
     * Encrypt access token before saving.
     *
     * @param string $value Raw token.
     * @return string Encrypted token.
     */
    public function encrypt_token( $value ) {
        if ( empty( $value ) ) {
            // Password field is always empty in form (value="").
            // Empty submission means "keep existing" — return saved value unchanged.
            return get_option( 'capiflow_access_token', '' );
        }

        // If it looks already encrypted (from a re-save), return as is.
        if ( strpos( $value, 'EAA' ) !== 0 && strlen( $value ) > 100 ) {
            return $value;
        }

        return Encryption::encrypt( $value );
    }

    /**
     * Sanitize boolean option.
     *
     * @param mixed $value Value.
     * @return bool
     */
    public function sanitize_bool( $value ) {
        return (bool) $value;
    }

    /**
     * Sanitize content_id_strategy option.
     *
     * Only allows the three defined strategy keys.
     *
     * @param string $value Submitted value.
     * @return string Validated strategy key.
     */
    public function sanitize_content_id_strategy( $value ) {
        $allowed = array( 'sku', 'parent_sku', 'product_id' );
        $value   = sanitize_text_field( (string) $value );
        return in_array( $value, $allowed, true ) ? $value : 'sku';
    }


    /**
     * Enqueue admin assets.
     *
     * @param string $hook_suffix Page hook suffix.
     */
    public function enqueue_admin_assets( string $hook_suffix ): void {
        $capiflow_pages = array(
            'toplevel_page_capiflow-dashboard',
            'capiflow_page_capiflow-settings',
            'capiflow_page_capiflow-setup',
        );
        if ( ! in_array( $hook_suffix, $capiflow_pages, true ) ) {
            return;
        }

        wp_enqueue_style(
            'capiflow-admin',
            CAPIFLOW_PLUGIN_URL . 'admin/css/admin-styles.css',
            array(),
            CAPIFLOW_VERSION
        );

        wp_enqueue_script(
            'capiflow-admin',
            CAPIFLOW_PLUGIN_URL . 'admin/js/admin-scripts.js',
            array( 'jquery' ),
            CAPIFLOW_VERSION,
            true
        );

        wp_localize_script( 'capiflow-admin', 'capiFLowAdmin', array(
            'ajaxUrl'       => admin_url( 'admin-ajax.php' ),
            'nonce'         => wp_create_nonce( 'capiflow_admin' ),
            'hasSavedToken' => ! empty( get_option( 'capiflow_access_token', '' ) ),
            'hasSavedPixel' => ! empty( get_option( 'capiflow_pixel_id', '' ) ),
            'i18n'          => array(
                'testing' => __( 'Testing connection...', 'capiflow' ),
                'saving'  => __( 'Saving...', 'capiflow' ),
                'confirm' => __( 'Are you sure?', 'capiflow' ),
            ),
        ) );

        // ── Dashboard-specific assets (GAP 10) ─────────────────────────────
        // Only enqueue Chart.js + dashboard-charts.js on the Dashboard page.
        if ( 'toplevel_page_capiflow-dashboard' === $hook_suffix ) {

            // Chart.js 4.5.1 — bundled vendor (see admin/js/vendor/SOURCE.md for provenance).
            $chart_umd    = CAPIFLOW_PLUGIN_DIR . 'admin/js/vendor/chart.umd.js';
            $has_chartjs  = false;
            if ( file_exists( $chart_umd ) ) {
                wp_enqueue_script(
                    'capiflow-chartjs',
                    CAPIFLOW_PLUGIN_URL . 'admin/js/vendor/chart.umd.js',
                    array(),
                    '4.5.1',
                    true
                );
                $has_chartjs = true;
            }

            // Dashboard charts JS.
            // Dependencies: jquery is always available; capiflow-chartjs only if Chart.js exists.
            // Without Chart.js, the dashboard JS still works (KPI, terminal, table, insights)
            // — only the bar/doughnut charts won't render.
            $charts_js  = CAPIFLOW_PLUGIN_DIR . 'admin/js/dashboard-charts.js';
            $chart_deps = $has_chartjs ? array( 'jquery', 'capiflow-chartjs' ) : array( 'jquery' );

            if ( file_exists( $charts_js ) ) {
                wp_enqueue_script(
                    'capiflow-dashboard-charts',
                    CAPIFLOW_PLUGIN_URL . 'admin/js/dashboard-charts.js',
                    $chart_deps,
                    CAPIFLOW_VERSION,
                    true
                );

                // Pass config to dashboard JS.
                wp_localize_script( 'capiflow-dashboard-charts', 'capiflowDashboard', array(
                    'ajaxUrl'       => admin_url( 'admin-ajax.php' ),
                    'nonce'         => wp_create_nonce( 'capiflow_dashboard' ),
                    'setupComplete' => (bool) get_option( 'capiflow_wizard_complete', false ),
                    'hasChartJs'    => $has_chartjs,
                    'currency'      => function_exists( 'get_woocommerce_currency_symbol' )
                        ? get_woocommerce_currency_symbol()
                        : '$',
                    'i18n'          => array(
                        'loading'     => __( 'Loading...', 'capiflow' ),
                        'noData'      => __( 'No data yet.', 'capiflow' ),
                        'listening'   => __( '> Listening for events...', 'capiflow' ),
                        'refreshing'  => __( '> Refreshing...', 'capiflow' ),
                        'errorLoad'   => __( 'Failed to load data.', 'capiflow' ),
                    ),
                ) );
            }
        }
    }

    /**
     * Maybe redirect to setup wizard after activation.
     *
     * Uses headers_sent() guard — if another plugin/theme has already output
     * deprecation notices (common on PHP 8.1+ with older WP), fall back to
     * a JavaScript redirect instead of crashing with "headers already sent".
     */
    public function maybe_redirect_to_wizard(): void {
        if ( get_transient( 'capiflow_activation_redirect' ) ) {
            delete_transient( 'capiflow_activation_redirect' );
            if ( ! is_multisite() && ! isset( $_GET['activate-multi'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
                $url = admin_url( 'admin.php?page=capiflow-setup&step=1' );
                if ( ! headers_sent() ) {
                    wp_safe_redirect( $url );
                    exit;
                }
                // Fallback: meta-refresh redirect when headers already sent.
                // Uses http-equiv instead of JS to avoid inline script (WP.org compliance).
                echo '<meta http-equiv="refresh" content="0;url=' . esc_url( $url ) . '">';
                exit;
            }
        }
    }

    /**
     * Render the dashboard page.
     */
    public function render_dashboard_page(): void {
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_die( esc_html__( 'You do not have permissions to access this page.', 'capiflow' ) );
        }
        include CAPIFLOW_PLUGIN_DIR . 'admin/views/dashboard-page.php';
    }

    /**
     * Render the setup wizard page.
     */
    public function render_wizard_page(): void {
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_die( esc_html__( 'You do not have permissions to access this page.', 'capiflow' ) );
        }
        include CAPIFLOW_PLUGIN_DIR . 'admin/views/setup-wizard.php';
    }

    /**
     * Render the settings page.
     */
    public function render_settings_page(): void {
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_die( esc_html__( 'You do not have permissions to access this page.', 'capiflow' ) );
        }
        $capiflow_active_tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : 'general'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        include CAPIFLOW_PLUGIN_DIR . 'admin/views/settings-page.php';
    }

    /**
     * AJAX: Test CAPI connection.
     */
    public function ajax_test_connection() {
        check_ajax_referer( 'capiflow_admin', 'nonce' );

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( 'Unauthorized' );
        }

        // Read from POST (live form values) first, fallback to saved options.
        $pixel_id = isset( $_POST['pixel_id'] )
            ? sanitize_text_field( wp_unslash( $_POST['pixel_id'] ) )
            : get_option( 'capiflow_pixel_id', '' );

        $access_token = isset( $_POST['access_token'] ) && ! empty( $_POST['access_token'] )
            ? sanitize_text_field( wp_unslash( $_POST['access_token'] ) )
            : '';

        // If no raw token from POST, try decrypting saved token.
        if ( empty( $access_token ) ) {
            $encrypted = get_option( 'capiflow_access_token', '' );
            if ( ! empty( $encrypted ) ) {
                $access_token = Encryption::decrypt( $encrypted );
            }
        }

        $sender = new CAPI_Sender();
        $result = $sender->test_connection( $pixel_id, $access_token );

        wp_send_json_success( $result );
    }

    /**
     * AJAX: Activate/deactivate license (Pro-only via filter).
     * Core has no license API — these handlers are stubs for the Pro plugin to override.
     */
    public function ajax_activate_license(): void {
        check_ajax_referer( 'capiflow_admin', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( 'Unauthorized' );
        }
        // Pro plugin hooks into wp_ajax_capiflow_activate_license to override.
        wp_send_json_error( array( 'message' => __( 'License management requires CapiFlow Pro.', 'capiflow' ) ) );
    }

    public function ajax_deactivate_license(): void {
        check_ajax_referer( 'capiflow_admin', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( 'Unauthorized' );
        }
        wp_send_json_error( array( 'message' => __( 'License management requires CapiFlow Pro.', 'capiflow' ) ) );
    }

    /**
     * AJAX: Manual Purchase event send.
     */
    public function ajax_send_purchase() {
        check_ajax_referer( 'capiflow_admin', 'nonce' );

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( 'Unauthorized' );
        }

        $order_id = isset( $_POST['order_id'] ) ? absint( $_POST['order_id'] ) : 0;
        if ( ! $order_id ) {
            wp_send_json_error( 'Invalid order ID' );
        }

        $order = wc_get_order( $order_id );
        if ( ! $order ) {
            wp_send_json_error( 'Order not found' );
        }

        // Clear the sent lock to allow re-send.
        $order->delete_meta_data( '_capiflow_purchase_sent' );
        $order->delete_meta_data( '_capiflow_purchase_event_id' );
        $order->save_meta_data();

        // Trigger purchase.
        $controller = new Purchase_Controller();
        $controller->handle_purchase( $order_id, $order );

        wp_send_json_success( array( 'message' => 'Purchase event queued for order #' . $order_id ) );
    }

    /**
     * AJAX: Get queue data for debug console.
     */
    public function ajax_get_queue_data() {
        check_ajax_referer( 'capiflow_admin', 'nonce' );

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( 'Unauthorized' );
        }

        $event_name = isset( $_POST['event_name'] ) ? sanitize_text_field( wp_unslash( $_POST['event_name'] ) ) : '';
        $status     = isset( $_POST['status'] ) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : '';

        $events = DB_Manager::get_recent_events( 50, $event_name, $status );
        $stats  = DB_Manager::get_queue_stats();

        wp_send_json_success( array(
            'events' => $events,
            'stats'  => $stats,
        ) );
    }

    /**
     * AJAX: Get recent log entries.
     */
    public function ajax_get_log_data() {
        check_ajax_referer( 'capiflow_admin', 'nonce' );

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( 'Unauthorized' );
        }

        $entries = Logger::get_recent_entries( 50 );

        wp_send_json_success( array( 'entries' => $entries ) );
    }

    /**
     * AJAX: Dismiss widget Pro CTA.
     */
    public function ajax_dismiss_widget_cta() {
        check_ajax_referer( 'capiflow_admin', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( 'Unauthorized' );
        }
        update_user_meta( get_current_user_id(), 'capiflow_widget_cta_dismissed', 1 );
        wp_send_json_success();
    }

    // =========================================================================
    // Dashboard AJAX handlers (GAP 10)
    // All use nonce 'capiflow_dashboard' (separate from admin nonce for security).
    // =========================================================================

    /**
     * AJAX: Get KPI data for dashboard cards.
     *
     * Returns: total_events, rescued_events, rescued_revenue, emq score.
     */
    public function ajax_get_kpi_data() {
        check_ajax_referer( 'capiflow_dashboard', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( 'Unauthorized' );
        }

        $days    = isset( $_POST['days'] ) ? absint( $_POST['days'] ) : 30; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $days    = max( 1, min( 365, $days ) ); // Clamp 1-365.
        $summary = DB_Manager::get_dashboard_summary( $days );
        $emq     = method_exists( Dataset_Quality::class, 'get_purchase_emq' )
            ? Dataset_Quality::get_purchase_emq()
            : null;

        // EMQ health data for the Meta Integration Health table.
        $emq_health = method_exists( Dataset_Quality::class, 'get_cached' )
            ? Dataset_Quality::get_cached()
            : null;

        wp_send_json_success( array_merge( $summary, array(
            'emq'                 => $emq,
            'emq_health'          => $emq_health,
            'period_days'         => $days,
            'business_protection' => apply_filters( 'capiflow_business_protection_data', null, $days ),
        ) ) );
    }

    /**
     * AJAX: Get conversion funnel data for bar chart.
     *
     * Returns event counts grouped by event_name for a given period.
     */
    public function ajax_get_funnel_data() {
        check_ajax_referer( 'capiflow_dashboard', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( 'Unauthorized' );
        }

        $days = isset( $_POST['days'] ) ? absint( $_POST['days'] ) : 30; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $days = max( 1, min( 365, $days ) );

        $data = method_exists( 'CapiFlow\Core\DB_Manager', 'get_funnel_data' )
            ? DB_Manager::get_funnel_data( $days )
            : array();

        wp_send_json_success( array(
            'funnel'      => $data,
            'period_days' => $days,
        ) );
    }

    /**
     * AJAX: Get daily event breakdown table data.
     */
    public function ajax_get_table_data() {
        check_ajax_referer( 'capiflow_dashboard', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( 'Unauthorized' );
        }

        $days = isset( $_POST['days'] ) ? absint( $_POST['days'] ) : 30; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $days = max( 1, min( 365, $days ) );

        $data = method_exists( DB_Manager::class, 'get_event_table_summary' )
            ? DB_Manager::get_event_table_summary( $days )
            : array();

        wp_send_json_success( array(
            'rows'        => $data,
            'period_days' => $days,
        ) );
    }

    /**
     * AJAX: Get latest events for Live Terminal.
     *
     * Polled every 15s by dashboard-charts.js.
     * Returns last 20 events with type, status, order_id, http_code, created_at.
     */
    public function ajax_get_live_events() {
        check_ajax_referer( 'capiflow_dashboard', 'nonce' );
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( 'Unauthorized' );
        }

        $events = method_exists( 'CapiFlow\Core\DB_Manager', 'get_recent_events' )
            ? DB_Manager::get_recent_events( 20 )
            : array();

        wp_send_json_success( array(
            'events'    => $events,
            'server_ts' => time(),
        ) );
    }
}

