<?php

namespace Limb_Chatbot\Includes\Services\Channel_Events;

/**
 * Value object representing a single channel event row.
 *
 * Channel events are general-purpose notifications stored in the
 * lbaic_channel_events table and consumed (pull + delete) by polling
 * endpoints.  Any feature can create events; any polling surface can read
 * them by WP user ID.
 *
 * Instances are lightweight DTOs: construct from code for insertion, or
 * hydrate from a database row via {@see self::from_row()}.
 *
 * @package Limb_Chatbot
 * @subpackage Services\Channel_Events
 * @since 2.1.0
 */
class Channel_Event {

	/**
	 * Persisted row ID; 0 for unsaved instances.
	 *
	 * @var int
	 */
	public int $id = 0;

	/**
	 * Event type slug — one of {@see Channel_Event_Types} constants.
	 *
	 * @var string
	 */
	public string $event_type;

	/**
	 * Optional plugin chat UUID surfaced directly in API responses.
	 *
	 * @var string|null
	 */
	public ?string $chat_uuid;

	/**
	 * Optional UUID of the chatbot user (visitor) associated with this event.
	 *
	 * @var string|null
	 */
	public ?string $chatbot_user_uuid;

	/**
	 * WordPress user ID of the intended recipient.
	 *
	 * Always set in persisted rows — the dispatcher fans out one row per
	 * recipient at write time.
	 *
	 * @var int
	 */
	public int $recipient_wp_user_id;

	/**
	 * Arbitrary JSON-serialisable context (message IDs, lead IDs, etc.).
	 *
	 * @var array<string,mixed>
	 */
	public array $payload = [];

	/**
	 * Read state for admin notification surfaces.
	 *
	 * Defaults to unread (`false`). Live-agent event handling is unaffected.
	 *
	 * @var bool
	 */
	public bool $is_read = false;

	/**
	 * UTC datetime string when this event was created (set by repository).
	 *
	 * @var string
	 */
	public string $created_at = '';

	/**
	 * @param  string               $event_type
	 * @param  int                  $recipient_wp_user_id
	 * @param  string|null          $chat_uuid
	 * @param  string|null          $chatbot_user_uuid
	 * @param  array<string,mixed>  $payload
	 */
	public function __construct(
		string $event_type,
		int $recipient_wp_user_id,
		?string $chat_uuid = null,
		?string $chatbot_user_uuid = null,
		array $payload = []
	) {
		$this->event_type           = $event_type;
		$this->recipient_wp_user_id = $recipient_wp_user_id;
		$this->chat_uuid            = $chat_uuid;
		$this->chatbot_user_uuid    = $chatbot_user_uuid;
		$this->payload              = $payload;
	}

	/**
	 * Human-readable label for this event's type.
	 *
	 * @return string
	 */
	public function get_label(): string {
		return Channel_Event_Types::get_label( $this->event_type );
	}

	/**
	 * Hydrate from a raw database row.
	 *
	 * @param  array<string,mixed>  $row
	 *
	 * @return static
	 */
	public static function from_row( array $row ) {
		$event = new static(
			(string) ( $row['event_type'] ?? '' ),
			(int) ( $row['recipient_wp_user_id'] ?? 0 ),
			$row['chat_uuid'] ?? null,
			$row['chatbot_user_uuid'] ?? null,
			json_decode( (string) ( $row['payload'] ?? '{}' ), true ) ?: []
		);

		$event->id         = (int) ( $row['id'] ?? 0 );
		$event->is_read    = ( (int) ( $row['is_read'] ?? 0 ) ) === 1;
		$event->created_at = (string) ( $row['created_at'] ?? '' );

		return $event;
	}

	/**
	 * Serialise to an array suitable for a REST API response.
	 *
	 * @return array<string,mixed>
	 */
	public function to_api_array(): array {
		return [
			'id'               => $this->id,
			'event_type'       => $this->event_type,
			'label'            => $this->get_label(),
			'chat_uuid'        => $this->chat_uuid,
			'chatbot_user_uuid' => $this->chatbot_user_uuid,
			'payload'          => $this->payload,
			'is_read'          => $this->is_read,
			'created_at'       => $this->created_at,
		];
	}
}
