<?php

namespace Limb_Chatbot\Includes\Integrations\Telegram\Services;

use Limb_Chatbot\Includes\Data_Objects\Chatbot;
use Limb_Chatbot\Includes\Data_Objects\Chatbot_Meta;
use Limb_Chatbot\Includes\Data_Objects\Config;
use Limb_Chatbot\Includes\Data_Objects\Setting;
use Limb_Chatbot\Includes\Exceptions\Error_Codes;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Integrations\Telegram\Telegram;
use Limb_Chatbot\Includes\Integrations\Telegram\Utilities\Webhook_Utility;

/**
 * Telegram Webhook Service
 *
 * Handles automatic webhook setup/deletion when fetch method changes.
 * - Event Subscription: Sets webhook URL
 * - Polling: Deletes webhook
 *
 * @package Limb_Chatbot\Includes\Integrations\Telegram\Services
 * @since 1.0.11
 */
class Telegram_Webhook_Service {

	/**
	 * Initialize the service and register hooks.
	 *
	 * @since 1.0.11
	 */
	public static function init(): void {
		// Handle when fetch method changes
		add_action( 'lbaic_parameter_agent_fetch_method_updated', [ self::class, 'handle_fetch_method_change' ] );
		add_action( 'lbaic_parameter_agent_fetch_method_preview_updated', [ self::class, 'handle_fetch_method_change' ] );
		// Handle when live agent config is changed (new config selected)
		add_action( 'lbaic_parameter_live_agent_config_id_updated', [ self::class, 'handle_config_id_change' ] );
		add_action( 'lbaic_parameter_live_agent_config_id_preview_updated', [ self::class, 'handle_config_id_change' ] );
	}

	/**
	 * Handle live_agent_config_id setting change.
	 *
	 * When a new Telegram config is selected and fetch method is event_subscription,
	 * set up the webhook for the new config.
	 *
	 * @param  mixed  $item  Setting array or Chatbot_Meta object.
	 *
	 * @return void
	 * @since 1.0.11
	 */
	public static function handle_config_id_change( $item ): void {
		$chatbot = null;

		// Handle both Setting array and Chatbot_Meta object
		if ( is_array( $item ) ) {
			$config_id  = $item['value'] ?? '';
			$is_preview = ! empty( $item['key'] ) && strpos( $item['key'], '.preview' ) !== false;
		} elseif ( $item instanceof Chatbot_Meta ) {
			$config_id  = $item->get_meta_value();
			$chatbot    = Chatbot::find( $item->get_post_id() );
			$is_preview = $chatbot && $chatbot->is_preview();
		} else {
			return;
		}

		if ( empty( $config_id ) ) {
			return;
		}

		// Get the Telegram config
		$config = Config::find( $config_id );
		if ( ! $config instanceof Config || ! $config->get_related_to_instance() instanceof Telegram ) {
			return;
		}

		// Check the fetch method - try chatbot meta first, then global setting
		$fetch_method = null;

		if ( $chatbot instanceof Chatbot ) {
			$fetch_method = $chatbot->get_parameter( 'agent_fetch_method' );
		}
		if ( empty( $fetch_method ) ) {
			if ( $is_preview ) {
				$fetch_method_setting = Setting::find( 'lbaic.utilities.chatbot.agent_fetch_method.preview' );
				$fetch_method         = $fetch_method_setting ? $fetch_method_setting->get_value() : null;
			} else {
				$fetch_method_setting = Setting::find( 'lbaic.utilities.chatbot.agent_fetch_method' );
				$fetch_method         = $fetch_method_setting ? $fetch_method_setting->get_value() : null;
			}
		}


		$webhook_utility = new Webhook_Utility( $config );
		if ( $fetch_method === 'event_subscription' ) {
			self::setup_webhook( $webhook_utility, $config );
		} else {
			self::remove_webhook( $webhook_utility );
		}
	}

	/**
	 * Handle telegram_fetch_method setting change.
	 *
	 * @param  array  $item  Setting array.
	 *
	 * @return void
	 * @since 1.0.11
	 */
	public static function handle_fetch_method_change( $item ): void {
		$chatbot    = null;
		$is_preview = false;
		// Handle both Setting array and Chatbot_Meta object
		if ( is_array( $item ) ) {
			$fetch_method = $item['value'] ?? '';
			$is_preview   = ! empty( $item['key'] ) && strpos( $item['key'], '.preview' ) !== false;
		} elseif ( $item instanceof Chatbot_Meta ) {
			$fetch_method = $item->get_meta_value();
			$chatbot      = Chatbot::find( $item->get_post_id() );
			$is_preview   = $chatbot ? $chatbot->is_preview() : false;
		} else {
			return;
		}

		// Get the live_agent_config_id - try chatbot meta first, then global setting
		$config_id = null;
		if ( $chatbot instanceof Chatbot ) {
			$config_id = $chatbot->get_parameter( 'live_agent_config_id' );
		}
		if ( empty( $config_id ) ) {
			if ( $is_preview ) {
				$config_id_setting = Setting::find( 'lbaic.utilities.chatbot.live_agent_config_id.preview' );
				$config_id         = $config_id_setting ? $config_id_setting->get_value() : null;
			}
		}

		if ( empty( $config_id ) ) {
			$config_id_setting = Setting::find( 'lbaic.utilities.chatbot.live_agent_config_id' );
			$config_id         = $config_id_setting ? $config_id_setting->get_value() : null;
		}

		if ( empty( $config_id ) ) {
			return;
		}

		// Get the Telegram config
		$config = Config::find( $config_id );
		if ( ! $config instanceof Config || ! $config->get_related_to_instance() instanceof Telegram ) {
			return;
		}

		if ( $is_preview && ( $config instanceof Config || $config->get_related_to_instance() instanceof Telegram ) ) {
			throw new Exception(
				Error_Codes::TECHNICAL_ERROR,
				$result['description'] ?? __( 'Messages fetch method can be changed only after save settings',
				'limb-chatbot' ),
				$result,
				400
			);
		}

		$webhook_utility = new Webhook_Utility( $config );
		if ( $fetch_method === 'event_subscription' ) {
			// Set webhook
			self::setup_webhook( $webhook_utility, $config );
		} else {
			// Delete webhook (polling mode or empty)
			self::remove_webhook( $webhook_utility );
		}
	}

	/**
	 * Setup Telegram webhook.
	 *
	 * @param  Webhook_Utility  $webhook_utility  Webhook utility instance.
	 * @param  Config  $config  Telegram config.
	 *
	 * @return void
	 * @since 1.0.11
	 */
	private static function setup_webhook( Webhook_Utility $webhook_utility, Config $config ): void {
		// Generate webhook URL
		$webhook_url = rest_url( 'limb/chatbot/v1/integrations/telegram/webhook' );

		// Generate secret token if not exists
		$params = $config->get_params();
		if ( empty( $params['webhook_secret'] ) ) {
			$params['webhook_secret'] = Webhook_Utility::generate_secret_token();
			$config->params           = $params;
			$config->encrypt_params();
			$config->save();
		}

		// Set the webhook
		$webhook_utility->set_webhook( $webhook_url, $params['webhook_secret'] );
	}

	/**
	 * Remove Telegram webhook.
	 *
	 * @param  Webhook_Utility  $webhook_utility  Webhook utility instance.
	 *
	 * @return void
	 * @since 1.0.11
	 */
	private static function remove_webhook( Webhook_Utility $webhook_utility ): void {
		$webhook_utility->delete_webhook();
	}
}

