<?php
/**
 * Truebe query log: one row per visitor question, recording whether it was
 * answered from the library or fell through as a gap. This is the data the
 * reporting view reads. Public-visitor questions only; internal admin chat
 * is not logged.
 */

if ( ! defined( 'ABSPATH' ) ) { exit; }
if ( class_exists( 'Truebe_Query_Log' ) ) { return; }

class Truebe_Query_Log {

	const STATUS_ANSWERED = 'answered';
	const STATUS_GAP      = 'gap';

	/** Table name with prefix. */
	public static function table() {
		global $wpdb;
		return $wpdb->prefix . 'truebe_query_log';
	}

	/** Create the table. Called on activation. */
	public static function install() {
		global $wpdb;
		$table   = self::table();
		$charset = $wpdb->get_charset_collate();
		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
		$sql = "CREATE TABLE {$table} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			question TEXT NOT NULL,
			status VARCHAR(20) NOT NULL DEFAULT 'gap',
			seed_id BIGINT UNSIGNED NULL,
			seed_label TEXT NULL,
			created_at DATETIME NOT NULL,
			PRIMARY KEY  (id),
			KEY status (status),
			KEY created_at (created_at)
		) {$charset};";
		dbDelta( $sql );
	}

	/** True if the table exists. Used to self-heal on any code path that writes or reads it. */
	private static function ensure_table() {
		global $wpdb;
		$table = self::table();
		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- checking table existence; fixed prefix + string.
		$exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) );
		if ( $exists !== $table ) {
			self::install();
		}
	}

	/**
	 * Record one visitor question.
	 *
	 * @param string   $question   The raw visitor question.
	 * @param string   $status     self::STATUS_ANSWERED or self::STATUS_GAP.
	 * @param int|null $seed_id    Matched seed id, if answered.
	 * @param string   $seed_label Matched seed label, if answered.
	 */
	public static function record( $question, $status, $seed_id = null, $seed_label = '' ) {
		$question = trim( (string) $question );
		if ( '' === $question ) { return; }
		self::ensure_table();
		global $wpdb;
		$table = self::table();
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- custom plugin table; no object cache for writes.
		$ok = $wpdb->insert(
			$table,
			array(
				'question'   => $question,
				'status'     => ( self::STATUS_ANSWERED === $status ) ? self::STATUS_ANSWERED : self::STATUS_GAP,
				'seed_id'    => $seed_id ? (int) $seed_id : null,
				'seed_label' => (string) $seed_label,
				'created_at' => current_time( 'mysql' ),
			),
			array( '%s', '%s', '%d', '%s', '%s' )
		);
		if ( false === $ok && function_exists( 'error_log' ) ) {
			error_log( 'Truebe query log insert failed: ' . $wpdb->last_error ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- surfaces a silent write failure for debugging; not user-facing.
		}
	}
}