<?php
/**
 * Admin UI for the tilvora_visualizer custom post type.
 *
 * Metabox on the project edit screen:
 *   - Upload a .glb model (falls back to bundled floor.glb if empty)
 *   - Edit this project's config.json (falls back to bundled default if empty)
 *   - Shows the visualizer URL + shortcode for copy-paste
 */

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

/* ── Register metabox ─────────────────────────────────────────────── */

add_action( 'add_meta_boxes_' . TILVORA_CPT, 'tilvora_register_project_metabox' );

function tilvora_register_project_metabox() {
	add_meta_box(
		'tilvora_project_settings',
		__( 'Tilvora — Visualizer Settings', 'tilvora-3d-flooring-visualizer' ),
		'tilvora_render_project_metabox',
		TILVORA_CPT,
		'normal',
		'high'
	);
}

/* ── Render metabox ───────────────────────────────────────────────── */

function tilvora_render_project_metabox( $post ) {
	wp_nonce_field( 'tilvora_save_project_metabox', 'tilvora_metabox_nonce' );
	wp_enqueue_media();

	$project_id      = $post->ID;
	$config_json     = tilvora_get_custom_config_json_raw( $project_id );
	$default_json    = tilvora_get_default_config_json_raw();
	$configurator_url = tilvora_get_configurator_url( $project_id );
	$shortcode       = '[tilvora id="' . $project_id . '"]';

	$model_id       = absint( get_post_meta( $project_id, TILVORA_META_MODEL_ID, true ) );
	$model_url      = $model_id ? wp_get_attachment_url( $model_id ) : '';
	$model_filename = $model_url ? basename( $model_url ) : '';

	$validation = tilvora_validate_config_json( $config_json );

	$js_default_config_json   = wp_json_encode( $default_json );
	$js_save_ajax_url         = wp_json_encode( admin_url( 'admin-ajax.php' ) );
	$js_save_nonce            = wp_json_encode( wp_create_nonce( 'tilvora_save_config_json' ) );
	$js_project_id            = (int) $project_id;
	$js_txt_overwrite         = wp_json_encode( __( 'Click again to overwrite', 'tilvora-3d-flooring-visualizer' ) );
	$js_txt_saving            = wp_json_encode( __( 'Saving Config JSON…', 'tilvora-3d-flooring-visualizer' ) );
	$js_txt_save_failed       = wp_json_encode( __( 'Config JSON failed to save — saving the rest of the project anyway.', 'tilvora-3d-flooring-visualizer' ) );
	$js_txt_empty_default     = wp_json_encode( __( 'Empty — bundled default will be used.', 'tilvora-3d-flooring-visualizer' ) );
	$js_txt_valid_json        = wp_json_encode( __( '✓ Valid JSON', 'tilvora-3d-flooring-visualizer' ) );
	$js_txt_invalid_prefix    = wp_json_encode( __( '✗ Invalid: ', 'tilvora-3d-flooring-visualizer' ) );

	$metabox_js = '(function () {' . "\n"
		. "\tvar defaultConfigJson = " . $js_default_config_json . ';' . "\n"
		. "\tvar tilvoraSaveAjaxUrl = " . $js_save_ajax_url . ';' . "\n"
		. "\tvar tilvoraSaveNonce   = " . $js_save_nonce . ';' . "\n"
		. "\tvar tilvoraProjectId   = " . $js_project_id . ';' . "\n\n"

		. "\t(function () {" . "\n"
		. "\t\tvar frame;" . "\n"
		. "\t\tvar selectBtn = document.getElementById('tilvora-model-select');" . "\n"
		. "\t\tvar removeBtn = document.getElementById('tilvora-model-remove');" . "\n"
		. "\t\tvar idInput   = document.getElementById('tilvora-model-id');" . "\n"
		. "\t\tvar statusEl  = document.getElementById('tilvora-model-status');" . "\n"
		. "\t\tif (!selectBtn) return;" . "\n"
		. "\t\tselectBtn.addEventListener('click', function (e) {" . "\n"
		. "\t\t\te.preventDefault();" . "\n"
		. "\t\t\tif (!window.wp || !wp.media) return;" . "\n"
		. "\t\t\tif (!frame) {" . "\n"
		. "\t\t\t\tframe = wp.media({ title: 'Select GLB Model', button: { text: 'Use this model' }, multiple: false, library: { type: 'model/gltf-binary' } });" . "\n"
		. "\t\t\t\tframe.on('select', function () {" . "\n"
		. "\t\t\t\t\tvar att = frame.state().get('selection').first().toJSON();" . "\n"
		. "\t\t\t\t\tidInput.value = att.id;" . "\n"
		. "\t\t\t\t\tstatusEl.textContent = att.filename || att.title || ('Attachment #' + att.id);" . "\n"
		. "\t\t\t\t\tremoveBtn.style.display = '';" . "\n"
		. "\t\t\t\t\tselectBtn.textContent = 'Change Model';" . "\n"
		. "\t\t\t\t});" . "\n"
		. "\t\t\t}" . "\n"
		. "\t\t\tframe.open();" . "\n"
		. "\t\t});" . "\n"
		. "\t\tremoveBtn.addEventListener('click', function (e) {" . "\n"
		. "\t\t\te.preventDefault();" . "\n"
		. "\t\t\tidInput.value = '';" . "\n"
		. "\t\t\tstatusEl.textContent = 'Using bundled default model (floor.glb)';" . "\n"
		. "\t\t\tremoveBtn.style.display = 'none';" . "\n"
		. "\t\t\tselectBtn.textContent = 'Select GLB Model';" . "\n"
		. "\t\t});" . "\n"
		. "\t})();" . "\n\n"

		. "\t(function () {" . "\n"
		. "\t\tvar btn = document.getElementById('tilvora-load-default');" . "\n"
		. "\t\tvar originalText = btn.textContent;" . "\n"
		. "\t\tvar armed = false, resetTimer = null;" . "\n"
		. "\t\tbtn.addEventListener('click', function () {" . "\n"
		. "\t\t\tif (!armed) {" . "\n"
		. "\t\t\t\tarmed = true;" . "\n"
		. "\t\t\t\tbtn.textContent = " . $js_txt_overwrite . ';' . "\n"
		. "\t\t\t\tbtn.classList.add('button-primary');" . "\n"
		. "\t\t\t\tresetTimer = setTimeout(function () {" . "\n"
		. "\t\t\t\t\tarmed = false;" . "\n"
		. "\t\t\t\t\tbtn.textContent = originalText;" . "\n"
		. "\t\t\t\t\tbtn.classList.remove('button-primary');" . "\n"
		. "\t\t\t\t}, 4000);" . "\n"
		. "\t\t\t\treturn;" . "\n"
		. "\t\t\t}" . "\n"
		. "\t\t\tclearTimeout(resetTimer);" . "\n"
		. "\t\t\tarmed = false;" . "\n"
		. "\t\t\tbtn.textContent = originalText;" . "\n"
		. "\t\t\tbtn.classList.remove('button-primary');" . "\n"
		. "\t\t\tdocument.getElementById('tilvora_config_json').value = defaultConfigJson;" . "\n"
		. "\t\t});" . "\n"
		. "\t})();" . "\n\n"

		. "\tdocument.getElementById('tilvora-load-file').addEventListener('click', function () {" . "\n"
		. "\t\tdocument.getElementById('tilvora-file-input').click();" . "\n"
		. "\t});" . "\n\n"

		. "\tvar postForm = document.getElementById('post');" . "\n"
		. "\tvar ffAjaxSaveInFlight = false;" . "\n"
		. "\tif (postForm) {" . "\n"
		. "\t\tpostForm.addEventListener('submit', function (e) {" . "\n"
		. "\t\t\tvar marker = document.getElementById('tilvora_config_json_saved_via_ajax');" . "\n"
		. "\t\t\tif (ffAjaxSaveInFlight || (marker && marker.value === '1')) { return; }" . "\n"
		. "\t\t\te.preventDefault();" . "\n"
		. "\t\t\tffAjaxSaveInFlight = true;" . "\n"
		. "\t\t\tvar raw = document.getElementById('tilvora_config_json').value;" . "\n"
		. "\t\t\tvar statusEl = document.getElementById('tilvora-json-status');" . "\n"
		. "\t\t\tif (statusEl) { statusEl.textContent = " . $js_txt_saving . '; statusEl.style.color = \'#646970\'; }' . "\n"
		. "\t\t\tfetch(" . "\n"
		. "\t\t\t\ttilvoraSaveAjaxUrl + '?action=tilvora_save_config_json&nonce=' + encodeURIComponent(tilvoraSaveNonce) + '&project_id=' + tilvoraProjectId," . "\n"
		. "\t\t\t\t{ method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'text/plain;charset=UTF-8' }, body: raw }" . "\n"
		. "\t\t\t).then(function (r) { return r.json(); }).catch(function () { return null; }).then(function (json) {" . "\n"
		. "\t\t\t\tffAjaxSaveInFlight = false;" . "\n"
		. "\t\t\t\tif (marker) marker.value = '1';" . "\n"
		. "\t\t\t\tif (json && json.success === false && statusEl) {" . "\n"
		. "\t\t\t\t\tstatusEl.textContent = " . $js_txt_save_failed . '; statusEl.style.color = \'#b32d2e\';' . "\n"
		. "\t\t\t\t}" . "\n"
		. "\t\t\t\tpostForm.requestSubmit ? postForm.requestSubmit(e.submitter) : postForm.submit();" . "\n"
		. "\t\t\t});" . "\n"
		. "\t\t});" . "\n"
		. "\t}" . "\n\n"

		. "\tdocument.getElementById('tilvora-file-input').addEventListener('change', function (e) {" . "\n"
		. "\t\tvar file = e.target.files && e.target.files[0];" . "\n"
		. "\t\tif (!file) return;" . "\n"
		. "\t\tvar reader = new FileReader();" . "\n"
		. "\t\treader.onload = function (evt) { document.getElementById('tilvora_config_json').value = evt.target.result; };" . "\n"
		. "\t\treader.readAsText(file);" . "\n"
		. "\t\te.target.value = '';" . "\n"
		. "\t});" . "\n\n"

		. "\tdocument.getElementById('tilvora-validate-json').addEventListener('click', function () {" . "\n"
		. "\t\tvar status = document.getElementById('tilvora-json-status');" . "\n"
		. "\t\tvar val = document.getElementById('tilvora_config_json').value.trim();" . "\n"
		. "\t\tif (val === '') { status.textContent = " . $js_txt_empty_default . '; status.style.color = \'#646970\'; return; }' . "\n"
		. "\t\ttry { JSON.parse(val); status.textContent = " . $js_txt_valid_json . '; status.style.color = \'#1a7e3e\'; }' . "\n"
		. "\t\tcatch (err) { status.textContent = " . $js_txt_invalid_prefix . " + err.message; status.style.color = '#b32d2e'; }" . "\n"
		. "\t});" . "\n\n"

		. '})();';

	wp_register_script( 'tilvora-project-metabox', false, [], TILVORA_VERSION, true );
	wp_enqueue_script( 'tilvora-project-metabox' );
	wp_add_inline_script( 'tilvora-project-metabox', $metabox_js );
	?>
	<div class="tilvora-metabox" style="max-width:900px">

		<!-- ── Visualizer link + shortcode ─────────────────────────── -->
		<?php if ( 'publish' === $post->post_status ) : ?>
		<table class="form-table" style="margin-bottom:0">
			<tr>
				<th><?php esc_html_e( 'Visualizer URL', 'tilvora-3d-flooring-visualizer' ); ?></th>
				<td>
					<a href="<?php echo esc_url( $configurator_url ); ?>" target="_blank" rel="noopener"><?php echo esc_html( $configurator_url ); ?></a>
					<p class="description"><?php esc_html_e( 'Direct link to the full-screen 3D visualizer for this project.', 'tilvora-3d-flooring-visualizer' ); ?></p>
				</td>
			</tr>
			<tr>
				<th><?php esc_html_e( 'Embed Shortcode', 'tilvora-3d-flooring-visualizer' ); ?></th>
				<td>
					<code style="font-size:13px;user-select:all"><?php echo esc_html( $shortcode ); ?></code>
					<p class="description"><?php esc_html_e( 'Paste this into any page or post to add a "Design Your Floor" button.', 'tilvora-3d-flooring-visualizer' ); ?></p>
				</td>
			</tr>
		</table>
		<hr />
		<?php else : ?>
		<p class="description" style="margin-bottom:16px">
			<?php esc_html_e( 'Publish this project to get the visualizer URL and shortcode.', 'tilvora-3d-flooring-visualizer' ); ?>
		</p>
		<hr />
		<?php endif; ?>

		<!-- ── 3D Model ─────────────────────────────────────────────── -->
		<table class="form-table">
			<tr>
				<th><?php esc_html_e( '3D Model', 'tilvora-3d-flooring-visualizer' ); ?></th>
				<td>
					<p id="tilvora-model-status" style="margin:0 0 8px;">
						<?php echo $model_id
							? esc_html( $model_filename )
							: esc_html__( 'Using bundled default model (floor.glb)', 'tilvora-3d-flooring-visualizer' ); ?>
					</p>
					<input type="hidden" name="tilvora_model_id" id="tilvora-model-id" value="<?php echo esc_attr( $model_id ); ?>" />
					<button type="button" class="button" id="tilvora-model-select"><?php echo $model_id ? esc_html__( 'Change Model', 'tilvora-3d-flooring-visualizer' ) : esc_html__( 'Select GLB Model', 'tilvora-3d-flooring-visualizer' ); ?></button>
					<button type="button" class="button" id="tilvora-model-remove" style="<?php echo $model_id ? '' : 'display:none;'; ?>"><?php esc_html_e( 'Remove (use bundled default)', 'tilvora-3d-flooring-visualizer' ); ?></button>
					<p class="description"><?php esc_html_e( 'Upload your own .glb 3D model for this visualizer. If none is selected, the plugin\'s bundled default model is used instead.', 'tilvora-3d-flooring-visualizer' ); ?></p>
				</td>
			</tr>
		</table>

		<!-- ── Config JSON ─────────────────────────────────────────── -->
		<p class="description">
			<?php esc_html_e( 'Advanced settings for this visualizer: starting camera angle and zoom limits, background/lighting options, currency symbol, and mesh name mappings. Most projects never need to touch this. Add materials under Tilvora → Materials Library. Leave this box blank to use the bundled default.', 'tilvora-3d-flooring-visualizer' ); ?>
		</p>
		<textarea
			name="tilvora_config_json"
			id="tilvora_config_json"
			rows="18"
			style="width:100%;font-family:Consolas,Monaco,monospace;font-size:12px;"
			placeholder="<?php echo esc_attr( __( 'Leave blank to use the bundled default config.json…', 'tilvora-3d-flooring-visualizer' ) ); ?>"
		><?php echo esc_textarea( $config_json ); ?></textarea>
		<input type="hidden" name="tilvora_config_json_saved_via_ajax" id="tilvora_config_json_saved_via_ajax" value="" />
		<p>
			<button type="button" class="button" id="tilvora-load-default"><?php esc_html_e( 'Load default template', 'tilvora-3d-flooring-visualizer' ); ?></button>
			<button type="button" class="button" id="tilvora-load-file"><?php esc_html_e( 'Load from file…', 'tilvora-3d-flooring-visualizer' ); ?></button>
			<input type="file" id="tilvora-file-input" accept=".json,application/json" style="display:none;" />
			<button type="button" class="button" id="tilvora-validate-json"><?php esc_html_e( 'Validate JSON', 'tilvora-3d-flooring-visualizer' ); ?></button>
			<span id="tilvora-json-status" style="margin-left:8px;"></span>
		</p>

		<?php if ( is_wp_error( $validation ) ) : ?>
			<div class="notice notice-error inline">
				<p><?php echo esc_html( $validation->get_error_message() ); ?> <?php esc_html_e( 'The bundled default config is being used until this is fixed.', 'tilvora-3d-flooring-visualizer' ); ?></p>
			</div>
		<?php endif; ?>

	</div>
	<?php
}

