<?php
/**
 * `wp blaminhor pto ...` — Post Types Order commands.
 *
 * @package BlaminhorEssentials
 */

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

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

/**
 * Reorder post types and taxonomy terms via the menu_order column.
 */
class Blaminhor_Essentials_CLI_Post_Types_Order extends Blaminhor_Essentials_CLI_Module {

	/**
	 * @var string
	 */
	protected $module_id = 'post-types-order';

	/**
	 * Show the current Post Types Order settings.
	 *
	 * @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' => 'auto_sort',  'value' => $settings['auto_sort'] ? 'true' : 'false' ),
			array( 'key' => 'post_types', 'value' => implode( ',', (array) $settings['post_types'] ) ),
			array( 'key' => 'taxonomies', 'value' => implode( ',', (array) $settings['taxonomies'] ) ),
			array( 'key' => 'capability', 'value' => (string) $settings['capability'] ),
		);
		$this->format_for_output( $rows, $assoc_args, array( 'key', 'value' ) );
	}

	/**
	 * Update Post Types Order settings.
	 *
	 * ## OPTIONS
	 *
	 * [--auto-sort=<bool>]
	 * : Apply the stored order automatically in queries.
	 *
	 * [--post-types=<csv>]
	 * : Comma-separated post type slugs to make reorderable.
	 *
	 * [--taxonomies=<csv>]
	 * : Comma-separated taxonomy slugs to make reorderable.
	 *
	 * [--capability=<cap>]
	 * : WP capability required to reorder (default manage_options).
	 *
	 * @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(
			'capability' => isset( $assoc_args['capability'] ) ? (string) $assoc_args['capability'] : (string) $current['capability'],
		);

		if ( isset( $assoc_args['post-types'] ) ) {
			$data['post_types'] = array_filter( array_map( 'sanitize_key', explode( ',', (string) $assoc_args['post-types'] ) ) );
		} else {
			$data['post_types'] = (array) $current['post_types'];
		}

		if ( isset( $assoc_args['taxonomies'] ) ) {
			$data['taxonomies'] = array_filter( array_map( 'sanitize_key', explode( ',', (string) $assoc_args['taxonomies'] ) ) );
		} else {
			$data['taxonomies'] = (array) $current['taxonomies'];
		}

		if ( isset( $assoc_args['auto-sort'] ) ) {
			if ( $this->parse_bool( $assoc_args['auto-sort'] ) ) {
				$data['auto_sort'] = '1';
			}
		} elseif ( ! empty( $current['auto_sort'] ) ) {
			$data['auto_sort'] = '1';
		}

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

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

	/**
	 * List items of a post type or taxonomy with their current menu_order.
	 *
	 * ## OPTIONS
	 *
	 * <type>
	 * : Post type slug, or taxonomy slug when --taxonomy is set.
	 *
	 * [--taxonomy]
	 * : Treat <type> as a taxonomy slug rather than a post type.
	 *
	 * [--format=<format>]
	 * : Render format (table, json, csv, yaml, ids). Default: table.
	 *
	 * @subcommand list-items
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args: [<type>].
	 * @param array $assoc_args Associative args.
	 */
	public function list_items( $args, $assoc_args ) {
		if ( empty( $args[0] ) ) {
			WP_CLI::error( __( 'Missing <type> argument.', 'blaminhor-essentials' ) );
		}
		$type   = sanitize_key( (string) $args[0] );
		$module = $this->get_module_instance();

		if ( isset( $assoc_args['taxonomy'] ) ) {
			$items = $module->get_taxonomy_items( $type );
		} else {
			$items = $module->get_post_type_items( $type );
		}

		$rows = array();
		foreach ( (array) $items as $i ) {
			$i = (array) $i;
			$rows[] = array(
				'id'    => (string) (int) ( isset( $i['ID'] ) ? $i['ID'] : ( isset( $i['term_id'] ) ? $i['term_id'] : 0 ) ),
				'name'  => isset( $i['post_title'] ) ? (string) $i['post_title'] : ( isset( $i['name'] ) ? (string) $i['name'] : '' ),
				'order' => (string) (int) ( isset( $i['menu_order'] ) ? $i['menu_order'] : 0 ),
			);
		}
		$this->format_for_output( $rows, $assoc_args, array( 'id', 'name', 'order' ) );
	}

