/*
 * Queue - A Queueing system that can be used to handle labs in higher education
 * Copyright (C) 2016-2024  Delft University of Technology
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package nl.tudelft.queue.service;

import static org.mockito.Mockito.*;

import java.security.Security;
import java.time.LocalDateTime;
import java.util.Set;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

import lombok.SneakyThrows;
import nl.martijndwars.webpush.PushService;
import nl.tudelft.queue.model.LabRequest;
import nl.tudelft.queue.realtime.NotificationPayload;
import nl.tudelft.queue.realtime.Subscription;
import nl.tudelft.queue.realtime.SubscriptionContainer;

@SpringBootTest(classes = QueuePushService.class)
public class QueuePushServiceTest {
	private static final Long P1 = 78323L;
	private static final Long P2 = 87923L;

	private static final String AUTH = "3sVS5udr0wAL2gEqbKOHbg==";
	private static final String KEY = "BMj7XzH3WNjP5nk8lTnTBKMpMgcetcrznI35KXy1BpLTY6ES6+uDrqgiJ1jXIasgp4W/ZLYqfr3ozT/KeVNH2LQ=";

	@Autowired
	private QueuePushService qps;

	@MockBean
	private PushService ps;

	@MockBean
	private SubscriptionContainer sc;

	@BeforeEach
	@SneakyThrows
	void setUp() {
		when(sc.get(P1)).thenReturn(Set.of(
				Subscription.builder()
						.auth(AUTH)
						.endpoint("nwjdabsjdas")
						.lastUsed(LocalDateTime.now())
						.p256dhKey(KEY)
						.person(78323L)
						.build()));

		when(sc.get(P2)).thenReturn(Set.of(
				Subscription.builder()
						.auth(AUTH)
						.endpoint("dascsa")
						.lastUsed(LocalDateTime.now())
						.p256dhKey(KEY)
						.person(87923L)
						.build(),

				Subscription.builder()
						.auth(AUTH)
						.endpoint("hgtfhfg")
						.lastUsed(LocalDateTime.now())
						.p256dhKey(KEY)
						.person(87923L)
						.build()));

		Security.addProvider(new BouncyCastleProvider());
	}

	@Test
	@SneakyThrows
	void sendToPersonSendsToEverySubscription() {
		qps.sendToPerson(P2, builder -> builder.payload("kndsnad"));

		verify(ps, times(2)).sendAsync(any());
	}

	@Test
	@SneakyThrows
	void sendToPersonSendsToOnlyOneSubscription() {
		qps.sendToPerson(P1, builder -> builder.payload("kndsnad"));

		verify(ps, times(1)).sendAsync(any());
	}

	@Test
	@SneakyThrows
	void sendToPeopleSendsToAllInTheList() {
		qps.sendToPeople(Set.of(P1, P2), builder -> builder.payload("kjdnbasjdsa"));

		verify(ps, times(3)).sendAsync(any());
	}

	@Test
	@SneakyThrows
	void notifyAboutREquestSendsMessageToRequester() {
		qps.notifyAboutRequest(LabRequest.builder()
				.requester(P2)
				.build(), NotificationPayload.builder().build());

		verify(ps, times(2)).sendAsync(any());
	}
}
