<?php
/**
 * Activity Guard – Real Time Notifier to Slack Rest Route.
 *
 * This class is used to response and all rest route works.
 *
 * @package WPNTS\Inc
 */

namespace WPNTS\Inc;

use WPNTS\Inc\wpnts_nts_fs; // phpcs:ignore
use WPNTS\Inc\Activate; // phpcs:ignore
use WPNTS\Inc\Deactivate; // phpcs:ignore
use WPNTS\Inc\TelegramNotifier; // phpcs:ignore
use WPNTS\Inc\SlackChannelRouter; // phpcs:ignore

defined('ABSPATH') || die('Hey, what are you doing here? You silly human!');
/**
 * Security used to rest route created.
 *
 * @since 1.0.0
 */
class SlackAttachment {

	/**
	 * @var array $attachments List of attachments to be sent to Slack.
	 */
	private $attachments = [];

	/**
	 * Adds an attachment to the list of attachments for Slack messages or other purposes.
	 *
	 * This function constructs an attachment with various fields such as plugin name, title, description, link,
	 * date, and optionally a rating represented by stars. It formats the attachment in a structure compatible with
	 * Slack's message format, allowing for rich messages to be sent.
	 *
	 * @param string   $plugin_name        The name of the plugin.
	 * @param string   $title             The title of the ticket or issue.
	 * @param string   $ticket_description A brief description of the ticket or issue.
	 * @param string   $link              A URL linking to the detailed ticket or resource.
	 * @param string   $date              The date when the ticket was created or updated.
	 * @param string   $color             The color to be used for the attachment (Slack supports hex color codes).
	 * @param string   $emoji             An emoji to be appended to the title for better visual emphasis.
	 * @param int|null $rating            An optional rating, represented by a number of stars (1-5). Defaults to null if not provided.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function addAttachment( $plugin_name, $title, $ticket_description, $link, $date, $color, $emoji, $rating = null ) {

		$fields = [
			[
				'title' => "Name: $plugin_name",
				'short' => false,
			],
			[
				'title' => "Title: $title $emoji",
				'short' => false,
			],
			[
				'value' => "Description: $ticket_description",
				'short' => false,
			],
			[
				'value' => "Link: <{$link}|view>",
				'short' => false,
			],
			[
				'value' => "Date: $date",
				'short' => false,
			],
		];

		if ( $rating !== null ) {
			$fields[] = [
				'value' => str_repeat(':star:', $rating),
				'short' => false,
			];
		}

		$attachment = [
			'fallback' => $title,
			'color' => $color,
			'fields' => $fields,
		];

		$this->attachments[] = $attachment;
	}



	/**
	 * For attatchment call of ratting and review.
	 */
	public function getMessage() {
		return [
			'attachments' => $this->attachments,
		];
	}


	/**
	 * Adds a notification for a plugin update to the list of attachments.
	 *
	 * This function constructs a Slack-compatible message notifying users of a new version of the plugin.
	 * It includes an emoji and color for customization, and adds the notification to the attachments list.
	 *
	 * @param string $plugin_name The name of the plugin being updated.
	 * @param string $new_version The new version of the plugin available for update.
	 * @param string $emoji      An optional emoji to be used in the message (default is ':clap:').
	 * @param string $color      The color for the notification message (default is '#00FF00').
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function addPluginUpdateNotification( $plugin_name, $new_version, $emoji = ':clap:', $color = '#00FF00' ) {
		$message = "$emoji A new version of the $plugin_name plugin is available for update ($new_version).";

		$fields = [
			[
				'title' => $message,
				'short' => false,
			],
		];

		$attachment = [
			'fallback' => $message,
			'color' => $color,
			'fields' => $fields,
		];

		$this->attachments[] = $attachment;
	}


	/**
	 * Retrieves the site URL add option from the global API settings.
	 *
	 * @return string The formatted site URL if `siteURL_add` is true, otherwise an empty string.
	 */
	public function getSiteURLAddOption() {
		$global_api_settings = get_option( 'wpnts_global_api_settings');
		$schedules_global_interval = json_decode($global_api_settings);
		$siteURL_add = $schedules_global_interval->siteURL_add ?? false;

		// Check if siteURL_add is enabled and return the formatted site URL.
		if ( $siteURL_add === true ) {
			$site_url = is_multisite() ? network_site_url() . get_blog_details()->path : site_url();
			return "(🌐 Site: $site_url)";
		} else {
			return '';
		}
	}


