<?php

namespace Limb_Chatbot\Includes\Services\Channel_Events;

use wpdb;

/**
 * Persistence layer for the general-purpose channel event queue.
 *
 * The table uses a fan-out write pattern: one row per recipient WP user.
 * This makes consumption a trivially simple indexed query without any pivot
 * or read-tracking table.
 *
 * Events are NOT auto-deleted on read. The consumer must explicitly call
 * as read) to clear events.
 *
 * All public methods guard against the table not yet existing so the plugin
 * degrades gracefully while a migration is pending.
 *
 * @package Limb_Chatbot
 * @subpackage Services\Channel_Events
 * @since 2.1.0
 */
class Channel_Event_Repository {

	/**
	 * Unprefixed table name.
	 */
	const TABLE_NAME = 'lbaic_channel_events';

	/**
	 * @var wpdb
	 */
	private wpdb $wpdb;

	/**
	 * Cache for the table-existence check (one SHOW TABLES per request).
	 *
	 * @var bool|null  null = not yet checked
	 */
	private ?bool $table_exists_cache = null;

	/**
	 * @param  wpdb|null  $wpdb
	 */
	public function __construct( ?wpdb $wpdb = null ) {
		$this->wpdb = $wpdb ?? $GLOBALS['wpdb'];
	}

	/**
	 * Persist a single channel event row.
	 *
	 * @param  Channel_Event  $event
	 *
	 * @return int|null  Inserted row ID, null on failure or missing table.
	 */
	public function insert( Channel_Event $event ): ?int {
		$table = $this->wpdb->prefix . self::TABLE_NAME;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
		$result = $this->wpdb->insert(
			$table,
			[
				'event_type'           => $event->event_type,
				'chat_uuid'            => $event->chat_uuid,
				'chatbot_user_uuid'    => $event->chatbot_user_uuid,
				'recipient_wp_user_id' => $event->recipient_wp_user_id,
				'payload'              => wp_json_encode( $event->payload ),
				'is_read'              => $event->is_read ? 1 : 0,
				'created_at'           => current_time( 'mysql', true ),
			],
			[ '%s', '%s', '%s', '%d', '%s', '%d', '%s' ]
		);

		return $result === false ? null : (int) $this->wpdb->insert_id;
	}
}
