use strict;
use warnings;

use RT::Test tests => undef;
my ( $baseurl, $m ) = RT::Test->started_ok;

my $alice         = RT::Test->load_or_create_user( Name => 'alice', EmailAddress => 'alice@localhost' );
my $current_alice = RT::CurrentUser->new( RT->SystemUser );
$current_alice->Load('alice');

my $group = RT::Test->load_or_create_group( 'test', Members => [$alice] );

my $general = RT::Test->load_or_create_queue( Name => 'General' );
my $support = RT::Test->load_or_create_queue( Name => 'Support' );

my $custom_role = RT::CustomRole->new( RT->SystemUser );
my ( $ret, $msg ) = $custom_role->Create(
    Name      => 'Manager',
    MaxValues => 0,
);
ok( $ret, "Created custom role: $msg" );

for my $queue ( $general, $support ) {
    my ( $ret, $msg ) = $custom_role->AddToObject( $queue->Id );
    ok( $ret, 'Added custom role to queue ' . $queue->Name );
}


RT::Test->create_ticket(
    Queue     => 'General',
    Subject   => 'Bilbo',
    Requestor => 'alice@localhost',
    $custom_role->GroupType => 'alice@localhost',
);

RT::Test->create_ticket(
    Queue                   => 'Support',
    Subject                 => 'Frodo',
    Requestor               => 'alice@localhost',
    $custom_role->GroupType => 'alice@localhost',
);

test_search( 0, 'without ShowTicket' );

{
    my ( $ret, $msg ) = $alice->PrincipalObj->GrantRight( Right => 'ShowTicket', Object => RT->System );
    ok( $ret, $msg );

    test_search( 2, 'ShowTicket granted globally' );

    ( $ret, $msg ) = $alice->PrincipalObj->RevokeRight( Right => 'ShowTicket', Object => RT->System );
    ok( $ret, $msg );
}

{
    my ( $ret, $msg ) = $group->PrincipalObj->GrantRight( Right => 'ShowTicket', Object => RT->System );
    ok( $ret, $msg );

    test_search( 2, 'ShowTicket granted for group globally' );

    ( $ret, $msg ) = $group->PrincipalObj->RevokeRight( Right => 'ShowTicket', Object => RT->System );
    ok( $ret, $msg );
}

{
    my $requestor = RT::Group->new( RT->SystemUser );
    $requestor->LoadRoleGroup(
        Object => RT->System,
        Name   => "Requestor",
    );
    ok $requestor->id, "Loaded global requestor role group";

    my ( $ret, $msg ) = $requestor->PrincipalObj->GrantRight( Right => 'ShowTicket', Object => RT->System );
    ok( $ret, $msg );

    test_search( 2, 'ShowTicket granted for Requestor globally' );

    ( $ret, $msg ) = $requestor->PrincipalObj->RevokeRight( Right => 'ShowTicket', Object => RT->System );
    ok( $ret, $msg );
}

{
    my $custom_role_group = RT::Group->new( RT->SystemUser );
    $custom_role_group->LoadRoleGroup(
        Object => RT->System,
        Name   => $custom_role->GroupType,
    );
    ok $custom_role_group->id, "Loaded global custom role group";

    my ( $ret, $msg ) = $custom_role_group->PrincipalObj->GrantRight( Right => 'ShowTicket', Object => RT->System );
    ok( $ret, $msg );

    test_search( 2, 'ShowTicket granted for custom role globally' );

    ( $ret, $msg ) = $custom_role_group->PrincipalObj->RevokeRight( Right => 'ShowTicket', Object => RT->System );
    ok( $ret, $msg );
}

{
    my ( $ret, $msg ) = $alice->PrincipalObj->GrantRight( Right => 'ShowTicket', Object => $support );
    ok( $ret, $msg );

    test_search( 1, 'ShowTicket granted on queue level' );

    ( $ret, $msg ) = $alice->PrincipalObj->RevokeRight( Right => 'ShowTicket', Object => $support );
    ok( $ret, $msg );
}

{
    my ( $ret, $msg ) = $group->PrincipalObj->GrantRight( Right => 'ShowTicket', Object => $support );
    ok( $ret, $msg );

    test_search( 1, 'ShowTicket granted for group on queue level' );

    ( $ret, $msg ) = $group->PrincipalObj->RevokeRight( Right => 'ShowTicket', Object => $support );
    ok( $ret, $msg );
}

{
    my $requestor = RT::Group->new( RT->SystemUser );
    $requestor->LoadRoleGroup(
        Object => $support,
        Name   => "Requestor",
    );
    ok $requestor->id, "Loaded queue requestor role group";

    my ( $ret, $msg ) = $requestor->PrincipalObj->GrantRight( Right => 'ShowTicket', Object => $support );
    ok( $ret, $msg );

    test_search( 1, 'ShowTicket granted for requestor on queue level' );


    ( $ret, $msg ) = $requestor->PrincipalObj->RevokeRight( Right => 'ShowTicket', Object => $support );
    ok( $ret, $msg );
}

{
    my $custom_role_group = RT::Group->new( RT->SystemUser );
    $custom_role_group->LoadRoleGroup(
        Object => $support,
        Name   => $custom_role->GroupType,
    );
    ok $custom_role_group->id, "Loaded queue custom role group";

    my ( $ret, $msg ) = $custom_role_group->PrincipalObj->GrantRight( Right => 'ShowTicket', Object => $support );
    ok( $ret, $msg );

    test_search( 1, 'ShowTicket granted for custom role on queue level' );


    ( $ret, $msg ) = $custom_role_group->PrincipalObj->RevokeRight( Right => 'ShowTicket', Object => $support );
    ok( $ret, $msg );
}

sub test_search {
    my $count = shift;
    my $desc  = shift;

    my $txns = RT::Transactions->new($current_alice);
    $txns->FromSQL(q{ObjectType='RT::Ticket' and Type='Create'});
    if ($count) {
        is( $txns->Count, $count, "Found $count transaction(s): $desc" );
        if ( $count == 1 ) {
            is( $txns->First->Object->Subject, 'Frodo', 'Found the correct transaction' );
        }
        else {
            is_deeply(
                [ sort( map { $_->Object->Subject } @{ $txns->ItemsArrayRef } ) ],
                [ 'Bilbo', 'Frodo' ],
                'Found all transactions'
            );
        }
    }
    else {
        ok( !$txns->Count, "No transactions found: $desc" );
        ok( !$txns->First, 'Really no transactions' );
    }
}

done_testing;
