#!perl
use Cassandane::Tiny;

sub test_calendarevent_set_preserve_non_iana_dtend_timezone
  : needs_component_jmap {
    my ($self) = @_;

    my $jmap   = $self->{jmap};
    my $caldav = $self->{caldav};

    xlog $self, "Create event with differing DTSTART and DTEND non-IANA timezones";
    my $ical = <<'EOF';
BEGIN:VCALENDAR
PRODID:-//Foo//Bar//EN
CALSCALE:GREGORIAN
BEGIN:VTIMEZONE
TZID:Singapore Standard Time
X-EM-DISPLAYNAME:(UTC+08:00) Kuala Lumpur\, Singapore
BEGIN:STANDARD
TZNAME:Malay Peninsula Standard Time
DTSTART:00010101T000000
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
END:STANDARD
END:VTIMEZONE
BEGIN:VTIMEZONE
TZID:AUS Eastern Standard Time
BEGIN:STANDARD
DTSTART:16010101T030000
TZOFFSETFROM:+1100
TZOFFSETTO:+1000
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=4
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:16010101T020000
TZOFFSETFROM:+1000
TZOFFSETTO:+1100
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=10
END:DAYLIGHT
END:VTIMEZONE
VERSION:2.0
BEGIN:VEVENT
TRANSP:TRANSPARENT
DTSTART;TZID=AUS Eastern Standard Time:20240901T160000
DTEND;TZID=Singapore Standard Time:20240901T170000
UID:569470DB-7710-4B0B-80EB-3A4A7B528C77
DTSTAMP:20160901T000000Z
SUMMARY:test
END:VEVENT
END:VCALENDAR
EOF
    $caldav->Request('PUT', 'Default/test.ics', $ical, 'Content-Type' => 'text/calendar');

    xlog $self, "Assert timezone ids are mapped to IANA names";
    my $res = $jmap->CallMethods([
        [ 'CalendarEvent/query', {}, 'R1' ],
        [
            'CalendarEvent/get',
            {
                '#ids' => {
                    resultOf => 'R1',
                    name     => 'CalendarEvent/query',
                    path     => '/ids'
                },
                properties => [ 'timeZone', 'locations' ],
            },
            'R2'
        ],
    ]);
    my $eventId = $res->[1][1]{list}[0]{id};
    $self->assert_not_null($eventId);

    $self->assert_str_equals('Australia/Sydney', $res->[1][1]{list}[0]{timeZone});
    my @locations = values %{ $res->[1][1]{list}[0]{locations} };
    $self->assert_deep_equals(
        \@locations,
        [ { '@type' => 'Location', timeZone => 'Asia/Singapore', relativeTo => 'end' } ]
    );

    xlog $self, "Update event title, keeping timezones untouched";
    $res = $jmap->CallMethods([
        [
            'CalendarEvent/set',
            {
                update => {
                    $eventId => {
                        title => 'updatedTitle',
                    },
                },
            },
            'R1'
        ],
        [
            'CalendarEvent/get',
            {
                'ids'      => [$eventId],
                properties => [ 'timeZone', 'locations' ],
            },
            'R2'
        ],
    ]);
    $self->assert(exists $res->[0][1]{updated}{$eventId});

    $self->assert_str_equals('Australia/Sydney', $res->[1][1]{list}[0]{timeZone});
    @locations = values %{ $res->[1][1]{list}[0]{locations} };
    $self->assert_deep_equals(
        \@locations,
        [ { '@type' => 'Location', timeZone => 'Asia/Singapore', relativeTo => 'end' } ]
    );

    $res = $caldav->Request('GET', 'Default/test.ics');
    $ical = Data::ICal->new(data => $res->{content});

    xlog "Assert non-IANA VTIMEZONEs are kept";
    my @timezoneTzIds = sort
      map  { $_->value }
      map  { $_->property('TZID')->@* }
      grep { $_->ical_entry_type eq 'VTIMEZONE' } @{ $ical->entries };
    $self->assert_deep_equals(
        [
            'AUS Eastern Standard Time',
            'Singapore Standard Time',
        ],
        \@timezoneTzIds
    );

    xlog "Assert non-IANA TZIDs are kept for DTSTART and DTEND";
    my @dtstartTzIds = map { $_->parameters->{'TZID'} }
      map  { $_->property('DTSTART')->@* }
      grep { $_->ical_entry_type eq 'VEVENT' } @{ $ical->entries };
    $self->assert_deep_equals(
        [
            'AUS Eastern Standard Time',
        ],
        \@dtstartTzIds
    );

    my @dtendTzIds = map { $_->parameters->{'TZID'} }
      map  { $_->property('DTEND')->@* }
      grep { $_->ical_entry_type eq 'VEVENT' } @{ $ical->entries };
    $self->assert_deep_equals(
        [
            'Singapore Standard Time',
        ],
        \@dtendTzIds
    );
}
