<?php
/**
 * Custom Fields tab — define meta fields shown on the vehicle edit screen.
 *
 * Extracted from AdminSettings per QUALITY-IMPROVEMENT-PLAN.md §T2-2.
 *
 * @package ThemeREX\AutoDealer\Admin\Settings\Tabs
 */

declare(strict_types=1);

namespace ThemeREX\AutoDealer\Admin\Settings\Tabs;

defined( 'ABSPATH' ) || exit;

use ThemeREX\AutoDealer\Admin\AdminSettings;
use ThemeREX\AutoDealer\Admin\Settings\AbstractSettingsTab;
use ThemeREX\AutoDealer\Admin\AdminAssets;

final class FieldsTab extends AbstractSettingsTab {

	/**
	 * Allowed field types for custom meta fields.
	 *
	 * @var string[]
	 */
	public const FIELD_TYPES = array(
		'text',
		'number',
		'textarea',
		'select',
		'checkbox',
		'date',
		'url',
	);

	public function getKey(): string {
		return 'fields';
	}

	public function getLabel(): string {
		return __( 'Custom Fields', 'trx-auto-dealer' );
	}

	public function register(): void {
		// This tab's register() runs *inside* AdminSettings::registerSettings,
		// which is itself hooked to `admin_init` — so adding another
		// `admin_init` hook here is too late (admin_init has already fired for
		// this request) and the save handler never ran, so edits + deletes
		// silently vanished (UAT #21). Switching to `admin_post_*` works
		// because admin-post.php fires `admin_init` first, *then* the
		// admin_post_* action, so a hook bound during admin_init still runs.
		add_action( 'admin_post_trx_ad_save_custom_fields', array( $this, 'handleFieldsSave' ) );
	}

	/**
	 * Custom POST handler — writes to AdminSettings::FIELDS_OPTION_KEY directly
	 * (not Settings API; this is a repeating row-list with its own format).
	 */
	public function handleFieldsSave(): void {
		if (
			! isset( $_POST['trx_ad_fields_nonce'] )
			|| ! wp_verify_nonce(
				sanitize_text_field( wp_unslash( $_POST['trx_ad_fields_nonce'] ) ),
				'trx_ad_save_custom_fields'
			)
		) {
			wp_die( esc_html__( 'Invalid request.', 'trx-auto-dealer' ), 400 );
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Permission denied.', 'trx-auto-dealer' ), 403 );
		}

		// Sanitized at the read: unslash + text-field-sanitize every leaf of
		// the nested field-definition array; the loop below then applies the
		// per-key sanitizers (sanitize_key, esc_url_raw, ...).
		$raw = isset( $_POST['trx_ad_cf'] ) && is_array( $_POST['trx_ad_cf'] )
			? map_deep( wp_unslash( $_POST['trx_ad_cf'] ), 'sanitize_text_field' )
			: array();

		$fields = array();

		foreach ( $raw as $field ) {
			if ( ! is_array( $field ) ) {
				continue;
			}

			$label = sanitize_text_field( $field['label'] ?? '' );
			if ( $label === '' ) {
				continue;
			}

			$key = sanitize_key( $field['key'] ?? '' );
			if ( $key === '' ) {
				$key = sanitize_key( str_replace( ' ', '_', strtolower( $label ) ) );
			}

			$type = sanitize_key( $field['type'] ?? 'text' );
			if ( ! in_array( $type, self::FIELD_TYPES, true ) ) {
				$type = 'text';
			}

			$fields[] = array(
				'id'          => sanitize_key( $field['id'] ?? wp_generate_uuid4() ),
				'label'       => $label,
				'key'         => $key,
				'type'        => $type,
				'options'     => sanitize_text_field( $field['options'] ?? '' ),
				'description' => sanitize_text_field( $field['description'] ?? '' ),
				'group'       => sanitize_text_field( $field['group'] ?? '' ),
			);
		}

		update_option( AdminSettings::FIELDS_OPTION_KEY, $fields );

		wp_safe_redirect(
			add_query_arg(
				array(
					'post_type' => 'trx_ad_listing',
					'page'      => AdminSettings::PAGE_SLUG,
					'tab'       => 'fields',
					'updated'   => '1',
				),
				admin_url( 'edit.php' )
			)
		);
		exit;
	}