	/**
	 * Sends an email notification to the specified recipient.
	 *
	 * This function generates an HTML email with a timestamp, a custom notification message, and a footer.
	 * It uses WordPress's wp_mail() function to send the email.
	 *
	 * @param string $to                  The email address of the recipient.
	 * @param string $subject             The subject line for the email.
	 * @param string $notification_message The message content of the email.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function sendEmailNotification( $to, $subject, $notification_message ) {
		$timestamp = current_time('mysql');

		// Customize the email message as needed.
		$message = '<html><body style="background-color: #f4f4f4; padding: 20px; font-family: Arial, sans-serif;">';
		$message .= '<div style="background-color: #ffffff; max-width: 600px; margin: 0 auto; padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);">';

		// Include the date.
		$message .= '<h3 style="color: #666; text-align: center;">Site Notification: ' . esc_html($timestamp) . '</h3>';
		$message .= '<p style="color: #666;">Time: ' . esc_html($timestamp) . '</p>';

		// Include the activation details.
		$message .= '<h5>' . esc_html($notification_message) . ' </h5><br>';

		$message .= '<p style="color: #666;">Powered by <a href="https://wordpress.org/plugins/notifier-to-slack/" target="_blank">Notifier To Slack</a>.</p>';
		$message .= '</div></body></html>';

		// Email headers.
		$headers[] = 'Content-Type: text/html; charset=UTF-8';

		// Send the email.
		wp_mail($to, $subject, $message, $headers);
	}



	/**
	 * Logs an activity message to the database.
	 *
	 * This function stores activity logs in the database, including severity, timestamp, IP address, user information,
	 * event type, and message content. It also retrieves the user's Gravatar and role, and stores them with the log.
	 *
	 * @param string $severity      The severity of the event (e.g., 'High', 'Medium', 'Low').
	 * @param string $time          The timestamp of the event.
	 * @param string $ip            The IP address from where the event occurred.
	 * @param string $current_user_name The username of the current user who triggered the event.
	 * @param string $event_type    The type of event (e.g., 'Maintenance', 'Error', 'Update').
	 * @param string $log_message   A detailed message about the event.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function log_activity_to_db( $severity, $time, $ip, $current_user_name, $event_type, $log_message ) {
		global $wpdb;
		$activity_log_table = $wpdb->prefix . 'wpnts_activity_log';

		// Get the Gravatar URL for the current user.
		$user = get_user_by( 'login', $current_user_name );
		$thumb = ( $user && $user->user_email ) ? get_avatar_url( $user->user_email, [ 'size' => 64 ] ) : null;

		// Get the primary role of the user.
		$user_role = '';
		if ( $user && ! empty( $user->roles ) ) {
			$user_role = ucfirst( $user->roles[0] );
		} else {
			$user_role = 'Unknown';
		}

		// Prepare the data to be inserted.
		$data = [
			'severity'   => $severity,
			'date'       => $time,
			'ip'         => $ip,
			'user'         => $current_user_name,
			'event_type' => $event_type,
			'message'    => $log_message,
			'thumb'      => $thumb,
			'user_role'       => $user_role,
		];

		// Insert the data into the database.
		$wpdb->insert( $activity_log_table, $data );
	}

	/**
	 * Retrieves the user's IP address if admin want to track site visitors.
	 *
	 * This function checks various server variables to determine the user's IP address,
	 * including HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, and REMOTE_ADDR.
	 *
	 * @return string The user's IP address.
	 */
	public function get_user_ip() {

		if ( ! empty($_SERVER['HTTP_CLIENT_IP']) ) {
			$user_ip = sanitize_text_field(wp_unslash($_SERVER['HTTP_CLIENT_IP']));
		} elseif ( ! empty($_SERVER['HTTP_X_FORWARDED_FOR']) ) {
			$user_ip = sanitize_text_field(wp_unslash($_SERVER['HTTP_X_FORWARDED_FOR']));
		} else {
			if ( isset($_SERVER['REMOTE_ADDR']) ) {
				$user_ip = sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR']));
			}
		}

		return $user_ip;
	}

