<?php


class Wiaas_Authentication_Test extends Wiaas_Unit_Test_Case {
    var $user_id, $organization_id, $request_uri;

    public function setUp() {
        parent::setUp();

        // set admin as current user
        wp_set_current_user(1);

        // create testing user
        $this->user_id = wp_create_user('test', 'test', 'test@mail.com');

        // create organization
        $this->organization_id = wp_insert_term(
            'test_organization',
            Wiaas_User_Organization::TAXONOMY_NAME
        )['term_id'];

        update_user_meta($this->user_id, '_wiaas_organization_id', $this->organization_id);


        # assign user to organization
        wp_set_terms_for_user(
            $this->user_id,
            Wiaas_User_Organization::TAXONOMY_NAME,
            [$this->organization_id]);

        wp_set_current_user($this->user_id);

        $this->request_uri = $_SERVER['REQUEST_URI'];
    }

    function tearDown() {
        parent::tearDown();

        wp_set_current_user(1);

        wp_delete_user($this->user_id);

        wp_delete_term(
            $this->organization_id,
            Wiaas_User_Organization::TAXONOMY_NAME);

        delete_user_meta($this->user_id, '_wiaas_organization_id');
        delete_user_meta($this->user_id, '_wiaas_current_user_admin_role');

        $_SERVER['REQUEST_URI'] = $this->request_uri;
    }

    /**
     * @covers Wiaas_Authentication::authenticate_current_user()
     * @group authentication
     */
    function test_user_authentication_fail_when_no_selected_role() {

        $this->assertFalse(
            Wiaas_Authentication::authenticate_current_user($this->user_id)
        );

        $this->assertTrue(
            is_wp_error(
                Wiaas_Authentication::authenticate_user_on_login(wp_get_current_user())
            )
        );

    }

    /**
     * @covers Wiaas_Authentication::authenticate_current_user()
     * @group authentication
     */
    function test_user_authentication_forwards_error() {
        // add roles to organization
        $organization_roles = array( 'supplier', 'customer' );
        update_term_meta($this->organization_id, '_wiaas_organization_roles', $organization_roles);

        update_user_meta($this->user_id, '_wiaas_current_user_admin_role', 'supplier');

        $this->assertFalse(
            Wiaas_Authentication::authenticate_current_user(false)
        );
    }

    /**
     * @covers Wiaas_Authentication::authenticate_current_user()
     * @group authentication
     */
    function test_current_user_authentication_fail_when_organization_has_no_roles() {

        $roles = array('administrator', 'supplier', 'customer', 'commercial_lead');

        foreach ($roles as $role) {
            update_user_meta($this->user_id, '_wiaas_current_user_admin_role', $role);

            $this->assertFalse(
                Wiaas_Authentication::authenticate_current_user($this->user_id)
            );
        }
    }

    /**
     * @covers Wiaas_Authentication::authenticate_current_user()
     * @group authentication
     */
    function test_current_user_authentication_fail_when_organization_has_different_roles() {
        // add roles to organization
        $organization_roles = array( 'supplier', 'customer' );
        update_term_meta($this->organization_id, '_wiaas_organization_roles', $organization_roles);

        $user_roles = array('administrator', 'commercial_lead');

        foreach ($user_roles as $user_role) {
            update_user_meta($this->user_id, '_wiaas_current_user_admin_role', $user_role);

            $this->assertFalse(
                Wiaas_Authentication::authenticate_current_user($this->user_id)
            );
        }
    }

    /**
     * @covers Wiaas_Authentication::authenticate_current_user()
     * @group authentication
     */
    function test_current_user_authentication_valid_when_organization_has_requested_role() {
        // add roles to organization
        $organization_roles = array( 'administrator', 'commercial_lead' );
        update_term_meta($this->organization_id, '_wiaas_organization_roles', $organization_roles);

        $user_roles = $organization_roles;

        foreach ($user_roles as $user_role) {
            update_user_meta($this->user_id, '_wiaas_current_user_admin_role', $user_role);

           $this->assertEquals(
               $this->user_id,
               Wiaas_Authentication::authenticate_current_user($this->user_id)
           );
        }
    }

    /**
     * @covers Wiaas_Authentication::authenticate_current_user()
     * @group authentication
     */
    function test_current_user_authentication_invalid_when_organization_has_no_customer_role() {
        // add roles to organization
        $organization_roles = array( 'administrator', 'commercial_lead' );
        update_term_meta($this->organization_id, '_wiaas_organization_roles', $organization_roles);

        $user_roles = $organization_roles;

        $_SERVER['REQUEST_URI'] = get_home_url('') . '/' . rest_get_url_prefix();

        foreach ($user_roles as $user_role) {
            update_user_meta($this->user_id, '_wiaas_current_user_admin_role', $user_role);

            $this->assertFalse(
                Wiaas_Authentication::authenticate_current_user($this->user_id)
            );
        }
    }

    /**
     * @covers Wiaas_Authentication::authenticate_current_user()
     * @group authentication
     */
    function test_current_user_authentication_valid_when_organization_has_customer_role() {
        // add roles to organization
        $organization_roles = array( 'administrator', 'commercial_lead', 'customer' );
        update_term_meta($this->organization_id, '_wiaas_organization_roles', $organization_roles);

        $user_roles = $organization_roles;

        $_SERVER['REQUEST_URI'] = get_home_url('') . '/' . rest_get_url_prefix();

        foreach ($user_roles as $user_role) {
            update_user_meta($this->user_id, '_wiaas_current_user_admin_role', $user_role);

            $this->assertEquals(
                $this->user_id,
                Wiaas_Authentication::authenticate_current_user($this->user_id)
            );
        }
    }

