package dictionary

import (
	"context"
	"git.noahlan.cn/n-admin/n-admin-server/dal/errx"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/ent"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/ent/dictionarydetail"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/internal/utils/entx"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/internal/utils/hander"
	"git.noahlan.cn/noahlan/ntool-biz/core/nstatus"
	"git.noahlan.cn/noahlan/ntool-biz/core/nstatus/code"
	"git.noahlan.cn/noahlan/ntool-biz/core/nstatus/msg"
	"git.noahlan.cn/noahlan/ntool-biz/core/orm/nent/types"

	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/internal/svc"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/types/core"
)

type CreateDictionaryDetailLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewCreateDictionaryDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateDictionaryDetailLogic {
	return &CreateDictionaryDetailLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// Details
func (l *CreateDictionaryDetailLogic) CreateDictionaryDetail(in *core.DictionaryDetailInfo) (*core.BaseIDResp, error) {
	var dbData *ent.DictionaryDetail
	if err := entx.WithTx(l.ctx, l.svcCtx.DB, func(tx *ent.Tx) error {
		var err error
		if err := l.preCheck(tx, in); err != nil {
			return err
		}
		// query last sort
		var maxStruct struct {
			Max int
		}
		err = tx.DictionaryDetail.Query().
			Select(dictionarydetail.FieldSort).
			Where(dictionarydetail.DictionaryIDEQ(in.DictionaryId)).
			Aggregate(ent.Max(dictionarydetail.FieldSort)).
			Scan(l.ctx, &maxStruct)
		if err != nil {
			return hander.HandleEntErr(err, in)
		}

		// create
		create := tx.DictionaryDetail.Create()
		create.SetStatus(types.ParseStatus(in.Status)).
			SetTitle(in.Title).
			SetKey(in.Key).
			SetValue(in.Value).
			SetDictionaryID(in.DictionaryId).
			SetSort(uint32(maxStruct.Max + 1))
		dbData, err = create.Save(l.ctx)
		if err != nil {
			return hander.HandleEntErr(err, in)
		}
		return nil
	}); err != nil {
		return nil, err
	}
	return &core.BaseIDResp{
		ID:   dbData.ID,
		Code: code.StatusOK,
		Msg:  msg.CreateSuccess,
	}, nil
}

func (l *CreateDictionaryDetailLogic) preCheck(tx *ent.Tx, in *core.DictionaryDetailInfo) error {
	if in.DictionaryId == 0 {
		return nstatus.NewBizErrWithCode(errx.DictionaryDetailPIDNotEmpty)
	}
	if in.Key == "" {
		return nstatus.NewBizErrWithCode(errx.DictionaryDetailKeyNotEmpty)
	}
	exist, err := tx.DictionaryDetail.Query().
		Where(dictionarydetail.KeyEQ(in.Key), dictionarydetail.DictionaryIDEQ(in.DictionaryId)).
		Exist(l.ctx)
	if err != nil {
		return hander.HandleEntErr(err, in)
	}
	if exist {
		return nstatus.NewBizErrWithCode(errx.DictionaryDetailExists)
	}
	return nil
}
