<?php

namespace WeDevs\Wpuf\Pro\Admin;

use WP_Error;

/**
 * New user approve class for registration
 *
 * @since   2.8
 *
 * @package WP User Frontend
 */
class New_User_Approve {

    /**
     * Class constructor.
     */
    public function __construct() {
        add_action( 'wpuf_profile_setting', [ $this, 'add_form_settings' ], 10, 2 );
        add_action( 'wpuf_after_register', [ $this, 'insert_user_status' ], 10, 3 );
        add_filter( 'manage_users_columns', [ $this, 'new_modify_user_table' ] );
        add_filter( 'manage_users_custom_column', [ $this, 'new_modify_user_table_row' ], 10, 3 );
        add_filter( 'user_row_actions', [ $this, 'user_row_action_links' ], 10, 2 );
        add_filter( 'wp_authenticate_user', [ $this, 'validate_login' ], 10, 2 );
        add_action( 'restrict_manage_users', [ $this, 'status_filter' ], 10, 1 );
        add_action( 'pre_user_query', [ $this, 'filter_by_status' ] );
        add_action( 'admin_footer-users.php', [ $this, 'admin_footer' ] );
        add_action( 'load-users.php', [ $this, 'bulk_action' ] );
        add_filter( 'wpuf_settings_fields', [ $this, 'add_global_settings' ] );
        add_filter( 'wpuf_mail_options', [ $this, 'add_mail_settings' ] );
    }

    /**
     * Get the valid statuses.
     *
     * @return array
     */
    public function get_valid_statuses() {
        return [ 'pending', 'approved', 'denied' ];
    }

    /**
     * Add setting to registration form
     *
     * @return void
     */
    public function add_form_settings( $form_settings, $post ) {
        $status_selected = isset( $form_settings['wpuf_user_status'] ) ? $form_settings['wpuf_user_status'] : 'approved';
        ?>

        <tr>
            <th><?php _e( 'New User Status', 'wpuf-pro' ); ?></th>
            <td>
                <label>
                    <input type="hidden" name="wpuf_settings[wpuf_user_status]" value="approved">
                    <input type="checkbox" id="wpuf_new_user_status" name="wpuf_settings[wpuf_user_status]"
                           value="pending"<?php checked( $status_selected, 'pending' ); ?>>

                    <?php _e( 'Require approval', 'wpuf-pro' ); ?>
                </label>

                <p class="description"><?php _e(
                        'If enabled registered user cannot login until approved by an admin', 'wpuf-pro'
                    ); ?></p>
            </td>
        </tr>
        <?php
    }

    /**
     * Add setting to registration form
     *
     * @return void
     */
    public function insert_user_status( $user_id, $form_id ) {
        $form_settings = wpuf_get_form_settings( $form_id );
        $status        = isset( $form_settings['wpuf_user_status'] ) ? $form_settings['wpuf_user_status'] : 'approved';
        $key           = 'wpuf_user_status';
        update_user_meta( $user_id, $key, $status );
    }

    /**
     * Update user status
     *
     * @return void
     */
    public function update_user_status() {
        $wp_list_table = _get_list_table( 'WP_Users_List_Table' );
        $key           = 'wpuf_user_status';
        $user_id       = isset( $_GET['user'] ) ? $_GET['user'] : '';
        $status        = '';
        switch ( $wp_list_table->current_action() ) {
            case 'wpuf-approve-user':
                $status = 'approved';
                break;
            case 'wpuf-pending-user':
                $status = 'pending';
                break;
            case 'wpuf-deny-user':
                $status = 'denied';
                break;
            default:
        }
        if ( update_user_meta( $user_id, $key, $status ) ) {
            \WeDevs\Wpuf\Pro\Frontend\Profile_Form::user_status_update_notification( $status, $user_id );
        }
    }

    /**
     * Add status column to users table
     *
     * @return array
     */
    public function new_modify_user_table( $column ) {
        $column['status'] = __( 'Status', 'wpuf-pro' );

        return $column;
    }

    /**
     * Pull user status
     *
     * @return string
     */
    public function new_modify_user_table_row( $value, $column_name, $user_id ) {
        $this->update_user_status();
        switch ( $column_name ) {
            case 'status':
                return ucfirst( $this->get_user_status( $user_id ) );
                break;
            default:
        }

        return $value;
    }

