<?php

namespace Limb_Chatbot\Includes\Integrations\Telegram\Endpoints\Messages;

use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Exceptions\Error_Codes;
use Limb_Chatbot\Includes\Integrations\Telegram\Endpoints\Telegram_Endpoint;
use Limb_Chatbot\Includes\Integrations\Telegram\Utilities\Messages_Utility;

/**
 * Telegram Messages Endpoint
 *
 * Handles message and forum topic operations with the Telegram API including:
 * - Creating forum topics (createForumTopic)
 * - Sending messages (sendMessage)
 * - Getting updates (getUpdates)
 *
 * @package Limb_Chatbot\Includes\Integrations\Telegram\Endpoints\Messages
 * @since 1.0.11
 */
class Messages_Endpoint extends Telegram_Endpoint {

	/**
	 * Messages_Endpoint constructor.
	 *
	 * @param Messages_Utility $utility Utility object containing configuration and context.
	 *
	 * @since 1.0.11
	 */
	public function __construct( Messages_Utility $utility ) {
		parent::__construct( $utility );
	}

	/**
	 * Send a message to a chat or topic.
	 *
	 * @param string|int  $chat_id           Chat ID.
	 * @param string      $text              Message text.
	 * @param int|null    $message_thread_id Optional topic thread ID.
	 * @param string|null $parse_mode        Optional parse mode (HTML, Markdown, MarkdownV2).
	 *
	 * @return array Message data.
	 * @throws Exception
	 * @since 1.0.11
	 */
	public function send_message( $chat_id, string $text, ?int $message_thread_id = null, ?string $parse_mode = 'HTML' ): array {
		$http_client = $this->http_client_factory();
		$url         = $this->build_url( 'sendMessage' );

		$body = [
			'chat_id' => $chat_id,
			'text'    => $text,
		];

		if ( $message_thread_id !== null ) {
			$body['message_thread_id'] = $message_thread_id;
		}

		if ( $parse_mode !== null ) {
			$body['parse_mode'] = $parse_mode;
		}

		$response = $http_client->post(
			$url,
			[
				'headers'   => [ 'Content-Type' => 'application/json' ],
				'body'      => json_encode( $body ),
				'timeout'   => $this->utility->get_timeout(),
				'sslverify' => false, // Temporary SSL bypass for servers with certificate issues
			]
		);

		$handler = new Messages_Response_Handler( $response, $http_client, $this );
		$result  = $handler->get_body();

		if ( empty( $result['ok'] ) || ! isset( $result['result'] ) ) {
			throw new Exception(
				Error_Codes::TECHNICAL_ERROR,
				__( 'Failed to send Telegram message.', 'limb-chatbot' ),
				$result,
				400
			);
		}

		return $result['result'];
	}

	/**
	 * Get updates from Telegram.
	 *
	 * @param int|null $offset  Offset for pagination.
	 * @param int      $limit   Maximum number of updates to retrieve.
	 * @param int      $timeout Timeout for long polling.
	 *
	 * @return array Array of update objects.
	 * @throws Exception
	 * @since 1.0.11
	 */
	public function get_updates( ?int $offset = null, int $limit = 100, int $timeout = 0 ): array {
		$http_client = $this->http_client_factory();

		$params = [
			'limit'   => $limit,
			'timeout' => $timeout,
		];

		if ( $offset !== null ) {
			$params['offset'] = $offset;
		}

		$url = $this->build_url( 'getUpdates' ) . '?' . http_build_query( $params );

		$response = $http_client->get(
			$url,
			[
				'timeout'   => $this->utility->get_timeout() + $timeout,
			]
		);

		$handler = new Messages_Response_Handler( $response, $http_client, $this );
		$result  = $handler->get_body();

		if ( empty( $result['ok'] ) || ! isset( $result['result'] ) ) {
			throw new Exception(
				Error_Codes::TECHNICAL_ERROR,
				__( 'Failed to get Telegram updates.', 'limb-chatbot' ),
				$result,
				400
			);
		}

		return $result['result'];
	}

	/**
	 * Close a forum topic.
	 *
	 * @param string|int $chat_id           Chat ID.
	 * @param int        $message_thread_id Topic thread ID.
	 *
	 * @return bool True on success.
	 * @throws Exception
	 * @since 1.0.11
	 */
	public function close_forum_topic( $chat_id, int $message_thread_id ): bool {
		$http_client = $this->http_client_factory();
		$url         = $this->build_url( 'closeForumTopic' );

		$body = [
			'chat_id'           => $chat_id,
			'message_thread_id' => $message_thread_id,
		];

		$response = $http_client->post(
			$url,
			[
				'headers'   => [ 'Content-Type' => 'application/json' ],
				'body'      => json_encode( $body ),
				'timeout'   => $this->utility->get_timeout(),
				'sslverify' => false, // Temporary SSL bypass for servers with certificate issues
			]
		);

		$handler = new Messages_Response_Handler( $response, $http_client, $this );
		$result  = $handler->get_body();

		return ! empty( $result['ok'] ) && $result['result'] === true;
	}

