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

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

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

/**
 * Filters
 */
add_action( 'rest_api_init', __NAMESPACE__ . '\\register_api_init' );
add_filter( 'bp_rest_group_schema', __NAMESPACE__ . '\\group_schema' );
add_action( 'bp_actions', __NAMESPACE__ . '\\groups_action_create_group', 9 );
add_filter( 'nisje_notification_enrich_data', __NAMESPACE__ . '\\enrich_notification_data', 10, 3 );

// Notifications.
$group_post_types = apply_filters( 'nisje_group_post_types', [
	'nisje-user-content',
	'nisje-news-group',
	'nisje-event-group',
	'nisje-wiki-group',
] );

// Notifications.
foreach ( $group_post_types as $group_post_type ) {
	add_action( "rest_insert_{$group_post_type}", __NAMESPACE__ . '\\register_insert_group_post_notification', 10, 3 );
}

/**
 * Extend with custom rest fields.
 *
 * @return void
 */
function register_api_init() {
	bp_rest_register_field( 'groups', 'total_member_count', [
		'get_callback' => function( $group ) {
			return (int) groups_get_groupmeta( $group['id'], 'total_member_count', true );
		},
		'schema'       => [
			'context'     => [ 'view', 'edit' ],
			'description' => esc_html__( 'Count of all Group members.', 'nisje' ),
			'readonly'    => true,
			'type'        => 'integer',
		],
	] );

	bp_rest_register_field( 'groups', 'last_activity', [
		'get_callback' => function( $group ) {
			return bp_rest_prepare_date_response( groups_get_groupmeta( $group['id'], 'last_activity' ) );
		},
		'schema'       => [
			'context'     => [ 'view', 'edit' ],
			'description' => esc_html__( 'The date the Group was last active, in the site\'s timezone', 'nisje' ),
			'type'        => 'string',
			'readonly'    => true,
			'format'      => 'date-time',
		],
	] );

	bp_rest_register_field( 'groups', 'group_types', [
		'get_callback' => function( $group ) {
			return bp_groups_get_group_type( $group['id'] );
		},
		'schema'       => [
			'context'           => [ 'view', 'edit', 'member' ],
			'description'       => esc_html__( 'Group Types.', 'nisje' ),
			'readonly'          => true,
			'type'              => 'array',
			'items'             => [
				'type' => 'string',
			],
			'sanitize_callback' => function( $value ) {
				if ( ! empty( $value ) ) {
					$types = explode( ',', $value );

					$registered_types = bp_groups_get_group_types();

					$valid_types = array_intersect( $types, $registered_types );

					if ( ! empty( $valid_types ) ) {
						return $valid_types;
					} else {
						return null;
					}
				}

				return $value;
			},
			'validate_callback' => function( $value, $request, $param ) {
				if ( ! empty( $value ) ) {
					$types = explode( ',', $value );

					$registered_types = bp_groups_get_group_types();
					foreach ( $types as $type ) {
						if ( ! in_array( $type, $registered_types, true ) ) {
							// translators: 1: user provied group type 2: List of registered group types.
							return new \WP_Error( 'nisje_rest_group_invalid_group_type', sprintf( esc_html__( 'The group type you provided, %1$s, is not one of %2$s.', 'nisje' ), $type, implode( ', ', $registered_types ) ) );
						}
					}
				}
				return true;
			},
		],
	] );
}

/**
 * Filters the group schema.
 *
 * @param array $schema The endpoint schema.
 */
function group_schema( array $schema ) : array {
	if ( isset( $schema['properties']['id'] ) ) {
		$schema['properties']['id']['context'][] = 'listing';
	}

	if ( isset( $schema['properties']['name'] ) ) {
		$schema['properties']['name']['context'][] = 'listing';
	}

	return $schema;
}

/**
 * Redirect to react create screen.
 */
function groups_action_create_group() {
	if ( ! bp_is_groups_component() || ! bp_is_current_action( 'create' ) ) {
		return;
	}

	bp_core_redirect( trailingslashit( bp_get_groups_directory_permalink() ) . 'new' );
}

