package ana

import (
	"testing"
	"time"

	"gogs.inhome.blapointe.com/ana-ledger/src/ledger"
)

func TestNewInterestPredictor(t *testing.T) {
	acc := "x"
	curr := ledger.USD
	cases := map[string]struct {
		apy   float64
		given ledger.Balances
		delta time.Duration
		want  ledger.Balances
	}{
		"zero": {
			apy:   0,
			given: ledger.Balances{acc: ledger.Balance{curr: 100}},
			delta: time.Hour * 24 * 365,
			want:  ledger.Balances{acc: ledger.Balance{curr: 100}},
		},
		"50%": {
			apy:   .5,
			given: ledger.Balances{acc: ledger.Balance{curr: 100}},
			delta: time.Hour * 24 * 365,
			want:  ledger.Balances{acc: ledger.Balance{curr: 163.21}},
		},
	}

	for name, d := range cases {
		c := d
		t.Run(name, func(t *testing.T) {
			predictor := NewInterestPredictor(acc, string(curr), c.apy)
			got := predictor(c.given, c.delta)
			if got.Debug() != c.want.Debug() {
				t.Errorf("want\n\t%+v, got\n\t%+v", c.want, got)
			}
		})
	}
}

func TestGetContributions(t *testing.T) {
	input := ledger.Register{
		"2001-01": ledger.Balances{
			"a": ledger.Balance{"x": 1},
			"b": ledger.Balance{"z": 1},
		},
		"2001-02": ledger.Balances{
			"a": ledger.Balance{"y": 1},
		},
		"2001-03": ledger.Balances{
			"b": ledger.Balance{"z": 4},
		},
	}

	got := getContributions(input)
	t.Logf("%+v", got)
	if len(got) != 2 {
		t.Error(len(got))
	}
	if len(got["a"]) != 1 {
		t.Error(len(got["a"]))
	} else if len(got["a"][0]) != 2 {
		t.Error(got["a"])
	} else if got["a"][0]["x"] != -1 {
		t.Error(got["a"][0])
	} else if got["a"][0]["y"] != 1 {
		t.Error(got["a"][0])
	}

	if len(got["b"]) != 1 {
		t.Error(len(got["b"]))
	} else if len(got["b"][0]) != 1 {
		t.Error(got["b"])
	} else if got["b"][0]["z"] != 3 {
		t.Error(got["b"][0])
	}
}

func TestGetMonthlyAutoContributionRate(t *testing.T) {
	input := []ledger.Balance{
		ledger.Balance{"x": 2},
		ledger.Balance{"x": 4},
		ledger.Balance{"y": 3},
	}
	got := getMonthlyAutoContributionRate(input, time.Hour*24*365/4)
	if len(got) != 2 {
		t.Error(got)
	}
	if got["x"] != 0 { // too few contribution
		t.Error(got["x"])
	}
	if got["y"] != 0 { // too few contribution
		t.Error(got["y"])
	}
}

func TestNewContributionPredictor(t *testing.T) {
	name := "x"
	currency := ledger.USD
	predictor := NewContributionPredictor(map[string]ledger.Balance{
		name: {currency: 10},
		"y":  {"XYZ": 3},
	})
	month := time.Hour * 24 * 365 / 12

	if got := predictor(ledger.Balances{}, 2*month); got[name][currency] != 20 {
		t.Error(got[name])
	} else if got["y"]["XYZ"] != 6 {
		t.Error(got["y"])
	}

	if got := predictor(ledger.Balances{name: {currency: 30}}, 2*month); got[name][currency] != 30+20 {
		t.Error(got)
	} else if got["y"]["XYZ"] != 6 {
		t.Error(got["y"])
	}

	if got := predictor(ledger.Balances{"z": {"ABC": 100}}, 2*month); got[name][currency] != 20 {
		t.Error(got)
	} else if got["y"]["XYZ"] != 6 {
		t.Error(got["y"])
	} else if got["z"]["ABC"] != 100 {
		t.Error(got["z"])
	}
}