	/**
	 * Reopen a closed forum topic.
	 *
	 * @param string|int $chat_id           Chat ID.
	 * @param int        $message_thread_id Topic thread ID.
	 *
	 * @return bool True on success.
	 * @throws Exception
	 * @since 1.0.11
	 */
	public function reopen_forum_topic( $chat_id, int $message_thread_id ): bool {
		$http_client = $this->http_client_factory();
		$url         = $this->build_url( 'reopenForumTopic' );

		$body = [
			'chat_id'           => $chat_id,
			'message_thread_id' => $message_thread_id,
		];

		$response = $http_client->post(
			$url,
			[
				'headers'   => [ 'Content-Type' => 'application/json' ],
				'body'      => json_encode( $body ),
				'timeout'   => $this->utility->get_timeout(),
				'sslverify' => false, // Temporary SSL bypass for servers with certificate issues
			]
		);

		$handler = new Messages_Response_Handler( $response, $http_client, $this );
		$result  = $handler->get_body();

		return ! empty( $result['ok'] ) && $result['result'] === true;
	}

	/**
	 * Get user profile photos.
	 *
	 * @param int      $user_id Telegram user ID.
	 * @param int      $offset  Photo offset.
	 * @param int      $limit   Max number of photos to retrieve (1-100).
	 *
	 * @return array UserProfilePhotos object with total_count and photos.
	 * @throws Exception
	 * @since 1.0.11
	 */
	public function get_user_profile_photos( int $user_id, int $offset = 0, int $limit = 1 ): array {
		$http_client = $this->http_client_factory();

		$params = [
			'user_id' => $user_id,
			'offset'  => $offset,
			'limit'   => $limit,
		];

		$url = $this->build_url( 'getUserProfilePhotos' ) . '?' . http_build_query( $params );

		$response = $http_client->get(
			$url,
			[
				'timeout'   => $this->utility->get_timeout(),
				'sslverify' => false, // Temporary SSL bypass for servers with certificate issues
			]
		);

		$handler = new Messages_Response_Handler( $response, $http_client, $this );
		$result  = $handler->get_body();

		if ( empty( $result['ok'] ) || ! isset( $result['result'] ) ) {
			throw new Exception(
				Error_Codes::TECHNICAL_ERROR,
				__( 'Failed to get user profile photos.', 'limb-chatbot' ),
				$result,
				400
			);
		}

		return $result['result'];
	}

	/**
	 * Get file path by file_id.
	 *
	 * @param string $file_id Telegram file ID.
	 *
	 * @return array File object with file_path.
	 * @throws Exception
	 * @since 1.0.11
	 */
	public function get_file( string $file_id ): array {
		$http_client = $this->http_client_factory();

		$url = $this->build_url( 'getFile' ) . '?' . http_build_query( [ 'file_id' => $file_id ] );

		$response = $http_client->get(
			$url,
			[
				'timeout'   => $this->utility->get_timeout(),
				'sslverify' => false, // Temporary SSL bypass for servers with certificate issues
			]
		);

		$handler = new Messages_Response_Handler( $response, $http_client, $this );
		$result  = $handler->get_body();

		if ( empty( $result['ok'] ) || ! isset( $result['result'] ) ) {
			throw new Exception(
				Error_Codes::TECHNICAL_ERROR,
				__( 'Failed to get file.', 'limb-chatbot' ),
				$result,
				400
			);
		}

		return $result['result'];
	}

	/**
	 * Get full file download URL.
	 *
	 * @param string $file_path File path from getFile response.
	 *
	 * @return string Full download URL.
	 * @throws Exception
	 * @since 1.0.11
	 */
	public function get_file_url( string $file_path ): string {
		$token = $this->get_bot_token();
		return self::API_BASE_URL . '/file/bot' . $token . '/' . $file_path;
	}

	/**
	 * Get user avatar URL.
	 *
	 * @param int $user_id Telegram user ID.
	 *
	 * @return string|null Avatar URL or null if no photo.
	 * @since 1.0.11
	 */
	public function get_user_avatar_url( int $user_id ): ?string {
		try {
			$photos = $this->get_user_profile_photos( $user_id, 0, 1 );

			if ( empty( $photos['total_count'] ) || empty( $photos['photos'][0] ) ) {
				return null;
			}

			// Get the smallest photo (last in the array for first photo set)
			$photo_sizes = $photos['photos'][0];
			$smallest    = end( $photo_sizes ); // Get largest for better quality

			if ( empty( $smallest['file_id'] ) ) {
				return null;
			}

			$file = $this->get_file( $smallest['file_id'] );

			if ( empty( $file['file_path'] ) ) {
				return null;
			}

			return $this->get_file_url( $file['file_path'] );
		} catch ( \Exception $e ) {
			return null;
		}
	}
}

