<?php
/**
 * File Path: includes/admin/class-mbs-telemetry.php
 *
 * Telemetry Opt-In Manager — My Book Showroom
 *
 * Manages the anonymous usage data consent flow:
 *   1. Shows an admin notice after wizard completion, once consent is unknown.
 *   2. Handles the AJAX consent action (opted_in | opted_out | deferred).
 *   3. Schedules/clears the weekly cron event and binds the cron hook.
 *
 * Consent option: `mbs_telemetry_consent`
 *   - (empty / not set) = no decision yet
 *   - `opted_in`        = user opted in; weekly cron active
 *   - `opted_out`       = user opted out; no cron, no network calls
 *   - `deferred`        = dismissed without choosing; re-show after 7 days
 *
 * Cron event name: `mbs_telemetry_weekly_ping`  ← CANONICAL — never vary this name.
 * The name must match exactly in both this file and class-mbs-telemetry-client.php.
 *
 * Orchestrator wiring (class-mbs-plugin.php — OUTSIDE is_admin() block):
 *   require_once MBS_INCLUDES_DIR . 'admin/class-mbs-telemetry.php';
 *   new MBS_Telemetry();
 *
 * Story 14-9 — Sprint 14.
 *
 * @package    My_Book_Showroom
 * @subpackage Includes/Admin
 * @since      1.0.0
 */

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

class MBS_Telemetry {

	/** Canonical cron event name — must match class-mbs-telemetry-client.php. */
	const CRON_HOOK = 'mbs_telemetry_weekly_ping';

	/** Option key that stores the user's consent decision. */
	const CONSENT_KEY = 'mbs_telemetry_consent';

	/** Transient key used for the 7-day defer window. */
	const DEFER_TRANSIENT = 'mbs_telemetry_deferred';

	// ── Bootstrap ─────────────────────────────────────────────────────────────

	public function __construct() {
		// Bind the cron hook regardless of admin/front context — WP Cron fires
		// in all contexts and needs the action registered to execute.
		if ( get_option( self::CONSENT_KEY, '' ) === 'opted_in' ) {
			add_action( self::CRON_HOOK, array( 'MBS_Telemetry_Client', 'send_ping' ) );
		}

		// Admin-only hooks.
		add_action( 'admin_notices',                 array( $this, 'maybe_show_notice' ) );
		add_action( 'wp_ajax_mbs_telemetry_consent', array( $this, 'handle_ajax_consent' ) );
	}

	// ── Admin notice ──────────────────────────────────────────────────────────

	/**
	 * Conditionally show the telemetry consent notice.
	 *
	 * Conditions (all must be true):
	 *   1. Setup wizard has been dismissed (option mbs_setup_wizard_dismissed === '1').
	 *   2. Consent has not been set yet (or was deferred and the 7-day TTL has expired).
	 *   3. Current user is an admin.
	 *
	 * @return void
	 */
	public function maybe_show_notice(): void {
		if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) {
			return;
		}

		// Wizard must be completed (v1: site option; v2: user meta done or skipped).
		$uid         = get_current_user_id();
		$wizard_done = get_option( MBS_Setup_Wizard::DISMISSED_KEY ) === '1'
		            || (bool) get_user_meta( $uid, MBS_Setup_Wizard::META_DONE, true )
		            || (bool) get_user_meta( $uid, MBS_Setup_Wizard::META_SKIP, true );
		if ( ! $wizard_done ) {
			return;
		}

		$consent = get_option( self::CONSENT_KEY, '' );

		// Already decided — do not show again.
		if ( in_array( $consent, array( 'opted_in', 'opted_out' ), true ) ) {
			return;
		}

		// Deferred — wait for the transient TTL to expire before re-showing.
		if ( 'deferred' === $consent && false !== get_transient( self::DEFER_TRANSIENT ) ) {
			return;
		}

