<?php
/**
 * File Path: includes/migrations/class-mbs-migration-2-8.php
 *
 * MBS_Migration_2_8 — Sprint F-SORT-1 — Pre-compute sort keys
 *
 * Pre-compute mbs_sort_key for all title-like taxonomy terms and
 * mbs_title_sort_key for all existing book posts. Idempotent.
 *
 * @package MyBookShowroom
 * @since   3.2.0
 */

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

/**
 * Class MBS_Migration_2_8
 *
 * Pre-compute mbs_sort_key for all title-like taxonomy terms and
 * mbs_title_sort_key for all existing book posts. Idempotent.
 *
 * @implements MBS_Migration
 */
class MBS_Migration_2_8 implements MBS_Migration { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix

	/**
	 * {@inheritdoc}
	 *
	 * @return string
	 */
	public function version(): string {
		return '2.8';
	}

	/**
	 * {@inheritdoc}
	 *
	 * Pre-compute mbs_sort_key for all title-like taxonomy terms and
 * mbs_title_sort_key for all existing book posts. Idempotent.
	 *
	 * @return void
	 */
	public function up(): void {
		global $wpdb;
		$title_taxes = array(
			'mbs_series', 'mbs_collection', 'mbs_universe', 'mbs_genre',
			'mbs_theme', 'mbs_content_warning', 'mbs_publisher', 'mbs_imprint',
		);
		foreach ( $title_taxes as $tax ) {
			// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
			$rows = $wpdb->get_results( $wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- DAO layer -- direct DB access is intentional per MBS architecture
				"SELECT t.term_id, t.name
				 FROM {$wpdb->terms} t
				 JOIN {$wpdb->term_taxonomy} tt ON tt.term_id = t.term_id
				 WHERE tt.taxonomy = %s
				   AND NOT EXISTS (
				       SELECT 1 FROM {$wpdb->termmeta}
				       WHERE term_id = t.term_id AND meta_key = 'mbs_sort_key'
				   )",
				$tax
			) );
			if ( ! empty( $rows ) ) {
				foreach ( $rows as $row ) {
					$wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- DAO layer -- direct DB access is intentional per MBS architecture
						$wpdb->termmeta,
						array(
							'term_id'    => (int) $row->term_id,
							'meta_key'   => 'mbs_sort_key', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- standard WP query pattern; VIP rule does not apply to this plugin
							'meta_value' => mbs_compute_sort_key( $row->name ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- standard WP query pattern; VIP rule does not apply to this plugin
						),
						array( '%d', '%s', '%s' )
					);
				}
			}
		}

		// Books: mbs_title_sort_key from post_title.
		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
		$books = $wpdb->get_results( $wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- DAO layer -- direct DB access is intentional per MBS architecture
			"SELECT ID, post_title
			 FROM {$wpdb->posts}
			 WHERE post_type   = %s
			   AND post_status != 'auto-draft'
			   AND NOT EXISTS (
			       SELECT 1 FROM {$wpdb->postmeta}
			       WHERE post_id  = {$wpdb->posts}.ID
			         AND meta_key = 'mbs_title_sort_key'
			   )",
			MBS_POST_TYPE
		) );
		if ( ! empty( $books ) ) {
			foreach ( $books as $book ) {
				$wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- DAO layer -- direct DB access is intentional per MBS architecture
					$wpdb->postmeta,
					array(
						'post_id'    => (int) $book->ID,
						'meta_key'   => 'mbs_title_sort_key', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- standard WP query pattern; VIP rule does not apply to this plugin
						'meta_value' => mbs_compute_sort_key( $book->post_title ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- standard WP query pattern; VIP rule does not apply to this plugin
					),
					array( '%d', '%s', '%s' )
				);
			}
		}
	}
}
