package tenant

import (
	"context"

	"github.com/tidbcloud/account/idl/pbgen/proto/central"
	"github.com/tidbcloud/account/internel/dao/entity"
	"github.com/tidbcloud/account/internel/svc/org/tenantctx"
	"github.com/tidbcloud/tiinf/errs"
	"go.buf.build/protocolbuffers/go/linuxgit/tidbcloud/base"
	"go.uber.org/zap"
)

func (s *tenantService) CreatePocApplication(ctx context.Context, req *central.CreatePocApplicationReq) (*central.CreatePocApplicationResp, error) {
	userContext := s.userContext(ctx)
	userID := s.CurrentUser(ctx).ID
	logger := s.Log(ctx)

	// sanitize request
	sanitizedRequest := &central.CreatePocApplicationReq{
		OrgId:         req.OrgId,
		PocRecordType: req.PocRecordType,
		SubTopic:      req.SubTopic,
		Msg:           req.Msg,
		Questions:     nil,
	}
	for _, question := range req.Questions {
		pocQuestion := &central.PocQuestion{
			Number:   question.Number,
			Type:     question.Type,
			Question: s.SanitizerPolicy().Sanitize(question.Question),
			Options:  nil,
			Note:     s.SanitizerPolicy().Sanitize(question.Note),
		}
		for _, option := range question.Options {
			pocQuestion.Options = append(pocQuestion.Options, &central.PocQuestion_Option{
				Name:       s.SanitizerPolicy().Sanitize(option.Name),
				IsSelected: option.IsSelected,
			})
		}
		sanitizedRequest.Questions = append(sanitizedRequest.Questions, pocQuestion)
	}

	pocApplication, err := buildCreatePocParams(sanitizedRequest, userID)
	if err != nil {
		logger.Error("failed to build create poc application params", zap.String("feature", "poc"), zap.String("sentry", "salesforce"), zap.Error(err))
		return nil, err
	}
	pocApplicationID, err := userContext.CreatePocApplication(ctx, pocApplication)
	if err != nil {
		logger.Error("failed to build create poc application", zap.String("feature", "poc"), zap.String("sentry", "salesforce"), zap.Error(err))
		return nil, err
	}
	resp := &central.CreatePocApplicationResp{
		Id:       pocApplicationID,
		BaseResp: &base.BaseResp{},
	}

	return resp, nil
}

func PocQuestionType2Entity(questionType central.PocQuestion_Type) (entity.PocQuestionType, error) {
	switch questionType {
	case central.PocQuestion_RADIO:
		return entity.PocQuestionTypeRadio, nil
	case central.PocQuestion_CHECKBOX:
		return entity.PocQuestionTypeCheckbox, nil
	case central.PocQuestion_TEXT:
		return entity.PocQuestionTypeText, nil
	default:
		return entity.PocQuestionTypeUnspecified, errs.NewBadRequest("invalid question type", nil)
	}
}

func buildCreatePocParams(req *central.CreatePocApplicationReq, userID entity.ID) (*tenantctx.PocApplication, error) {
	questions := req.Questions
	if len(questions) == 0 {
		return nil, errs.NewBadRequest("questions is empty", nil)
	}
	pocApplication := &tenantctx.PocApplication{
		TenantID:  req.OrgId,
		Questions: nil,
		CreatorID: userID.Uint64(),
		PocExtraFields: &entity.PocExtraFields{
			PocRecordType: req.PocRecordType,
			SubTopic:      req.SubTopic,
			Message:       req.Msg,
		},
	}

	pocQuestions := make([]tenantctx.PocQuestion, 0, len(questions))
	questionNumMap := make(map[uint64]bool)
	for _, question := range questions {
		if _, ok := questionNumMap[question.Number]; ok {
			return nil, errs.NewBadRequest("question number is duplicated", nil)
		}
		questionNumMap[question.Number] = true

		questionType, err := PocQuestionType2Entity(question.Type)
		if err != nil {
			return nil, err
		}

		if question.Question == "" {
			return nil, errs.NewBadRequest("question is empty", nil)
		}

		questionOptions := make([]tenantctx.PocQuestionOption, 0, len(question.Options))
		if questionType == entity.PocQuestionTypeRadio || questionType == entity.PocQuestionTypeCheckbox {
			if len(question.Options) == 0 {
				return nil, errs.NewBadRequest("question options is empty for question type radio or checkbox", nil)
			}

			for _, option := range question.Options {
				questionOptions = append(questionOptions, tenantctx.PocQuestionOption{
					Name:       option.Name,
					IsSelected: option.IsSelected,
				})
			}
		}

		pocQuestion := tenantctx.PocQuestion{
			Number:   question.Number,
			Type:     questionType,
			Question: question.Question,
			Options:  questionOptions,
			Note:     question.Note,
		}

		pocQuestions = append(pocQuestions, pocQuestion)
	}
	pocApplication.Questions = pocQuestions
	return pocApplication, nil
}
