<?php
/**
 * `wp blaminhor cookies ...` — Cookie banner commands.
 *
 * @package BlaminhorEssentials
 */

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

if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
	return;
}

/**
 * Configure the cookie consent banner and inspect the consent log.
 *
 * Per-service overrides (Google Analytics, Meta Pixel, etc.) are managed
 * through the admin UI for now — too many free-text fields to be useful
 * via CLI flags.
 */
class Blaminhor_Essentials_CLI_Cookies extends Blaminhor_Essentials_CLI_Module {

	/**
	 * @var string
	 */
	protected $module_id = 'cookies';

	/**
	 * Show the current Cookies settings + policy version.
	 *
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args (unused).
	 * @param array $assoc_args Associative args.
	 */
	public function get( $args, $assoc_args ) {
		$module   = $this->get_module_instance();
		$settings = $module->get_effective_settings();

		$rows = array(
			array( 'key' => 'policy_version',     'value' => (string) $settings['policy_version'] ),
			array( 'key' => 'hide_for_admins',    'value' => $settings['hide_for_admins'] ? 'true' : 'false' ),
			array( 'key' => 'layout',             'value' => (string) $settings['layout'] ),
			array( 'key' => 'symmetry_lock',      'value' => $settings['symmetry_lock'] ? 'true' : 'false' ),
			array( 'key' => 'show_revoke_icon',   'value' => $settings['show_revoke_icon'] ? 'true' : 'false' ),
			array( 'key' => 'auto_geo',           'value' => $settings['auto_geo'] ? 'true' : 'false' ),
			array( 'key' => 'force_preset',       'value' => (string) $settings['force_preset'] ),
			array( 'key' => 'dark_mode',          'value' => (string) $settings['dark_mode'] ),
			array( 'key' => 'gcm_enabled',        'value' => $settings['gcm_enabled'] ? 'true' : 'false' ),
			array( 'key' => 'tcf_enabled',        'value' => $settings['tcf_enabled'] ? 'true' : 'false' ),
			array( 'key' => 'wp_consent_api',     'value' => $settings['wp_consent_api'] ? 'true' : 'false' ),
			array( 'key' => 'intercept_inline',   'value' => $settings['intercept_inline'] ? 'true' : 'false' ),
			array( 'key' => 'privacy_policy_url', 'value' => (string) $settings['privacy_policy_url'] ),
		);
		$this->format_for_output( $rows, $assoc_args, array( 'key', 'value' ) );
	}

	/**
	 * Update Cookies banner settings.
	 *
	 * ## OPTIONS
	 *
	 * [--layout=<layout>]
	 * : banner-bottom, banner-top, modal-center.
	 *
	 * [--hide-for-admins=<bool>]
	 * [--symmetry-lock=<bool>]
	 * [--show-revoke-icon=<bool>]
	 * [--auto-geo=<bool>]
	 * [--force-preset=<preset>]
	 * : Force a region preset (e.g. eea, ccpa, lgpd). Empty = automatic.
	 *
	 * [--dark-mode=<mode>]
	 * : auto, light, dark.
	 *
	 * [--gcm=<bool>]
	 * : Send Google Consent Mode v2 signals.
	 *
	 * [--tcf=<bool>]
	 * : Send TCF 2.x signals.
	 *
	 * [--wp-consent-api=<bool>]
	 * : Bridge to the official WP Consent API.
	 *
	 * [--intercept-inline=<bool>]
	 * : Block inline tracking scripts until consent is given.
	 *
	 * [--privacy-url=<url>]
	 * : Public URL of your privacy policy.
	 *
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args (unused).
	 * @param array $assoc_args Associative args.
	 */
	public function set( $args, $assoc_args ) {
		$this->ensure_capabilities();
		$module  = $this->get_module_instance();
		$current = $module->get_effective_settings();

		$data = array(
			'layout'             => isset( $assoc_args['layout'] ) ? (string) $assoc_args['layout'] : (string) $current['layout'],
			'force_preset'       => isset( $assoc_args['force-preset'] ) ? (string) $assoc_args['force-preset'] : (string) $current['force_preset'],
			'dark_mode'          => isset( $assoc_args['dark-mode'] ) ? (string) $assoc_args['dark-mode'] : (string) $current['dark_mode'],
			'privacy_policy_url' => isset( $assoc_args['privacy-url'] ) ? (string) $assoc_args['privacy-url'] : (string) $current['privacy_policy_url'],
			'color_bg'           => (string) $current['color_bg'],
			'color_text'         => (string) $current['color_text'],
			'color_button_bg'    => (string) $current['color_button_bg'],
			'color_button_text'  => (string) $current['color_button_text'],
			'color_button_border'=> (string) $current['color_button_border'],
			'color_dark_bg'      => (string) $current['color_dark_bg'],
			'color_dark_text'    => (string) $current['color_dark_text'],
			'active_services'    => (array) $current['active_services'],
		);

		$bool_map = array(
			'hide-for-admins'   => 'hide_for_admins',
			'symmetry-lock'     => 'symmetry_lock',
			'show-revoke-icon'  => 'show_revoke_icon',
			'auto-geo'          => 'auto_geo',
			'gcm'               => 'gcm_enabled',
			'tcf'               => 'tcf_enabled',
			'wp-consent-api'    => 'wp_consent_api',
			'intercept-inline'  => 'intercept_inline',
		);
		foreach ( $bool_map as $flag => $key ) {
			if ( array_key_exists( $flag, $assoc_args ) ) {
				if ( $this->parse_bool( $assoc_args[ $flag ] ) ) {
					$data[ $key ] = '1';
				}
			} elseif ( ! empty( $current[ $key ] ) ) {
				$data[ $key ] = '1';
			}
		}

		$result = $module->apply_settings( $data );
		if ( is_wp_error( $result ) ) {
			WP_CLI::error( $result->get_error_message() );
		}

		blaminhor_essentials_log( 'Cookies settings updated via WP-CLI.', 'info', 'cli', array( 'event' => 'cookies_set' ) );
		WP_CLI::success( __( 'Cookies settings updated.', 'blaminhor-essentials' ) );
	}