	/**
	 * Sends a notification to Slack webhook.
	 *
	 * This is a reusable function to send notifications to Slack, eliminating code duplication
	 * across the codebase. It handles the common pattern of creating payload and sending to webhook.
	 *
	 * @param string $webhook_url The Slack webhook URL.
	 * @param string $message The message to send to Slack.
	 * @param array $attachments Optional. Array of attachments for rich messages.
	 * @param int $timeout Optional. Request timeout in seconds. Default 5.
	 * @param bool $ssl_verify Optional. Whether to verify SSL. Default false.
	 * 
	 * @return array|WP_Error The response from wp_remote_post or WP_Error on failure.
	 * @since 1.0.0
	 */
	public function send_slack_notification( $webhook_url, $message, $attachments = [], $timeout = 5, $ssl_verify = false ) {
		// Return early if webhook URL is empty
		if ( empty( $webhook_url ) ) {
			return new \WP_Error( 'empty_webhook', 'Webhook URL is empty' );
		}

		// Prepare payload
		$payload_data = [ 'text' => $message ];
		
		// Add attachments if provided
		if ( ! empty( $attachments ) ) {
			$payload_data['attachments'] = $attachments;
		}

		$payload = wp_json_encode( $payload_data );

		// Prepare arguments for wp_remote_post
		$args = [
			'body'      => $payload,
			'headers'   => [ 'Content-Type' => 'application/json' ],
			'timeout'   => $timeout,
			'sslverify' => $ssl_verify,
		];

		// Send the request
		return wp_remote_post( $webhook_url, $args );
	}

	/**
	 * Sends a notification to Telegram bot.
	 *
	 * This is a reusable function to send notifications to Telegram, similar to send_slack_notification.
	 * It handles the Telegram Bot API request with proper formatting.
	 *
	 * @param string $bot_token The Telegram bot token.
	 * @param string $chat_id The Telegram chat ID.
	 * @param string $message The message to send to Telegram (should be pre-formatted with HTML).
	 * @param int $timeout Optional. Request timeout in seconds. Default 5.
	 * @param bool $ssl_verify Optional. Whether to verify SSL. Default false.
	 * 
	 * @return array|WP_Error The response from wp_remote_post or WP_Error on failure.
	 * @since 1.0.0
	 */
	public function send_telegram_notification( $bot_token, $chat_id, $message, $timeout = 5, $ssl_verify = false ) {
		// Return early if bot token or chat ID is empty
		if ( empty( $bot_token ) || empty( $chat_id ) ) {
			return new \WP_Error( 'empty_credentials', 'Telegram bot token or chat ID is empty' );
		}

		// Telegram API endpoint
		$api_url = "https://api.telegram.org/bot{$bot_token}/sendMessage";

		// Prepare payload
		$payload_data = [
			'chat_id' => $chat_id,
			'text' => $message,
			'parse_mode' => 'HTML',
			'disable_web_page_preview' => false,
		];

		$payload = wp_json_encode( $payload_data );

		// Prepare arguments for wp_remote_post
		$args = [
			'body'      => $payload,
			'headers'   => [ 'Content-Type' => 'application/json' ],
			'timeout'   => $timeout,
			'sslverify' => $ssl_verify,
		];

		// Send the request
		return wp_remote_post( $api_url, $args );
	}