/* ── Save metabox ─────────────────────────────────────────────────── */

add_action( 'save_post_' . TILVORA_CPT, 'tilvora_save_project_metabox', 10, 1 );

function tilvora_save_project_metabox( $post_id ) {
	$metabox_nonce = isset( $_POST['tilvora_metabox_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['tilvora_metabox_nonce'] ) ) : '';
	if ( '' === $metabox_nonce || ! wp_verify_nonce( $metabox_nonce, 'tilvora_save_project_metabox' ) ) {
		return;
	}
	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}

	if ( isset( $_POST['tilvora_model_id'] ) ) {
		update_post_meta( $post_id, TILVORA_META_MODEL_ID, absint( $_POST['tilvora_model_id'] ) );
	}

	if ( isset( $_POST['tilvora_config_json'] ) ) {
		if ( isset( $_POST['tilvora_config_json_saved_via_ajax'] ) && '1' === $_POST['tilvora_config_json_saved_via_ajax'] ) {
			return;
		}
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Raw JSON may contain SVG markup; sanitized via tilvora_sanitize_config_json() below.
		$raw        = wp_unslash( $_POST['tilvora_config_json'] );
		$validation = tilvora_validate_config_json( $raw );
		if ( is_wp_error( $validation ) ) {
			set_transient( 'tilvora_json_error_' . $post_id, $validation->get_error_message(), 60 );
			return;
		}
		$sanitized = tilvora_sanitize_config_json( $raw );
		if ( is_wp_error( $sanitized ) ) {
			set_transient( 'tilvora_json_error_' . $post_id, $sanitized->get_error_message(), 60 );
			return;
		}
		delete_transient( 'tilvora_json_error_' . $post_id );
		tilvora_db_set_config_json_raw( $post_id, $sanitized );
	}
}

/* ── AJAX: save config JSON via raw request body (bypasses $_POST corruption) ── */

add_action( 'wp_ajax_tilvora_save_config_json', 'tilvora_ajax_save_config_json' );

function tilvora_ajax_save_config_json() {
	check_ajax_referer( 'tilvora_save_config_json', 'nonce' );

	$project_id = isset( $_GET['project_id'] ) ? absint( $_GET['project_id'] ) : 0;
	if ( ! $project_id || ! current_user_can( 'edit_post', $project_id ) ) {
		wp_send_json_error( [ 'message' => __( 'You are not allowed to edit this project.', 'tilvora-3d-flooring-visualizer' ) ], 403 );
		return;
	}

	$raw = file_get_contents( 'php://input' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
	if ( false === $raw ) {
		$raw = '';
	}

	$validation = tilvora_validate_config_json( $raw );
	if ( is_wp_error( $validation ) ) {
		set_transient( 'tilvora_json_error_' . $project_id, $validation->get_error_message(), 60 );
		wp_send_json_success( [ 'valid' => false, 'message' => $validation->get_error_message() ] );
		return;
	}

	$sanitized = tilvora_sanitize_config_json( $raw );
	if ( is_wp_error( $sanitized ) ) {
		set_transient( 'tilvora_json_error_' . $project_id, $sanitized->get_error_message(), 60 );
		wp_send_json_error( [ 'message' => $sanitized->get_error_message() ], 400 );
		return;
	}

	tilvora_db_set_config_json_raw( $project_id, $sanitized );
	delete_transient( 'tilvora_json_error_' . $project_id );
	wp_send_json_success( [ 'valid' => true ] );
}
