#!perl
use Cassandane::Tiny;

sub test_email_import_received_at
{
    my ($self) = @_;
    my $jmap = $self->{jmap};
    my ($maj, $min) = Cassandane::Instance->get_version();

    my @testCases = ({
        desc => 'receivedAt set by client',
        headers => "Date: Sat, 1 Jan 2022 01:00:00 +1100\r\n",
        receivedAt => '2022-02-01T12:00:00Z',
        wantSentAt => '2022-01-01T01:00:00+11:00',
        wantReceivedAt => '2022-02-01T12:00:00Z',
    }, {
        desc => 'receivedAt set by client',
        headers => "Date: Sat, 1 Jan 2022 01:00:00 +1100\r\n" .
                   "Received: from foo ([192.168.0.1]) by bar (Baz); Mon, 15 Aug 2022 07:49:01 -0400\r\n",
        receivedAt => '2022-02-01T12:00:00Z',
        wantSentAt => '2022-01-01T01:00:00+11:00',
        wantReceivedAt => '2022-02-01T12:00:00Z',
    }, {
        desc => 'receivedAt from Received header',
        creationId => 'receivedAtFromReceivedHeader',
        headers => "Date: Sat, 1 Jan 2022 01:00:00 +1100\r\n" .
                   "Received: from foo ([192.168.0.1]) by bar (Baz); Mon, 15 Aug 2022 07:49:01 -0400\r\n",
        wantSentAt => '2022-01-01T01:00:00+11:00',
        wantReceivedAt => '2022-08-15T11:49:01Z',
        skipVersionBefore => [3,7],
    }, {
        desc => 'receivedAt from first Received header',
        headers => "Date: Sat, 1 Jan 2022 01:00:00 +1100\r\n" .
                   "Received: from rcv1 ([192.168.0.1]) by bar (Baz); Mon, 15 Aug 2022 07:49:01 -0400\r\n" .
                   "Received: from rcv2 ([192.168.0.2]) by tux (Qux); Sat, 13 Aug 2022 12:01:10 -0200\r\n" .
                   "Received: from rcv3 ([192.168.0.3]) by baz (Hkl); Tue, 16 Aug 2022 13:01:10 -0200\r\n",
        wantSentAt => '2022-01-01T01:00:00+11:00',
        wantReceivedAt => '2022-08-15T11:49:01Z',
        skipVersionBefore => [3,7],
    }, {
        desc => 'receivedAt from Date header',
        headers => "Date: Sat, 1 Jan 2022 01:00:00 +1100\r\n",
        wantSentAt => '2022-01-01T01:00:00+11:00',
        wantReceivedAt => '2021-12-31T14:00:00Z',
        skipVersionBefore => [3,7],
    }, {
        desc => 'not set',
        wantSentAt => undef,
        wantReceivedAt => undef,
    }, {
        desc => 'receivedAt from first valid Received header',
        headers => "Date: Sat, 1 Jan 2022 01:00:00 +1100\r\n" .
                   "Received: from rcv1 ([192.168.0.1]) by bar (Baz); invalid datetime\r\n" .
                   "Received: from rcv2 ([192.168.0.2]) by tux (Qux); Sat, 13 Aug 2022 12:01:10 -0200\r\n" .
                   "Received: from rcv3 ([192.168.0.3]) by baz (Hkl); Sat, 13 Aug 2022 12:00:45 -0200\r\n",
        wantSentAt => '2022-01-01T01:00:00+11:00',
        wantReceivedAt => '2022-08-13T14:01:10Z',
        skipVersionBefore => [3,9],
    }, {
        desc => 'receivedAt from X-DeliveredInternalDate header',
        headers => "Date: Sat, 1 Jan 2022 01:00:00 +1100\r\n" .
                   "Received: from rcv1 ([192.168.0.2]) by tux (Qux); Sat, 13 Aug 2022 12:01:10 -0200\r\n" .
                   "Received: from rcv2 ([192.168.0.3]) by baz (Hkl); Sat, 13 Aug 2022 12:00:45 -0200\r\n" .
                   "X-DeliveredInternalDate: Mon, 15 Aug 2022 13:00:45 -0200\r\n",
                   ,
        wantSentAt => '2022-01-01T01:00:00+11:00',
        wantReceivedAt => '2022-08-15T15:00:45Z',
        skipVersionBefore => [3,9],
    });

    while (my ($i, $tc) = each @testCases) {

        my $skipVersionBefore = $tc->{skipVersionBefore} || [0,0];
        my ($needMaj, $needMin) = @{$skipVersionBefore};
        if ($maj < $needMaj || ($maj == $needMaj && $min < $needMin)) {
            xlog "maj=$maj needMaj=$needMaj min=$min needMin=$needMin";
            xlog $self, "Skipping test $tc->{creationId}";
            next;
        }

        xlog $self, "Running test $tc->{creationId}";

        my $mime = $tc->{headers} || '';
        $mime .= <<'EOF';
From: sender@local
To: receiver@local
Subject: test
MIME-Version: 1.0
Content-Type: text/plain; charset='UTF-8'
Content-Transfer-Encoding: quoted-printable
EOF
        $mime =~ s/\r?\n/\r\n/gs;
        $mime .= "\r\n";
        $mime .= $tc->{desc} || 'foo';

        xlog $self, "Upload blob";
        my $blobId = ($jmap->Upload($mime, 'message/rfc822'))->{blobId};
        $self->assert_not_null($blobId);

        my $creationId = "email" . ($i + 1);

        xlog $self, "Import $creationId" . (": $tc->{desc}" || '');
        my $res = $jmap->CallMethods([
            ['Email/import', {
                emails => {
                    $creationId => {
                        blobId => $blobId,
                        mailboxIds => {
                            '$inbox' => JSON::true
                        },
                        receivedAt => $tc->{receivedAt},
                    },
                },
            }, 'R1'],
            ['Email/get', {
                ids => [
                    "#$creationId",
                ],
                properties => ['receivedAt', 'sentAt'],
            }, 'R2']
        ]);

        $self->assert_not_null($res->[0][1]{created}{$creationId});

        xlog $self, "Assert sentAt";
        if ($tc->{wantSentAt}) {
            $self->assert_str_equals($tc->{wantSentAt},
                $res->[1][1]{list}[0]{sentAt});
        } else {
            $self->assert_null($res->[1][1]{list}[0]{sentAt});
        }

        xlog $self, "Assert receivedAt";
        $self->assert_not_null($res->[1][1]{list}[0]{receivedAt});
        if ($tc->{wantReceivedAt}) {
            $self->assert_str_equals($tc->{wantReceivedAt},
                $res->[1][1]{list}[0]{receivedAt});
        } else {
            $self->assert_not_null($res->[1][1]{list}[0]{receivedAt});
        }
    }
}
