<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\CalendarBundle\Tests\RemoteCalendar\Connector\MSGraph;

use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\MapCalendarToUser;
use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\MSUserAbsenceReader;
use Chill\MainBundle\Entity\User;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\Clock\MockClock;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;

/**
 * @internal
 *
 * @coversNothing
 */
class MSUserAbsenceReaderTest extends TestCase
{
    use ProphecyTrait;

    /**
     * @dataProvider provideDataTestUserAbsence
     */
    public function testUserAbsenceReader(string $mockResponse, bool $expected, string $message): void
    {
        $user = new User();
        $client = new MockHttpClient([new MockResponse($mockResponse)]);
        $mapUser = $this->prophesize(MapCalendarToUser::class);
        $mapUser->getUserId($user)->willReturn('1234');
        $clock = new MockClock(new \DateTimeImmutable('2023-07-07T12:00:00'));

        $absenceReader = new MSUserAbsenceReader($client, $mapUser->reveal(), $clock);

        self::assertEquals($expected, $absenceReader->isUserAbsent($user), $message);
    }

    public static function provideDataTestUserAbsence(): iterable
    {
        // contains data that was retrieved from microsoft graph api on 2023-07-06

        yield [
            <<<'JSON'
            {
              "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('4feb0ae3-7ffb-48dd-891e-c86b2cdeefd4')/mailboxSettings/automaticRepliesSetting",
              "status": "disabled",
              "externalAudience": "none",
              "internalReplyMessage": "Je suis en congé.",
              "externalReplyMessage": "",
              "scheduledStartDateTime": {
                "dateTime": "2023-07-06T12:00:00.0000000",
                "timeZone": "UTC"
              },
              "scheduledEndDateTime": {
                "dateTime": "2023-07-07T12:00:00.0000000",
                "timeZone": "UTC"
              }
            }
            JSON,
            false,
            'User is present',
        ];

        yield [
            <<<'JSON'
               {
                  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('4feb0ae3-7ffb-48dd-891e-c86b2cdeefd4')/mailboxSettings/automaticRepliesSetting",
                  "status": "scheduled",
                  "externalAudience": "none",
                  "internalReplyMessage": "Je suis en congé.",
                  "externalReplyMessage": "",
                  "scheduledStartDateTime": {
                    "dateTime": "2023-07-06T11:00:00.0000000",
                    "timeZone": "UTC"
                  },
                  "scheduledEndDateTime": {
                    "dateTime": "2023-07-21T11:00:00.0000000",
                    "timeZone": "UTC"
                  }
                }
            JSON,
            true,
            'User is absent with absence scheduled, we are within this period',
        ];

        yield [
            <<<'JSON'
               {
                  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('4feb0ae3-7ffb-48dd-891e-c86b2cdeefd4')/mailboxSettings/automaticRepliesSetting",
                  "status": "scheduled",
                  "externalAudience": "none",
                  "internalReplyMessage": "Je suis en congé.",
                  "externalReplyMessage": "",
                  "scheduledStartDateTime": {
                    "dateTime": "2023-07-08T11:00:00.0000000",
                    "timeZone": "UTC"
                  },
                  "scheduledEndDateTime": {
                    "dateTime": "2023-07-21T11:00:00.0000000",
                    "timeZone": "UTC"
                  }
                }
            JSON,
            false,
            'User is present: absence is scheduled for later',
        ];

        yield [
            <<<'JSON'
               {
                  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('4feb0ae3-7ffb-48dd-891e-c86b2cdeefd4')/mailboxSettings/automaticRepliesSetting",
                  "status": "scheduled",
                  "externalAudience": "none",
                  "internalReplyMessage": "Je suis en congé.",
                  "externalReplyMessage": "",
                  "scheduledStartDateTime": {
                    "dateTime": "2023-07-05T11:00:00.0000000",
                    "timeZone": "UTC"
                  },
                  "scheduledEndDateTime": {
                    "dateTime": "2023-07-06T11:00:00.0000000",
                    "timeZone": "UTC"
                  }
                }
            JSON,
            false,
            'User is present: absence is past',
        ];

        yield [
            <<<'JSON'
                {
                  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('4feb0ae3-7ffb-48dd-891e-c86b2cdeefd4')/mailboxSettings/automaticRepliesSetting",
                  "status": "alwaysEnabled",
                  "externalAudience": "none",
                  "internalReplyMessage": "Je suis en congé.",
                  "externalReplyMessage": "",
                  "scheduledStartDateTime": {
                    "dateTime": "2023-07-06T12:00:00.0000000",
                    "timeZone": "UTC"
                  },
                  "scheduledEndDateTime": {
                    "dateTime": "2023-07-07T12:00:00.0000000",
                    "timeZone": "UTC"
                  }
                }
            JSON,
            true,
            'User is absent: absence is always enabled',
        ];
    }

    public function testIsUserAbsentWithoutRemoteId(): void
    {
        $user = new User();
        $client = new MockHttpClient();

        $mapUser = $this->prophesize(MapCalendarToUser::class);
        $mapUser->getUserId($user)->willReturn(null);
        $clock = new MockClock(new \DateTimeImmutable('2023-07-07T12:00:00'));

        $absenceReader = new MSUserAbsenceReader($client, $mapUser->reveal(), $clock);

        self::assertNull($absenceReader->isUserAbsent($user), 'when no user found, absence should be null');
    }
}
