package bizutils

import (
	"context"
	"testing"

	"github.com/stretchr/testify/suite"
	"google.golang.org/genproto/googleapis/rpc/errdetails"
)

type testContextSuite struct {
	suite.Suite
}

func TestContextSuite(t *testing.T) {
	suite.Run(t, &testContextSuite{})
}

func (s *testContextSuite) TestMutableErrorDetailsContext() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// init ctx2
	ctx2 := WithInitMutableErrorDetails(ctx)
	mDetails2 := getMutableErrorDetailsFromContext(ctx2)
	s.Require().NotNil(mDetails2)

	// write ctx2 error details
	errInfo1 := &errdetails.ErrorInfo{
		Reason: "dummy reason",
	}
	s.Require().NoError(AppendErrorDetails(ctx2, errInfo1))

	// init ctx3
	ctx3 := WithInitMutableErrorDetails(ctx)
	mDetails3 := getMutableErrorDetailsFromContext(ctx3)
	s.Require().NotNil(mDetails3)
	s.Require().NotEqual(mDetails2, mDetails3)

	errInfo2 := &errdetails.ErrorInfo{
		Reason: "dummy reason 2",
	}
	errInfo3 := &errdetails.ErrorInfo{
		Reason: "dummy reason 3",
	}
	// write ctx3 error details
	s.Require().NoError(AppendErrorDetails(ctx3, errInfo2, errInfo3))

	// get error details from ctx/ctx2/ctx3
	details := GetErrorDetailsFromContext(ctx)
	s.Require().Nil(details)
	details2 := GetErrorDetailsFromContext(ctx2)
	s.Require().NotNil(details2)
	s.Require().Equal(mDetails2.ErrorDetails, details2)
	details3 := GetErrorDetailsFromContext(ctx3)
	s.Require().NotNil(details3)
	s.Require().Equal(mDetails3.ErrorDetails, details3)

	// test error details content
	s.Require().Equal(1, len(details2))
	s.Require().Equal(2, len(details3))
	s.Require().Equal(errInfo1, details2[0])
	s.Require().Equal(errInfo2, details3[0])
	s.Require().Equal(errInfo3, details3[1])

	// write some more error details into ctx2 and test
	s.Require().NoError(AppendErrorDetails(ctx2, errInfo2, errInfo3))
	s.Require().Equal(1, len(details2))
	details2New := GetErrorDetailsFromContext(ctx2)
	s.Require().Equal(3, len(details2New))
	s.Require().Equal(errInfo1, details2New[0])
	s.Require().Equal(errInfo2, details2New[1])
	s.Require().Equal(errInfo3, details2New[2])
}
