package ugh_test

import (
	"io"
	"sync"
	"testing"
	"time"

	tea "charm.land/bubbletea/v2"
	"charm.land/huh/v2"
	"git.sr.ht/~timofurrer/ugh"
)

const (
	testWidth  = 120
	testHeight = 40
)

func newTestForm(appInR io.Reader, appOutW io.Writer, groups ...*huh.Group) *huh.Form {
	return huh.NewForm(groups...).
		WithProgramOptions(
			tea.WithInput(appInR),
			tea.WithOutput(appOutW),
			tea.WithWindowSize(testWidth, testHeight),
		)
}

func newTestConsole(t *testing.T) *ugh.Console {
	return ugh.New(t, ugh.WithTimeout(5*time.Second))
}

func runTestForm(t *testing.T, c *ugh.Console, groups ...*huh.Group) {
	t.Helper()
	appInR, appInW := io.Pipe()
	appOutR, appOutW := io.Pipe()
	form := newTestForm(appInR, appOutW, groups...)

	var onceCloseOutW sync.Once

	closeOutW := func() {
		onceCloseOutW.Do(func() {
			err := appOutW.Close()
			if err != nil {
				t.Errorf("failed to close write output pipe for test app: %v", err)
			}
		})
	}

	var wg sync.WaitGroup
	wg.Go(func() {
		defer closeOutW()

		_ = form.Run()
	})

	c.Run(t.Context(), appOutR, appInW)

	if err := appInR.Close(); err != nil {
		t.Errorf("failed to close read input pipe for test app: %v", err)
	}

	if err := appInW.Close(); err != nil {
		t.Errorf("failed to close write input pipe for test app: %v", err)
	}

	if err := appOutR.Close(); err != nil {
		t.Errorf("failed to close read output pipe for test app: %v", err)
	}

	closeOutW()

	wg.Wait()
}