	/**
	 * Sends notification to Slack, Telegram (if enabled), and logs activity to database.
	 *
	 * This is a comprehensive notification function that handles both Slack and Telegram notifications
	 * and activity logging in one call, reducing code duplication.
	 *
	 * @param string $webhook_url The Slack webhook URL.
	 * @param string $message The message to send.
	 * @param string $severity The severity level for activity log.
	 * @param string $event_type The event type for activity log.
	 * @param string $user_name Optional. Username for activity log. Default current user.
	 * @param array $attachments Optional. Slack attachments.
	 * @param string $settings_option Optional. Settings option name for channel and user tag routing.
	 * 
	 * @return array Array with Slack and Telegram responses.
	 * @since 1.0.0
	 */
	public function send_notification_and_log( $webhook_url, $message, $severity, $event_type, $user_name = '', $attachments = [], $settings_option = '' ) {
		$responses = [
			'slack' => null,
			'telegram' => null
		];

		// Format message for Slack (remove HTML, keep emojis)
		$slack_message = $this->format_message_for_platform( $message, 'slack' );
		
		// Format message for Activity Log (remove emojis, keep HTML)
		$activity_log_message = $this->format_message_for_platform( $message, 'activity_log' );

		// Get global API settings
		$global_api_settings = get_option( 'wpnts_global_api_settings' );
		$api_settings = $global_api_settings ? json_decode( $global_api_settings, true ) : [];
		
		// Send Slack notification if enabled (default to true for backward compatibility)
		$slack_enabled = $api_settings['slack_notifications_enabled'] ?? true;
		if ( $slack_enabled ) {
			// Use SlackChannelRouter if settings_option is provided, otherwise use direct send
			if ( ! empty( $settings_option ) ) {
				$responses['slack'] = SlackChannelRouter::send_notification_with_routing(
					$settings_option,
					$slack_message,
					$attachments
				);
			} else {
				$responses['slack'] = $this->send_slack_notification( $webhook_url, $slack_message, $attachments );
			}
		}

		// Send Telegram notification if enabled
		if ( $global_api_settings ) {
			$telegram_enabled = $api_settings['telegram_notifications_enabled'] ?? false;
			
			if ( $telegram_enabled ) {
				$bot_token = $api_settings['telegram_bot_token'] ?? '';
				$chat_id = $api_settings['telegram_chat_id'] ?? '';
				
				if ( ! empty( $bot_token ) && ! empty( $chat_id ) ) {
					// Format message for Telegram
					$telegram_message = $this->format_message_for_platform( $message, 'telegram' );
					
					$responses['telegram'] = $this->send_telegram_notification(
						$bot_token,
						$chat_id,
						$telegram_message
					);
				}
			}
		}

		// Prepare data for activity logging
		$time = current_time( 'mysql' );
		$ip = $this->get_user_ip();
		
		// Use provided username or get current user
		if ( empty( $user_name ) ) {
			$current_user = wp_get_current_user();
			$user_name = $current_user->display_name ?: $current_user->user_login ?: 'System';
		}

		// Log activity to database with Activity Log-formatted message
		$this->log_activity_to_db( $severity, $time, $ip, $user_name, $event_type, $activity_log_message );

		return $responses;
	}



	/**
	 * Updates WordPress option with JSON encoded data.
	 *
	 * This function standardizes the option update process with JSON encoding,
	 * reducing code duplication across REST API endpoints.
	 *
	 * @param string $option_name The name of the option to update.
	 * @param array $data The data to JSON encode and store.
	 * @param bool $merge_with_existing Optional. Whether to merge with existing data. Default false.
	 * 
	 * @return bool True on success, false on failure.
	 * @since 1.0.0
	 */
	public function update_json_option( $option_name, $data, $merge_with_existing = false ) {
		if ( $merge_with_existing ) {
			// Get existing data and merge
			$existing_data = json_decode( get_option( $option_name, '{}' ), true );
			$data = array_merge( $existing_data, $data );
		}

		return update_option( $option_name, wp_json_encode( $data ) );
	}

