package grpc_errcode

import (
	"context"
	"encoding/json"
	"testing"

	"github.com/pingcap/errcode"
	grpcerr "github.com/pingcap/errcode/grpc"
	"github.com/pingcap/errors"
	"github.com/stretchr/testify/suite"
	"github.com/tidbcloud/dataflow-service-ng/internal/bizutils"
	"google.golang.org/genproto/googleapis/rpc/errdetails"
)

type testGRPCErrorCodeSuite struct {
	suite.Suite
}

func TestGRPCErrorCodeSuite(t *testing.T) {
	suite.Run(t, &testGRPCErrorCodeSuite{})
}

func (s *testGRPCErrorCodeSuite) TestErrorConvert() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	ctx2 := bizutils.WithInitMutableErrorDetails(ctx)

	errInfo1 := &errdetails.ErrorInfo{
		Reason: "dummy reason",
	}
	errInfo1Json, err := json.Marshal(errInfo1)
	s.Require().NoError(err)
	s.Require().NoError(bizutils.AppendErrorDetails(ctx2, errInfo1))

	theRawErr := errors.New("dummy error")
	convertedErr := errorConvert(ctx2, theRawErr)
	_, ok := convertedErr.(grpcerr.ErrorCodeStatus)
	s.Require().False(ok)

	theCodedErr := errcode.NewInternalErr(theRawErr)
	convertedErr = errorConvert(ctx, theCodedErr)
	ecs, ok := convertedErr.(grpcerr.ErrorCodeStatus)
	s.Require().True(ok)
	s.Require().Equal(theRawErr.Error(), ecs.Error())
	status := ecs.GRPCStatus()
	details := status.Details()
	s.Require().Equal(0, len(details))

	theCodedErr = errcode.NewInternalErr(theRawErr)
	convertedErr = errorConvert(ctx2, theCodedErr)
	ecs, ok = convertedErr.(grpcerr.ErrorCodeStatus)
	s.Require().True(ok)
	s.T().Logf("code: %+v\n", ecs.Code())
	s.Require().Equal(theRawErr.Error(), ecs.Error())
	status = ecs.GRPCStatus()
	statusJson, err := json.Marshal(status.Proto())
	s.Require().NoError(err)
	s.T().Logf("status: %+v\n", string(statusJson))
	details = status.Details()
	s.Require().Equal(1, len(details))
	detailJson, err := json.Marshal(details[0])
	s.T().Logf("detail: %+v\n", string(detailJson))
	s.Require().NoError(err)
	s.Require().Equal(errInfo1Json, detailJson)
}
