package main

import (
	"errors"
	"io/ioutil"
	"os"
	"syscall"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/valyala/fasthttp"
)

func mockSignal(t *testing.T, sig syscall.Signal) {
	t.Helper()
	if err := syscall.Kill(syscall.Getpid(), sig); err != nil {
		t.Fatal(err)
	}
}

func makeMockConfig(t *testing.T) (string, func()) {
	t.Helper()
	cfgFile, _ := ioutil.TempFile("", "config.*.json")

	_, err := cfgFile.WriteString(`{"log":{"event-file":"event.log","app-file":"app.log","sentry-dsn":""},"web":{"host":"127.0.0.1","port":"40001"}}`)
	if err != nil {
		t.Fatal(err)
	}

	return cfgFile.Name(), func() {
		if err := os.Remove(cfgFile.Name()); err != nil {
			t.Fatal(err)
		}
	}
}

func waitServerStart(t *testing.T) {
	t.Helper()
	c := &fasthttp.Client{}
	var statusCode int
	var body []byte
	err := errors.New("waiting server start")
	for err != nil {
		time.Sleep(1 * time.Second)
		t.Log(err)
		statusCode, body, err = c.Get(nil, "http://127.0.0.1:40001/health_check")
	}
	assert.Equal(t, 200, statusCode)
	assert.Equal(t, `{"detail":"pong"}`, string(body))
}

func resetProgramArgs(args ...string) func() {
	old := os.Args

	newArgs := make([]string, len(old))
	newArgs[0] = os.Args[0]
	copy(newArgs[1:], args)

	os.Args = newArgs

	return func() {
		os.Args = old
	}
}

func Test_main(t *testing.T) {
	t.Run("should normally start", func(t *testing.T) {
		cfg, removeCfg := makeMockConfig(t)
		resetArgs := resetProgramArgs("-c", cfg)
		defer removeCfg()
		defer resetArgs()

		go func() {
			waitServerStart(t)
			mockSignal(t, syscall.SIGINT)
		}()
		main()
		t.Log("pass")
	})

	t.Run("should print help", func(t *testing.T) {
		resetArgs := resetProgramArgs("-h")
		defer resetArgs()

		main()
		t.Log("pass")
	})

	t.Run("should print default config", func(t *testing.T) {
		resetArgs := resetProgramArgs("-echo_conf")
		defer resetArgs()

		main()
		t.Log("pass")
	})
}