	/**
	 * Schedules or updates a WordPress cron event.
	 *
	 * This function handles cron scheduling with proper cleanup of existing events,
	 * reducing code duplication in cron management.
	 *
	 * @param string $hook The hook name for the cron event.
	 * @param int $interval The interval in seconds.
	 * @param array $args Optional. Arguments to pass to the hook. Default empty array.
	 * @param bool $replace_existing Optional. Whether to replace existing cron. Default true.
	 * 
	 * @return bool True on success, false on failure.
	 * @since 1.0.0
	 */
	public function schedule_cron_event( $hook, $interval, $args = [], $replace_existing = true ) {
		// Clear existing cron if replacing
		if ( $replace_existing && wp_next_scheduled( $hook, $args ) ) {
			wp_clear_scheduled_hook( $hook, $args );
		}

		// Schedule new cron event
		return wp_schedule_event( time(), $this->get_cron_recurrence( $interval ), $hook, $args );
	}

	/**
	 * Gets or creates a custom cron recurrence for the given interval.
	 *
	 * @param int $interval The interval in seconds.
	 * @return string The recurrence key.
	 * @since 1.0.0
	 */
	private function get_cron_recurrence( $interval ) {
		$recurrence_key = 'wpnts_every_' . $interval . '_seconds';
		
		// Add custom recurrence if it doesn't exist
		add_filter( 'cron_schedules', function( $schedules ) use ( $interval, $recurrence_key ) {
			if ( ! isset( $schedules[ $recurrence_key ] ) ) {
				$schedules[ $recurrence_key ] = [
					'interval' => $interval,
					'display'  => sprintf( __( 'Every %d seconds', 'notifier-to-slack' ), $interval )
				];
			}
			return $schedules;
		});

		return $recurrence_key;
	}

	/**
	 * Gets current user information in a standardized format.
	 *
	 * @return array Array containing user information.
	 * @since 1.0.0
	 */
	public function get_current_user_info() {
		$current_user = wp_get_current_user();
		
		return [
			'id' => $current_user->ID,
			'login' => $current_user->user_login,
			'display_name' => $current_user->display_name,
			'email' => $current_user->user_email,
			'roles' => $current_user->roles,
			'primary_role' => ! empty( $current_user->roles ) ? ucfirst( $current_user->roles[0] ) : 'Unknown'
		];
	}

	/**
	 * Processes message template by replacing placeholders with actual values.
	 *
	 * This function takes a message template with placeholders like {plugin_name}, {user_name}, etc.
	 * and replaces them with actual values provided in the data array.
	 *
	 * @param string $template The message template with placeholders.
	 * @param array $data Associative array of placeholder => value pairs.
	 * @param string $settings_option The option name to get custom templates from.
	 * @param string $template_key The key for the specific template in settings.
	 * @param string $format_type Optional. Format type: 'slack' or 'activity_log'. Default 'slack'.
	 * 
	 * @return string The processed message with placeholders replaced.
	 * @since 1.0.0
	 */
	public function process_message_template( $template, $data = [], $settings_option = '', $template_key = '', $format_type = 'slack' ) {
		// Get custom template from settings if provided
		if ( ! empty( $settings_option ) && ! empty( $template_key ) ) {
			$settings = get_option( $settings_option );
			if ( $settings ) {
				$settings_data = json_decode( $settings, true );
				if ( isset( $settings_data[ $template_key ] ) && ! empty( $settings_data[ $template_key ] ) ) {
					$template = $settings_data[ $template_key ];
				}
			}
		}

		// Add common placeholders
		$common_data = [
			'site_url' => $this->getSiteURLAddOption(),
			'date' => current_time( 'Y-m-d' ),
			'time' => current_time( 'H:i:s' ),
			'datetime' => current_time( 'Y-m-d H:i:s' ),
		];

		// Merge provided data with common data
		$all_data = array_merge( $common_data, $data );

		// Replace placeholders in the template
		foreach ( $all_data as $placeholder => $value ) {
			$template = str_replace( '{' . $placeholder . '}', $value, $template );
		}

		// Apply format-specific processing
		$template = $this->format_message_for_platform( $template, $format_type );

		return $template;
	}

