<?php
/**
 * Mentions
 *
 * @package Nisje
 */

declare( strict_types = 1 );
namespace Nisje\Mentions;

defined( 'ABSPATH' ) || die( 'This is Nisje!' );

/**
 * Filters
 */
add_action( 'init', __NAMESPACE__ . '\\setup_shortcodes' );
add_action( 'save_post', __NAMESPACE__ . '\\at_name_post_notification', 10, 3 );
add_action( 'wp_insert_comment', __NAMESPACE__ . '\\at_name_comment_notification', 10, 2 );
add_filter( 'nisje_notification_enrich_data', __NAMESPACE__ . '\\enrich_notification_data', 10, 3 );

// Notifications.
add_filter( 'nisje_register_notification_types', __NAMESPACE__ . '\\register_notifications' );
add_action( 'nisje_post_mention', __NAMESPACE__ . '\\post_mention_notification', 10, 3 );
add_action( 'nisje_comment_mention', __NAMESPACE__ . '\\comment_mention_notification', 10, 3 );

/**
 * Add mention shortcode
 *
 * @return void
 */
function setup_shortcodes() {
	add_shortcode( 'nisje-mention', __NAMESPACE__ . '\\nisje_mention_shortcode_cb' );
}

/**
 * Mention shortcode callback.
 *
 * @param array $atts Shortcode attributes.
 * @return string Parsed content
 */
function nisje_mention_shortcode_cb( array $atts ) : string {
	if ( isset( $atts['user_id'] ) && ! empty( $atts['user_id'] ) ) {
		$user_id = absint( $atts['user_id'] );

		$name = bp_core_get_user_displayname( $user_id );
		$link = bp_core_get_user_domain( $user_id );

		if ( ! empty( $name ) && $link ) {
			return '<a class="mention" href="' . esc_url( $link ) . '" data-user-id="' . esc_attr( $user_id ) . '">@' . esc_html( $name ) . '</a>';
		}
	}

	return '';
}

/**
 * Catch mentions in a post item after it has been inserted to the DB.
 *
 * If mentions are found, add hook for notications to hook into.
 *
 * @param int      $post_id Post ID.
 * @param \WP_Post $post    Post object.
 * @param boolean  $update  Update.
 */
function at_name_post_notification( int $post_id, \WP_Post $post, bool $update ) {
	if ( ! ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) ) {
		$pattern = '/\<a class="mention.*?\<\/a>/';

		if ( preg_match_all( $pattern, $post->post_content, $matches ) && is_array( $matches[0] ) ) {
			foreach ( $matches[0] as $match ) {
				$pattern = '/data-user-id="[0-9]*"/';

				if ( preg_match_all( $pattern, $match, $matches ) && is_array( $matches[0] ) ) {
					$user_id = (int) preg_replace( '/[^0-9]/', '', $matches[0][0] );
					do_action( 'nisje_post_mention', $post_id, $user_id, $post, $update );
				}
			}
		}
	}
}

/**
 * Catch mentions in a comment before it is saved into the database.
 *
 * If mentions are found, add hook for notications to hook into.
 *
 * @param int         $comment_id Comment ID.
 * @param \WP_Comment $comment    Comment object.
 */
function at_name_comment_notification( int $comment_id, \WP_Comment $comment ) {
	if ( '1' === $comment->comment_approved ) {
		$pattern = '/\<a class="mention.*?\<\/a>/';

		if ( preg_match_all( $pattern, $comment->comment_content, $matches ) && is_array( $matches[0] ) ) {
			foreach ( $matches[0] as $match ) {
				$pattern = '/data-user-id="[0-9]*"/';

				if ( preg_match_all( $pattern, $match, $matches ) && is_array( $matches[0] ) ) {
					$user_id = (int) preg_replace( '/[^0-9]/', '', $matches[0][0] );
					do_action( 'nisje_comment_mention', $comment_id, $user_id, $comment );
				}
			}
		}
	}
}

/**
 * Populate Notifications
 *
 * @param array  $args         Arguments.
 * @param string $action       Action.
 * @param array  $notification Arguments.
 */