    /**
     * Add setting to registration form
     *
     * @return array
     */
    public function user_row_action_links( $actions, $user_object ) {
        $user_id     = $user_object->ID;
        $user_status = $this->get_user_status( $user_id );
        $approve_user = "<a href='" . admin_url( "users.php?action=wpuf-approve-user&amp;user=$user_id" ) . "'>" . __(
                'Approve', 'wpuf-pro'
            ) . '</a>';
        $pending_user = "<a href='" . admin_url( "users.php?action=wpuf-pending-user&amp;user=$user_id" ) . "'>" . __(
                'Pending', 'wpuf-pro'
            ) . '</a>';
        $deny_user    = "<a href='" . admin_url( "users.php?action=wpuf-deny-user&amp;user=$user_id" ) . "'>" . __(
                'Deny', 'wpuf-pro'
            ) . '</a>';
        switch ( $user_status ) {
            case 'approved':
                $actions['wpuf-deny-user']    = $deny_user;
                $actions['wpuf-pending-user'] = $pending_user;
                break;
            case 'pending':
                $actions['wpuf-approve-user'] = $approve_user;
                $actions['wpuf-deny-user']    = $deny_user;
                break;
            case 'denied':
                $actions['wpuf-approve-user'] = $approve_user;
                $actions['wpuf-pending-user'] = $pending_user;
                break;
            default:
        }

        return $actions;
    }

    /**
     * Get the status of a user.
     *
     * @param int $user_id
     *
     * @return string the status of the user
     */
    public function get_user_status( $user_id ) {
        $user_status = get_user_meta( $user_id, 'wpuf_user_status', true );
        if ( empty( $user_status ) ) {
            $user_status = 'approved';
        }

        return $user_status;
    }

    /**
     * The default message that is shown to a user depending on their status when trying to sign in.
     *
     * @return string
     */
    public function get_authentication_message( $status ) {
        $message = '';
        $default_pending_msg = '<strong>' . __( 'ERROR:', 'wpuf-pro' ) . '</strong> ' . __(
            'Your account has to be approved by an administrator before you can login.',
            'wpuf-pro'
        );
        $default_denied_msg  = '<strong>' . __( 'ERROR:', 'wpuf-pro' ) . '</strong> ' . __(
            'Your account has been denied by an administrator, please contact admin to approve your account.',
            'wpuf-pro'
        );
        $pending_user_message = wpuf_get_option( 'pending_user_message', 'wpuf_profile', $default_pending_msg );
        $denied_user_message  = wpuf_get_option( 'denied_user_message', 'wpuf_profile', $default_denied_msg );
        if ( $status == 'pending' ) {
            $message = $pending_user_message;
        } else if ( $status == 'denied' ) {
            $message = $denied_user_message;
        }

        return $message;
    }

    /**
     * Generate error for login form based on user status
     *
     * @return string
     */
    public function validate_login( $user, $password ) {
        $status = $this->get_user_status( $user->ID );
        switch ( $status ) {
            case 'pending':
                $pending_message = $this->get_authentication_message( 'pending' );
                $user            = new \WP_Error( 'wpuf_pending_user_error', $pending_message );
                break;
            case 'denied':
                $denied_message = $this->get_authentication_message( 'denied' );
                $user           = new \WP_Error( 'wpuf_denied_user_error', $denied_message );
                break;
            default:
        }

        return $user;
    }

