<?php
namespace AcademyProGroupPlus\Dashboard\Ajax\Frontend;

use Academy\Classes\AbstractAjaxHandler;
use Academy\Classes\Sanitizer;
use AcademyProGroupPlus\Helper as GroupPlusHelper;
use AcademyProGroupPlus\Db\Models\{
    Group,
    Team
};
use AcademyProGroupPlus\Roles\{
    GroupOrganizer,
    TeamOrganizer
};
use WP_User;
use AcademyProGroupPlus\Interfaces\Ajax\Frontend\TeamHandlerInterface;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}


class TeamHandler extends AbstractAjaxHandler implements TeamHandlerInterface {
	protected $namespace = 'academy_pro_group_plus/frontend';
	public function __construct() {
		$this->actions = array(
			'get_team' => array(
				'callback' => array( $this, 'get_team' ),
				'capability' => 'academy_team_member',
			),
			'get_teams' => array(
				'callback' => array( $this, 'get_teams' ),
				'capability' => 'academy_team_member',
			),
			'create_team' => array(
				'callback' => array( $this, 'create_team' ),
				'capability' => 'manage_academy_team',
			),
			'update_team' => array(
				'callback' => array( $this, 'update_team' ),
				'capability' => 'manage_academy_team',
			),
			'delete_team' => array(
				'callback' => array( $this, 'delete_team' ),
				'capability' => 'manage_academy_team',
			),
			'create_user_to_team' => array(
				'callback' => array( $this, 'create_user_to_team' ),
				'capability' => 'manage_academy_team',
			),
			'add_members_to_team' => array(
				'callback' => array( $this, 'add_members_to_team' ),
				'capability' => 'manage_academy_team',
			),
			'remove_members_from_team' => array(
				'callback' => array( $this, 'remove_members_from_team' ),
				'capability' => 'manage_academy_team',
			),
			'get_members_from_team' => array(
				'callback' => array( $this, 'get_members_from_team' ),
				'capability' => 'academy_team_member',
			),
			'add_organizers_to_team' => array(
				'callback' => array( $this, 'add_organizers_to_team' ),
				'capability' => 'manage_academy_team',
			),
			'remove_organizers_from_team' => array(
				'callback' => array( $this, 'remove_organizers_from_team' ),
				'capability' => 'manage_academy_team',
			),
			'get_organizers_from_team' => array(
				'callback' => array( $this, 'get_organizers_from_team' ),
				'capability' => 'manage_academy_team',
			),
			'add_courses_to_team' => array(
				'callback' => array( $this, 'add_courses_to_team' ),
				'capability' => 'manage_academy_team',
			),
			'remove_courses_from_team' => array(
				'callback' => array( $this, 'remove_courses_from_team' ),
				'capability' => 'manage_academy_team',
			),
			'get_courses_from_team' => array(
				'callback' => array( $this, 'get_courses_from_team' ),
				'capability' => 'academy_team_member',
			),
		);
	}
    public function get_teams( $payload_data ) : void {
        $payload = Sanitizer::sanitize_payload(
            [
                'group_id'        => 'integer',
                'per_page'        => 'integer',
                'current_page'    => 'integer',
                'order_by'        => 'string',
                'search'          => 'string',
                'order_direction' => 'string',
            ],
            $payload_data
        );

        $conditions = [];
        $args       = [];
        $user_id    = get_current_user_id();
        $join       = '';

        // Restrict non-admins
        if ( ! current_user_can( 'manage_options' ) ) {
            $join = "
                LEFT JOIN " . Group::add_prefix( 'group_organizers' ) . " ugr ON t.group_id = ugr.group_id
                LEFT JOIN " . Group::add_prefix( 'team_organizers' )  . " tgr ON t.id = tgr.team_id
                LEFT JOIN " . Group::add_prefix( 'team_members' )     . " tmr ON t.id = tmr.team_id
            ";

            $conditions[] = '(ugr.organizer_id = %d OR tgr.organizer_id = %d OR tmr.member_id = %d)';
            $args[]       = $user_id;
            $args[]       = $user_id;
            $args[]       = $user_id;
        }

        $group_id = absint( $payload['group_id'] ?? 0 );
        $team_id  = absint( $payload['team_id'] ?? 0 );

        // Validate group
        if ( $group_id === 0 || empty( Group::ins()->get_by_id( $group_id ) ) ) {
            $output['message'] = __( 'Invalid Group ID.', 'academy-pro' );
            wp_send_json_error( $output, 404 );
        }

        $conditions[] = 't.group_id = %d';
        $args[]       = $group_id;

        // Single team check
        if ( $team_id > 0 && ! empty( Team::ins()->get_by_id( $team_id ) ) ) {
            $conditions[]          = 't.id = %d';
            $args[]                = $team_id;
            $payload['per_page']   = 1;
        }

        // Search
        if ( ! empty( $search = ( $payload['search'] ?? '' ) ) ) {
            $conditions[] = 't.name LIKE %s';
            $args[]       = "%{$search}%";
        }

        // Fetch data
        $data = Team::ins()->get_advance(
            't.*',                    // Select fields
            't.id',                   // For pagination
            't',                      // Main alias
            $join,                    // Joins
            $conditions,              // Where
            $args,                    // Bindings
            ' GROUP BY t.id ',        // Prevent duplicates
            $payload['per_page'] ?? 20,
            $payload['current_page'] ?? 1,
            $payload['order_by'] ?? null,
            $payload['order_direction'] ?? 'DESC'
        );

        // Map extra info
        $data['data'] = array_map(
            function( array $team ) use ( $group_id ) {
                $team['members']              = Team::ins()->members_count( $group_id, $team['id'] );
                $team['author']               = Group::get_user_info( $team['user_id'] );
                $team['is_current_user_leader'] = GroupPlusHelper::ins()->current_user_entity_exists( $team['id'], 'team_organizers' )
                    || GroupPlusHelper::ins()->current_user_entity_exists( $team['group_id'], 'group_organizers' );
                return $team;
            },
            $data['data'] ?? []
        );

        // Handle single row result
        if ( isset( $data['id'] ) ) {
            $data['is_current_user_leader'] = GroupPlusHelper::ins()->current_user_entity_exists( $data['id'], 'team_organizers' )
                || GroupPlusHelper::ins()->current_user_entity_exists( $data['group_id'], 'group_organizers' );
        }

        wp_send_json_success(
            $data,
            empty( $data ) && ( $payload['per_page'] ?? 20 ) === 1 ? 404 : 200
        );
    }