function enrich_notification_data( array $args, string $action, array $notification ) : array {
	if ( in_array( $action, [ 'post_mention', 'comment_mention' ], true ) ) {
		$args['item_id'] = bp_core_get_user_displayname( $notification['item_id'] );

		$post       = get_post( $notification['secondary_item_id'] );
		$is_group   = false;
		$group_name = '';

		if ( $post instanceof \WP_Post ) {
			if ( $post->post_parent ) {
				$url      = sprintf( '/groups/%1$s/activity/%2$s/', $post->post_parent, $post->ID );
				$is_group = true;

				$group = nisje_get_group( $post->post_parent );
				if ( ! is_wp_error( $group ) ) {
					$group_name = $group->name;
				}
			} else {
				$url = sprintf( '/activity/%s/', $post->ID );
			}

			$args['href']              = $url;
			$args['secondary_item_id'] = wp_strip_all_tags( get_the_title( $post->ID ) );

			if ( 50 < strlen( $args['secondary_item_id'] ) ) {
				$args['secondary_item_id'] = preg_replace( '/\s+?(\S+)?$/', '', substr( $args['secondary_item_id'], 0, 50 ) ) . '...';
			}
		}

		if ( 'post_mention' === $action ) {
			if ( $is_group ) {
				$args['message'] = [
					'raw'      => '%1$s mentioned you on the post "%2$s" in the group %3$s',
					// translators: %1$s name of the user mentioning, %2$s the post.
					'rendered' => sprintf( esc_html__( '%1$s mentioned you on the post "%2$s" in the group %3$s', 'nisje' ), '<strong>' . $args['item_id'] . '</strong>', $args['secondary_item_id'], $group_name ),
				];
			} else {
				$args['message'] = [
					'raw'      => '%1$s mentioned you on the post "%2$s"',
					// translators: %1$s name of the user mentioning, %2$s the post.
					'rendered' => sprintf( esc_html__( '%1$s mentioned you in on the post "%2$s"', 'nisje' ), '<strong>' . $args['item_id'] . '</strong>', $args['secondary_item_id'] ),
				];
			}
		} else {
			if ( $is_group ) {
				$args['message'] = [
					'raw'      => '%1$s mentioned you in a comment on the post "%2$s" in the group %3$s',
					// translators: %1$s name of the user mentioning, %2$s the post.
					'rendered' => sprintf( esc_html__( '%1$s mentioned you in a comment on the post "%2$s" in the group %3$s', 'nisje' ), '<strong>' . $args['item_id'] . '</strong>', $args['secondary_item_id'], $group_name ),
				];
			} else {
				$args['message'] = [
					'raw'      => '%1$s mentioned you in a comment on the post "%2$s"',
					// translators: %1$s name of the user mentioning, %2$s the post.
					'rendered' => sprintf( esc_html__( '%1$s mentioned you in a comment on the post "%2$s"', 'nisje' ), '<strong>' . $args['item_id'] . '</strong>', $args['secondary_item_id'] ),
				];
			}
		}
	}

	return $args;
}

/**
 * Register notification.
 *
 * @param array $notifications Registered notifications.
 * @return array
 */
function register_notifications( array $notifications ) : array {
	$notifications[] = [
		'key'         => 'post_mention',
		'label'       => esc_html__( 'Post Mention', 'nisje' ),
		'description' => esc_html__( 'When someone mention you in a post', 'nisje' ) . ' - App',
	];

	$notifications[] = [
		'key'         => 'comment_mention',
		'label'       => esc_html__( 'Comment Mention', 'nisje' ),
		'description' => esc_html__( 'When someone mention you in a comment', 'nisje' ) . ' - App',
	];

	$notifications[] = [
		'key'         => 'email_post_mention',
		'label'       => esc_html__( 'Post Mention', 'nisje' ),
		'description' => esc_html__( 'When someone mention you in a post', 'nisje' ) . ' - ' . esc_html__( 'E-mail notification', 'nisje' ),
		'type'        => 'email',
		'is_core_bp'  => false,
	];

	$notifications[] = [
		'key'         => 'email_comment_mention',
		'label'       => esc_html__( 'Comment Mention', 'nisje' ),
		'description' => esc_html__( 'When someone mention you in a comment', 'nisje' ) . ' - ' . esc_html__( 'E-mail notification', 'nisje' ),
		'type'        => 'email',
		'is_core_bp'  => false,
	];

	return $notifications;
}