    /**
     * Add a filter to the user table to filter by user status
     *
     * @uses restrict_manage_users
     */
    public function status_filter( $which ) {
        $id = 'wpuf_user_approve_filter-' . $which;
        $filter_button   = submit_button(
            __( 'Filter Users by Status', 'wpuf-pro' ), 'button', 'wpuf-status-query-submit', false,
            [ 'id' => 'wpuf-status-query-submit' ]
        );
        $filtered_status = $this->selected_status();
        ?>

        <label class="screen-reader-text" for="<?php echo $id; ?>"><?php _e(
                'View all users', 'wpuf-pro'
            ); ?></label>
        <select id="<?php echo $id; ?>" name="<?php echo $id; ?>" style="float: none; margin: 0 0 0 15px;">
            <option value=""><?php _e( 'View all users', 'wpuf-pro' ); ?></option>
            <?php foreach ( $this->get_valid_statuses() as $status ) : ?>
                <option value="<?php echo esc_attr( $status ); ?>"<?php selected(
                    $status, $filtered_status
                ); ?>><?php echo esc_html( ucfirst( $status ) ); ?></option>
            <?php endforeach; ?>
        </select>

        <style>
            #wpuf-status-query-submit {
                float: right;
                margin: 0 0 0 5px;
            }
        </style>
        <?php
    }

    /**
     * Modify the user query if the status filter is being used.
     *
     * @param $query
     *
     * @uses pre_user_query
     */
    public function filter_by_status( $query ) {
        global $wpdb;
        if ( ! is_admin() && ! did_action( 'admin_init' ) ) {
            return;
        }
        if ( function_exists( 'get_current_screen' ) ) {
            $screen = get_current_screen();
        }
        if ( isset( $screen ) && 'users' != $screen->id ) {
            return;
        }
        if ( $this->selected_status() != NULL ) {
            $filter = $this->selected_status();
            $query->query_from .= " INNER JOIN {$wpdb->usermeta} ON ( {$wpdb->users}.ID = $wpdb->usermeta.user_id )";
            if ( 'approved' == $filter ) {
                $query->query_fields = "DISTINCT SQL_CALC_FOUND_ROWS {$wpdb->users}.ID";
                $query->query_from   .= " LEFT JOIN {$wpdb->usermeta} AS mt1 ON ({$wpdb->users}.ID = mt1.user_id AND mt1.meta_key = 'wpuf_user_status')";
                $query->query_where  .= " AND ( ( $wpdb->usermeta.meta_key = 'wpuf_user_status' AND CAST($wpdb->usermeta.meta_value AS CHAR) = 'approved' ) OR mt1.user_id IS NULL )";
            } else {
                $query->query_where .= " AND ( ($wpdb->usermeta.meta_key = 'wpuf_user_status' AND CAST($wpdb->usermeta.meta_value AS CHAR) = '{$filter}') )";
            }
        }
    }

    /**
     * Selected Status
     */
    public function selected_status() {
        if ( ! empty( $_REQUEST['wpuf_user_approve_filter-top'] ) || ! empty( $_REQUEST['wpuf_user_approve_filter-bottom'] ) ) {
            return esc_attr(
                ( ! empty( $_REQUEST['wpuf_user_approve_filter-top'] ) ) ? $_REQUEST['wpuf_user_approve_filter-top'] : $_REQUEST['wpuf_user_approve_filter-bottom']
            );
        }

        return NULL;
    }

    /**
     * Use javascript to add the ability to bulk modify the status of users.
     *
     * @uses admin_footer-users.php
     */
    public function admin_footer() {
        $screen = get_current_screen();
        if ( $screen->id == 'users' ) :
            ?>
            <script type="text/javascript">
                jQuery( document ).ready( function ( $ ) {
                    $( '<option>' ).val( 'approve' ).text( '<?php _e(
                        'Approve', 'wpuf-pro'
                    ); ?>' ).appendTo( "select[name='action']" );
                    $( '<option>' ).val( 'approve' ).text( '<?php _e(
                        'Approve', 'wpuf-pro'
                    ); ?>' ).appendTo( "select[name='action2']" );

                    $( '<option>' ).val( 'pending' ).text( '<?php _e(
                        'Pending', 'wpuf-pro'
                    ); ?>' ).appendTo( "select[name='action']" );
                    $( '<option>' ).val( 'pending' ).text( '<?php _e(
                        'Pending', 'wpuf-pro'
                    ); ?>' ).appendTo( "select[name='action2']" );

                    $( '<option>' ).val( 'deny' ).text( '<?php _e(
                        'Deny', 'wpuf-pro'
                    ); ?>' ).appendTo( "select[name='action']" );
                    $( '<option>' ).val( 'deny' ).text( '<?php _e(
                        'Deny', 'wpuf-pro'
                    ); ?>' ).appendTo( "select[name='action2']" );
                } );
            </script>
        <?php
        endif;
    }

    /**
     * Process the bulk status updates
     *
     * @uses load-users.php
     */
    public function bulk_action() {
        $screen = get_current_screen();
        if ( $screen->id == 'users' ) {
            // get the action
            $wp_list_table = _get_list_table( 'WP_Users_List_Table' );
            $action        = $wp_list_table->current_action();
            $allowed_actions = [ 'approve', 'pending', 'deny' ];
            if ( ! in_array( $action, $allowed_actions ) ) {
                return;
            }
            // security check
            check_admin_referer( 'bulk-users' );
            // make sure ids are submitted
            if ( isset( $_REQUEST['users'] ) ) {
                $user_ids = array_map( 'intval', $_REQUEST['users'] );
            }
            if ( empty( $user_ids ) ) {
                return;
            }
            $sendback = remove_query_arg(
                [
                    'approved',
                    'pending',
                    'denied',
                    'deleted',
                    'ids',
                    'new_user_approve_filter',
                    'new_user_approve_filter2',
                    'pw-status-query-submit',
                    'new_role',
                ], wp_get_referer()
            );
            if ( ! $sendback ) {
                $sendback = admin_url( 'users.php' );
            }
            $pagenum  = $wp_list_table->get_pagenum();
            $sendback = add_query_arg( 'paged', $pagenum, $sendback );
            $status   = '';
            switch ( $action ) {
                case 'approve':
                    $approved = 0;
                    foreach ( $user_ids as $user_id ) {
                        if ( update_user_meta( $user_id, 'wpuf_user_status', 'approved' ) ) {
                            \WeDevs\Wpuf\Pro\Frontend\Profile_Form::user_status_update_notification( 'approved', $user_id );
                            $approved ++;
                        }
                    }
                    $sendback = add_query_arg(
                        [
                            'approved' => $approved,
                            'ids'      => join( ',', $user_ids ),
                        ], $sendback
                    );
                    break;
                case 'pending':
                    $pending = 0;
                    foreach ( $user_ids as $user_id ) {
                        if ( update_user_meta( $user_id, 'wpuf_user_status', 'pending' ) ) {
                            \WeDevs\Wpuf\Pro\Frontend\Profile_Form::user_status_update_notification( 'pending', $user_id );
                            $pending ++;
                        }
                    }
                    $sendback = add_query_arg(
                        [
                            'pending' => $pending,
                            'ids'     => join( ',', $user_ids ),
                        ], $sendback
                    );
                    break;
                case 'deny':
                    $denied = 0;
                    foreach ( $user_ids as $user_id ) {
                        if ( update_user_meta( $user_id, 'wpuf_user_status', 'denied' ) ) {
                            \WeDevs\Wpuf\Pro\Frontend\Profile_Form::user_status_update_notification( 'denied', $user_id );
                            $denied ++;
                        }
                    }
                    $sendback = add_query_arg(
                        [
                            'denied' => $denied,
                            'ids'    => join( ',', $user_ids ),
                        ], $sendback
                    );
                    break;
                default:
                    return;
            }
            $sendback = remove_query_arg(
                [
                    'action',
                    'action2',
                    'tags_input',
                    'post_author',
                    'comment_status',
                    'ping_status',
                    '_status',
                    'post',
                    'bulk_edit',
                    'post_view',
                ], $sendback
            );
            wp_redirect( $sendback );
            exit();
        }
    }

    /**
     * Add mail settings to the email notification
     *
     * @since 4.1.3 only email settings moved from add_global_settings
     *
     * @param $mail_settings
     *
     * @return array
     */
    public function add_mail_settings( $mail_settings ) {
        $mail_settings[] = [
            'name'  => 'pending_user_email',
            'label' => '<span class="dashicons dashicons-groups"></span> ' . __( 'Pending User Email', 'wpuf-pro' ),
            'type'  => 'html',
            'class' => 'pending-user-email',
        ];
        $mail_settings[] = [
            'name'    => 'enable_pending_user_email_notification',
            'label'   => __( 'Pending User Email Notification', 'wpuf-pro' ),
            'desc'    => __( 'Enable email notification for pending user', 'wpuf-pro' ),
            'default' => 'on',
            'type'    => 'checkbox',
            'class'   => 'pending-user-email-option',
        ];
        $mail_settings[] = [
            'name'    => 'pending_user_email_subject',
            'label'   => __( 'Pending Email Subject for User', 'wpuf-pro' ),
            'desc'    => __( 'This sets the subject of the emails sent to newly registered user.', 'wpuf-pro' ),
            'default' => 'Status has been changed to pending',
            'type'    => 'text',
            'class'   => 'pending-user-email-option',
        ];
        $mail_settings[] = [
            'name'    => 'pending_user_email_body',
            'label'   => __( 'Pending Email Body for User', 'wpuf-pro' ),
            'desc'    => sprintf(
                /* translators: 1: line break, 2: strong tag open, 3: strong tag close, 4-7: code tags for placeholders */
                __( 'This sets the body of the emails sent to newly registered user.%1$s%2$sYou may use:%3$s %4$s %5$s %6$s %7$s', 'wpuf-pro' ),
                '<br>',
                '<strong>',
                '</strong>',
                '<code>{username}</code>',
                '<code>{user_email}</code>',
                '<code>{display_name}</code>',
                '<code>{user_status}</code>',
            ),
            'default' => 'Hi {username},

            Your account status has been changed to pending by an administrator.

            Thanks',
            'type'    => 'wysiwyg',
            'class'   => 'pending-user-email-option',
        ];
        $mail_settings[] = [
            'name'  => 'denied_user_email',
            'label' => '<span class="dashicons dashicons-dismiss"></span> ' . __( 'Denied User Email', 'wpuf-pro' ),
            'type'  => 'html',
            'class' => 'denied-user-email',
        ];
        $mail_settings[] = [
            'name'    => 'enable_denied_user_email_notification',
            'label'   => __( 'Denied User Email Notification', 'wpuf-pro' ),
            'desc'    => __( 'Enable email notification for denied user', 'wpuf-pro' ),
            'default' => 'on',
            'type'    => 'checkbox',
            'class'   => 'denied-user-email-option',
        ];
        $mail_settings[] = [
            'name'    => 'denied_user_email_subject',
            'label'   => __( 'Denied Email Subject for User', 'wpuf-pro' ),
            'desc'    => __( 'This sets the subject of the emails sent to denied user.', 'wpuf-pro' ),
            'default' => 'Denied your request',
            'type'    => 'text',
            'class'   => 'denied-user-email-option',
        ];
        $mail_settings[] = [
            'name'    => 'denied_user_email_body',
            'label'   => __( 'Denied Email Body for User', 'wpuf-pro' ),
            'desc'    => sprintf(
                /* translators: 1: line break, 2: strong tag open, 3: strong tag close, 4-7: code tags for placeholders */
                __( 'This sets the body of the emails sent to denied user.%1$s%2$sYou may use:%3$s %4$s %5$s %6$s %7$s', 'wpuf-pro' ),
                '<br>',
                '<strong>',
                '</strong>',
                '<code>{username}</code>',
                '<code>{user_email}</code>',
                '<code>{display_name}</code>',
                '<code>{user_status}</code>',
            ),
            'default' => 'Hi {username},

            Your account has been denied by an administrator, please contact admin to approve your account.

            Thanks',
            'type'    => 'wysiwyg',
            'class'   => 'denied-user-email-option',
        ];

        $mail_settings[] = [
            'name'  => 'approved_user_email',
            'label' => '<span class="dashicons dashicons-smiley"></span> ' . __( 'Approved User Email', 'wpuf-pro' ),
            'type'  => 'html',
            'class' => 'approved-user-email',
        ];
        $mail_settings[] = [
            'name'    => 'enable_approved_user_email_notification',
            'label'   => __( 'Approved User Email Notification', 'wpuf-pro' ),
            'desc'    => __( 'Enable email notification for approved user', 'wpuf-pro' ),
            'default' => 'on',
            'type'    => 'checkbox',
            'class'   => 'approved-user-email-option',
        ];
        $mail_settings[] = [
            'name'    => 'approved_user_email_subject',
            'label'   => __( 'Approved Email Subject for User', 'wpuf-pro' ),
            'desc'    => __( 'This sets the subject of the emails sent to approved user.', 'wpuf-pro' ),
            'default' => 'Approved your request',
            'type'    => 'text',
            'class'   => 'approved-user-email-option',
        ];
        $mail_settings[] = [
            'name'    => 'approved_user_email_body',
            'label'   => __( 'Approved Email Body for User', 'wpuf-pro' ),
            'desc'    => sprintf(
                /* translators: 1: line break, 2: strong tag open, 3: strong tag close, 4-7: code tags for placeholders */
                __( 'This sets the body of the emails sent to approved user.%1$s%2$sYou may use:%3$s %4$s %5$s %6$s %7$s', 'wpuf-pro' ),
                '<br>',
                '<strong>',
                '</strong>',
                '<code>{username}</code>',
                '<code>{user_email}</code>',
                '<code>{display_name}</code>',
                '<code>{user_status}</code>',
            ),
            'default' => 'Hi {username},

            Your account has been approved by an administrator.

            Thanks',
            'type'    => 'wysiwyg',
            'class'   => 'approved-user-email-option',
        ];

        $mail_settings[] = [
            'name'  => 'account_activated_user_email',
            'label' => '<span class="dashicons dashicons-smiley"></span> ' . __( 'Account Activated Email', 'wpuf-pro' ),
            'type'  => 'html',
            'class' => 'account-activated-user-email',
        ];
        $mail_settings[] = [
            'name'    => 'account_activated_user_email_notification',
            'label'   => __( 'Account Activated Email Notification', 'wpuf-pro' ),
            'desc'    => __( 'Enable email notification when the account is activated', 'wpuf-pro' ),
            'default' => 'on',
            'type'    => 'checkbox',
            'class'   => 'account-activated-user-email-option',
        ];
        $mail_settings[] = [
            'name'    => 'account_activated_user_email_subject',
            'label'   => __( 'Account Activated Email Subject for User', 'wpuf-pro' ),
            'desc'    => __( 'This sets the subject of the emails sent to approved users', 'wpuf-pro' ),
            'default' => 'Your account has been activated',
            'type'    => 'text',
            'class'   => 'account-activated-user-email-option',
        ];
        $mail_settings[] = [
            'name'    => 'account_activated_user_email_body',
            'label'   => __( 'Account Activated Email Body for User', 'wpuf-pro' ),
            'desc'    => sprintf(
                /* translators: 1: line break, 2: strong tag open, 3: strong tag close, 4-7: code tags for placeholders */
                __( 'This sets the body of the emails sent to approved users.%1$s%2$sYou may use:%3$s %4$s %5$s %6$s %7$s', 'wpuf-pro' ),
                '<br>',
                '<strong>',
                '</strong>',
                '<code>{login_url}</code>',
                '<code>{username}</code>',
                '<code>{user_email}</code>',
                '<code>{display_name}</code>'
            ),
            'default' => 'Hi {username},

            Congrats! Your account has been activated. To login visit the following {login_url}

            Thanks',
            'type'    => 'wysiwyg',
            'class'   => 'account-activated-user-email-option',
        ];

        return $mail_settings;
    }

    public function add_global_settings( $settings_fields ) {
        $settings_fields['wpuf_profile'][] = [
            'name'    => 'avatar_size',
            'label'   => __( 'Avatar Size', 'wpuf-pro' ),
            'desc'    => __(
                'Avatar size to crop when upload using the registration/profile form.(e.g:100x100)', 'wpuf-pro'
            ),
            'type'    => 'text',
            'default' => '100x100',
        ];
        $settings_fields['wpuf_profile'][] = [
            'name'    => 'pending_user_message',
            'label'   => __( 'Pending User Message', 'wpuf-pro' ),
            'desc'    => __( 'Pending user will see this message when try to log in.', 'wpuf-pro' ),
            'default' => '<strong>' . __( 'ERROR:', 'wpuf-pro' ) . '</strong> ' . __(
                'Your account has to be approved by an administrator before you can login.',
                'wpuf-pro'
            ),
            'type'    => 'textarea',
        ];
        $settings_fields['wpuf_profile'][] = [
            'name'    => 'denied_user_message',
            'label'   => __( 'Denied User Message', 'wpuf-pro' ),
            'desc'    => __( 'Denied user will see this message when try to log in.', 'wpuf-pro' ),
            'default' => '<strong>' . __( 'ERROR:', 'wpuf-pro' ) . '</strong> ' . __(
                'Your account has been denied by an administrator, please contact admin to approve your account.',
                'wpuf-pro'
            ),
            'type'    => 'textarea',
        ];

        return $settings_fields;
    }

}
