<?php

namespace Limb_Chatbot\Includes\Integrations\Slack\Utilities;

use Limb_Chatbot\Includes\Data_Objects\Config;
use Limb_Chatbot\Includes\Integrations\Slack\Endpoints\Messages\Messages_Endpoint;
use Limb_Chatbot\Includes\Integrations\Slack\Slack;
use Limb_Chatbot\Includes\Utilities\Slack_Messages_Utility as Global_Utility;

/**
 * Slack Messages Utility
 *
 * Provider-specific utility for Slack message and channel operations.
 * Wraps the Messages_Endpoint with context-aware configuration.
 *
 * @package Limb_Chatbot\Includes\Integrations\Slack\Utilities
 * @since 1.0.0
 */
class Messages_Utility {

	/**
	 * Global utility instance holding context.
	 *
	 * @var Global_Utility
	 * @since 1.0.0
	 */
	public Global_Utility $global_utility;

	/**
	 * API endpoint handler for message operations.
	 *
	 * @var Messages_Endpoint
	 * @since 1.0.0
	 */
	public Messages_Endpoint $endpoint;

	/**
	 * Slack configuration object.
	 *
	 * @var Config|null
	 * @since 1.0.0
	 */
	public ?Config $config = null;

	/**
	 * HTTP request timeout in seconds.
	 *
	 * @var int
	 * @since 1.0.0
	 */
	public int $timeout = 30;

	/**
	 * Constructor.
	 *
	 * Initializes the utility with global context, loads the config if not set,
	 * and instantiates the related API endpoint.
	 *
	 * @param Global_Utility $global_utility Global utility object containing config.
	 *
	 * @since 1.0.0
	 */
	public function __construct( Global_Utility $global_utility ) {
		$this->global_utility = $global_utility;
		// Load default config if not set
		if ( is_null( $this->global_utility->config ) ) {
			$this->config = Config::where( [
				'default'    => true,
				'related_to' => Slack::class,
			] )->first();
		} else {
			$this->config = $this->global_utility->config;
		}

		// Copy properties from global utility
		$this->timeout = $this->global_utility->get_timeout();

		// Initialize endpoint
		$this->endpoint = new Messages_Endpoint( $this );
	}

	/**
	 * Create a Slack channel.
	 *
	 * @param string $name       Channel name.
	 * @param bool   $is_private Whether channel is private.
	 *
	 * @return array Channel data.
	 * @since 1.0.0
	 */
	public function create_channel( string $name, bool $is_private = false ) {
		return $this->endpoint->create_channel( $name, $is_private );
	}

	/**
	 * Invite users to a channel.
	 *
	 * @param string $channel_id Channel ID.
	 * @param array  $user_ids   Array of user IDs.
	 *
	 * @return array Response data.
	 * @since 1.0.0
	 */
	public function invite_users( string $channel_id, array $user_ids ) {
		return $this->endpoint->invite_users( $channel_id, $user_ids );
	}

	/**
	 * Post a message to a channel.
	 *
	 * @param string $channel_id Channel ID.
	 * @param string $text       Message text.
	 * @param array  $blocks     Optional message blocks.
	 *
	 * @return array Response data.
	 * @since 1.0.0
	 */
	public function post_message( string $channel_id, string $text, array $blocks = [] ) {
		return $this->endpoint->post_message( $channel_id, $text, $blocks );
	}

	/**
	 * Get conversation history from a channel.
	 *
	 * @param string      $channel_id Channel ID.
	 * @param string|null $oldest     Oldest timestamp to fetch from.
	 * @param int         $limit      Maximum number of messages to fetch.
	 *
	 * @return array Array of messages.
	 * @since 1.0.0
	 */
	public function get_history( string $channel_id, ?string $oldest = null, int $limit = 100 ): array {
		return $this->endpoint->get_history( $channel_id, $oldest, $limit );
	}

	/**
	 * Get configuration object.
	 *
	 * @return Config|null
	 * @since 1.0.0
	 */
	public function get_config(): ?Config {
		return $this->config;
	}

	/**
	 * Get timeout value.
	 *
	 * @return int
	 * @since 1.0.0
	 */
	public function get_timeout(): int {
		return $this->timeout;
	}
}

