<?php

/**
 * Handles user authentication for wiaas
 *
 * User roles are inherited from organization
 *
 * Class Wiaas_Authentication
 */
class Wiaas_Authentication {

    const SUPER_ADMIN_USER_ID = 1;

    public static function init() {
        // authenticate current user
        add_action('determine_current_user', array(__CLASS__, 'authenticate_current_user'), 999);

        // authenticates user on login
        add_filter( 'authenticate', array( __CLASS__, 'authenticate_user_on_login' ), 999, 3);

        // retrieve preferred user role for user
        add_filter('get_user_metadata', array(__CLASS__, 'maybe_filter_user_roles'), 10, 3);

        // redirect to dashboard after login
        add_filter( 'login_redirect', array( __CLASS__, 'login_redirect' ) );

        // add role selector to login form
        add_action('login_form', array(__CLASS__, 'pick_role_on_login'));
    }

    /**
     * Redirect admin user to dashboard
     *
     * @return string
     */
    public static function login_redirect() {
        return  admin_url('index.php') ;
    }

    /**
     * Add role selector to login form
     */
    public static function pick_role_on_login() {
        ?>
        <p>
            <label for="user_role"><?php esc_html_e( 'Role' , 'wiaas'); ?><br />
                <select id="user_role" class="input" name="role">
                    <option value="administrator"><?php esc_html_e('Administrator', 'wiaas') ?></option>
                    <option value="supplier"><?php esc_html_e('Supplier', 'wiaas') ?></option>
                    <option value="commercial_lead"><?php esc_html_e('Commercial Lead', 'wiaas') ?></option>
                </select>
        </p>
        <?php
    }


    /**
     * Authenticate current user based on roles assigned to organization
     *
     * @param int|false $user_id
     * @return int|false|WP_Error
     */
    public static function authenticate_current_user($user_id) {
        // do nothing if user not authenticated, user is super admin or this is REST API request
        if (! $user_id || $user_id === self::SUPER_ADMIN_USER_ID) {
            return $user_id;
        }

        $is_rest_api = strpos($_SERVER['REQUEST_URI'], rest_get_url_prefix());

        $role = $is_rest_api ?
            'customer' :
            get_user_meta($user_id, '_wiaas_current_user_admin_role', true);

        $result = self::_can_user_have_role($user_id, $role, $is_rest_api);

        if (is_wp_error($result)) {
            return false;
        }

        return $user_id;
    }

    /**
     * Authenticate wiaas user on login based on roles assigned to organization
     *
     * @param WP_User $user
     * @return WP_User|WP_Error
     */
    public static function authenticate_user_on_login($user) {
        // check if rest request
        $is_rest_api = strpos($_SERVER['REQUEST_URI'], rest_get_url_prefix());
        // do nothing if there is an error already,
        // user is super admin or
        // this is rest request
        if (is_wp_error($user) || $user->ID === 1 || $is_rest_api) {
            return $user;
        }

        if (empty($_POST['role'])) {
            return new WP_Error('error', 'You must selected role to login!');
        }

        // get selected role
        $requested_role = sanitize_key($_POST['role']);

        // validate can user have requested role
        $result = self::_can_user_have_role($user->ID, $requested_role, false);

        // if user organization has no requested role prevent access
        if (is_wp_error($result)) {
            return $result;
        }

        // remember role for user and continue
        update_user_meta($user->ID, '_wiaas_current_user_admin_role', $requested_role);

        return $user;
    }


    /**
     *
     * Filters user roles retrieval so that selected user role is retrieved for admin panel
     * and customer role is retrieved for JSON API request
     *
     * @param $null
     * @param int $user_id
     * @param string $meta_key
     * @return array|null
     */
    public static function maybe_filter_user_roles($null, $user_id, $meta_key) {

        global $wpdb;

        if ($user_id !== 0 && $user_id !== self::SUPER_ADMIN_USER_ID && $meta_key === $wpdb->get_blog_prefix() . 'capabilities') {

            $is_rest_api = strpos($_SERVER['REQUEST_URI'], rest_get_url_prefix());

            $role = $is_rest_api ?
                'customer' :
                get_user_meta($user_id, '_wiaas_current_user_admin_role', true);

            return array( array ( "$role" => true ));
        }

        return null;
    }



    // PRIVATE

    /**
     * Determines if user can have requested role based on his organization roles
     *
     * @param int $user_id
     * @param string $user_role
     * @param bool $is_rest_api
     * @return bool|WP_Error
     */
    private static function _can_user_have_role($user_id, $user_role, $is_rest_api) {
        // check if role valid for access
        if (! wp_roles()->is_role($user_role)) {
            return new WP_Error('error', 'Role is not valid!');
        }

        // only customer role can access API
        if ($is_rest_api && $user_role !== 'customer') {
            return new WP_Error('error', 'No access!');
        }

        // customer role cannot access admin backend
        if (! $is_rest_api && $user_role === 'customer') {
            return new WP_Error('error', 'No access!');
        }

        // import organization functions (during user authentication it is not yet loaded)
        require_once dirname( __FILE__ ) . '/user/wiaas-organization-functions.php';

        // get user organization
        $organization_id = wiaas_get_user_organization_id($user_id);

        // validate if user has organization
        if (empty( $organization_id)) {
            return new WP_Error('error', 'Account not completed!');
        }
        // get organization roles
        $roles = wiaas_get_organization_roles($organization_id);

        // validate if user has organization roles
        if (!in_array($user_role, $roles)) {
            return new WP_Error( 'error', 'Your account is not authorized for requested role.  Please contact us for help.' );
        }

        return true;
    }
}

Wiaas_Authentication::init();
