<?php
/**
 * Custom Taxonomy Order premium screens — packed only in the Pro add-on overlay.
 *
 * Secure design (rafter-secure-design):
 * - Identity: WordPress users who already pass the module reorder capability.
 * - AuthZ: Reset uses the same nonce + capability + per-term edit checks as save.
 *   Lite cannot run this file; Freemium::unlocked requires Pro + license.
 * - Mutation: Reset deletes `_wpps_taxonomy_order` term meta for one taxonomy
 *   (optional parent scope). It does not delete terms.
 *
 * @package CustomTaxonomyOrder
 */

namespace CustomTaxonomyOrder;

use CustomTaxonomyOrder\Includes\TaxonomyHelper;

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

/**
 * Custom taxonomies, extra query surfaces, and bulk reset — not shipped in Lite.
 */
final class Premium {

	public static function boot( Module $module ): void {
		if ( ! function_exists( 'wp_powersuite_freemium_unlocked' ) || ! wp_powersuite_freemium_unlocked( 'custom-taxonomy-order' ) ) {
			return;
		}

		add_filter( 'wp_powersuite_custom_taxonomy_order_matches_premium_context', [ self::class, 'filterPremiumContext' ], 10, 4 );
		add_action(
			'wp_ajax_wpps_cto_reset_order',
			static function () use ( $module ): void {
				self::ajaxResetOrder( $module );
			}
		);
	}

	/**
	 * @param array<string, mixed> $args
	 * @param array<string, mixed> $settings
	 */
	public static function filterPremiumContext( bool $match, string $taxonomy, array $args, array $settings ): bool {
		unset( $args );

		if ( $match ) {
			return true;
		}

		if ( is_admin() ) {
			if ( ! empty( $settings['apply_admin'] ) ) {
				return true;
			}
			if ( ! empty( $settings['apply_menus'] ) && self::isMenuAdminScreen() ) {
				return $taxonomy !== 'nav_menu';
			}

			return false;
		}

		if ( ! empty( $settings['apply_archives'] ) && ( is_category() || is_tag() || is_tax( $taxonomy ) ) ) {
			return true;
		}

		return false;
	}

	public static function ajaxResetOrder( Module $module ): void {
		$module->assertAjaxAllowed();

		$taxonomy = isset( $_POST['taxonomy'] ) ? sanitize_key( wp_unslash( (string) $_POST['taxonomy'] ) ) : '';
		$settings = $module->getSettings();

		if ( ! in_array( $taxonomy, $settings['taxonomies'], true ) ) {
			wp_send_json_error( [ 'message' => __( 'Invalid taxonomy.', 'wp-powersuite' ) ] );
		}

		$parent_id = isset( $_POST['parent_id'] ) ? max( 0, (int) $_POST['parent_id'] ) : 0;

		// A full reset must clear order for every hierarchy level, not just the
		// currently scoped parent.
		$reset_all = ! empty( $_POST['reset_all'] );
		$mode      = $reset_all ? 'global' : 'within_parent';

		$result = self::resetOrder(
			$taxonomy,
			$settings['reorder_capability'],
			$parent_id,
			$mode
		);

		if ( ! $result['success'] ) {
			wp_send_json_error( [ 'message' => $result['message'] ] );
		}

		wp_send_json_success( [ 'message' => $result['message'], 'updated' => $result['updated'] ] );
	}

	/**
	 * @return array{success: bool, message: string, updated: int}
	 */
	private static function resetOrder(
		string $taxonomy,
		string $reorder_capability,
		int $parent_id = 0,
		string $hierarchical_mode = 'within_parent'
	): array {
		$taxonomy = sanitize_key( $taxonomy );
		if ( ! TaxonomyHelper::userCanReorderTaxonomy( $taxonomy, $reorder_capability ) ) {
			return [
				'success' => false,
				'message' => __( 'You do not have permission to reset order for this taxonomy.', 'wp-powersuite' ),
				'updated' => 0,
			];
		}

		$meta_key = TaxonomyHelper::getOrderMetaKey();
		$args     = [
			'taxonomy'   => $taxonomy,
			'hide_empty' => false,
			'fields'     => 'ids',
		];

		if ( TaxonomyHelper::isHierarchical( $taxonomy ) && $hierarchical_mode === 'within_parent' ) {
			$args['parent'] = max( 0, $parent_id );
		}

		$term_ids = get_terms( $args );
		if ( is_wp_error( $term_ids ) || ! is_array( $term_ids ) ) {
			return [
				'success' => false,
				'message' => __( 'Could not load terms for reset.', 'wp-powersuite' ),
				'updated' => 0,
			];
		}

		$updated = self::batchDeleteTermOrder( $term_ids, $meta_key, $taxonomy );

		clean_term_cache( $term_ids, $taxonomy );

		return [
			'success' => true,
			'message' => __( 'Order reset successfully.', 'wp-powersuite' ),
			'updated' => $updated,
		];
	}

	/**
	 * @param list<int|string> $term_ids
	 */
	private static function batchDeleteTermOrder( array $term_ids, string $meta_key, string $taxonomy ): int {
		global $wpdb;

		$ids = array_values(
			array_filter(
				array_map( 'intval', $term_ids ),
				static fn( int $id ): bool => $id > 0
			)
		);

		if ( $ids === [] ) {
			return 0;
		}

		$allowed = array_filter(
			$ids,
			static fn( int $term_id ): bool => TaxonomyHelper::userCanEditTerm( $term_id, $taxonomy )
		);

		if ( $allowed === [] ) {
			return 0;
		}

		$placeholders = implode( ', ', array_fill( 0, count( $allowed ), '%d' ) );
		$sql          = "DELETE FROM {$wpdb->termmeta} WHERE meta_key = %s AND term_id IN ({$placeholders})";
		$params       = array_merge( [ $meta_key ], $allowed );

		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- placeholders built above.
		$result = $wpdb->query( $wpdb->prepare( $sql, ...$params ) );

		return $result === false ? 0 : (int) $result;
	}

	private static function isMenuAdminScreen(): bool {
		global $pagenow;

		return $pagenow === 'nav-menus.php';
	}
}
