package main_test

import (
	"encoding/json"
	"fmt"
	"github.com/spf13/viper"
	"os"
	"pgm/config"
	"pgm/data"
	"pgm/db"
	"pgm/loader"
	"pgm/logger"
	"testing"
)

// init should always return true
// init will not write incorrect values to file
func TestInit(t *testing.T) {
	t.Parallel()
	var cfg string
	testCases := []initTest{
		{a: "junk", b: "notreal", c: "failingonpurpose", want: true},
		{a: "test_host_dir", b: "test_screen_dr", c: "test_log_dir", want: true},
	}
	cfg, err := os.UserHomeDir()
	if err != nil {
		logger.Logger("failed to find home dir " + err.Error())
		fmt.Println("an error was encountered and logged")
		os.Exit(0)
	}
	for _, tc := range testCases {
		got := config.IsInit(tc.a, tc.b, tc.c, cfg + "/.pgm.yml")
		if tc.want != got {
			t.Errorf("want %t, got %t", tc.want, got)
		}
	}
}

func TestLogs(t *testing.T) {
	t.Parallel()
	var s string
	var want bool = true
	s = "test"
	got := logger.Logger(s)
	if want != got {
		t.Errorf("want %t, got %t", want, got)
	}
}

func TestLoadConfig(t *testing.T) {
	t.Parallel()
	var v *viper.Viper

	var want error = nil
	v, got := config.ReadConfig()
	_ = v
	if want != got {
		t.Error("load config reaturned a non nil error")
	}

}


// loader function will test that it can load the ui to chose a database
// and quits the ui.
// "test" is added into the array of files a user has configured and selected
func TestLoader(t *testing.T) {
	t.Parallel()
	var tc []string
	var s string
	var b string
	var want error = nil
	s = "test"
	b = "test"
	tc = data.ReadHosts()
	tc = append(tc, "test")
	got := loader.Loader(tc, s, b)
	if want != got {
		t.Errorf("want %t, got %t", want, got)
	}

}

func TestViperPgmConfig(t *testing.T) {
	t.Parallel()
	testCases := []viperReturnKey{
		{a: "junk", b: "r", want: false, need: ""},
		{a: "test_user", b: "r", want: true, need: "test"},
	}
	for _, tc := range testCases{
		found, got := data.ViperPgmConfig(tc.a, tc.b)
		if tc.want != found{
			t.Errorf("want %t, got %t", tc.want, found)
		}
		if tc.need != got {
			t.Errorf("want %s, got %s", tc.need, got)
		}
	}

}

func TestViperScnConfig(t *testing.T) {
	t.Parallel()
	testCases := []viperScnReturn {
		{t: "test", want: "test"},
		{t: "userSessions", want: "active sessions"},
	}
	for _, tc := range testCases {
		var v *viper.Viper
		v, err := data.ViperScrConfig("scn", map[string]interface{}{})
		if err != nil {
			logger.Logger("[ERROR] scn cfg test error: " + err.Error())
		}
		got := v.GetString(tc.t + ".title")
		if tc.want != got {
			t.Errorf("want %s, got %s", tc.want, got)
		}

	}

}


func TestDbConn(t *testing.T) {
	t.Parallel()
	found, c := data.ViperPgmConfig("test_db", "r")
	testCases := []connTest{
		{connstring: c, want: nil},
	}
	if found != true {
		logger.Logger("[LOG] failed to find test_db in .pgm.yaml")
	}
	for _, tc := range testCases {
		var h data.HostDetails
		err := json.Unmarshal([]byte(tc.connstring), &h)
		if err != nil {
			logger.Logger("[ERROR] db conn test failure: " + err.Error())
		}
		got, err := db.DbConn(h)
		if tc.want != err {
			t.Error("db conn returned an invalid error for test scenario, see logs")
		}
		err = got.Close()
		if err != nil {
			logger.Logger("[ERROR] Unable to close connection during test")
		}

	}



}


//func TestScreener(t *testing.T) {
//	t.Parallel()
//	var p data.HostDetails
//	var testDb string
//	var found bool
//	var want error = nil
//	found, testDb = data.ViperPgmConfig("test_db", "r")
//	if found != true {
//		t.Error("missing test_db parameter in .pgm.yaml for screener test")
//		logger.Logger("[LOG] missing test_db parameter in .pgm.yaml for TestScreener test")
//		os.Exit(1)
//	}
//	err := json.Unmarshal([]byte(testDb), &p)
//	if err != nil {
//		logger.Logger("[LOG] test screener failed: " + err.Error())
//		os.Exit(1)
//	}
//	got := loader.Screener(p)
//	if want != got {
//		t.Errorf("want %t, got %t", want, got)
//	}
//
//}

type connTest struct {
	connstring string
	want error

}

type viperScnReturn struct {
	t string
	want string
}

type viperReturnKey struct {
	a, b string
	want bool
	need string
}


type initTest struct {
	a, b, c string
	want bool
}