	/**
	 * Formats message content based on the target platform (Slack, Telegram, or Activity Log).
	 *
	 * This function handles the conversion between different formatting styles
	 * to ensure messages display correctly on each platform.
	 *
	 * @param string $message The message to format.
	 * @param string $format_type The target format: 'slack', 'telegram', or 'activity_log'.
	 * 
	 * @return string The formatted message.
	 * @since 1.0.0
	 */
	private function format_message_for_platform( $message, $format_type ) {
		if ( $format_type === 'slack' ) {
			// For Slack: Remove HTML tags but keep Slack emojis and formatting
			$message = $this->convert_html_to_slack_format( $message );
		} elseif ( $format_type === 'telegram' ) {
			// For Telegram: Convert to Telegram's HTML format
			$message = $this->convert_html_to_telegram_format( $message );
		} elseif ( $format_type === 'activity_log' ) {
			// For Activity Log: Remove Slack emojis but keep HTML tags
			$message = $this->convert_slack_to_html_format( $message );
		}

		return $message;
	}

	/**
	 * Converts HTML formatting to Slack-compatible formatting.
	 *
	 * @param string $message The message with HTML formatting.
	 * @return string The message with Slack formatting.
	 * @since 1.0.0
	 */
	private function convert_html_to_slack_format( $message ) {
		// Convert HTML bold to Slack bold
		$message = preg_replace( '/<b>(.*?)<\/b>/i', '*$1*', $message );
		$message = preg_replace( '/<strong>(.*?)<\/strong>/i', '*$1*', $message );
		
		// Convert HTML italic to Slack italic
		$message = preg_replace( '/<i>(.*?)<\/i>/i', '_$1_', $message );
		$message = preg_replace( '/<em>(.*?)<\/em>/i', '_$1_', $message );
		
		// Convert HTML strikethrough to Slack strikethrough
		$message = preg_replace( '/<s>(.*?)<\/s>/i', '~$1~', $message );
		$message = preg_replace( '/<strike>(.*?)<\/strike>/i', '~$1~', $message );
		$message = preg_replace( '/<del>(.*?)<\/del>/i', '~$1~', $message );
		
		// Convert HTML code to Slack code
		$message = preg_replace( '/<code>(.*?)<\/code>/i', '`$1`', $message );
		
		// Remove other HTML tags
		$message = strip_tags( $message );
		
		// Keep Slack emojis as they are (they're already in correct format)
		
		return $message;
	}

	/**
	 * Converts Slack formatting to HTML-compatible formatting.
	 *
	 * @param string $message The message with Slack formatting and emojis.
	 * @return string The message with HTML formatting.
	 * @since 1.0.0
	 */
	private function convert_slack_to_html_format( $message ) {
		// Remove Slack emojis (text between colons)
		$message = preg_replace( '/:[a-zA-Z0-9_+-]+:/', '', $message );
		
		// Convert Slack bold to HTML bold
		$message = preg_replace( '/\*([^*]+)\*/', '<b>$1</b>', $message );
		
		// Convert Slack italic to HTML italic
		$message = preg_replace( '/_([^_]+)_/', '<i>$1</i>', $message );
		
		// Convert Slack strikethrough to HTML strikethrough
		$message = preg_replace( '/~([^~]+)~/', '<s>$1</s>', $message );
		
		// Convert Slack code to HTML code
		$message = preg_replace( '/`([^`]+)`/', '<code>$1</code>', $message );
		
		// Clean up extra spaces left by removed emojis
		$message = preg_replace( '/\s+/', ' ', $message );
		$message = trim( $message );
		
		return $message;
	}

