<?php
/**
 * Settings page + OAuth callback handler.
 *
 * @package GoValid_QR
 */

defined( 'ABSPATH' ) || exit;

class GoValid_Admin_Settings {

	/**
	 * Register hooks.
	 */
	public function register(): void {
		add_action( 'admin_init', array( $this, 'register_settings' ) );
		add_action( 'admin_init', array( $this, 'maybe_handle_oauth_callback' ) );
		add_action( 'admin_post_govalid_qr_connect', array( $this, 'handle_connect' ) );
		add_action( 'admin_post_govalid_qr_disconnect', array( $this, 'handle_disconnect' ) );
		add_action( 'admin_post_govalid_qr_clear_cache', array( $this, 'handle_clear_cache' ) );
		add_action( 'admin_post_govalid_qr_create_verify_page', array( $this, 'handle_create_verify_page' ) );
	}

	/**
	 * Register WordPress settings.
	 */
	public function register_settings(): void {
		register_setting( 'govalid_qr_settings', 'govalid_qr_client_id', array(
			'type'              => 'string',
			'sanitize_callback' => 'sanitize_text_field',
		) );
		register_setting( 'govalid_qr_settings', 'govalid_qr_client_secret', array(
			'type'              => 'string',
			'sanitize_callback' => 'sanitize_text_field',
		) );
		register_setting( 'govalid_qr_settings', 'govalid_qr_base_url', array(
			'type'              => 'string',
			'default'           => GOVALID_QR_DEFAULT_BASE_URL,
			'sanitize_callback' => 'sanitize_url',
		) );
		register_setting( 'govalid_qr_widget_settings', 'govalid_qr_floating_verify', array(
			'type'              => 'string',
			'default'           => '1',
			'sanitize_callback' => 'sanitize_text_field',
		) );
		register_setting( 'govalid_qr_widget_settings', 'govalid_qr_verify_position', array(
			'type'              => 'string',
			'default'           => 'bottom-right',
			'sanitize_callback' => 'sanitize_text_field',
		) );
		register_setting( 'govalid_qr_widget_settings', 'govalid_qr_custom_verify_domain', array(
			'type'              => 'string',
			'default'           => '',
			'sanitize_callback' => array( $this, 'sanitize_custom_verify_domain' ),
		) );
		// Also register in its own group so the Custom Verification tab can save independently.
		register_setting( 'govalid_qr_verify_settings', 'govalid_qr_custom_verify_domain', array(
			'type'              => 'string',
			'default'           => '',
			'sanitize_callback' => array( $this, 'sanitize_custom_verify_domain' ),
		) );
		register_setting( 'govalid_qr_verify_settings', 'govalid_qr_show_powered_by', array(
			'type'              => 'string',
			'default'           => '',
			'sanitize_callback' => 'sanitize_text_field',
		) );
	}

	/**
	 * Sanitize the custom verify domain toggle and schedule rewrite flush on change.
	 *
	 * @param string $value New value.
	 * @return string
	 */
	public function sanitize_custom_verify_domain( $value ): string {
		$value = sanitize_text_field( $value );
		$old   = get_option( 'govalid_qr_custom_verify_domain', '' );
		if ( $old !== $value ) {
			update_option( 'govalid_qr_flush_rewrite', '1' );
		}
		return $value;
	}

	/**
	 * Handle "Connect with GoValid" action.
	 */
	public function handle_connect(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Unauthorized.', 'govalid-qr-validator' ) );
		}
		check_admin_referer( 'govalid_qr_connect' );

		// Store a nonce for the OAuth callback — verified in handle_oauth_callback().
		set_transient( 'govalid_oauth_callback_nonce', wp_create_nonce( 'govalid_oauth_callback' ), 10 * MINUTE_IN_SECONDS );

		$client_id = get_option( 'govalid_qr_client_id', '' );
		if ( empty( $client_id ) ) {
			wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr&error=missing_credentials' ) ) );
			exit;
		}

		$oauth = new GoValid_OAuth();
		$url   = $oauth->initiate_authorization();

		// phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- External OAuth authorization URL requires cross-domain redirect.
		wp_redirect( $url );
		exit;
	}

	/**
	 * Intercept OAuth callback early (before output) so wp_redirect works.
	 */
	public function maybe_handle_oauth_callback(): void {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( ! isset( $_GET['page'] ) || 'govalid-qr-oauth-callback' !== $_GET['page'] ) {
			return;
		}
		$this->handle_oauth_callback();
	}

	/**
	 * Handle the OAuth callback page.
	 */
	public function handle_oauth_callback(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Unauthorized.', 'govalid-qr-validator' ) );
		}

		// Verify the nonce stored during handle_connect() to validate this callback session.
		$callback_nonce = get_transient( 'govalid_oauth_callback_nonce' );
		if ( ! $callback_nonce || ! wp_verify_nonce( $callback_nonce, 'govalid_oauth_callback' ) ) {
			delete_transient( 'govalid_oauth_callback_nonce' );
			wp_die( esc_html__( 'Invalid or expired OAuth session. Please try connecting again.', 'govalid-qr-validator' ) );
		}
		delete_transient( 'govalid_oauth_callback_nonce' );

		$code  = isset( $_GET['code'] ) ? sanitize_text_field( wp_unslash( $_GET['code'] ) ) : '';
		$state = isset( $_GET['state'] ) ? sanitize_text_field( wp_unslash( $_GET['state'] ) ) : '';
		$error = isset( $_GET['error'] ) ? sanitize_text_field( wp_unslash( $_GET['error'] ) ) : '';

		if ( ! empty( $error ) ) {
			$message = isset( $_GET['error_description'] )
				? sanitize_text_field( wp_unslash( $_GET['error_description'] ) )
				: $error;
			wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr&error=' . rawurlencode( $message ) ) ) );
			exit;
		}

		if ( empty( $code ) || empty( $state ) ) {
			wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr&error=missing_params' ) ) );
			exit;
		}

		$oauth  = new GoValid_OAuth();
		$result = $oauth->handle_callback( $code, $state );

		if ( is_wp_error( $result ) ) {
			wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr&error=' . rawurlencode( $result->get_error_message( ) ) ) ) );
			exit;
		}

		wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr&connected=1' ) ) );
		exit;
	}

	/**
	 * Handle disconnect action.
	 */
	public function handle_disconnect(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Unauthorized.', 'govalid-qr-validator' ) );
		}
		check_admin_referer( 'govalid_qr_disconnect' );

		$oauth = new GoValid_OAuth();
		$oauth->disconnect();

		wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr&disconnected=1' ) ) );
		exit;
	}

	/**
	 * Handle clear cache action.
	 */
	public function handle_clear_cache(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Unauthorized.', 'govalid-qr-validator' ) );
		}
		check_admin_referer( 'govalid_qr_clear_cache' );

		GoValid_Cache::get_instance()->flush_all();

		wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr&cache_cleared=1' ) ) );
		exit;
	}

	/**
	 * Handle auto-create verification page action.
	 */
	public function handle_create_verify_page(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Unauthorized.', 'govalid-qr-validator' ) );
		}
		check_admin_referer( 'govalid_qr_create_verify_page' );

		$result = GoValid_QR::create_verify_page();

		if ( is_wp_error( $result ) ) {
			wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr&tab=custom-verify&error=' . rawurlencode( $result->get_error_message( ) ) ) ) );
		} else {
			wp_safe_redirect( add_query_arg( '_wpnonce', wp_create_nonce( 'govalid-admin' ), admin_url( 'admin.php?page=govalid-qr&tab=custom-verify&page_created=1' ) ) );
		}
		exit;
	}
}