	/**
	 * Bump the policy version to force every visitor to re-consent.
	 *
	 * ## OPTIONS
	 *
	 * [--version=<version>]
	 * : Specific version string. Default: today's date as YYYY.MM.DD.
	 *
	 * [--yes]
	 * : Skip the interactive confirmation prompt.
	 *
	 * @subcommand bump-version
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args (unused).
	 * @param array $assoc_args Associative args.
	 */
	public function bump_version( $args, $assoc_args ) {
		$this->ensure_capabilities();
		$module  = $this->get_module_instance();
		$current = $module->get_effective_settings();

		$new_version = isset( $assoc_args['version'] )
			? (string) $assoc_args['version']
			: date_i18n( 'Y.m.d' );

		WP_CLI::confirm(
			sprintf(
				/* translators: 1: current, 2: new */
				__( 'Bump policy version from "%1$s" to "%2$s"? Every visitor will see the banner again.', 'blaminhor-essentials' ),
				$current['policy_version'],
				$new_version
			),
			$assoc_args
		);

		$current['policy_version'] = $new_version;
		$current['force_reconsent'] = '1';
		$result = $module->apply_settings( $current );
		if ( is_wp_error( $result ) ) {
			WP_CLI::error( $result->get_error_message() );
		}

		blaminhor_essentials_log( sprintf( 'Cookies policy bumped to "%s" via WP-CLI.', $new_version ), 'info', 'cli', array( 'event' => 'cookies_bump' ) );
		WP_CLI::success( sprintf(
			/* translators: %s: new version */
			__( 'Policy version bumped to "%s".', 'blaminhor-essentials' ),
			$new_version
		) );
	}

	/**
	 * Print summary stats from the consent log.
	 *
	 * ## OPTIONS
	 *
	 * [--days=<n>]
	 * : Window in days (default 30).
	 *
	 * @subcommand log-stats
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args (unused).
	 * @param array $assoc_args Associative args.
	 */
	public function log_stats( $args, $assoc_args ) {
		global $wpdb;
		$table = $wpdb->prefix . 'blaminhor_essentials_consent_log';
		$days  = isset( $assoc_args['days'] ) ? max( 1, (int) $assoc_args['days'] ) : 30;
		$since = gmdate( 'Y-m-d H:i:s', time() - $days * DAY_IN_SECONDS );

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$total = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$table} WHERE created_at >= %s", $since ) );
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$all   = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table}" );

		$rows = array(
			array( 'key' => 'window_days',         'value' => (string) $days ),
			array( 'key' => 'consents_in_window',  'value' => (string) $total ),
			array( 'key' => 'consents_all_time',   'value' => (string) $all ),
		);
		$this->format_for_output( $rows, $assoc_args, array( 'key', 'value' ) );
	}

	/**
	 * Purge old consent log rows.
	 *
	 * ## OPTIONS
	 *
	 * [--older-than=<days>]
	 * : Delete rows older than N days (default 365).
	 *
	 * [--yes]
	 * : Skip the interactive confirmation prompt.
	 *
	 * @subcommand clear-log
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args (unused).
	 * @param array $assoc_args Associative args.
	 */
	public function clear_log( $args, $assoc_args ) {
		$this->ensure_capabilities();
		global $wpdb;
		$table = $wpdb->prefix . 'blaminhor_essentials_consent_log';
		$days  = isset( $assoc_args['older-than'] ) ? max( 0, (int) $assoc_args['older-than'] ) : 365;
		$cut   = gmdate( 'Y-m-d H:i:s', time() - $days * DAY_IN_SECONDS );

		WP_CLI::confirm(
			sprintf(
				/* translators: %d: days */
				__( 'Delete every consent-log row older than %d days?', 'blaminhor-essentials' ),
				$days
			),
			$assoc_args
		);

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$deleted = (int) $wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE created_at < %s", $cut ) );

		blaminhor_essentials_log( sprintf( 'Cookies log: %d rows pruned via WP-CLI.', $deleted ), 'info', 'cli', array( 'event' => 'cookies_clear_log' ) );
		WP_CLI::success( sprintf(
			/* translators: %d: deleted count */
			__( '%d consent-log rows deleted.', 'blaminhor-essentials' ),
			$deleted
		) );
	}
}
