package com.example.demo;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;

import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@SpringBootTest
class DemoApplicationTests {

	FluxErrorAndOtherMethods sample;

	@BeforeEach
	void createInstance() {
		System.out.println("createInstance() >> ");
		sample = new FluxErrorAndOtherMethods();
	}

	@Test
	void method_stringFlux() {

		StepVerifier.create(sample.stringFlux())
				.expectNext("These")
				.expectNext("Strings")
				.expectNext("will")
				.expectNext("create")
				.expectNext("flux")
				.verifyComplete();

	}

	@Test
	void method_stringFluxWithconcat() {

		StepVerifier.create(sample.stringFluxWithconcat())
				.expectNext("These")
				.expectNext("Strings")
				.expectNext("will")
				.expectNext("create")
				.expectNext("flux")
				.expectNext("new message")
				.verifyComplete();
	}

	@Test
	void method_stringFluxSorting() {

		StepVerifier.create(sample.stringFluxSorting())
				.expectNext("will")
				.expectNext("flux")
				.expectNext("create")
				.expectNext("These")
				.expectNext("Strings")
				.verifyComplete();
	}

	@Test
	void method_stringFluxDistinct() {

		StepVerifier.create(sample.stringFluxDistinct())
				.expectNext("These")
				.expectNext("Strings")
				.expectNext("will")
				.expectNext("create")
				.expectNext("flux")
				.verifyComplete();
	}

	@Test
	void method_ConcatFlatMapImmediate() {
		Flux<String> strFlux = Flux.just("These","Strings","will","create","flux" )
				.concatWith(Flux.just("Hello", "World", "This", "is", "concat", "method"))
				.delayElements(Duration.ZERO)
				.flatMap( s -> Flux.just(s) )
				.log();

		StepVerifier.create(strFlux)
				.expectNext("These","Strings","will","create","flux", "Hello", "World", "This", "is", "concat", "method" )
				.verifyComplete();
	}

	@Test
	void method_stringFluxFilter() {
		StepVerifier.create(sample.stringFluxFilter())
				.expectNext( "Ravi", "Manoj", "Devi", "Basha" )
				.verifyComplete();
	}

	@Test
	void method_stringFluxMap() {
		StepVerifier.create(sample.stringFluxMap())
				.expectNext( "THESE","STRINGS","WILL","CREATE","FLUX" )
				.verifyComplete();
	}

	@Test
	void method_stringFluxFlatMap() {
		StepVerifier.create(sample.stringFluxFlatMap())
				.expectNext( "These-@1","Strings-@1","will-@1","create-@1","flux-@1" )
				.verifyComplete();
	}

	void method_ConcatArraySubscriberException() {
/*
				.expectNext("THESE","STRINGS","CREATE","HELLO", "WORLD", "CONCAT", "METHOD", "SERVER", "MESSAGE" )
				.thenAwait(Duration.ofMillis(100))
				.expectError(RuntimeException.class)
				.verify();
*/	}

	@Test
	void method_onErrorReturn() {
		StepVerifier.create(sample.fluxOnErrorReturn())
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.verifyComplete();
	}


	@Test
	void method_onErrorReturnwithClass() {
		StepVerifier.create(sample.fluxOnErrorReturnWithClassType())
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.verifyComplete();
	}

	@Test
	void method_onErrorComplete() {
		StepVerifier.create(sample.fluxOnErrorComplete())
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.verifyComplete();
	}

	@Test
	void method_onErrorContinue() {
		StepVerifier.create(sample.fluxOnErrorContinue())
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 10 )
				.verifyComplete();
	}

	@Test
	void method_fluxDataToMap() {
		Map<String, String> result = new HashMap<>();
		result.put( "krishna", "8125486447");
		result.put( "ramu", "8125719324");
		result.put( "balla", "9908263541");
		StepVerifier.create(sample.fluxCollectMap())
				.expectNext(result)
				.verifyComplete();
	}

	@Test
	void method_onErrorResume() {
		StepVerifier.create(sample.fluxOnErrorResume())
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 1 )
				.expectNext( 2 )
				.expectNext( 3 )
				.verifyComplete();
	}

	@Test
	void method_onErrorMap() {
		StepVerifier.create(sample.fluxOnErrorMap())
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectError( RuntimeException.class )
				.verify();
	}

	@Test
	void method_doOnError() {
		StepVerifier.create(sample.fluxDoOnError())
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectError( RuntimeException.class )
				.verify();
	}

	@Test
	void method_retry() {
		StepVerifier.create(sample.fluxRetry())
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectError( RuntimeException.class )
				.verify();
	}

	@Test
	void method_retryWhen() {
		StepVerifier.create(sample.fluxOnRetryWhen())
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectError( RuntimeException.class )
				.verify();
	}

	@Test
	void method_retryBackOff() {
		StepVerifier.create(sample.fluxOnRetryWhenBackOff())
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectError( RuntimeException.class )
				.verify();
	}

	@Test
	void method_retryWhenWithFixedDuration() {
		StepVerifier.create(sample.fluxOnRetryWhenFixedDelay())
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectNext( 100 )
				.expectNext( 25 )
				.expectNext( 20 )
				.expectNext( 50 )
				.expectError( RuntimeException.class )
				.verify();
	}

	@Test
	void method_collectList() {
		StepVerifier.create(sample.fluxCollectList())
				.expectNext(Arrays.asList(1, 4, 5, 2, 0, 10))
				.verifyComplete();

	}

	@Test
	void method_collectSortedList() {
		StepVerifier.create(sample.fluxCollectSortedList())
				.expectNext(Arrays.asList(10, 5, 4, 2, 1, 0))
				.verifyComplete();

	}

}