<?php
/**
 * Student account audit logging.
 *
 * @package TutorHelper_Bookings
 */

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

/**
 * Records changes made to student accounts.
 */
final class TutorHelper_Student_Audit_Log {

	/**
	 * Record a student-account change.
	 *
	 * Password values must never be passed to this method.
	 *
	 * @param int    $student_user_id Student WordPress user ID.
	 * @param string $action          Audit action.
	 * @param string $field_key       Changed field.
	 * @param mixed  $old_value       Previous value.
	 * @param mixed  $new_value       New value.
	 * @param string $context         Change origin.
	 *
	 * @return bool
	 */
	public static function record(
		$student_user_id,
		$action,
		$field_key = '',
		$old_value = '',
		$new_value = '',
		$context = 'admin'
	) {
		global $wpdb;

		$student_user_id = absint(
			$student_user_id
		);

		$changed_by_user_id = get_current_user_id();

		if (
			! $student_user_id
			|| ! $changed_by_user_id
		) {
			return false;
		}

		$table_name =
			TutorHelper_Bookings_Database::get_table_name(
				'student_audit'
			);

		if ( '' === $table_name ) {
			return false;
		}

		$result = $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Audit records are stored in the TutorHelper custom audit table; caching does not apply to writes.
			$table_name,
			array(
				'student_user_id' =>
					$student_user_id,

				'changed_by_user_id' =>
					$changed_by_user_id,

				'action' =>
					sanitize_key( $action ),

				'field_key' =>
					sanitize_key( $field_key ),

				'old_value' =>
					self::prepare_value(
						$old_value
					),

				'new_value' =>
					self::prepare_value(
						$new_value
					),

				'context' =>
					sanitize_key( $context ),

				'created_at' =>
					current_time(
						'mysql',
						true
					),
			),
			array(
				'%d',
				'%d',
				'%s',
				'%s',
				'%s',
				'%s',
				'%s',
				'%s',
			)
		);

		return false !== $result;
	}

	/**
	 * Return recent audit entries for a student.
	 *
	 * @param int $student_user_id Student WordPress user ID.
	 * @param int $limit           Maximum rows.
	 *
	 * @return array
	 */
	public static function get_for_student(
		$student_user_id,
		$limit = 50
	) {
		global $wpdb;

		$table_name =
			TutorHelper_Bookings_Database::get_table_name(
				'student_audit'
			);

		$student_user_id = absint(
			$student_user_id
		);

		$limit = max(
			1,
			min(
				200,
				absint( $limit )
			)
		);

		if (
			'' === $table_name
			|| ! $student_user_id
		) {
			return array();
		}

		return $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Audit history must include newly recorded changes immediately, so this custom-table read is intentionally uncached.
			$wpdb->prepare(
				'SELECT *
				FROM %i
				WHERE student_user_id = %d
				ORDER BY created_at DESC, id DESC
				LIMIT %d',
				$table_name,
				$student_user_id,
				$limit
			)
		);
	}

	/**
	 * Convert an audit value to safe text.
	 *
	 * @param mixed $value Value.
	 *
	 * @return string
	 */
	private static function prepare_value(
		$value
	) {
		if ( is_bool( $value ) ) {
			return $value ? '1' : '0';
		}

		if (
			is_array( $value )
			|| is_object( $value )
		) {
			return wp_json_encode(
				$value
			);
		}

		return sanitize_textarea_field(
			(string) $value
		);
	}
}
