package net.pokeranalytics.android.unitTests

import androidx.test.ext.junit.runners.AndroidJUnit4
import io.realm.Realm
import net.pokeranalytics.android.calculus.bankroll.BankrollCalculator
import net.pokeranalytics.android.calculus.bankroll.BankrollReportSetup
import net.pokeranalytics.android.components.SessionInstrumentedUnitTest
import net.pokeranalytics.android.model.realm.*
import net.pokeranalytics.android.model.realm.Currency
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import java.util.*

@RunWith(AndroidJUnit4::class)
class BankrollInstrumentedUnitTest : SessionInstrumentedUnitTest() {

	private fun createDefaultTransactionTypes(realm: Realm) {
		TransactionType.Value.values().forEachIndexed { index, value ->
			val type = TransactionType()
			type.additive = value.additive
			type.kind = index
			type.lock = true
			realm.insertOrUpdate(type)
		}
	}

	// convenience extension
	fun Session.Companion.testInstance(netResult: Double, startDate: Date, endDate: Date?): Session {
		val session: Session = newInstance(super.mockRealm, false)
		session.result?.netResult = netResult
		session.startDate = startDate
		session.endDate = endDate
		return session
	}

	@Test
	fun testReport() {

		val realm = mockRealm

		realm.executeTransaction {

			this.createDefaultTransactionTypes(realm)

			val br1 = realm.createObject(Bankroll::class.java, "1")
			br1.name = "br1"
			val br2 = realm.createObject(Bankroll::class.java, "2")
			br2.name = "br2"

			br1.initialValue = 100.0
			br2.initialValue = 1000.0

			val t1 = realm.createObject(Transaction::class.java, UUID.randomUUID().toString())
			t1.amount = 100.0
			t1.type = TransactionType.getByValue(TransactionType.Value.BONUS, realm)
			t1.bankroll = br1

			val t2 = realm.createObject(Transaction::class.java, UUID.randomUUID().toString())
			t2.amount = 500.0
			t2.type = TransactionType.getByValue(TransactionType.Value.BONUS, realm)
			t2.bankroll = br2

			val s1 = newSessionInstance(realm)
			s1.bankroll = br1
			s1.result?.cashout = 200.0

			val s2 = newSessionInstance(realm)
			s2.bankroll = br2
			s2.result?.cashout = 500.0

		}

		val br1 = realm.where(Bankroll::class.java).equalTo("name", "br1").findFirst()
		val brSetup1 = BankrollReportSetup(br1)
		val report1 = BankrollCalculator.computeReport(realm, brSetup1)
		Assert.assertEquals(400.0, report1.total, EPSILON)

		val br2 = realm.where(Bankroll::class.java).equalTo("name", "br2").findFirst()
		val brSetup2 = BankrollReportSetup(br2)
		val report2 = BankrollCalculator.computeReport(realm, brSetup2)
		Assert.assertEquals(2000.0, report2.total, EPSILON)

		val brSetupAll = BankrollReportSetup()
		val reportAll = BankrollCalculator.computeReport(realm, brSetupAll)
		Assert.assertEquals(2400.0, reportAll.total, EPSILON)

	}


	@Test
	fun testReportWithRate() {

		val realm = mockRealm

		var br1: Bankroll? = null
		realm.executeTransaction {

			this.createDefaultTransactionTypes(realm)

			val c1 = realm.createObject(Currency::class.java, UUID.randomUUID().toString())
			c1.rate = 10.0

			br1 = realm.createObject(Bankroll::class.java, "1")
			br1?.currency = c1
			br1?.initialValue = 100.0

			val t1 = realm.createObject(Transaction::class.java, UUID.randomUUID().toString())
			t1.amount = 100.0
			t1.type = TransactionType.getByValue(TransactionType.Value.BONUS, realm)
			t1.bankroll = br1

			val s1 = newSessionInstance(realm)
			s1.bankroll = br1
			s1.result?.cashout = 200.0

		}

		val brSetup1 = BankrollReportSetup(br1)
		val report1 = BankrollCalculator.computeReport(realm, brSetup1)
		Assert.assertEquals(400.0, report1.total, EPSILON)

		val brSetupAll = BankrollReportSetup()
		val reportAll = BankrollCalculator.computeReport(realm, brSetupAll)
		Assert.assertEquals(4000.0, reportAll.total, EPSILON)

	}
}