<?php
/**
 * Slack Channel Router - Handles routing notifications to specific channels and tagging users
 *
 * @package WPNTS\Inc
 */

namespace WPNTS\Inc;

defined('ABSPATH') || die('Hey, what are you doing here? You silly human!');

/**
 * SlackChannelRouter class
 *
 * @since 1.0.0
 */
class SlackChannelRouter {

	/**
	 * Parse Slack channel from settings
	 *
	 * @param string $slack_channel The channel string from settings (e.g., "#general-note" or empty).
	 * @return string The parsed channel name or empty string if not set.
	 * @since 1.0.0
	 */
	public static function parse_channel( $slack_channel ) {
		if ( empty( $slack_channel ) ) {
			return '';
		}

		// Remove # if present
		$channel = trim( $slack_channel );
		$channel = ltrim( $channel, '#' );

		// Validate channel name (alphanumeric, hyphens, underscores)
		if ( preg_match( '/^[a-z0-9_-]+$/i', $channel ) ) {
			return '#' . $channel;
		}

		return '';
	}

	/**
	 * Parse Slack user/group tags from settings
	 *
	 * @param string $slack_user_tag The user tag string from settings (e.g., "@sam" or "@team-name" or "@sam, @john").
	 * @return array Array of parsed user/group tags.
	 * @since 1.0.0
	 */
	public static function parse_user_tags( $slack_user_tag ) {
		if ( empty( $slack_user_tag ) ) {
			return [];
		}

		$tags = [];
		$raw_tags = explode( ',', $slack_user_tag );

		foreach ( $raw_tags as $tag ) {
			$tag = trim( $tag );
			// Remove @ if present
			$tag = ltrim( $tag, '@' );

			// Validate tag name (alphanumeric, hyphens, underscores, dots)
			if ( preg_match( '/^[a-z0-9_.-]+$/i', $tag ) ) {
				$tags[] = '@' . $tag;
			}
		}

		return $tags;
	}

	/**
	 * Build Slack message with channel override and user tags
	 *
	 * @param string $webhook_url The default webhook URL.
	 * @param string $message The message text.
	 * @param string $slack_channel Optional. Custom Slack channel.
	 * @param string $slack_user_tag Optional. User/group tags to mention.
	 * @param array  $attachments Optional. Message attachments.
	 * @return array The payload array for Slack.
	 * @since 1.0.0
	 */
	public static function build_slack_payload( $webhook_url, $message, $slack_channel = '', $slack_user_tag = '', $attachments = [] ) {
		$payload = [
			'text' => $message,
		];

		// Add channel override if provided
		$channel = self::parse_channel( $slack_channel );
		if ( ! empty( $channel ) ) {
			$payload['channel'] = $channel;
		}

		// Add user tags to message if provided
		$user_tags = self::parse_user_tags( $slack_user_tag );
		if ( ! empty( $user_tags ) ) {
			$tags_string = 'cc: ' . implode( ', ', $user_tags );
			$payload['text'] = $message . "\n\n" . $tags_string;
		}

		// Add attachments if provided
		if ( ! empty( $attachments ) ) {
			$payload['attachments'] = $attachments;
		}

		return $payload;
	}

	/**
	 * Send Slack notification with channel and user tag support
	 *
	 * @param string $webhook_url The Slack webhook URL.
	 * @param string $message The message text.
	 * @param string $slack_channel Optional. Custom Slack channel.
	 * @param string $slack_user_tag Optional. User/group tags to mention.
	 * @param array  $attachments Optional. Message attachments.
	 * @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 static function send_slack_notification_with_channel(
		$webhook_url,
		$message,
		$slack_channel = '',
		$slack_user_tag = '',
		$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' );
		}

		// Build payload with channel and user tags
		$payload_data = self::build_slack_payload( $webhook_url, $message, $slack_channel, $slack_user_tag, $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 );
	}

	/**
	 * Get Slack channel and user tag from feature settings
	 *
	 * @param string $settings_option The WordPress option name containing the settings.
	 * @return array Array with 'channel' and 'user_tag' keys.
	 * @since 1.0.0
	 */
	public static function get_channel_and_tags_from_settings( $settings_option ) {
		$settings = get_option( $settings_option, '{}' );
		$settings_data = json_decode( $settings, true );

		return [
			'channel'  => isset( $settings_data['slack_channel'] ) ? $settings_data['slack_channel'] : '',
			'user_tag' => isset( $settings_data['slack_user_tag'] ) ? $settings_data['slack_user_tag'] : '',
		];
	}

	/**
	 * Get webhook URL from settings
	 *
	 * @param string $settings_option The WordPress option name containing the settings.
	 * @return string The webhook URL or empty string.
	 * @since 1.0.0
	 */
	public static function get_webhook_from_settings( $settings_option ) {
		$settings = get_option( $settings_option, '{}' );
		$settings_data = json_decode( $settings, true );

		return isset( $settings_data['webhook'] ) ? $settings_data['webhook'] : '';
	}

	/**
	 * Send notification with automatic channel and tag routing
	 *
	 * This is a convenience method that automatically retrieves channel and tags from settings
	 *
	 * @param string $settings_option The WordPress option name containing the settings.
	 * @param string $message The message text.
	 * @param array  $attachments Optional. Message attachments.
	 * @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 static function send_notification_with_routing(
		$settings_option,
		$message,
		$attachments = [],
		$timeout = 5,
		$ssl_verify = false
	) {
		// Get webhook URL
		$webhook_url = self::get_webhook_from_settings( $settings_option );

		if ( empty( $webhook_url ) ) {
			return new \WP_Error( 'empty_webhook', 'Webhook URL is empty' );
		}

		// Get channel and user tags
		$routing = self::get_channel_and_tags_from_settings( $settings_option );

		// Send notification with channel and tags
		return self::send_slack_notification_with_channel(
			$webhook_url,
			$message,
			$routing['channel'],
			$routing['user_tag'],
			$attachments,
			$timeout,
			$ssl_verify
		);
	}
}
