package client

import (
	"context"
	"io/ioutil"
	"net/http/httptest"
	"os"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"git.mills.io/prologic/msgbus"
)

func TestClientPublish(t *testing.T) {
	assert := assert.New(t)
	require := require.New(t)

	testdir, err := ioutil.TempDir("", "msgbus-logs-*")
	require.NoError(err)
	defer os.RemoveAll(testdir)

	mb, err := msgbus.NewMessageBus(msgbus.WithLogPath(testdir))
	require.NoError(err)
	defer os.RemoveAll(testdir)

	server := httptest.NewServer(mb)
	defer server.Close()

	client := NewClient(server.URL, nil)

	err = client.Publish("hello", "hello world")
	assert.NoError(err)

	topic := mb.NewTopic("hello")
	msg, ok := mb.Get(topic)
	require.True(ok)
	assert.Equal(int64(1), msg.ID)
	assert.Equal(topic, msg.Topic)
	assert.Equal([]byte("hello world"), msg.Payload)
}

func TestCancelContextOnSubscribe(t *testing.T) {

	assert := assert.New(t)
	require := require.New(t)

	logDir, err := ioutil.TempDir("", "msgbus-logs-*")
	require.NoError(err)
	defer os.RemoveAll(logDir)

	mb, err := msgbus.NewMessageBus(msgbus.WithLogPath(logDir))
	require.NoError(err)
	defer os.RemoveAll(logDir)

	server := httptest.NewServer(mb)
	defer server.Close()

	client := NewClient(server.URL, nil)

	sub := client.Subscribe("hello", 1, func(msg *msgbus.Message) error { return nil })

	ctx, cancel := context.WithCancel(context.Background())
	cancel()

	failAfter := time.NewTimer(5 * time.Second)

	errChan := make(chan error)
	go func() {
		errChan <- sub.Run(ctx)
	}()

	loop := true
	for loop {
		select {
		case <-failAfter.C:
			loop = false
			t.Fatal("Run() with cancelled context did not exit on time")
		case runError := <-errChan:
			loop = false
			assert.ErrorIs(runError, context.Canceled)
		}
	}

	cancel()
	<-ctx.Done()

}
