package json

import (
	"bytes"
	"errors"
	"testing"

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

type jsonSample struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

type errWriter struct {
	err error
}

func (w errWriter) Write([]byte) (int, error) {
	return 0, w.err
}

func TestPrinterJSONPrintObject(t *testing.T) {
	t.Parallel()

	var output bytes.Buffer
	err := NewJSON(&output).PrintObject(jsonSample{ID: 1, Name: "workspace"})

	require.NoError(t, err)
	require.Equal(t, "{\n  \"id\": 1,\n  \"name\": \"workspace\"\n}\n", output.String())
}

func TestPrinterJSONPrintList(t *testing.T) {
	t.Parallel()

	var output bytes.Buffer
	err := NewJSON(&output).PrintList([]any{
		jsonSample{ID: 1, Name: "workspace-a"},
		jsonSample{ID: 2, Name: "workspace-b"},
	})

	require.NoError(t, err)
	require.Equal(t, "[\n  {\n    \"id\": 1,\n    \"name\": \"workspace-a\"\n  },\n  {\n    \"id\": 2,\n    \"name\": \"workspace-b\"\n  }\n]\n", output.String())
}

func TestPrinterJSONPrintObjectReturnsMarshalError(t *testing.T) {
	t.Parallel()

	err := NewJSON(&bytes.Buffer{}).PrintObject(func() {})

	require.Error(t, err)
	require.ErrorContains(t, err, "encode response")
}

func TestPrinterJSONPrintObjectReturnsWriterError(t *testing.T) {
	t.Parallel()

	writeErr := errors.New("write failed")
	err := NewJSON(errWriter{err: writeErr}).PrintObject(jsonSample{ID: 1, Name: "workspace"})

	require.ErrorIs(t, err, writeErr)
}
