package io.mifos.individuallending.internal.service;

import io.mifos.portfolio.api.v1.domain.ChargeDefinition;
import io.mifos.portfolio.service.internal.repository.BalanceSegmentEntity;
import io.mifos.portfolio.service.internal.repository.BalanceSegmentRepository;
import io.mifos.portfolio.service.internal.service.ChargeDefinitionService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.mockito.Mockito;

import java.math.BigDecimal;
import java.util.*;

@RunWith(Parameterized.class)
public class ScheduledChargesServiceTest {

  private static final String PRODUCT_IDENTIFIER = "a";
  private static final String SEGMENT_SET_IDENTIFIER = "b";

  static class TestCase {
    final String description;
    List<BalanceSegmentEntity> balanceSegmentEntities = Collections.emptyList();
    String fromSegment = null;
    String toSegment = null;
    @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
    Optional<ChargeRange> expectedResult = Optional.empty();

    private TestCase(String description) {
      this.description = description;
    }

    TestCase balanceSegmentEntities(List<BalanceSegmentEntity> balanceSegmentEntities) {
      this.balanceSegmentEntities = balanceSegmentEntities;
      return this;
    }

    TestCase fromSegment(String fromSegment) {
      this.fromSegment = fromSegment;
      return this;
    }

    TestCase toSegment(String toSegment) {
      this.toSegment = toSegment;
      return this;
    }

    TestCase expectedResult(@SuppressWarnings("OptionalUsedAsFieldOrParameterType") Optional<ChargeRange> expectedResult) {
      this.expectedResult = expectedResult;
      return this;
    }
  }

  @Parameterized.Parameters
  public static Collection testCases() {
    final Collection<ScheduledChargesServiceTest.TestCase> ret = new ArrayList<>();
    ret.add(new ScheduledChargesServiceTest.TestCase("simple"));
    ret.add(new TestCase("two segments, one referenced")
        .balanceSegmentEntities(Arrays.asList(
            new BalanceSegmentEntity(null, SEGMENT_SET_IDENTIFIER, "first", BigDecimal.ZERO),
            new BalanceSegmentEntity(null, SEGMENT_SET_IDENTIFIER, "second", BigDecimal.TEN)))
        .fromSegment("first")
        .toSegment("first")
        .expectedResult(Optional.of(new ChargeRange(BigDecimal.ZERO, Optional.of(BigDecimal.TEN))))
    );
    ret.add(new TestCase("two segments, both referenced")
        .balanceSegmentEntities(Arrays.asList(
            new BalanceSegmentEntity(null, SEGMENT_SET_IDENTIFIER, "lower", BigDecimal.ZERO),
            new BalanceSegmentEntity(null, SEGMENT_SET_IDENTIFIER, "higher", BigDecimal.TEN)))
        .fromSegment("lower")
        .toSegment("higher")
        .expectedResult(Optional.of(new ChargeRange(BigDecimal.ZERO, Optional.empty())))
    );
    ret.add(new TestCase("two segments, one mis-referenced")
        .balanceSegmentEntities(Arrays.asList(
            new BalanceSegmentEntity(null, SEGMENT_SET_IDENTIFIER, "first", BigDecimal.ZERO),
            new BalanceSegmentEntity(null, SEGMENT_SET_IDENTIFIER, "second", BigDecimal.TEN)))
        .fromSegment("first")
        .toSegment("second2")
        .expectedResult(Optional.empty())
    );
    return ret;
  }

  private final ScheduledChargesServiceTest.TestCase testCase;

  public ScheduledChargesServiceTest(final ScheduledChargesServiceTest.TestCase testCase) {
    this.testCase = testCase;
  }

  @Test
  public void findChargeRange() throws Exception {

    final ChargeDefinitionService chargeDefinitionServiceMock = Mockito.mock(ChargeDefinitionService.class);
    final BalanceSegmentRepository balanceSegmentRepositoryMock = Mockito.mock(BalanceSegmentRepository.class);

    Mockito.doReturn(testCase.balanceSegmentEntities.stream())
        .when(balanceSegmentRepositoryMock)
        .findByProductIdentifierAndSegmentSetIdentifier(PRODUCT_IDENTIFIER, SEGMENT_SET_IDENTIFIER);

    final ScheduledChargesService testSubject = new ScheduledChargesService(chargeDefinitionServiceMock, balanceSegmentRepositoryMock);
    final ChargeDefinition chargeDefinition = new ChargeDefinition();

    chargeDefinition.setForSegmentSet(SEGMENT_SET_IDENTIFIER);
    chargeDefinition.setFromSegment(testCase.fromSegment);
    chargeDefinition.setToSegment(testCase.toSegment);
    final Optional<ChargeRange> result = testSubject.findChargeRange(PRODUCT_IDENTIFIER, chargeDefinition);
    Assert.assertEquals(testCase.expectedResult, result);
  }
}