	public function render(): void {
		$fields = AdminSettings::getCustomFields();

		// Pre-render the <option> list once so the inline add-row script can
		// inject it as a single JS string literal. A previous version echoed a
		// multi-line PHP loop directly inside a single-quoted JS string, which
		// produced an unterminated string literal and threw a SyntaxError —
		// that broke the whole IIFE, so neither "Add Field" nor the row remove
		// buttons worked (UAT #20/#21).
		if ( isset( $_GET['updated'] ) && $_GET['updated'] === '1' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			echo '<div class="notice notice-success is-dismissible"><p>';
			esc_html_e( 'Custom fields saved.', 'trx-auto-dealer' );
			echo '</p></div>';
		}

		?>
		<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
			<input type="hidden" name="action" value="trx_ad_save_custom_fields">
			<?php wp_nonce_field( 'trx_ad_save_custom_fields', 'trx_ad_fields_nonce' ); ?>

			<p class="description" style="margin:15px 0 10px;">
				<?php esc_html_e( 'Define custom fields that appear on the vehicle edit screen.', 'trx-auto-dealer' ); ?>
			</p>

			<table class="widefat trx-ad-fields-table" id="trx-ad-fields-table">
				<thead>
					<tr>
						<th class="trx-ad-col-sort" style="width:30px;"></th>
						<th><?php esc_html_e( 'Label', 'trx-auto-dealer' ); ?></th>
						<th><?php esc_html_e( 'Key', 'trx-auto-dealer' ); ?></th>
						<th><?php esc_html_e( 'Type', 'trx-auto-dealer' ); ?></th>
						<th><?php esc_html_e( 'Options', 'trx-auto-dealer' ); ?></th>
						<th><?php esc_html_e( 'Description', 'trx-auto-dealer' ); ?></th>
						<th><?php esc_html_e( 'Group', 'trx-auto-dealer' ); ?></th>
						<th style="width:50px;"></th>
					</tr>
				</thead>
				<tbody id="trx-ad-fields-body">
					<?php
					if ( ! empty( $fields ) ) {
						foreach ( $fields as $i => $field ) {
							$this->renderFieldRow( $i, $field );
						}
					}
					?>
				</tbody>
			</table>

			<p>
				<button type="button" class="button" id="trx-ad-add-field">
					<?php esc_html_e( '+ Add Field', 'trx-auto-dealer' ); ?>
				</button>
			</p>

			<?php submit_button( __( 'Save Custom Fields', 'trx-auto-dealer' ) ); ?>
		</form>

		<?php
		// The tab behavior lives in assets/js/admin.js (initFieldsTab, guarded
		// on #trx-ad-fields-body); only DATA crosses the PHP->JS boundary, via
		// wp_localize_script (wp.org 2026-07 review round 2: no PHP-composed
		// script bodies).
		wp_localize_script(
			AdminAssets::JS_HANDLE,
			'trxAdFieldsTab',
			array(
				'fieldTypes' => self::FIELD_TYPES,
				'i18n'       => array(
					'labelPh'   => __( 'Field Label', 'trx-auto-dealer' ),
					'keyPh'     => __( 'auto_generated', 'trx-auto-dealer' ),
					'optionsPh' => __( 'opt1, opt2 (select only)', 'trx-auto-dealer' ),
					'descPh'    => __( 'Help text', 'trx-auto-dealer' ),
					'groupPh'   => __( 'Group', 'trx-auto-dealer' ),
					'remove'    => __( 'Remove', 'trx-auto-dealer' ),
				),
			)
		);
	}

	private function renderFieldRow( int $i, array $field ): void {
		$pfx = 'trx_ad_cf[' . $i . ']';
		?>
		<tr draggable="true">
			<td class="trx-ad-col-sort">
				<span class="dashicons dashicons-menu" style="cursor:grab;color:#999;"></span>
			</td>
			<td>
				<input type="hidden" name="<?php echo esc_attr( $pfx ); ?>[id]" value="<?php echo esc_attr( $field['id'] ?? '' ); ?>">
				<input type="text" name="<?php echo esc_attr( $pfx ); ?>[label]" value="<?php echo esc_attr( $field['label'] ?? '' ); ?>"
						class="regular-text" placeholder="<?php esc_attr_e( 'Field Label', 'trx-auto-dealer' ); ?>" required>
			</td>
			<td>
				<input type="text" name="<?php echo esc_attr( $pfx ); ?>[key]" value="<?php echo esc_attr( $field['key'] ?? '' ); ?>"
						class="regular-text" placeholder="<?php esc_attr_e( 'auto_generated', 'trx-auto-dealer' ); ?>">
			</td>
			<td>
				<select name="<?php echo esc_attr( $pfx ); ?>[type]">
					<?php foreach ( self::FIELD_TYPES as $t ) : ?>
						<option value="<?php echo esc_attr( $t ); ?>" <?php selected( $field['type'] ?? 'text', $t ); ?>>
							<?php echo esc_html( ucfirst( $t ) ); ?>
						</option>
					<?php endforeach; ?>
				</select>
			</td>
			<td>
				<input type="text" name="<?php echo esc_attr( $pfx ); ?>[options]" value="<?php echo esc_attr( $field['options'] ?? '' ); ?>"
						class="regular-text" placeholder="<?php esc_attr_e( 'opt1, opt2 (select only)', 'trx-auto-dealer' ); ?>">
			</td>
			<td>
				<input type="text" name="<?php echo esc_attr( $pfx ); ?>[description]" value="<?php echo esc_attr( $field['description'] ?? '' ); ?>"
						class="regular-text" placeholder="<?php esc_attr_e( 'Help text', 'trx-auto-dealer' ); ?>">
			</td>
			<td>
				<input type="text" name="<?php echo esc_attr( $pfx ); ?>[group]" value="<?php echo esc_attr( $field['group'] ?? '' ); ?>"
						class="small-text" placeholder="<?php esc_attr_e( 'Group', 'trx-auto-dealer' ); ?>">
			</td>
			<td>
				<button type="button" class="button-link trx-ad-remove-field" style="color:#b32d2e;" title="<?php esc_attr_e( 'Remove', 'trx-auto-dealer' ); ?>">
					<span class="dashicons dashicons-trash"></span>
				</button>
			</td>
		</tr>
		<?php
	}
}
