package sop_node

import (
	"context"
	"fmt"
	"github.com/suyuan32/simple-admin-common/msg/errormsg"
	"github.com/suyuan32/simple-admin-common/utils/pointy"
	"github.com/zeromicro/go-zero/core/errorx"
	"net/http"
	"wechat-api/ent"
	"wechat-api/ent/label"
	"wechat-api/ent/predicate"
	"wechat-api/ent/sopnode"
	"wechat-api/hook"
	"wechat-api/internal/utils/dberrorhandler"

	"wechat-api/internal/svc"
	"wechat-api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetApiSopNodeListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetApiSopNodeListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetApiSopNodeListLogic {
	return &GetApiSopNodeListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx}
}

func (l *GetApiSopNodeListLogic) GetApiSopNodeList(req *types.BatchSopNodeListReq, r *http.Request) (*types.SopNodeListResp2, error) {
	tokenStr := r.Header.Get("Authorization")
	_, err := hook.CheckDesktopAuth(tokenStr, l.svcCtx.DB)
	if err != nil {
		return nil, errorx.NewCodeInvalidArgumentError("check auth failed")
	}

	var predicates []predicate.SopNode
	if req.StageIds != nil && len(req.StageIds) > 0 {
		predicates = append(predicates, sopnode.StageIDIn(req.StageIds...))
	} else {
		return nil, dberrorhandler.DefaultEntError(l.Logger, fmt.Errorf("StageIds 不能为空"), req)
	}
	data, err := l.svcCtx.DB.SopNode.Query().Where(predicates...).All(l.ctx)

	if err != nil {
		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
	}

	resp := &types.SopNodeListResp2{}
	resp.Msg = errormsg.Success

	childNodeList, _ := getSopNodeList(l, data)
	resp.Data = childNodeList

	return resp, nil
}

// 从node列表中找到指定 ParentId 的所有节点
func getSopNodeList(l *GetApiSopNodeListLogic, nodeList []*ent.SopNode) ([]*types.SopNodeInfoWithLable, error) {
	// 遍历 nodeList 找到 ParentId 为指定 parentId 的所有节点
	var result []*types.SopNodeInfoWithLable
	for _, node := range nodeList {
		var actionMessage []types.Action
		if len(node.ActionMessage) > 0 {
			actionMessage = make([]types.Action, len(node.ActionMessage))
			for i, condition := range node.ActionMessage {
				actionMessage[i] = types.Action{
					Type:    condition.Type,
					Content: condition.Content,
				}
			}
		}

		var actionForward *types.ActionForward
		if node.ActionForward != nil {
			actionForward = &types.ActionForward{}
			actionForward.Wxid = node.ActionForward.Wxid
			if len(node.ActionForward.Action) > 0 {
				forwardAction := make([]types.Action, len(node.ActionForward.Action))
				for i, condition := range node.ActionForward.Action {
					forwardAction[i] = types.Action{
						Type:    condition.Type,
						Content: condition.Content,
					}
				}
				actionForward.Action = forwardAction
			}
		} else {
			actionForward = nil
		}

		actionLabelAddList := make([]string, 0)
		labelList, err := l.svcCtx.DB.Label.Query().Where(label.IDIn(node.ActionLabelAdd...)).All(l.ctx)
		if err != nil {
			return nil, dberrorhandler.DefaultEntError(l.Logger, err, nil)
		}
		for _, val := range labelList {
			actionLabelAddList = append(actionLabelAddList, val.Name)
		}

		actionLabelDelList := make([]string, 0)
		labelList, err = l.svcCtx.DB.Label.Query().Where(label.IDIn(node.ActionLabelAdd...)).All(l.ctx)
		if err != nil {
			return nil, dberrorhandler.DefaultEntError(l.Logger, err, nil)
		}
		for _, val := range labelList {
			actionLabelDelList = append(actionLabelDelList, val.Name)
		}

		child := types.SopNodeInfoWithLable{
			BaseIDInfo: types.BaseIDInfo{
				Id:        &node.ID,
				CreatedAt: pointy.GetPointer(node.CreatedAt.UnixMilli()),
				UpdatedAt: pointy.GetPointer(node.UpdatedAt.UnixMilli()),
			},
			Status:             &node.Status,
			StageId:            &node.StageID,
			ParentId:           &node.ParentID,
			Name:               &node.Name,
			ConditionType:      &node.ConditionType,
			ConditionList:      node.ConditionList,
			NoReplyCondition:   &node.NoReplyCondition,
			NoReplyUnit:        &node.NoReplyUnit,
			ActionMessage:      actionMessage,
			ActionLabelAdd:     node.ActionLabelAdd,
			ActionLabelDel:     node.ActionLabelDel,
			ActionForward:      actionForward,
			ActionLabelAddList: actionLabelAddList,
			ActionLabelDelList: actionLabelDelList,
		}
		result = append(result, &child)

	}
	return result, nil
}
