package testutil

import (
	"errors"
	"flag"
	"io"
	"os"
	"path/filepath"
	"testing"

	"github.com/google/go-cmp/cmp"
)

var update *bool = flag.Bool("update", false, "save current tests results as golden files")

// GoldenEqual compares the bytes of the provided r with the contents of the
// golden file for a complete data match.
//
// When running tests with the -update flag, the contents of golden-files will
// be overwritten with the provided contents of r, creating the testdata/
// directory if it does not exist.
//
//nolint:gocognit,gocyclo
func GoldenEqual(tb testing.TB, r io.Reader) {
	tb.Helper()

	wd, err := os.Getwd()
	if err != nil {
		tb.Fatal("cannot get current working directory path:", err)
	}

	actual, err := io.ReadAll(r)
	if err != nil {
		tb.Fatal("cannot read provided data:", err)
	}

	file := filepath.Join(wd, "testdata", tb.Name()+".golden")
	dir := filepath.Dir(file)

	if *update {
		_, err = os.Stat(dir)
		if err != nil && !errors.Is(err, os.ErrExist) && !errors.Is(err, os.ErrNotExist) {
			tb.Fatal("cannot find testdata folder for golden files:", err)
		}

		if errors.Is(err, os.ErrNotExist) {
			if err = os.MkdirAll(dir, os.ModePerm); err != nil {
				tb.Fatal("cannot create testdata folder for golden files:", err)
			}
		}

		if err = os.WriteFile(file, actual, os.ModePerm); err != nil {
			tb.Fatal("cannot write data into golden file:", err)
		}

		tb.Skip("skipped due force updating golden file")

		return
	}

	expected, err := os.ReadFile(file)
	if err != nil {
		tb.Fatal("cannot read golden file data:", err)
	}

	if diff := cmp.Diff(string(actual), string(expected)); diff != "" {
		tb.Error(diff)
	}
}
