#!perl
use Cassandane::Tiny;

my sub install_test($name, $arg) {
    $name //= do {
        my ( undef, undef, $line ) = caller;
        "test_at_line_$line";
    };

    require Sub::Install;
    Sub::Install::install_sub({
        as   => "test_email_query_listid_$name",
        code => sub ($self) {
            $self->assert_email_query_listid($arg);
        },
    });
}

install_test("simple", {
    header => "Foo <xxx.yyy.zzz>",
    listId => "xxx.yyy.zzz",
    wantMatch => 1,
});

install_test("whitespace", {
    header => "Foo <xxx.y\tyy. ZZZ>",
    listId => "xxx.yyy.zzz",
    wantMatch => 1,
});

install_test("group", {
    # as seen from Yahoo, Google, et al
    header => "list aaa\@bbb.ccc; contact aaa-contact\@bbb.ccc",
    listId => "aaa\@bbb.ccc",
    wantMatch => 1,
});

install_test("group_ignore_space", {
    # as seen from Yahoo, Google, et al
    header => "list aaa\@bbb.ccc; contact aaa-contact\@bbb.ccc",
    listId => 'aaa @ bbb . ccc',
    wantMatch => 1,
});

install_test("group_ignore_contact", {
    # as seen from Yahoo, Google, et al
    header => "list aaa\@bbb.ccc; contact aaa-contact\@bbb.ccc",
    listId => 'aaa-contact@bbb.ccc',
    wantMatch => 0,
});

install_test("group_no_substring", {
    # as seen from Yahoo, Google, et al
    header => "list aaa\@bbb.ccc; contact aaa-contact\@bbb.ccc",
    listId => 'aaa',
    wantMatch => 0,
});

install_test("group_no_wildcard", {
    # as seen from Yahoo, Google, et al
    header => "list aaa\@bbb.ccc; contact aaa-contact\@bbb.ccc",
    listId => 'aaa*',
    wantMatch => 0,
});

install_test("no_bracket", {
    # as seen from Sentry, just plain text
    header => "sub3.sub2.sub1.top",
    listId => "sub3.sub2.sub1.top",
    wantMatch => 1,
});

install_test("unclosed_bracket", {
    header => "Foo <xxx.yyy.zzz",
    listId => "xxx.yyy.zzz",
    wantMatch => 1,
});

install_test("phrase_html", {
    # bogus id as seen in the wild
    header => "\"<b>foo</b>\" <xxx.yyy.zzz>",
    listId => "xxx.yyy.zzz",
    wantMatch => 1,
});

install_test("phrase_and_list", {
    # phrase followed by 'list'
    header => "1234567890 list <xxx.yyy.zzz>",
    listId => "xxx.yyy.zzz",
    wantMatch => 1,
});

install_test("no_substring_search", {
    header => "Foo <xxx.yyy.zzz>",
    listId => "yyy",
    wantMatch => 0,
});

install_test("no_wildcard_search", {
    header => "Foo <xxx.yyy.zzz>",
    listId => "xxx*",
    wantMatch => 0,
});

sub assert_email_query_listid($self, $arg)
{
    my $jmap = $self->{jmap};
    my $imap = $self->{store}->get_client();

    $imap->create("matches") or die;

    $self->{instance}->install_sieve_script(<<"EOF"
require ["x-cyrus-jmapquery", "x-cyrus-log", "variables", "fileinto"];
if allof(
  jmapquery text:
  {
     "listId" : "$arg->{listId}"
  }
.
)
{
  fileinto "matches";
}
EOF
    );

    xlog $self, "Deliver message";
    $self->{instance}->deliver($self->{gen}->generate(
        extra_headers => [['List-ID', $arg->{header}]],
        body => 'test',
    ));

    my $wantMatch = $arg->{wantMatch} ? 1 : 0;

    xlog $self, "Assert Sieve filter";
    $imap->select('matches');
    $self->assert_num_equals($wantMatch, $imap->get_response_code('exists'));    $imap->unselect();

    xlog $self, "Run squatter";
    $self->{instance}->run_command({cyrus => 1}, 'squatter');

    xlog $self, "Query for 'listId' criteria";
    my $res = $jmap->CallMethods([
        ['Email/query', {
            filter => {
                listId => $arg->{listId},
            },
        }, 'R1' ]
    ], [
        'urn:ietf:params:jmap:core',
        'urn:ietf:params:jmap:mail',
        'https://cyrusimap.org/ns/jmap/mail',
    ]);
    $self->assert_num_equals($wantMatch, scalar @{$res->[0][1]{ids}});
}
