<?php

declare(strict_types=1);

namespace SbpJm\FlarumMSTeamsWebhook\Service;

use Flarum\Notification\Blueprint\BlueprintInterface;
use Flarum\Settings\SettingsRepositoryInterface;
use Flarum\User\User;
use GuzzleHttp\Client;
use RuntimeException;
use SbpJm\FlarumMSTeamsWebhook\Support\NotificationPayloadFactory;
use SbpJm\FlarumMSTeamsWebhook\Support\TargetResolver;

class TeamsActivityNotifier
{
    public function __construct(
        protected Client $http,
        protected SettingsRepositoryInterface $settings,
        protected GraphTokenProvider $tokenProvider,
        protected TargetResolver $targetResolver,
        protected NotificationPayloadFactory $payloadFactory
    ) {
    }

    public function notify(User $user, BlueprintInterface $blueprint): void
    {
        $target = $this->targetResolver->resolve($user);

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

        $this->notifyToTarget($user, $blueprint, $target);
    }

    public function notifyToTarget(User $user, BlueprintInterface $blueprint, string $target): void
    {
        $payload = $this->payloadFactory->make($user, $blueprint);
        $token = $this->tokenProvider->getAccessToken();

        $response = $this->http->request(
            'POST',
            sprintf('https://graph.microsoft.com/v1.0/users/%s/teamwork/sendActivityNotification', rawurlencode($target)),
            [
                'headers' => [
                    'Authorization' => 'Bearer ' . $token,
                    'Content-Type' => 'application/json',
                ],
                'json' => $payload,
                'timeout' => (int) $this->settings->get('sbp-jm-msteams-webhook.timeout_seconds', '15'),
                'http_errors' => false,
            ]
        );

        $status = $response->getStatusCode();

        if ($status < 200 || $status >= 300) {
            throw new RuntimeException(sprintf(
                'Teams activity notification failed for user %s with status %s: %s',
                $user->id,
                $status,
                (string) $response->getBody()
            ));
        }
    }
}