/**
 * Register post mention notification
 *
 * @param int     $post_id Post ID.
 * @param int     $user_id User ID.
 * @param WP_Post $post Post object.
 */
function post_mention_notification( $post_id, $user_id, $post ) {
	if ( \Nisje\Nofications\is_notification_active( $user_id, 'nisje_notification_post_mention' ) ) {
		$post = get_post( $post_id );

		if ( $post instanceof \WP_Post ) {
			if ( intval( $user_id ) !== intval( $post->post_author ) ) {
				bp_notifications_add_notification( [
					'user_id'           => $user_id,
					'item_id'           => $post->post_author,
					'secondary_item_id' => $post->ID,
					'component_name'    => 'nisje',
					'component_action'  => 'post_mention',
					'date_notified'     => bp_core_current_time(),
					'is_new'            => 1,
				] );
			}
		}
	}

	if ( \Nisje\Nofications\is_notification_active( $user_id, 'nisje_notification_email_post_mention' ) ) {
		$post = get_post( $post_id );

		if ( $post instanceof \WP_Post ) {
			if ( intval( $user_id ) !== intval( $post->post_author ) ) {
				$author = get_userdata( $post->post_author );

				$type       = 'activity-at-message';
				$group_name = '';

				if ( $post->post_parent ) {
					$url   = sprintf( '/groups/%1$s/activity/%2$s/', $post->post_parent, $post->ID );
					$type  = 'groups-at-message';
					$group = nisje_get_group( $post->post_parent );
					if ( ! is_wp_error( $group ) ) {
						$group_name = $group->name;
					}
				} else {
					$url = sprintf( '/activity/%s/', $post->ID );
				}

				$args = [
					'tokens' => [
						'activity'         => '',
						'usermessage'      => wp_strip_all_tags( $post->post_content ),
						'group.name'       => $group_name,
						'mentioned.url'    => esc_url( home_url( $url ) ),
						'poster.name'      => $author->display_name,
						'receiver-user.id' => $user_id,
						'unsubscribe'      => '',
					],
				];

				bp_send_email( $type, $user_id, $args );
			}
		}
	}
}

/**
 * Register comment mention notification
 *
 * @param int         $comment_id Comment ID.
 * @param int         $user_id    User ID.
 * @param \WP_Comment $comment    Comment.
 */
function comment_mention_notification( $comment_id, $user_id, $comment ) {
	if ( \Nisje\Nofications\is_notification_active( $user_id, 'nisje_notification_comment_mention' ) ) {
		$post = get_post( $comment->comment_post_ID );

		if ( $post instanceof \WP_Post ) {
			bp_notifications_add_notification( [
				'user_id'           => $user_id,
				'item_id'           => $comment->user_id,
				'secondary_item_id' => $post->ID,
				'component_name'    => 'nisje',
				'component_action'  => 'comment_mention',
				'date_notified'     => bp_core_current_time(),
				'is_new'            => 1,
			] );
		}
	}

	if ( \Nisje\Nofications\is_notification_active( $user_id, 'nisje_notification_email_comment_mention' ) ) {
		$post = get_post( $comment->comment_post_ID );

		if ( $post instanceof \WP_Post ) {
			$author = get_userdata( $comment->user_id );

			$group_name = '';
			$type       = 'activity-at-message';

			if ( $post->post_parent ) {
				$url   = sprintf( '/groups/%1$s/activity/%2$s/', $post->post_parent, $post->ID );
				$type  = 'groups-at-message';
				$group = nisje_get_group( $post->post_parent );
				if ( ! is_wp_error( $group ) ) {
					$group_name = $group->name;
				}
			} else {
				$url = sprintf( '/activity/%s/', $post->ID );
			}

			$args = [
				'tokens' => [
					'activity'         => '',
					'usermessage'      => wp_strip_all_tags( $comment->comment_content ),
					'group.name'       => $group_name,
					'mentioned.url'    => esc_url( home_url( $url ) ),
					'poster.name'      => $author->display_name,
					'receiver-user.id' => $user_id,
					'unsubscribe'      => '',
				],
			];

			bp_send_email( $type, $user_id, $args );
		}
	}
}