    public function get_team( $payload_data ) : void
    {
        $payload_data['per_page'] = 1;
        $this->get_teams($payload_data);
    }

    public function create_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'     => 'integer',
            'name'         => 'string',
            'description'  => 'string',
        ], $payload_data);

        $output = [];

        $group_id = abs(intval($payload['group_id'] ?? 0));


        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP OR NOT */
        if(!Group::ins()->is_organizer($group_id)){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }


        if(
            $group_id == 0 || 
            empty($group = Group::ins()->get_by_id($group_id))
        ){
            $output['message'] = __('Invalid Group ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }

        if(empty($payload['name'] ?? '')){
            $output['message'] = __('Team name is required.', 'academy-pro');
            wp_send_json_error($output, 400);
        }
        
		do_action( 'academy_pro_group_plus/api/before_create_team', $payload );
        $team_id = $created = Team::ins()->create([
            'name'         => $payload['name'],
            'description'  => $payload['description'] ?? '',
            'group_id'     => $group_id,
            'user_id'      => get_current_user_id(),
        ]);

        if(!$created){
            do_action( 'academy_pro_group_plus/api/after_create_team', $payload );
            $output['message'] = __('Error.', 'academy-pro');
            wp_send_json_error($output, 500);
        }

        $output['message'] = __('Team created!.', 'academy-pro');

        $output['data'] = Team::ins()->get_by_id($team_id);
        $output['data']['author'] = Group::get_user_info( $output['data']['user_id'] ?? 0 );
        wp_send_json_success($output, 201);
    }
    
    public function update_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'     => 'integer',
            'team_id'      => 'team_id',
            'name'         => 'string',
            'description'  => 'string',
        ], $payload_data);

        $output = [];
        $group_id = abs(intval($payload['group_id'] ?? 0));
        $team_id  = abs(intval($payload['team_id'] ?? 0));

        
        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP/TEAM OR NOT */
        if(
            !(
                Group::ins()->is_organizer($group_id) ||
                Team::ins()->is_organizer($group_id, $team_id)
            )
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }

        if(
            ($group_id == 0) ||  
            ($team_id  == 0) ||  
            empty( Group::ins()->get_by_id( $group_id ) ) || 
            empty( $team = Team::ins()->get_by_id($team_id) )
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }

        if(empty($payload['name'] ?? '')){
            $output['message'] = __('Group name is required.', 'academy-pro');
            wp_send_json_error($output, 400);
        }

		do_action( 'academy_pro_group_plus/api/before_update_team', $payload );
        $updated = Team::ins()->update([
            'name'         => $payload['name'],
            'description'  => $payload['description'] ?? $group['description'] ?? '',
        ],[
            'id'       => $team_id,
            'group_id' => $group_id,
        ]);

        if(!$updated){
            do_action( 'academy_pro_group_plus/api/after_update_team', $payload );
            $output['message'] = __('Error.', 'academy-pro');
            wp_send_json_error($output, 500);
        }

        $output['message'] = __('Team Updated!.', 'academy-pro');
        $output['data'] = $team;
        $output['data']['author'] = Group::get_user_info( $output['data']['user_id'] ?? 0 );
        wp_send_json_success($output);
    }

    public function delete_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'     => 'integer',
            'team_id'      => 'team_id',
        ], $payload_data);

        $output = [];

        $group_id = abs(intval($payload['group_id'] ?? 0));
        $team_id  = abs(intval($payload['team_id'] ?? 0));



        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP OR NOT */
        if(
            !Group::ins()->is_organizer($group_id)
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }

        if(
            ($group_id == 0) ||  
            ($team_id  == 0) ||  
            empty(Group::ins()->get_by_id($group_id)) || 
            empty(Team::ins()->get_by_id($team_id))
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }


		do_action( 'academy_pro_group_plus/api/before_delete_team', $payload );
        $deleted = Team::ins()->delete([
            'id'       => $team_id,
            'group_id' => $group_id,
        ]);

        if(!$deleted){
            do_action( 'academy_pro_group_plus/api/after_delete_team', $payload );
            $output['message'] = __('Error.', 'academy-pro');
            wp_send_json_error($output, 500);
        }

        $output['message'] = __('Team Deleted!.', 'academy-pro');
        $output['id'] = $team_id;
        wp_send_json_success($output);
    }


    /** create user: member, organizer */
    public function create_user_to_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'        => 'integer',
            'team_id'         => 'integer',

            'user_type'       => 'string',

            'username'        => 'string',
            'email'           => 'string',
            'password'        => 'string',
        ], $payload_data);

        $output = [];

        $group_id  = abs(intval($payload['group_id'] ?? 0));
        $team_id   = abs(intval($payload['team_id'] ?? 0));
        $user_type = $payload['user_type'] ?? '';

        Team::ins()->is_seats_available( $group_id );

        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP/TEAM OR NOT */
        if(
            !(
                Group::ins()->is_organizer($group_id) ||
                Team::ins()->is_organizer($group_id, $team_id)
            )
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }

        if(!in_array($user_type, ['member','organizer'])){
            $output['message'] = __('user_type must be member or organizer', 'academy-pro');
            wp_send_json_error($output, 400);
        }

        if(
            ($group_id == 0) ||  
            ($team_id  == 0) ||  
            empty(Group::ins()->get_by_id($group_id)) || 
            empty(Team::ins()->get_by_id($team_id))
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }

        if(empty($payload['username'] ?? '')){
            $output['errors']['username'][] = __('username field is required.', 'academy-pro');
        }
        if(empty($payload['email'] ?? '')){
            $output['errors']['email'][] = __('email field is required.', 'academy-pro');
        }
        if(empty($payload['password'] ?? '')){
            $output['errors']['password'][] = __('password field is required.', 'academy-pro');
        }
            

        if(
            !empty($payload['username'] ?? '') && 
            username_exists($payload['username']) 
        ){
            $output['errors']['username'][] = __("username  already exists.", 'academy-pro');
        }

        if(
            !empty($payload['email'] ?? '') && 
            email_exists($payload['email']) 
        ){
            $output['errors']['email'][] = __("email already exists.", 'academy-pro');
        }

        if(
            strlen($payload['password']) < 6
        ){
            $output['errors']['password'][] = __("password is too short, minimum password length is 10 characters.", 'academy-pro');
        }

        if(
            strlen($payload['password']) > 30
        ){
            $output['errors']['password'][] = __("password is too long, maximum password length is 30 characters.", 'academy-pro');
        }

        if(count($output['errors'] ?? []) > 0){
            wp_send_json_error($output, 400);
        }


		do_action( 'academy_pro_group_plus/api/before_create_user_to_team', $payload );
        
        $user_id = wp_create_user($payload['username'], $payload['password'], $payload['email']);

        if(is_wp_error($user_id)){
            $output['message'] = __('Error [1].', 'academy-pro');
            wp_send_json_error($output, 500);
        }

        $output['data'] = Group::get_user_info( $user_id );
		do_action( 'academy_pro_group_plus/api/after_create_user_to_team', $payload );

        if(
            $user_type == 'member' && 
            Team::ins()->add_member($group_id, $team_id, $user_id)
        ){
            $output['message'] = __('Member created & assigned to team!', 'academy-pro');
            wp_send_json_success($output, 201);
        }

        if(
            $user_type == 'organizer'
        ){
            

            if(Team::ins()->add_organizer($group_id, $team_id, $user_id)){
                $output['message'] = __('Organizer created & assigned to team!', 'academy-pro');
                wp_send_json_success($output, 201);
            }
        }

        $output['message'] = __('Unknown error.', 'academy-pro');
        wp_send_json_error($output, 500);
    }
    /** member */
    public function add_members_to_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'        => 'integer',
            'team_id'         => 'integer',
            'members'         => 'array',
        ], $payload_data);

        $output = [];

        $group_id = abs(intval($payload['group_id'] ?? 0));
        $team_id  = abs(intval($payload['team_id'] ?? 0));


        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP/TEAM OR NOT */
        if(
            !(
                Group::ins()->is_organizer($group_id) ||
                Team::ins()->is_organizer($group_id, $team_id)
            )
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }

        if(
            ($group_id == 0) ||  
            ($team_id  == 0) ||  
            empty(Group::ins()->get_by_id($group_id)) || 
            empty(Team::ins()->get_by_id($team_id))
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }

        if(
            empty($members = $payload['members'] ?? false) || 
            !is_array($members)
        ){
            $output['message'] = __('members field should be filled with user_id.', 'academy-pro');
            wp_send_json_error($output, 400);
        }

        foreach ($members as $member_id) {
			Team::ins()->is_seats_available( $group_id, count( $output['assigned'] ?? [] ) );
            if(Team::ins()->add_member($group_id, $team_id, $member_id)){
                $output['assigned'][] = $member_id;
                $output['members'][] = Group::get_user_info( $member_id );
            }
        }

        $output['data'] = $output['members'][0];
        // translators: %d is assigned members
        $output['message'] = sprintf( __( '%d members assigned.', 'academy-pro' ), count($output['assigned'] ?? []) );

        wp_send_json_success( $output );
    }
    
    public function remove_members_from_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'        => 'integer',
            'team_id'         => 'integer',
            'members'         => 'array',
        ], $payload_data);

        $output = [];

        $group_id = abs(intval($payload['group_id'] ?? 0));
        $team_id  = abs(intval($payload['team_id'] ?? 0));



        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP/TEAM OR NOT */
        if(
            !(
                Group::ins()->is_organizer($group_id) ||
                Team::ins()->is_organizer($group_id, $team_id)
            )
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }


        if(
            ($group_id == 0) ||  
            ($team_id  == 0) ||  
            empty(Group::ins()->get_by_id($group_id)) || 
            empty(Team::ins()->get_by_id($team_id))
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }

        if(
            empty($members = $payload['members'] ?? false) || 
            !is_array($members)
        ){
            $output['message'] = __('members field should be filled with member_id.', 'academy-pro');
            wp_send_json_error($output, 400);
        }
        
        foreach ($members as $member_id) {
            if(Team::ins()->remove_member($group_id, $team_id, $member_id)){
                $output['removed'][] = $member_id;
            }
        }
        
        $output['id'] = $output['removed'][0] ?? 0;
        // translators: %d is removed members
        $output['message'] = sprintf( __( '%d members removed.', 'academy-pro' ), count( $output['removed'] ?? [] ) );
        wp_send_json_success($output);
    }

    public function get_members_from_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'        => 'integer',
            'team_id'         => 'integer',
            'search'          => 'string',

            'per_page'     => 'integer',
            'current_page' => 'integer',
        ], $payload_data);

        $output = [];

        $group_id = abs(intval($payload['group_id'] ?? 0));
        $team_id  = abs(intval($payload['team_id'] ?? 0));
        $search  = $payload['search'] ?? NULL;



        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP/TEAM OR NOT */
        if(
            !(
                Group::ins()->is_organizer($group_id) ||
                Team::ins()->is_organizer($group_id, $team_id) ||
                Team::ins()->is_member($group_id, $team_id)
            )
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }

        if(
            ($group_id == 0) ||  
            ($team_id  == 0)
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }
        $data = Team::ins()->members(
            $group_id, 
            $team_id,
            abs(intval($payload['per_page'] ?? 20)),
            abs(intval($payload['current_page'] ?? 0)),
            NULL,
            'DESC',
            $search
        );
        $data['data'] = array_map( function( $user ) {
            // $user['user_email'] = '';
            return $user;
        }, $data['data'] ?? [] );
        wp_send_json_success( $data );
    }

    /** organizer */
    public function add_organizers_to_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'        => 'integer',
            'team_id'         => 'integer',
            'organizers'      => 'array',
        ], $payload_data);

        $output = [];

        $group_id = abs(intval($payload['group_id'] ?? 0));
        $team_id  = abs(intval($payload['team_id'] ?? 0));



        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP/TEAM OR NOT */
        if(
            !(
                Group::ins()->is_organizer($group_id) ||
                Team::ins()->is_organizer($group_id, $team_id)
            )
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }

        if(
            ($group_id == 0) ||  
            ($team_id  == 0) ||  
            empty(Group::ins()->get_by_id($group_id)) || 
            empty(Team::ins()->get_by_id($team_id))
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }

        if(
            empty($organizers = $payload['organizers'] ?? false) || 
            !is_array($organizers)
        ){
            $output['message'] = __('organizers field should be filled with organizer_id.', 'academy-pro');
            wp_send_json_error($output, 400);
        }

        foreach ($organizers as $organizer_id) {
            if(Team::ins()->add_organizer($group_id, $team_id, $organizer_id)){
                $output['assigned'][] = $organizer_id;
                $output['organizers'][] = Group::get_user_info( $organizer_id );
            }
        }

        $output['data'] = $output['organizers'][0] ?? [];
        // translators: %d is assigned organizers
        $output['message'] = sprintf( __( '%d organizers assigned.', 'academy-pro' ), count( $output['assigned'] ?? [] ) );
        wp_send_json_success( $output );
    }
    
    public function remove_organizers_from_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'        => 'integer',
            'team_id'         => 'integer',
            'organizers'      => 'array',
        ], $payload_data);

        $output = [];

        $group_id = abs(intval($payload['group_id'] ?? 0));
        $team_id  = abs(intval($payload['team_id'] ?? 0));



        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP/TEAM OR NOT */
        if(
            !(
                Group::ins()->is_organizer($group_id) ||
                Team::ins()->is_organizer($group_id, $team_id)
            )
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }

        if(
            ($group_id == 0) ||  
            ($team_id  == 0) ||  
            empty(Group::ins()->get_by_id($group_id)) || 
            empty(Team::ins()->get_by_id($team_id))
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }

        if(
            empty($organizers = $payload['organizers'] ?? false) || 
            !is_array($organizers)
        ){
            $output['message'] = __('organizers field should be filled with organizer_id.', 'academy-pro');
            wp_send_json_error($output, 400);
        }
        
        foreach ($organizers as $organizer_id) {
            if(Team::ins()->remove_organizer($group_id, $team_id, $organizer_id)){
                $output['removed'][] = $organizer_id;
            }
        }
        
        $output['id'] = $output['removed'][0] ?? [];
        // translators: %d is removed organizers
        $output['message'] = sprintf( __( '%d organizers removed.', 'academy-pro' ), count( $output['removed'] ?? [] ) );
        wp_send_json_success( $output );
    }

    public function get_organizers_from_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'        => 'integer',
            'team_id'         => 'integer',

            'per_page'     => 'integer',
            'current_page' => 'integer',
        ], $payload_data);

        $output = [];

        $group_id = abs(intval($payload['group_id'] ?? 0));
        $team_id  = abs(intval($payload['team_id'] ?? 0));



        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP/TEAM OR NOT */
        if(
            !(
                Group::ins()->is_organizer($group_id) ||
                Team::ins()->is_organizer($group_id, $team_id)
            )
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }

        if(
            ($group_id == 0) ||  
            ($team_id  == 0)
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }

        wp_send_json_success(
            Team::ins()->organizers(
                $group_id, 
                $team_id,
                abs(intval($payload['per_page'] ?? 20)),
                abs(intval($payload['current_page'] ?? 1)),
            )
        );
    }

    /** course */
    public function add_courses_to_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id' => 'integer',
            'team_id'  => 'integer',
            'courses'  => 'array',
        ], $payload_data);

        $output = [];

        $group_id = abs(intval($payload['group_id'] ?? 0));
        $team_id  = abs(intval($payload['team_id'] ?? 0));



        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP/TEAM OR NOT */
        if(
            !(
                Group::ins()->is_organizer($group_id) ||
                Team::ins()->is_organizer($group_id, $team_id)
            )
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }

        if(
            ($group_id == 0) ||  
            ($team_id  == 0) ||  
            empty(Group::ins()->get_by_id($group_id)) || 
            empty(Team::ins()->get_by_id($team_id))
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }

        if(
            empty($courses = $payload['courses'] ?? false) || 
            !is_array($courses)
        ){
            $output['message'] = __('courses field should be filled with course_id.', 'academy-pro');
            wp_send_json_error($output, 400);
        }

        foreach ($courses as $course_id) {

            $total_members   = Team::ins()->members_count($group_id, $team_id);
            $available_seats = Group::ins()->get_available_seats_by_course($group_id, $course_id);

            if(
                $available_seats >= $total_members &&
                Team::ins()->add_course($group_id, $team_id, $course_id)
            ){
                $output['assigned'][] = $course_id;
            }
            else{
                $output['errors'][$course_id] = [
                    'total_members'   => $total_members,
                    'available_seats' => $available_seats,
                ];
            }
        }


        if ( $total = count( $output['assigned'] ?? [] ) ) {
            global $wpdb;
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $output['assigned'] = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT ID, post_title, post_status 
                    FROM {$wpdb->posts} 
                    WHERE ID IN (" . implode( ', ', array_fill( 0, $total, '%d') ) . ")",// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
                    ...$output['assigned']
                ),
                ARRAY_A
            );
            // translators: %d is assigned courses
            $output['message'] = sprintf( __( '%d courses assigned.', 'academy-pro' ), count( $output['assigned'] ?? [] ) );
        }
        else {
            $output['message'] = __( 'No courses assigned.', 'academy-pro' );
        }

        wp_send_json_success( $output );
    }
    
    public function remove_courses_from_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'        => 'integer',
            'team_id'         => 'integer',
            'courses'         => 'array',
        ], $payload_data);

        $output = [];

        $group_id = abs(intval($payload['group_id'] ?? 0));
        $team_id  = abs(intval($payload['team_id'] ?? 0));



        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP/TEAM OR NOT */
        if(
            !(
                Group::ins()->is_organizer($group_id) ||
                Team::ins()->is_organizer($group_id, $team_id)
            )
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }

        if(
            ($group_id == 0) ||  
            ($team_id  == 0) ||  
            empty(Group::ins()->get_by_id($group_id)) || 
            empty(Team::ins()->get_by_id($team_id))
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }

        if(
            empty($courses = $payload['courses'] ?? false) || 
            !is_array($courses)
        ){
            $output['message'] = __('courses field should be filled with course_id.', 'academy-pro');
            wp_send_json_error($output, 400);
        }
        
        foreach ($courses as $course_id) {
            if(Team::ins()->remove_course($group_id, $team_id, $course_id)){
                $output['removed'][] = $course_id;
            }
        }
        
        $output['id'] = $output['removed'][0] ?? 0;
        // translators: %d is removed courses
        $output['message'] = sprintf( __( '%d courses removed.', 'academy-pro' ), count( $output['removed'] ?? [] ) );
        wp_send_json_success( $output );
    }

    public function get_courses_from_team( $payload_data ) : void
    {
		$payload = Sanitizer::sanitize_payload([
            'group_id'        => 'integer',
            'team_id'         => 'integer',

            'per_page'     => 'integer',
            'current_page' => 'integer',
        ], $payload_data);

        $output = [];

        $group_id = abs(intval($payload['group_id'] ?? 0));
        $team_id  = abs(intval($payload['team_id'] ?? 0));



        /** VERIFY CURRENT USER IS ORGANIZER OF THIS GROUP/TEAM OR NOT */
        if(
            !(
                Group::ins()->is_organizer($group_id) ||
                Team::ins()->is_organizer($group_id, $team_id)||
                Team::ins()->is_member($group_id, $team_id)
            )
        ){
            $output['message'] = __('Unauthorized.', 'academy-pro');
            wp_send_json_error($output, 401);
        }

        if(
            ($group_id == 0) ||  
            ($team_id  == 0)
        ){
            $output['message'] = __('Invalid Group/Team ID.', 'academy-pro');
            wp_send_json_error($output, 404);
        }

        wp_send_json_success(
            Team::ins()->courses(
                $group_id, 
                $team_id,
                abs(intval($payload['per_page'] ?? 20)),
                abs(intval($payload['current_page'] ?? 1)),
            )
        );
    }
}