    /**
     * @covers Wiaas_Authentication::authenticate_user_on_login()
     * @group authentication
     */
    function test_login_authentication_fails_if_no_role_posted() {

        $user = wp_get_current_user();

        $error = Wiaas_Authentication::authenticate_user_on_login($user);

        $this->assertTrue(is_wp_error($error));

        $this->assertEquals('You must selected role to login!', $error->get_error_message());
    }

    /**
     * @covers Wiaas_Authentication::authenticate_user_on_login()
     * @group authentication
     */
    function test_login_authentication_does_nothing_if_rest_request() {

        $_SERVER['REQUEST_URI'] = get_home_url('') . '/' . rest_get_url_prefix();

        $user = wp_get_current_user();

        $response_user = Wiaas_Authentication::authenticate_user_on_login($user);

        $this->assertEquals(
            $user->ID,
            $response_user->ID
        );
    }

    /**
     * @covers Wiaas_Authentication::authenticate_user_on_login()
     * @group authentication
     */
    function test_login_authentication_fails_if_customer_role_requested() {

        $user = wp_get_current_user();

        $_POST['role'] = 'customer';

        $error = Wiaas_Authentication::authenticate_user_on_login($user);

        $this->assertTrue(is_wp_error($error));

        $this->assertEquals('No access!', $error->get_error_message());
    }


    /**
     * @covers Wiaas_Authentication::authenticate_user_on_login()
     * @group authentication
     */
    function test_login_authentication_fails_when_user_has_no_organization() {

        $_POST['role'] = 'supplier';

        delete_user_meta($this->user_id, '_wiaas_organization_id');

        $error = Wiaas_Authentication::authenticate_user_on_login(wp_get_current_user());

        $this->assertTrue(is_wp_error($error));

        $this->assertEquals('Account not completed!', $error->get_error_message());
    }

    /**
     * @covers Wiaas_Authentication::authenticate_user_on_login()
     * @group authentication
     */
    function test_login_authentication_fails_when_organization_has_no_roles() {

        $_POST['role'] = 'supplier';

        $error = Wiaas_Authentication::authenticate_user_on_login(wp_get_current_user());

        $this->assertTrue(is_wp_error($error));

        $this->assertEquals('Your account is not authorized for requested role.  Please contact us for help.', $error->get_error_message());
    }

    /**
     * @covers Wiaas_Authentication::authenticate_user_on_login()
     * @group authentication
     */
    function test_login_authentication_fails_when_organization_has_different_roles() {
        // add roles to organization
        $organization_roles = array( 'supplier', 'customer' );
        update_term_meta($this->organization_id, '_wiaas_organization_roles', $organization_roles);

        $_POST['role'] = 'commercial_lead';

        $error = Wiaas_Authentication::authenticate_user_on_login(wp_get_current_user());

        $this->assertTrue(is_wp_error($error));

        $this->assertEquals('Your account is not authorized for requested role.  Please contact us for help.', $error->get_error_message());
    }

    /**
     * @covers Wiaas_Authentication::authenticate_user_on_login()
     * @group authentication
     */
    function test_login_authentication_valid_when_organization_has_requested_role() {
        // add roles to organization
        $organization_roles = array( 'administrator', 'commercial_lead' );
        update_term_meta($this->organization_id, '_wiaas_organization_roles', $organization_roles);

        $user_roles = $organization_roles;

        foreach ($user_roles as $user_role) {
            $_POST['role'] = $user_role;

            $response_user = Wiaas_Authentication::authenticate_user_on_login(wp_get_current_user());

            $this->assertEquals(
                $this->user_id,
                $response_user->ID
            );
        }
    }

    /**
     * @covers Wiaas_Authentication::maybe_filter_user_roles()
     * @group authentication
     */
    function test_user_has_customer_role_on_rest_request() {
        $_SERVER['REQUEST_URI'] = get_home_url('') . '/' . rest_get_url_prefix();

        global $wpdb;

        $user_roles = Wiaas_Authentication::maybe_filter_user_roles(
            null, $this->user_id,
            $wpdb->get_blog_prefix() . 'capabilities'
        );

        $this->assertNotNull($user_roles);
        $this->assertCount(1, $user_roles);

        $user_roles = $user_roles[0];

        $this->assertNotNull($user_roles);
        $this->assertCount(1, $user_roles);
        $this->assertArrayHasKey('customer', $user_roles);
        $this->assertTrue($user_roles['customer']);

    }

    /**
     * @covers Wiaas_Authentication::maybe_filter_user_roles()
     * @group authentication
     */
    function test_user_has_no_role_if_not_selected() {

        global $wpdb;

        $user_roles = Wiaas_Authentication::maybe_filter_user_roles(
            null, $this->user_id,
            $wpdb->get_blog_prefix() . 'capabilities'
        );

        $this->assertNotNull($user_roles);
        $this->assertCount(1, $user_roles);

        $user_roles = $user_roles[0];

        $this->assertNotNull($user_roles);
        $this->assertCount(1, $user_roles);
        $this->assertEmpty(array_keys($user_roles)[0]);
    }

    /**
     * @covers Wiaas_Authentication::maybe_filter_user_roles()
     * @group authentication
     */
    function test_user_has_selected_role() {

        global $wpdb;

        update_user_meta($this->user_id, '_wiaas_current_user_admin_role', 'supplier');

        $user_roles = Wiaas_Authentication::maybe_filter_user_roles(
            null, $this->user_id,
            $wpdb->get_blog_prefix() . 'capabilities'
        );

        $this->assertNotNull($user_roles);
        $this->assertCount(1, $user_roles);

        $user_roles = $user_roles[0];

        $this->assertNotNull($user_roles);
        $this->assertCount(1, $user_roles);
        $this->assertArrayHasKey('supplier', $user_roles);
        $this->assertTrue($user_roles['supplier']);
    }
}
