package mock

import (
	"encoding/json"
	"fmt"
	"testing"

	"github.com/fiskerinc/cloud-services/pkg/testhelper"
)

type KafkaTestCase struct {
	ExpectedProduceMessages map[string]map[string]interface{}
	MockError               error
}

func (tc *KafkaTestCase) Setup(mock *KafkaMock) {
	mock.SetError(tc.MockError)
}

func (tc *KafkaTestCase) Validate(t *testing.T, name string, mock *KafkaMock) {
	tc.validate(t, fmt.Sprintf("%s expected", name), tc.ExpectedProduceMessages, mock.ProduceMessages, true)
	tc.validate(t, fmt.Sprintf("%s unexpected", name), mock.ProduceMessages, tc.ExpectedProduceMessages, false)
}

func (tc *KafkaTestCase) validate(t *testing.T, name string, control map[string]map[string]interface{}, source map[string]map[string]interface{}, compareValues bool) {
	for topic, expected := range control {
		if sent, hasTopic := source[topic]; hasTopic {
			for id, payload := range expected {
				if msg, hasID := sent[id]; hasID {
					if compareValues {
						tc.compare(t, name, payload, msg)
					}
				} else {
					t.Errorf(testhelper.TestErrorTemplate, fmt.Sprintf("%s id", name), id, nil)
				}
			}
		} else {
			t.Errorf(testhelper.TestErrorTemplate, fmt.Sprintf("%s topic", name), topic, nil)
		}
	}
}

func (tc *KafkaTestCase) compare(t *testing.T, name string, control interface{}, source interface{}) {
	data, err := json.Marshal(source)
	if err != nil {
		t.Errorf(testhelper.TestErrorTemplate, fmt.Sprintf("%s marshal payload", name), nil, err)
	} else if control != string(data) {
		t.Errorf(testhelper.TestErrorTemplate, fmt.Sprintf("%s message", name), control, string(data))
	}
}
