<?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\RemoteCalendar\Connector\MSGraph;

use Chill\CalendarBundle\Exception\UserAbsenceSyncException;
use Chill\MainBundle\Entity\User;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

final readonly class MSUserAbsenceReader implements MSUserAbsenceReaderInterface
{
    public function __construct(
        private HttpClientInterface $machineHttpClient,
        private MapCalendarToUser $mapCalendarToUser,
        private ClockInterface $clock,
    ) {}

    /**
     * @throw UserAbsenceSyncException when the data cannot be reached or is not valid from microsoft
     */
    public function isUserAbsent(User $user): ?bool
    {
        $id = $this->mapCalendarToUser->getUserId($user);

        if (null === $id) {
            return null;
        }

        try {
            $automaticRepliesSettings = $this->machineHttpClient
                ->request('GET', 'users/'.$id.'/mailboxSettings/automaticRepliesSetting')
                ->toArray(true);
        } catch (ClientExceptionInterface|DecodingExceptionInterface|RedirectionExceptionInterface|TransportExceptionInterface $e) {
            throw new UserAbsenceSyncException('Error receiving response for mailboxSettings', 0, $e);
        } catch (ServerExceptionInterface $e) {
            throw new UserAbsenceSyncException('Server error receiving response for mailboxSettings', 0, $e);
        }

        if (!array_key_exists('status', $automaticRepliesSettings)) {
            throw new \LogicException('no key "status" on automatic replies settings: '.json_encode($automaticRepliesSettings, JSON_THROW_ON_ERROR));
        }

        return match ($automaticRepliesSettings['status']) {
            'disabled' => false,
            'alwaysEnabled' => true,
            'scheduled' => RemoteEventConverter::convertStringDateWithoutTimezone($automaticRepliesSettings['scheduledStartDateTime']['dateTime']) < $this->clock->now()
                && RemoteEventConverter::convertStringDateWithoutTimezone($automaticRepliesSettings['scheduledEndDateTime']['dateTime']) > $this->clock->now(),
            default => throw new UserAbsenceSyncException('this status is not documented by Microsoft'),
        };
    }
}
