package config

import (
	"flag"
	"io/ioutil"
	"os"
	"testing"

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

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

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

func TestParseArgs(t *testing.T) {
	cfgName, removeCfg := createTempConfig(t, `{"log":{"event-file":"event.log","app-file":"app.log","sentry-dsn":"123"},"web":{"host":"127.0.0.2","port":"9999"}}`)
	fatalCfgName, remoteFatalCfg := createTempConfig(t, `{this-is-not-json}`)

	defer removeCfg()
	defer remoteFatalCfg()

	t.Run("should set config file", func(t *testing.T) {
		cfg, err := ParseArgs([]string{"-c", cfgName})
		if assert.NoError(t, err) {
			assert.Equal(t, cfgName, cfg.ConfigFile)
		}
	})

	t.Run("should issue printHelp command", func(t *testing.T) {
		_, err := ParseArgs([]string{"-h"})
		if assert.Error(t, err) {
			assert.Equal(t, flag.ErrHelp, err)
		}
	})

	t.Run("should issue printDefaultConfig command", func(t *testing.T) {
		_, err := ParseArgs([]string{"-echo_conf"})
		if assert.Error(t, err) {
			assert.Equal(t, flag.ErrHelp, err)
		}
	})

	t.Run("should issue unknown command", func(t *testing.T) {
		_, err := ParseArgs([]string{"----"})
		if assert.Error(t, err) {
			assert.NotEqual(t, flag.ErrHelp, err)
		}
	})

	t.Run("should set debug mode", func(t *testing.T) {
		cfg, err := ParseArgs([]string{"-debug", "-c", cfgName})
		if assert.NoError(t, err) {
			assert.True(t, cfg.Debug)
		}
	})

	t.Run("should load config", func(t *testing.T) {
		cfg, err := ParseArgs([]string{"-c", cfgName})
		if assert.NoError(t, err) {
			assert.Equal(t, "event.log", cfg.Log.EventLogFile)
			assert.Equal(t, "app.log", cfg.Log.AppLogFile)
			assert.Equal(t, "123", cfg.Log.SentryDSN)
			assert.Equal(t, "127.0.0.2", cfg.Web.Host)
			assert.Equal(t, "9999", cfg.Web.Port)
		}
	})

	t.Run("should stop if no config file set", func(t *testing.T) {
		_, err := ParseArgs([]string{"-c", ""})
		if assert.Error(t, err) {
			assert.EqualError(t, err, "config file not specified")
		}
	})

	t.Run("should stop if config file not exists", func(t *testing.T) {
		_, err := ParseArgs([]string{"-c", "/no/such/file"})
		if assert.Error(t, err) {
			assert.True(t, os.IsNotExist(err))
		}
	})

	t.Run("should stop if config file content is not json", func(t *testing.T) {
		_, err := ParseArgs([]string{"-c", fatalCfgName})
		assert.Error(t, err)
	})
}