	/**
	 * Converts HTML and Slack formatting to Telegram-compatible HTML formatting.
	 *
	 * Telegram supports a subset of HTML tags: <b>, <i>, <u>, <s>, <code>, <pre>, <a>
	 * This method converts Slack emojis to Unicode emojis and ensures proper HTML formatting.
	 *
	 * @param string $message The message with HTML or Slack formatting.
	 * @return string The message with Telegram-compatible HTML formatting.
	 * @since 1.0.0
	 */
	private function convert_html_to_telegram_format( $message ) {
		// First, convert Slack emojis to Unicode emojis
		$emoji_map = [
			':face_with_peeking_eye:' => '🫣',
			':face_with_raised_eyebrow:' => '🤨',
			':yawning_face:' => '🥱',
			':smiling_face_with_tear:' => '🥲',
			':fire:' => '🔥',
			':arrow_right:' => '➡️',
			':package:' => '📦',
			':clap:' => '👏',
			':star:' => '⭐',
			':warning:' => '⚠️',
			':check_mark:' => '✅',
			':x:' => '❌',
			':bell:' => '🔔',
			':rocket:' => '🚀',
			':tada:' => '🎉',
			':eyes:' => '👀',
			':thumbsup:' => '👍',
			':thumbsdown:' => '👎',
		];
		
		foreach ( $emoji_map as $slack_emoji => $unicode_emoji ) {
			$message = str_replace( $slack_emoji, $unicode_emoji, $message );
		}
		
		// Remove any remaining Slack emojis that aren't in our map
		$message = preg_replace( '/:[a-zA-Z0-9_+-]+:/', '', $message );
		
		// Convert Slack bold to HTML bold (if not already HTML)
		$message = preg_replace( '/\*([^*<>]+)\*/', '<b>$1</b>', $message );
		
		// Convert Slack italic to HTML italic (if not already HTML)
		$message = preg_replace( '/_([^_<>]+)_/', '<i>$1</i>', $message );
		
		// Convert Slack strikethrough to HTML strikethrough (if not already HTML)
		$message = preg_replace( '/~([^~<>]+)~/', '<s>$1</s>', $message );
		
		// Convert Slack code to HTML code (if not already HTML)
		$message = preg_replace( '/`([^`<>]+)`/', '<code>$1</code>', $message );
		
		// Ensure HTML tags are properly formatted for Telegram
		// Convert <strong> to <b>
		$message = preg_replace( '/<strong>(.*?)<\/strong>/i', '<b>$1</b>', $message );
		
		// Convert <em> to <i>
		$message = preg_replace( '/<em>(.*?)<\/em>/i', '<i>$1</i>', $message );
		
		// Convert <strike> and <del> to <s>
		$message = preg_replace( '/<strike>(.*?)<\/strike>/i', '<s>$1</s>', $message );
		$message = preg_replace( '/<del>(.*?)<\/del>/i', '<s>$1</s>', $message );
		
		// Remove unsupported HTML tags but keep their content
		$message = preg_replace( '/<br\s*\/?>/i', "\n", $message );
		$message = strip_tags( $message, '<b><i><u><s><code><pre><a>' );
		
		// Clean up extra spaces and newlines
		$message = preg_replace( '/\s+/', ' ', $message );
		$message = trim( $message );
		
		return $message;
	}