	/**
	 * Persist a new order for the given post type or taxonomy.
	 *
	 * ## OPTIONS
	 *
	 * <type>
	 * : Post type slug, or taxonomy slug when --taxonomy is set.
	 *
	 * --order=<ids>
	 * : Comma-separated IDs in the desired order (first = position 1).
	 *
	 * [--taxonomy]
	 * : Treat <type> as a taxonomy slug.
	 *
	 * ## EXAMPLES
	 *
	 *     $ wp blaminhor pto reorder page --order=42,11,7
	 *     $ wp blaminhor pto reorder category --order=3,1,2 --taxonomy
	 *
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args: [<type>].
	 * @param array $assoc_args Associative args.
	 */
	public function reorder( $args, $assoc_args ) {
		$this->ensure_capabilities();
		if ( empty( $args[0] ) ) {
			WP_CLI::error( __( 'Missing <type> argument.', 'blaminhor-essentials' ) );
		}
		if ( empty( $assoc_args['order'] ) ) {
			WP_CLI::error( __( 'Missing --order=<ids,csv>.', 'blaminhor-essentials' ) );
		}
		$type   = sanitize_key( (string) $args[0] );
		$ids    = array_map( 'absint', array_filter( explode( ',', (string) $assoc_args['order'] ) ) );
		$module = $this->get_module_instance();

		if ( isset( $assoc_args['taxonomy'] ) ) {
			$module->save_taxonomy_order( $ids );
		} else {
			$module->save_post_type_order( $ids );
		}

		blaminhor_essentials_log( sprintf( 'Post Types Order: reorder of "%s" via WP-CLI (%d IDs).', $type, count( $ids ) ), 'info', 'cli', array( 'event' => 'pto_reorder' ) );
		WP_CLI::success( sprintf(
			/* translators: 1: count, 2: type */
			__( 'Reordered %1$d items for "%2$s".', 'blaminhor-essentials' ),
			count( $ids ),
			$type
		) );
	}

	/**
	 * Clear every menu_order for a post type or taxonomy.
	 *
	 * ## OPTIONS
	 *
	 * <type>
	 * : Post type slug, or taxonomy slug when --taxonomy is set.
	 *
	 * [--taxonomy]
	 * : Treat <type> as a taxonomy slug.
	 *
	 * [--yes]
	 * : Skip the interactive confirmation prompt.
	 *
	 * @when after_wp_load
	 *
	 * @param array $args       Positional args: [<type>].
	 * @param array $assoc_args Associative args.
	 */
	public function reset( $args, $assoc_args ) {
		$this->ensure_capabilities();
		if ( empty( $args[0] ) ) {
			WP_CLI::error( __( 'Missing <type> argument.', 'blaminhor-essentials' ) );
		}
		$type = sanitize_key( (string) $args[0] );

		WP_CLI::confirm(
			sprintf(
				/* translators: %s: type slug */
				__( 'Reset every menu_order for "%s"? Items will fall back to the WordPress default order.', 'blaminhor-essentials' ),
				$type
			),
			$assoc_args
		);

		$module = $this->get_module_instance();
		if ( isset( $assoc_args['taxonomy'] ) ) {
			$module->reset_taxonomy_order( $type );
		} else {
			$module->reset_post_type_order( $type );
		}

		blaminhor_essentials_log( sprintf( 'Post Types Order: reset of "%s" via WP-CLI.', $type ), 'info', 'cli', array( 'event' => 'pto_reset' ) );
		WP_CLI::success( sprintf(
			/* translators: %s: type slug */
			__( 'Order reset for "%s".', 'blaminhor-essentials' ),
			$type
		) );
	}
}
