<?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'] );
		if ( $post instanceof \WP_Post ) {
			$args['secondary_item_id'] = wp_strip_all_tags( get_the_title( $post->ID ) );
		}

		if ( 'post_mention' === $action ) {
			$args['message'] = [
				'raw'      => '%1$s mentioned you in 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' ), $args['item_id'], $args['secondary_item_id'] ),
			];
		} 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' ), $args['item_id'], $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'       => __( 'Post Mention', 'nisje' ),
		'description' => __( 'When someone mention you in a post', 'nisje' ),
	];

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

	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 ) {
	$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,
			] );
		}
	}
}

/**
 * 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 ) {
	$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,
		] );
	}
}