	/**
	 * Sends notification with custom message template support to both Slack and Telegram.
	 *
	 * This function combines template processing with notification sending,
	 * allowing for customizable messages while maintaining backward compatibility.
	 * It automatically sends to both Slack and Telegram (if enabled) without requiring
	 * any changes to existing code that calls this method.
	 *
	 * @param string $webhook_url The Slack webhook URL.
	 * @param string $default_template The default message template.
	 * @param array $template_data Data for template placeholders.
	 * @param string $severity The severity level for activity log.
	 * @param string $event_type The event type for activity log.
	 * @param string $settings_option Optional. Settings option name for custom templates.
	 * @param string $template_key Optional. Template key in settings.
	 * @param string $user_name Optional. Username for activity log.
	 * @param array $attachments Optional. Slack attachments.
	 * 
	 * @return array Array with Slack and Telegram responses.
	 * @since 1.0.0
	 */
	public function send_templated_notification( $webhook_url, $default_template, $template_data, $severity, $event_type, $settings_option = '', $template_key = '', $user_name = '', $attachments = [] ) {
		$responses = [
			'slack' => null,
			'telegram' => null
		];

		// Process the message template for Slack
		$slack_message = $this->process_message_template( 
			$default_template, 
			$template_data, 
			$settings_option, 
			$template_key,
			'slack'
		);

		// Process the message template for Activity Log
		$activity_log_message = $this->process_message_template( 
			$default_template, 
			$template_data, 
			$settings_option, 
			$template_key,
			'activity_log'
		);

		// Get global API settings
		$global_api_settings = get_option( 'wpnts_global_api_settings' );
		$api_settings = $global_api_settings ? json_decode( $global_api_settings, true ) : [];
		
		// Send Slack notification if enabled (default to true for backward compatibility)
		$slack_enabled = $api_settings['slack_notifications_enabled'] ?? true;
		if ( $slack_enabled ) {
			// Use SlackChannelRouter to send notification with channel and user tag support
			$responses['slack'] = SlackChannelRouter::send_notification_with_routing(
				$settings_option,
				$slack_message,
				$attachments
			);
		}

		// Send Telegram notification if enabled
		if ( $global_api_settings ) {
			$telegram_enabled = $api_settings['telegram_notifications_enabled'] ?? false;
			
			if ( $telegram_enabled ) {
				$bot_token = $api_settings['telegram_bot_token'] ?? '';
				$chat_id = $api_settings['telegram_chat_id'] ?? '';
				
				if ( ! empty( $bot_token ) && ! empty( $chat_id ) ) {
					// Process the message template for Telegram
					$telegram_message = $this->process_message_template( 
						$default_template, 
						$template_data, 
						$settings_option, 
						$template_key,
						'telegram'
					);
					
					$responses['telegram'] = $this->send_telegram_notification(
						$bot_token,
						$chat_id,
						$telegram_message
					);
				}
			}
		}

		// Prepare data for activity logging
		$time = current_time( 'mysql' );
		$ip = $this->get_user_ip();
		
		// Use provided username or get current user
		if ( empty( $user_name ) ) {
			$current_user = wp_get_current_user();
			$user_name = $current_user->display_name ?: $current_user->user_login ?: 'System';
		}

		// Log activity to database with Activity Log-formatted message
		$this->log_activity_to_db( $severity, $time, $ip, $user_name, $event_type, $activity_log_message );

		return $responses;
	}

	/**
	 * Gets available placeholders for different notification types.
	 *
	 * @param string $notification_type The type of notification.
	 * @return array Array of available placeholders.
	 * @since 1.0.0
	 */
	public function get_available_placeholders( $notification_type ) {
		$common_placeholders = [ 'site_url', 'date', 'time', 'datetime' ];

		$type_specific_placeholders = [
			'plugin_activation' => [ 'plugin_name', 'user_name' ],
			'plugin_deactivation' => [ 'plugin_name', 'user_name' ],
			'plugin_update' => [ 'plugin_name', 'user_name', 'old_version', 'new_version' ],
			'login' => [ 'user_name', 'ip_address', 'action' ],
			'logout' => [ 'user_name', 'ip_address', 'action' ],
			'registration' => [ 'user_name', 'user_email', 'user_role' ],
			'wp_update' => [ 'old_version', 'new_version' ],
			'plugin_pending_update' => [ 'plugin_count', 'plugin_list' ],
		];

		$placeholders = $common_placeholders;
		if ( isset( $type_specific_placeholders[ $notification_type ] ) ) {
			$placeholders = array_merge( $placeholders, $type_specific_placeholders[ $notification_type ] );
		}

		return $placeholders;
	}
}