/**
 * 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 {
	$group_actions = [
		'new_membership_request',
		'membership_request_accepted',
		'membership_request_rejected',
		'group_invite',
		'member_promoted_to_admin',
		'member_promoted_to_mod',
		'new_group_post',
	];

	if ( in_array( $action, $group_actions, true ) ) {
		$group = nisje_get_group( $notification['item_id'] );

		if ( ! is_wp_error( $group ) ) {
			$args['avatar']  = $notification['item_id'];
			$args['context'] = 'groups';
			$args['item_id'] = $group->name;

			if ( 'new_membership_request' === $action ) {
				$args['secondary_item_id'] = bp_core_get_user_displayname( $notification['secondary_item_id'] );
				$args['href']              = '/groups/' . $notification['item_id'] . '/admin/membership-requests/';
				$args['message']           = [
					'raw'      => '%1$s requested membership to the group %2$s',
					// translators: %1$s name of the user requesting membership, %2$s group name.
					'rendered' => sprintf( esc_html__( '%1$s requested membership to the group %2$s', 'nisje' ),
						'<strong>' . $args['secondary_item_id'] . '</strong>',
						'<strong>' . $group->name . '</strong>'
					),
				];
			} elseif ( 'membership_request_accepted' === $action ) {
				$args['href']    = '/groups/' . $notification['item_id'] . '/';
				$args['message'] = [
					'raw'      => 'Your membership request for %s was accepted',
					// translators: %s group name.
					'rendered' => sprintf( esc_html__( 'Your membership request for %s was accepted', 'nisje' ),
						'<strong>' . $group->name . '</strong>'
					),
				];
			} elseif ( 'membership_request_rejected' === $action ) {
				$args['href']    = '/groups/' . $notification['item_id'] . '/';
				$args['message'] = [
					'raw'      => 'Your membership request for %s was rejected',
					// translators: %s group name.
					'rendered' => sprintf( esc_html__( 'Your membership request for %s was rejected', 'nisje' ),
						'<strong>' . $group->name . '</strong>'
					),
				];
			} elseif ( 'group_invite' === $action ) {
				$args['href']    = '/members/' . $notification['user_id'] . '/groups/invites/';
				$args['message'] = [
					'raw'      => 'You have an invitation to the group: %1$s',
					// translators: %1$s name of the group.
					'rendered' => sprintf( esc_html__( 'You have an invitation to the group: %1$s', 'nisje' ),
						'<strong>' . $group->name . '</strong>'
					),
				];
			} elseif ( 'member_promoted_to_admin' === $action ) {
				$args['href']    = '/groups/' . $notification['item_id'] . '/';
				$args['message'] = [
					'raw'      => 'You are promoted to admin in the group %1$s',
					// translators: %1$s group name.
					'rendered' => sprintf( esc_html__( 'You are promoted to admin in the group %1$s', 'nisje' ),
						'<strong>' . $group->name . '</strong>'
					),
				];
			} elseif ( 'member_promoted_to_mod' === $action ) {
				$args['href']    = '/groups/' . $notification['item_id'] . '/';
				$args['message'] = [
					'raw'      => 'You are promoted to moderator in the group %1$s',
					// translators: %1$s group name.
					'rendered' => sprintf( esc_html__( 'You are promoted to moderator in the group %1$s', 'nisje' ),
						'<strong>' . $group->name . '</strong>'
					),
				];
			} elseif ( 'new_group_post' === $action ) {
				$args['href']    = '/groups/' . $notification['item_id'] . '/';
				$args['message'] = [
					'raw'      => 'There is a new group post in the %1$s',
					// translators: %1$s group name.
					'rendered' => sprintf( esc_html__( 'There is a new group post in the group %1$s', 'nisje' ),
						'<strong>' . $group->name . '</strong>'
					),
				];
			}
		}
	}

	return $args;
}

/**
 * Register group post notification to all members of group
 *
 * @param WP_Post         $post Inserted or updated post object.
 * @param WP_REST_Request $request Request object.
 * @param bool            $creating True when creating a post, false when updating.
 */
function register_insert_group_post_notification( $post, $request, $creating ) {
	if ( $creating ) {
		$post     = get_post( $post->ID );
		$group_id = $request['group_id'];

		if ( $group_id ) {
			$group = nisje_get_group( $group_id );

			if ( $post instanceof \WP_Post && $group instanceof \BP_Groups_Group ) {
				$members = groups_get_group_members( [
					'group_id'            => $group->id,
					'exclude_banned'      => 1,
					'exclude_admins_mods' => 0,
					'exclude'             => [ intval( $post->post_author ) ],
					'type'                => 'first_joined',
				] );

				if ( $members ) {
					$feeds = [];

					foreach ( $members['members'] as $member ) {
						$feeds[] = $member->ID;
					}

					// Build activity.
					$activity = [
						'actor'      => 'user:' . $post->post_author,
						'verb'       => 'new_post:' . $post->ID,
						'object'     => 'post:' . $post->ID,
						'foreign_id' => 'group:' . $group->id,
					];

					foreach ( $feeds as $feed ) {
						foreach ( $feeds as $feed ) {
							bp_notifications_add_notification( [
								'user_id'           => $feed,
								'item_id'           => $group->id,
								'secondary_item_id' => $post->ID,
								'component_name'    => 'nisje',
								'component_action'  => 'new_group_post',
								'date_notified'     => bp_core_current_time(),
								'is_new'            => 1,
							] );
						}
					}
				}
			}
		}
	}
}
