<?php
/**
 * `wp blaminhor disable-comments ...` — Disable Comments module commands.
 *
 * @package BlaminhorEssentials
 */

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

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

/**
 * Toggle WP comments off across the install and run bulk cleanup actions.
 */
class Blaminhor_Essentials_CLI_Disable_Comments extends Blaminhor_Essentials_CLI_Module {

	/**
	 * @var string
	 */
	protected $module_id = 'disable-comments';

	/**
	 * Show the current Disable Comments settings + counts of open comments.
	 *
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args (unused).
	 * @param array $assoc_args Associative args.
	 */
	public function get( $args, $assoc_args ) {
		global $wpdb;
		$module   = $this->get_module_instance();
		$settings = $module->get_effective_settings();

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$total      = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->comments}" );
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$open       = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->posts} WHERE comment_status = 'open'" );

		$rows = array(
			array( 'key' => 'disable_comments', 'value' => $settings['disable_comments'] ? 'true' : 'false' ),
			array( 'key' => 'hide_from_admin',  'value' => $settings['hide_from_admin'] ? 'true' : 'false' ),
			array( 'key' => 'comments_in_db',   'value' => (string) $total ),
			array( 'key' => 'posts_with_open',  'value' => (string) $open ),
		);
		$this->format_for_output( $rows, $assoc_args, array( 'key', 'value' ) );
	}

	/**
	 * Update Disable Comments settings.
	 *
	 * ## OPTIONS
	 *
	 * [--disable-comments=<bool>]
	 * : Strip comment support globally.
	 *
	 * [--hide-from-admin=<bool>]
	 * : Remove the Comments admin menu and screen.
	 *
	 * @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();

		$bool_map = array(
			'disable-comments' => 'disable_comments',
			'hide-from-admin'  => 'hide_from_admin',
		);

		$data = array();
		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( 'Disable Comments settings updated via WP-CLI.', 'info', 'cli', array( 'event' => 'disable_comments_set' ) );
		WP_CLI::success( __( 'Disable Comments settings updated.', 'blaminhor-essentials' ) );
	}

	/**
	 * Close comments on every published post (sets comment_status='closed').
	 *
	 * ## OPTIONS
	 *
	 * [--yes]
	 * : Skip the interactive confirmation prompt.
	 *
	 * ## EXAMPLES
	 *
	 *     $ wp blaminhor disable-comments close-existing --yes
	 *
	 * @subcommand close-existing
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args (unused).
	 * @param array $assoc_args Associative args.
	 */
	public function close_existing( $args, $assoc_args ) {
		$this->ensure_capabilities();
		global $wpdb;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$open = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->posts} WHERE comment_status = 'open'" );
		if ( 0 === $open ) {
			WP_CLI::success( __( 'No posts with open comments — nothing to do.', 'blaminhor-essentials' ) );
			return;
		}

		WP_CLI::confirm(
			sprintf(
				/* translators: %d: number of posts to update */
				__( 'Close comments on %d posts? This sets comment_status="closed" everywhere.', 'blaminhor-essentials' ),
				$open
			),
			$assoc_args
		);

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$updated = (int) $wpdb->query( "UPDATE {$wpdb->posts} SET comment_status = 'closed', ping_status = 'closed' WHERE comment_status = 'open' OR ping_status = 'open'" );

		blaminhor_essentials_log( sprintf( 'Disable Comments: closed %d posts via WP-CLI.', $updated ), 'info', 'cli', array( 'event' => 'close_existing' ) );
		WP_CLI::success( sprintf(
			/* translators: %d: number of posts updated */
			__( '%d posts updated (comments and pings closed).', 'blaminhor-essentials' ),
			$updated
		) );
	}

	/**
	 * Delete every comment and its metadata in the database.
	 *
	 * This is irreversible. Make a backup first.
	 *
	 * ## OPTIONS
	 *
	 * [--yes]
	 * : Skip the interactive confirmation prompt.
	 *
	 * @subcommand delete-all
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args (unused).
	 * @param array $assoc_args Associative args.
	 */
	public function delete_all( $args, $assoc_args ) {
		$this->ensure_capabilities();
		global $wpdb;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->comments}" );
		if ( 0 === $count ) {
			WP_CLI::success( __( 'No comments in the database — nothing to delete.', 'blaminhor-essentials' ) );
			return;
		}

		WP_CLI::confirm(
			sprintf(
				/* translators: %d: number of comments to delete */
				__( 'IRREVERSIBLE: delete %d comments and their metadata? Run a backup first.', 'blaminhor-essentials' ),
				$count
			),
			$assoc_args
		);

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$wpdb->query( "DELETE FROM {$wpdb->commentmeta}" );
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$deleted = (int) $wpdb->query( "DELETE FROM {$wpdb->comments}" );
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$wpdb->query( "UPDATE {$wpdb->posts} SET comment_count = 0 WHERE comment_count > 0" );

		blaminhor_essentials_log( sprintf( 'Disable Comments: deleted %d comments via WP-CLI.', $deleted ), 'warning', 'cli', array( 'event' => 'delete_all_comments' ) );
		WP_CLI::success( sprintf(
			/* translators: %d: number of comments deleted */
			__( '%d comments and their metadata deleted.', 'blaminhor-essentials' ),
			$deleted
		) );
	}
}
