<?php

namespace Limb_Chatbot\Includes\Services;

use Exception;
use Limb_Chatbot\Includes\Data_Objects\Conversation_State;
use Limb_Chatbot\Includes\Repositories\Conversation_State_Repository;
use Limb_Chatbot\Includes\Traits\SingletonTrait;

/**
 * Class Conversation_State_Manager
 *
 * Manages the loading, creation, and caching of conversation states for chats.
 *
 * @package Limb_Chatbot\Includes\Services
 * @since 1.0.0
 */
class Conversation_State_Manager {

	use SingletonTrait;

	/**
	 * Repository for persisting and retrieving conversation states.
	 *
	 * @var Conversation_State_Repository
	 * @since 1.0.0
	 */
	private Conversation_State_Repository $repo;

	/**
	 * Currently loaded conversation state.
	 *
	 * @var Conversation_State|null
	 * @since 1.0.0
	 */
	private ?Conversation_State $state = null;

	/**
	 * Conversation_State_Manager constructor.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		$this->repo = new Conversation_State_Repository();
	}

	/**
	 * Load the conversation state for a given chat UUID.
	 * If none exists, a new state is created and persisted.
	 *
	 * @param  string  $chat_uuid  Unique identifier for the chat.
	 *
	 * @return Conversation_State Loaded or newly created conversation state.
	 * @throws Exception If upsert fails.
	 * @since 1.0.0
	 */
	public function load_for_chat( string $chat_uuid ): Conversation_State {
		$state = $this->repo->get_by_chat_uuid( $chat_uuid );

		if ( $state === null ) {
			$state = Conversation_State::make( [ 'chat_uuid' => $chat_uuid ] );
			$this->repo->upsert( $state );
		}

		$this->state = $state;

		return $this->state;
	}

	/**
	 * Get the currently loaded conversation state (if any).
	 *
	 * @return Conversation_State|null
	 * @since 1.0.0
	 */
	public function get_current_state(): ?Conversation_State {
		return $this->state;
	}
}
