# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.

########################################
# Test for xmlrpc calls to:            #
# Product.get_selectable_products()    #
# Product.get_enterable_products()     #
# Product.get_accessible_products()    #
# Product.get()                        #
########################################

use 5.14.0;
use strict;
use warnings;

use FindBin qw($RealBin);
use lib "$RealBin/../lib";

use Test::More tests => 134;
use QA::Util;
my ($config, @clients) = get_rpc_clients();

my $products = $clients[0]->bz_get_products();
my $public    = $products->{'Another Product'};
my $private   = $products->{'QA-Selenium-TEST'};
my $no_entry  = $products->{'QA Entry Only'};
my $no_search = $products->{'QA Search Only'};

my %id_map = reverse %$products;

my $tests = {
    'QA_Selenium_TEST' => {
        selectable => [$public, $private, $no_entry, $no_search],
        enterable  => [$public, $private, $no_entry, $no_search],
        accessible => [$public, $private, $no_entry, $no_search],
    },
    'unprivileged' => {
        selectable => [$public, $no_entry],
        not_selectable => $no_search,
        enterable  => [$public, $no_search],
        not_enterable => $no_entry,
        accessible => [$public, $no_entry, $no_search],
        not_accessible => $private,
    },
    '' => {
        selectable => [$public, $no_entry],
        not_selectable => $no_search,
        enterable  => [$public, $no_search],
        not_enterable => $no_entry,
        accessible => [$public, $no_entry, $no_search],
        not_accessible => $private,
    },
};

foreach my $rpc (@clients) {
    foreach my $user (keys %$tests) {
        my @selectable = @{ $tests->{$user}->{selectable} };
        my @enterable  = @{ $tests->{$user}->{enterable} };
        my @accessible = @{ $tests->{$user}->{accessible} };
        my $not_selectable = $tests->{$user}->{not_selectable};
        my $not_enterable  = $tests->{$user}->{not_enterable};
        my $not_accessible = $tests->{$user}->{not_accessible};

        $rpc->bz_log_in($user) if $user;
        $user ||= "Logged-out user";

        my $select_call =
            $rpc->bz_call_success('Product.get_selectable_products');
        my $select_ids = $select_call->result->{ids};
        foreach my $id (@selectable) {
            ok(grep($_ == $id, @$select_ids),
               "$user can select " . $id_map{$id});
        }
        if ($not_selectable) {
            ok(!grep($_ == $not_selectable, @$select_ids),
               "$user cannot select " . $id_map{$not_selectable});
        }

        my $enter_call =
            $rpc->bz_call_success('Product.get_enterable_products');
        my $enter_ids = $enter_call->result->{ids};
        foreach my $id (@enterable) {
            ok(grep($_ == $id, @$enter_ids), "$user can enter " . $id_map{$id});
        }
        if ($not_enterable) {
            ok(!grep($_ == $not_enterable, @$enter_ids),
               "$user cannot enter " . $id_map{$not_enterable});
        }

        my $access_call =
            $rpc->bz_call_success('Product.get_accessible_products');
        my $get_call = $rpc->bz_call_success('Product.get',
                                             { ids => \@accessible });
        my $products = $get_call->result->{products};
        my $expected_count = scalar @accessible;
        cmp_ok(scalar @$products, '==', $expected_count,
           "Product.get gets all $expected_count accessible products"
           . " for $user.");
        if ($not_accessible) {
            my $no_access_call = $rpc->bz_call_success(
                'Product.get', { ids => [$not_accessible] });
            ok(!scalar @{ $no_access_call->result->{products} },
               "$user gets 0 products when asking for "
               . $id_map{$not_accessible});
        }

        $rpc->bz_call_success('User.logout') if $user ne "Logged-out user";
    }
}