		$nonce = wp_create_nonce( 'mbs_telemetry_consent' );
		?>
		<div class="notice notice-info mbs-telemetry-notice" id="mbs-telemetry-notice" style="padding:12px 16px;">
			<p>
				<strong><?php esc_html_e( 'My Book Showroom — Usage Data', 'my-book-showroom' ); ?></strong>
			</p>
			<p>
				<?php esc_html_e( 'Help improve My Book Showroom by sharing anonymous usage data (WordPress version, PHP version, active layouts, feature usage counts). No personal data or book content is ever shared. Opt-out at any time in Settings.', 'my-book-showroom' ); ?>
			</p>
			<p>
				<button type="button"
				        class="button button-primary mbs-telemetry-consent-btn"
				        data-choice="opted_in"
				        data-nonce="<?php echo esc_attr( $nonce ); ?>">
					<?php esc_html_e( "Yes, I'll help", 'my-book-showroom' ); ?>
				</button>
				&nbsp;
				<button type="button"
				        class="button mbs-telemetry-consent-btn"
				        data-choice="opted_out"
				        data-nonce="<?php echo esc_attr( $nonce ); ?>">
					<?php esc_html_e( 'No thanks', 'my-book-showroom' ); ?>
				</button>
				&nbsp;
				<button type="button"
				        class="button-link mbs-telemetry-consent-btn"
				        data-choice="deferred"
				        data-nonce="<?php echo esc_attr( $nonce ); ?>"
				        style="margin-left:8px;color:#646970;">
					<?php esc_html_e( 'Remind me later', 'my-book-showroom' ); ?>
				</button>
			</p>
		</div>

		<script>
		(function ($) {
		    'use strict';
		    $( '.mbs-telemetry-consent-btn' ).on( 'click', function () {
		        var $btn    = $( this );
		        var choice  = $btn.data( 'choice' );
		        var nonce   = $btn.data( 'nonce' );
		        $btn.prop( 'disabled', true );
		        $.post( ajaxurl, {
		            action: 'mbs_telemetry_consent',
		            nonce:  nonce,
		            choice: choice,
		        }, function () {
		            $( '#mbs-telemetry-notice' ).fadeOut( 300, function () {
		                $( this ).remove();
		            } );
		        } );
		    } );
		})(jQuery);
		</script>
		<?php
	}

	// ── AJAX: consent handler ─────────────────────────────────────────────────

	/**
	 * Handle the telemetry consent AJAX action.
	 *
	 * Accepts POST: nonce, choice ('opted_in' | 'opted_out' | 'deferred').
	 * Updates the consent option and schedules/clears the cron event.
	 *
	 * @return void  Sends JSON and exits.
	 */
	public function handle_ajax_consent(): void {
		check_ajax_referer( 'mbs_telemetry_consent', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => 'Permission denied.' ), 403 );
		}

		$choice = sanitize_key( wp_unslash( $_POST['choice'] ?? '' ) );
		if ( ! in_array( $choice, array( 'opted_in', 'opted_out', 'deferred' ), true ) ) {
			wp_send_json_error( array( 'message' => 'Invalid choice.' ) );
		}

		switch ( $choice ) {
			case 'opted_in':
				update_option( self::CONSENT_KEY, 'opted_in' );
				delete_transient( self::DEFER_TRANSIENT );
				self::schedule_cron();
				break;

			case 'opted_out':
				update_option( self::CONSENT_KEY, 'opted_out' );
				delete_transient( self::DEFER_TRANSIENT );
				self::clear_cron();
				break;

			case 'deferred':
				update_option( self::CONSENT_KEY, 'deferred' );
				set_transient( self::DEFER_TRANSIENT, '1', WEEK_IN_SECONDS );
				break;
		}

		wp_send_json_success();
	}

	// ── Cron helpers ──────────────────────────────────────────────────────────

	/**
	 * Schedule the weekly telemetry ping if not already scheduled,
	 * and register the action callback for the current request.
	 *
	 * @return void
	 */
	public static function schedule_cron(): void {
		// V2-D-042: Site-wide cron -- only schedule on main site in multisite.
		if ( ! is_multisite() || is_main_site() ) {
			if ( ! wp_next_scheduled( self::CRON_HOOK ) ) {
				wp_schedule_event( time(), 'weekly', self::CRON_HOOK );
			}
		}
		add_action( self::CRON_HOOK, array( 'MBS_Telemetry_Client', 'send_ping' ) );
	}

	/**
	 * Clear the weekly telemetry cron event.
	 * Makes zero network requests after this call.
	 *
	 * @return void
	 */
	public static function clear_cron(): void {
		wp_clear_scheduled_hook( self::CRON_HOOK );
	}
}
