<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
const DROP_PRINT_CHANGE_PAPER_PAGE_SLUG = 'drop-print-change-paper';
function drop_print_change_paper_page_url( array $args = array() ): string {
	return add_query_arg( array_merge( array( 'page' => DROP_PRINT_CHANGE_PAPER_PAGE_SLUG ), $args ), admin_url( 'admin.php' ) );
}
function drop_print_change_paper_register_page() {
	add_submenu_page(
		'drop-print-settings',
		__( 'Change paper', 'drop-print' ),
		__( 'Change paper', 'drop-print' ),
		'manage_options',
		DROP_PRINT_CHANGE_PAPER_PAGE_SLUG,
		'drop_print_change_paper_render_page'
	);
}
add_action( 'admin_menu', 'drop_print_change_paper_register_page' );
function drop_print_change_paper_group_by_canonical( array $preview ): array {
	$by_canonical = array();
	foreach ( $preview['products'] as $product ) {
		foreach ( $product['variations'] as $row ) {
			if ( empty( $row['canonical_id'] ) || $row['canonical_id'] <= 0 ) {
				continue; 
			}
			$cid = (int) $row['canonical_id'];
			if ( ! isset( $by_canonical[ $cid ] ) ) {
				$by_canonical[ $cid ] = array(
					'canonical_id'   => $cid,
					'canonical_name' => $row['canonical_name'] ?? ( '#' . $cid ),
					'count'          => 0,
				);
			}
			$by_canonical[ $cid ]['count']++;
		}
	}
	uasort( $by_canonical, static function ( $a, $b ) {
		return $b['count'] <=> $a['count'];
	} );
	return $by_canonical;
}
function drop_print_change_paper_variations_for_canonical( array $preview, int $canonical_id ): array {
	$rows = array();
	foreach ( $preview['products'] as $product ) {
		foreach ( $product['variations'] as $row ) {
			if ( (int) ( $row['canonical_id'] ?? 0 ) !== $canonical_id ) {
				continue;
			}
			$rows[] = array(
				'variation_id' => $row['variation_id'],
				'product_id'   => $product['product_id'],
				'product_name' => $product['product_name'],
				'size_label'   => function_exists( 'drop_print_sku_migration_display_size_label' )
					? drop_print_sku_migration_display_size_label( $row['size_label'] )
					: $row['size_label'],
				'old_sku'      => $row['old_sku'],
			);
		}
	}
	return $rows;
}
function drop_print_change_paper_render_page() {
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_die( esc_html__( 'You do not have sufficient permissions to do this.', 'drop-print' ) );
	}
	$preview = drop_print_change_paper_papers_in_use_preview();
	if ( is_wp_error( $preview ) ) {
		echo '<div class="wrap"><h1>' . esc_html__( 'Change paper', 'drop-print' ) . '</h1>';
		echo '<div class="notice notice-error"><p>' . esc_html( $preview->get_error_message() ) . '</p></div></div>';
		return;
	}
	$source_id = isset( $_GET['source'] ) ? absint( $_GET['source'] ) : 0;
	echo '<div class="wrap dp-change-paper">';
	echo '<h1>' . esc_html__( 'Change paper', 'drop-print' ) . '</h1>';
	echo '<p>' . esc_html__( 'Move some or all of your existing prints onto a different paper. This does not change price or size, only which paper the print is made on.', 'drop-print' ) . '</p>';
	if ( $source_id > 0 ) {
		drop_print_change_paper_render_filter_view( $preview, $source_id );
	} else {
		drop_print_change_paper_render_landing_view( $preview );
	}
	echo '</div>';
}
function drop_print_change_paper_papers_in_use_preview() {
	static $preview = null;
	if ( null === $preview ) {
		$preview = function_exists( 'drop_print_sku_migration_build_preview' )
			? drop_print_sku_migration_build_preview()
			: new WP_Error( 'dp_change_paper_engine_missing', __( 'Not available.', 'drop-print' ) );
	}
	return $preview;
}
function drop_print_change_paper_render_landing_view( array $preview ) {
	$by_canonical = drop_print_change_paper_group_by_canonical( $preview );
	if ( empty( $by_canonical ) ) {
		echo '<p>' . esc_html__( 'No Drop Print products found yet.', 'drop-print' ) . '</p>';
		return;
	}
	?>
	<table class="widefat striped">
		<thead>
			<tr>
				<th><?php esc_html_e( 'Paper', 'drop-print' ); ?></th>
				<th><?php esc_html_e( 'Variations', 'drop-print' ); ?></th>
				<th></th>
			</tr>
		</thead>
		<tbody>
			<?php foreach ( $by_canonical as $row ) : ?>
				<tr>
					<td><?php echo esc_html( $row['canonical_name'] ); ?> <span style="color:#787c82">#<?php echo esc_html( $row['canonical_id'] ); ?></span></td>
					<td><?php echo esc_html( $row['count'] ); ?></td>
					<td><a class="button" href="<?php echo esc_url( drop_print_change_paper_page_url( array( 'source' => $row['canonical_id'] ) ) ); ?>"><?php esc_html_e( 'Change these →', 'drop-print' ); ?></a></td>
				</tr>
			<?php endforeach; ?>
		</tbody>
	</table>
	<?php
}
function drop_print_change_paper_render_filter_view( array $preview, int $source_id ) {
	$rows = drop_print_change_paper_variations_for_canonical( $preview, $source_id );
	$product_all_variation_ids = array();
	foreach ( $rows as $row ) {
		$product_all_variation_ids[ $row['product_id'] ] = true;
	}
	foreach ( array_keys( $product_all_variation_ids ) as $product_id ) {
		$ids = array();
		foreach ( $preview['products'][ $product_id ]['variations'] ?? array() as $v ) {
			$ids[] = (int) $v['variation_id'];
		}
		$product_all_variation_ids[ $product_id ] = $ids;
	}
	$source_name = '';
	foreach ( $preview['products'] as $product ) {
		foreach ( $product['variations'] as $row ) {
			if ( (int) ( $row['canonical_id'] ?? 0 ) === $source_id ) {
				$source_name = $row['canonical_name'] ?? '';
				break 2;
			}
		}
	}
	echo '<p><a href="' . esc_url( drop_print_change_paper_page_url() ) . '">&larr; ' . esc_html__( 'All papers', 'drop-print' ) . '</a></p>';
	echo '<h2>' . sprintf(
		esc_html__( 'Moving prints off %1$s (%2$d variations found)', 'drop-print' ),
		esc_html( $source_name ),
		count( $rows )
	) . '</h2>';
	if ( empty( $rows ) ) {
		echo '<p>' . esc_html__( 'Nothing found on this paper any more.', 'drop-print' ) . '</p>';
		return;
	}
	?>
	<div id="dp-change-paper-app" data-source-id="<?php echo esc_attr( $source_id ); ?>" data-product-siblings="<?php echo esc_attr( wp_json_encode( $product_all_variation_ids ) ); ?>">
		<p>
			<label for="dp-change-paper-target"><?php esc_html_e( 'Move to:', 'drop-print' ); ?></label>
			<select id="dp-change-paper-target">
				<option value=""><?php esc_html_e( 'Choose a paper…', 'drop-print' ); ?></option>
			</select>
			<button type="button" class="button" id="dp-change-paper-preview-btn" disabled><?php esc_html_e( 'Preview', 'drop-print' ); ?></button>
		</p>
		<p id="dp-change-paper-status"></p>
		<table class="widefat striped" id="dp-change-paper-table" hidden>
			<thead>
				<tr>
					<th class="check-column"><input type="checkbox" id="dp-change-paper-select-all" checked></th>
					<th><?php esc_html_e( 'Product', 'drop-print' ); ?></th>
					<th><?php esc_html_e( 'Size', 'drop-print' ); ?></th>
					<th><?php esc_html_e( 'New Drop Print code', 'drop-print' ); ?></th>
				</tr>
			</thead>
			<tbody id="dp-change-paper-tbody">
				<?php foreach ( $rows as $row ) : ?>
					<tr data-variation-id="<?php echo esc_attr( $row['variation_id'] ); ?>" data-product-id="<?php echo esc_attr( $row['product_id'] ); ?>" data-old-sku="<?php echo esc_attr( $row['old_sku'] ); ?>" hidden>
						<td class="check-column"><input type="checkbox" class="dp-change-paper-row-check" checked></td>
						<td><?php echo esc_html( $row['product_name'] ); ?></td>
						<td><?php echo esc_html( $row['size_label'] ); ?></td>
						<td class="dp-change-paper-new-sku">&mdash;</td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
		<p>
			<button type="button" class="button button-primary" id="dp-change-paper-apply-btn" hidden><?php esc_html_e( 'Change paper', 'drop-print' ); ?></button>
			<span id="dp-change-paper-progress"></span>
		</p>
	</div>
	<?php wp_nonce_field( 'drop_print_sku_migration_run' ); ?>
	<?php wp_nonce_field( 'drop_print_sku_migration_alternatives', 'dp_change_paper_alt_nonce', false ); ?>
	<script>
	(function () {
		var app = document.getElementById('dp-change-paper-app');
		if (!app) { return; }
		var targetSelect = document.getElementById('dp-change-paper-target');
		var previewBtn = document.getElementById('dp-change-paper-preview-btn');
		var applyBtn = document.getElementById('dp-change-paper-apply-btn');
		var statusEl = document.getElementById('dp-change-paper-status');
		var progressEl = document.getElementById('dp-change-paper-progress');
		var table = document.getElementById('dp-change-paper-table');
		var selectAll = document.getElementById('dp-change-paper-select-all');
		var runNonce = document.getElementById('_wpnonce');
		var altNonce = document.getElementById('dp_change_paper_alt_nonce');
		var resolvedByRow = {}; // variationId -> { canonicalId, canonicalName, newSku }
		function allRows() { return Array.prototype.slice.call(document.querySelectorAll('#dp-change-paper-tbody tr')); }
		// doc client/47 §3.2 - the SAME identity-list endpoint the substitution
		// modal uses, reused for this page's target-paper dropdown.
		fetch(ajaxurl, {
			method: 'POST',
			credentials: 'same-origin',
			body: (function () {
				var b = new URLSearchParams();
				b.set('action', 'drop_print_sku_migration_alternatives');
				b.set('nonce', altNonce ? altNonce.value : '');
				return b;
			})()
		}).then(function (r) { return r.json(); }).then(function (data) {
			if (!data || !data.success || !data.data || !Array.isArray(data.data.papers)) { return; }
			data.data.papers.forEach(function (paper) {
				var opt = document.createElement('option');
				opt.value = paper.canonical_id;
				var bits = [paper.name];
				if (paper.gsm) { bits.push(paper.gsm + 'gsm'); }
				if (paper.finish) { bits.push(paper.finish); }
				opt.textContent = bits.join(' · ');
				targetSelect.appendChild(opt);
			});
		});
		if (targetSelect) {
			targetSelect.addEventListener('change', function () {
				if (previewBtn) { previewBtn.disabled = !targetSelect.value; }
			});
		}
		if (previewBtn) {
			previewBtn.addEventListener('click', function () {
				var canonicalId = targetSelect.value;
				if (!canonicalId) { return; }
				var rows = allRows();
				var skus = rows.map(function (tr) { return tr.getAttribute('data-old-sku'); });
				if (statusEl) { statusEl.textContent = 'Checking sizes…'; }
				previewBtn.disabled = true;
				var body = new URLSearchParams();
				body.set('action', 'drop_print_sku_migration_resolve_override_batch');
				body.set('nonce', altNonce ? altNonce.value : '');
				skus.forEach(function (s) { body.append('skus[]', s); });
				body.set('canonical_id', canonicalId);
				fetch(ajaxurl, { method: 'POST', credentials: 'same-origin', body: body })
					.then(function (r) { return r.json(); })
					.then(function (data) {
						previewBtn.disabled = false;
						if (!data || !data.success || !data.data || !data.data.resolved) {
							if (statusEl) { statusEl.textContent = (data && data.data && data.data.message) || 'Could not check sizes - try again.'; }
							return;
						}
						resolvedByRow = {};
						var resolved = data.data.resolved;
						var okCount = 0;
						rows.forEach(function (tr) {
							var sku = tr.getAttribute('data-old-sku');
							var variationId = tr.getAttribute('data-variation-id');
							var r = resolved[sku];
							var cell = tr.querySelector('.dp-change-paper-new-sku');
							var checkbox = tr.querySelector('.dp-change-paper-row-check');
							if (r && r.new_sku) {
								resolvedByRow[variationId] = { canonicalId: r.canonical_id || canonicalId, canonicalName: r.canonical_name, newSku: r.new_sku };
								if (cell) { cell.textContent = r.new_sku; }
								if (checkbox) { checkbox.disabled = false; checkbox.checked = true; }
								okCount++;
							} else {
								if (cell) { cell.textContent = 'Could not size this one for the new paper - skipped'; }
								if (checkbox) { checkbox.checked = false; checkbox.disabled = true; }
							}
							tr.hidden = false;
						});
						if (table) { table.hidden = false; }
						if (applyBtn) { applyBtn.hidden = false; }
						if (statusEl) {
							statusEl.textContent = okCount === rows.length
								? ''
								: (rows.length - okCount) + ' of ' + rows.length + ' could not be sized for this paper and are excluded.';
						}
					})
					.catch(function () {
						previewBtn.disabled = false;
						if (statusEl) { statusEl.textContent = 'Could not reach the server - try again.'; }
					});
			});
		}
		if (selectAll) {
			selectAll.addEventListener('change', function () {
				document.querySelectorAll('.dp-change-paper-row-check:not(:disabled)').forEach(function (cb) { cb.checked = selectAll.checked; });
			});
		}
		// doc client/47 §5 - same chunking discipline as the migration screen's
		// "Run migration": product-grouped batches, never splitting one
		// product's variations across two chunk requests (apply()'s writer
		// rebuilds a product's WHOLE variation set from whatever the preview
		// holds for it - see apply_chunk()'s own caller-contract comment).
		var CHUNK_TARGET_SIZE = 100;
		// CRITICAL, matches the PHP-side comment above
		// drop_print_change_paper_render_filter_view()'s $product_all_variation_ids:
		// a product can have Drop Print variations on a DIFFERENT paper than the
		// one being changed here - those never appear as a table row, but their
		// ids MUST still be in the chunk's variation_ids or apply()'s writer
		// would silently delete them when it saves the product. This is that
		// complete per-product list, parsed once.
		var productSiblings = {};
		try { productSiblings = JSON.parse(app.getAttribute('data-product-siblings') || '{}'); } catch (err) { productSiblings = {}; }
		function buildChunks() {
			var byProduct = {};
			allRows().forEach(function (tr) {
				var productId = tr.getAttribute('data-product-id');
				if (!byProduct[productId]) { byProduct[productId] = []; }
			});
			// Seed each represented product with its COMPLETE variation set
			// (table rows + any sibling on a different paper), not just the
			// filtered rows visible in this table.
			Object.keys(byProduct).forEach(function (productId) {
				var ids = productSiblings[productId];
				byProduct[productId] = Array.isArray(ids) ? ids.map(String) : [];
			});
			var selected = {};
			document.querySelectorAll('.dp-change-paper-row-check:checked').forEach(function (cb) {
				var tr = cb.closest('tr');
				if (tr) { selected[tr.getAttribute('data-variation-id')] = true; }
			});
			var chunks = [];
			var current = { variationIds: [], selected: [] };
			Object.keys(byProduct).forEach(function (productId) {
				var ids = byProduct[productId];
				if (current.variationIds.length > 0 && current.variationIds.length + ids.length > CHUNK_TARGET_SIZE) {
					chunks.push(current);
					current = { variationIds: [], selected: [] };
				}
				ids.forEach(function (id) {
					current.variationIds.push(id);
					if (selected[id]) { current.selected.push(id); }
				});
			});
			if (current.variationIds.length > 0) { chunks.push(current); }
			return chunks;
		}
		if (applyBtn) {
			applyBtn.addEventListener('click', function () {
				var chunks = buildChunks();
				var totalSelected = chunks.reduce(function (n, c) { return n + c.selected.length; }, 0);
				if (totalSelected === 0) { return; }
				applyBtn.disabled = true;
				previewBtn.disabled = true;
				var totals = { products: 0, variations: 0, errors: [] };
				var i = 0;
				function next() {
					if (i >= chunks.length) {
						if (progressEl) {
							progressEl.textContent = 'Done - ' + totals.products + ' product(s) updated, ' + totals.variations + ' variation(s) changed.' + (totals.errors.length ? ' ' + totals.errors.length + ' error(s).' : '');
						}
						applyBtn.hidden = true;
						return;
					}
					var chunk = chunks[i];
					var expectedOld = {};
					var expectedNew = {};
					var overrideMap = {};
					chunk.variationIds.forEach(function (id) {
						var tr = document.querySelector('#dp-change-paper-tbody tr[data-variation-id="' + id + '"]');
						if (tr) { expectedOld[id] = tr.getAttribute('data-old-sku'); }
						var r = resolvedByRow[id];
						if (r) {
							expectedNew[id] = r.newSku;
							if (chunk.selected.indexOf(id) !== -1) { overrideMap[id] = r.canonicalId; }
						}
					});
					if (progressEl) { progressEl.textContent = 'Changing batch ' + (i + 1) + ' of ' + chunks.length + '…'; }
					var body = new URLSearchParams();
					body.set('action', 'drop_print_sku_migration_apply_chunk');
					body.set('_wpnonce', runNonce ? runNonce.value : '');
					body.set('payload', JSON.stringify({
						variation_ids: chunk.variationIds,
						selected_variation_ids: chunk.selected,
						expected_old_sku: expectedOld,
						expected_new_sku: expectedNew,
						override_canonical_id: overrideMap
					}));
					fetch(ajaxurl, { method: 'POST', credentials: 'same-origin', body: body })
						.then(function (r) { return r.json(); })
						.then(function (data) {
							if (!data || !data.success || !data.data || !data.data.apply) {
								if (progressEl) { progressEl.textContent = 'Batch ' + (i + 1) + ' of ' + chunks.length + ' failed - stopped. ' + totals.products + ' product(s) completed before the failure.'; }
								return;
							}
							totals.products += data.data.apply.products_migrated || 0;
							totals.variations += data.data.apply.variations_migrated || 0;
							if (Array.isArray(data.data.apply.errors)) { totals.errors = totals.errors.concat(data.data.apply.errors); }
							i++;
							next();
						})
						.catch(function () {
							if (progressEl) { progressEl.textContent = 'Could not reach the server on batch ' + (i + 1) + ' - stopped. ' + totals.products + ' product(s) completed before the failure.'; }
						});
				}
				next();
			});
		}
	})();
	</script>
	<?php
}
