package sop_task

import (
	"context"
	"errors"
	"github.com/suyuan32/simple-admin-common/msg/errormsg"
	"regexp"
	"strconv"
	"strings"
	"wechat-api/ent"
	"wechat-api/ent/contact"
	"wechat-api/ent/custom_types"
	"wechat-api/ent/labelrelationship"
	"wechat-api/ent/messagerecords"
	"wechat-api/ent/predicate"
	"wechat-api/ent/sopstage"
	"wechat-api/ent/soptask"
	"wechat-api/internal/utils/dberrorhandler"

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

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

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

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

func (l *PublishSopTaskLogic) PublishSopTask(req *types.IDReq) (resp *types.BaseMsgResp, err error) {
	organizationId := l.ctx.Value("organizationId").(uint64)

	// 开始事务
	//tx, err := l.svcCtx.DB.Tx(context.Background())
	//if err != nil {
	//	return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
	//}

	// 根据 id 查询 sop_task
	sopTask, err := l.svcCtx.DB.SopTask.Query().
		Where(
			soptask.ID(req.Id),
			soptask.Status(1),
			soptask.OrganizationIDEQ(organizationId),
		).
		WithTaskStages().
		Only(l.ctx)
	if err != nil {
		//_ = tx.Rollback()
		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
	}

	// 判断 sop_task 是否存在
	if sopTask != nil {
		if sopTask.BotWxidList == nil {
			return nil, errors.New(errormsg.ValidationError)
		}

		// 查询任务的所有 sop_stages
		err = l.svcCtx.DB.SopTask.UpdateOneID(req.Id).
			SetStatus(3).
			Exec(l.ctx)

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

		sopStages, err := l.svcCtx.DB.SopStage.Query().
			Where(sopstage.HasSopTaskWith(soptask.OrganizationIDEQ(organizationId), soptask.StatusEQ(3), soptask.DeletedAtIsNil()), sopstage.DeletedAtIsNil()).
			All(l.ctx)
		if err != nil {
			//_ = tx.Rollback()
			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
		}
		stageMap := make(map[uint64]*ent.SopStage)
		for _, stage := range sopStages {
			stageMap[stage.ID] = stage
		}
		// 遍历 stage
		for _, stage := range sopTask.Edges.TaskStages {
			if stage.ConditionType == 1 {
				// 构造查询条件
				var predicates []predicate.Contact

				for _, condition := range stage.ConditionList {
					subPredicate := contact.HasContactRelationshipsWith(
						labelrelationship.LabelIDIn(condition.LabelIdList...))
					labelrelationship.OrganizationIDEQ(organizationId)
					if condition.Equal == 2 {
						subPredicate = contact.Not(subPredicate)
					}
					predicates = append(predicates, subPredicate)
				}

				// 查询满足条件的联系人
				var contacts []*ent.Contact
				var err error
				sourceType := 3
				if stage.ConditionOperator == 1 {
					contacts, err = l.svcCtx.DB.Contact.Query().Where(contact.And(predicates...)).All(l.ctx)
				} else {
					contacts, err = l.svcCtx.DB.Contact.Query().Where(contact.Or(predicates...)).All(l.ctx)
				}

				if err != nil {
					//_ = tx.Rollback()
					return nil, err
				}

				// 遍历 contacts
				for _, c := range contacts {
					// 判断联系人所属微信是否包含在任务当中
					if sopTask.BotWxidList == nil || (sopTask.BotWxidList != nil && valueInArray(c.WxWxid, sopTask.BotWxidList)) {
						if stage.ActionMessage != nil {
							for i, message := range stage.ActionMessage {
								meta := custom_types.Meta{}
								if message.Meta != nil {
									meta.Filename = message.Meta.Filename
								}

								_, _ = l.svcCtx.DB.MessageRecords.Create().
									SetNotNilBotWxid(&c.WxWxid).
									SetNotNilContactID(&c.ID).
									SetNotNilContactType(&c.Type).
									SetNotNilContactWxid(&c.Wxid).
									SetNotNilContentType(&message.Type).
									SetNotNilContent(&message.Content).
									SetMeta(meta).
									SetNotNilSourceType(&sourceType).
									SetNotNilSourceID(&stage.ID).
									SetSubSourceID(uint64(i)).
									SetOrganizationID(organizationId).
									Save(l.ctx)

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

						if stage.ActionForward != nil {
							if stage.ActionForward.Wxid != "" {
								forwardWxids := splitString(stage.ActionForward.Wxid)
								for _, forwardWxid := range forwardWxids {
									for i, message := range stage.ActionForward.Action {
										meta := custom_types.Meta{}
										if message.Meta != nil {
											meta.Filename = message.Meta.Filename
										}
										content := varReplace(message.Content, c)
										_, err = l.svcCtx.DB.MessageRecords.Create().
											SetBotWxid(c.WxWxid).
											SetContactID(0).
											SetContactType(0).
											SetContactWxid(forwardWxid).
											SetContentType(message.Type).
											SetContent(content).
											SetMeta(meta).
											SetSourceType(sourceType).
											SetSourceID(stage.ID).
											SetSubSourceID(c.ID + uint64(i)).
											SetOrganizationID(organizationId).
											Save(l.ctx)

									}
								}
							}
						}

						// 查询当前联系人的标签关系
						currentLabelRelationships, err := l.svcCtx.DB.LabelRelationship.Query().Where(labelrelationship.ContactID(c.ID)).All(l.ctx)
						if err != nil {
							//_ = tx.Rollback()
							return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
						}

						// 提取当前标签ID
						var currentLabelIds []uint64
						for _, relationship := range currentLabelRelationships {
							currentLabelIds = append(currentLabelIds, relationship.LabelID)
						}

						if stage.ActionLabelAdd != nil || stage.ActionLabelDel != nil {
							// 递归调用 AddLabelRelationships
							err = l.AddLabelRelationships(stageMap, *c, currentLabelIds, stage.ActionLabelAdd, stage.ActionLabelDel, organizationId)
							if err != nil {
								//_ = tx.Rollback()
								return nil, err
							}
						}
					}
				}
			}
		}
		// 所有操作成功，提交事务
		//err = tx.Commit()
		//if err != nil {
		//	return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
		//}
		return &types.BaseMsgResp{Msg: errormsg.Success}, nil
	} else {
		// 所有操作成功，提交事务
		//err = tx.Commit()
		//if err != nil {
		//	return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
		//}
		//// 返回错误信息：任务不存在
		return nil, errors.New(errormsg.TargetNotFound)
	}
}

func (l *PublishSopTaskLogic) AddLabelRelationships(sopStages map[uint64]*ent.SopStage, contact ent.Contact, currentLabelIds []uint64, addLabelIds []uint64, delLabelIds []uint64, organizationId uint64) (err error) {
	//// 开始事务
	//tx, err := l.svcCtx.DB.Tx(context.Background())
	//if err != nil {
	//	return dberrorhandler.DefaultEntError(l.Logger, err, nil)
	//}

	// 获取 addLabelIds 中不在 currentLabelIds 中的标签ID
	var newLabelIds []uint64
	var remLabelIds []uint64
	var finalLabelIds []uint64
	// 创建一个映射，用于快速查找 currentLabelIds 中的元素
	currentLabelIdSet := make(map[uint64]struct{})
	for _, id := range currentLabelIds {
		currentLabelIdSet[id] = struct{}{}
	}

	delLabelIdSet := make(map[uint64]struct{})
	for _, id := range delLabelIds {
		delLabelIdSet[id] = struct{}{}
	}
	if addLabelIds != nil && len(addLabelIds) > 0 {
		// 遍历 addLabelIds，找出不在 currentLabelIds 中的元素
		for _, id := range addLabelIds {
			if _, ce := currentLabelIdSet[id]; !ce {
				if _, re := delLabelIdSet[id]; !re {
					newLabelIds = append(newLabelIds, id)
				}
			}
		}

		if len(newLabelIds) > 0 {
			// 创建需要新增的标签关系
			for _, id := range newLabelIds {
				currentLabelIdSet[id] = struct{}{}
				_, err = l.svcCtx.DB.LabelRelationship.Create().
					SetLabelID(id).
					SetContactID(contact.ID).
					SetOrganizationID(organizationId).
					Save(l.ctx)
				if err != nil {
					//_ = tx.Rollback()
					return dberrorhandler.DefaultEntError(l.Logger, err, nil)
				}
			}

			// 合并 currentLabelIds 和 newLabelIds
			currentLabelIds = append(currentLabelIds, newLabelIds...)
		}
	}

	if delLabelIds != nil && len(delLabelIds) > 0 {
		// 遍历 delLabelIds，找出在 currentLabelIds 中的元素
		for _, id := range delLabelIds {
			if _, exists := currentLabelIdSet[id]; exists {
				remLabelIds = append(remLabelIds, id)
				delete(currentLabelIdSet, id)
			}
		}

		if len(remLabelIds) > 0 {
			_, err = l.svcCtx.DB.LabelRelationship.Delete().Where(labelrelationship.LabelIDIn(remLabelIds...), labelrelationship.ContactIDEQ(contact.ID), labelrelationship.OrganizationIDEQ(organizationId)).Exec(l.ctx)
			if err != nil {
				//_ = tx.Rollback()
				return dberrorhandler.DefaultEntError(l.Logger, err, nil)
			}
		}
	}

	if len(newLabelIds) == 0 && len(remLabelIds) == 0 {
		return nil
	}

	for id := range currentLabelIdSet {
		finalLabelIds = append(finalLabelIds, id)
	}

	// 遍历 sop_stages，找出满足条件的 stage
	for key, stage := range sopStages {
		if stage != nil && stage.ConditionType == 1 && isLabelIdListMatchFilter(finalLabelIds, stage.ConditionOperator, stage.ConditionList) {
			// 判断是否有 contact_wxid、source_type、source_id、sub_source_id 相同的记录
			_, err := l.svcCtx.DB.MessageRecords.Query().
				Where(
					messagerecords.ContactWxid(contact.Wxid),
					messagerecords.SourceType(3),
					messagerecords.SourceID(stage.ID),
					messagerecords.SubSourceID(0),
				).
				Only(l.ctx)
			if !ent.IsNotFound(err) {
				continue
			}
			// 判断ActionMessage是否为空
			sourceType := 3
			if stage.ActionMessage != nil {
				for i, message := range stage.ActionMessage {
					meta := custom_types.Meta{}
					if message.Meta != nil {
						meta.Filename = message.Meta.Filename
					}
					_, _ = l.svcCtx.DB.MessageRecords.Create().
						SetNotNilBotWxid(&contact.WxWxid).
						SetNotNilContactID(&contact.ID).
						SetNotNilContactType(&contact.Type).
						SetNotNilContactWxid(&contact.Wxid).
						SetNotNilContentType(&message.Type).
						SetNotNilContent(&message.Content).
						SetMeta(meta).
						SetNotNilSourceType(&sourceType).
						SetNotNilSourceID(&stage.ID).
						SetSubSourceID(uint64(i)).
						SetOrganizationID(organizationId).
						Save(l.ctx)

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

			if stage.ActionForward != nil {
				if stage.ActionForward.Wxid != "" {
					forwardWxids := splitString(stage.ActionForward.Wxid)
					for _, forwardWxid := range forwardWxids {
						for i, message := range stage.ActionForward.Action {
							meta := custom_types.Meta{}
							if message.Meta != nil {
								meta.Filename = message.Meta.Filename
							}
							_, err = l.svcCtx.DB.MessageRecords.Create().
								SetBotWxid(contact.WxWxid).
								SetContactID(0).
								SetContactType(0).
								SetContactWxid(forwardWxid).
								SetContentType(message.Type).
								SetContent(message.Content).
								SetMeta(meta).
								SetSourceType(sourceType).
								SetSourceID(stage.ID).
								SetSubSourceID(contact.ID + uint64(i)).
								SetOrganizationID(organizationId).
								Save(l.ctx)

						}
					}
				}
			}

			if stage.ActionLabelAdd != nil || stage.ActionLabelDel != nil {
				// 递归调用 AddLabelRelationships
				sopStages[key] = nil
				err = l.AddLabelRelationships(sopStages, contact, finalLabelIds, stage.ActionLabelAdd, stage.ActionLabelDel, organizationId)
				if err != nil {
					//_ = tx.Rollback()
					return err
				}
			}
		}

	}

	// 所有操作成功，提交事务
	//err = tx.Commit()
	//if err != nil {
	//	return dberrorhandler.DefaultEntError(l.Logger, err, nil)
	//}
	return nil
}

func valueInArray(val string, array []string) bool {
	for _, item := range array {
		if item == val {
			return true
		}
	}
	return false
}

func isLabelIdListMatchFilter(labelIdList []uint64, conditionOperator int, conditionList []custom_types.Condition) bool {
	labelIdSet := make(map[uint64]struct{})
	for _, id := range labelIdList {
		labelIdSet[id] = struct{}{}
	}

	for _, condition := range conditionList {
		match := false
		for _, id := range condition.LabelIdList {
			if _, ok := labelIdSet[id]; ok {
				match = true
				break
			}
		}

		if condition.Equal == 2 {
			match = !match
		}

		if conditionOperator == 1 && !match {
			return false
		} else if conditionOperator == 2 && match {
			return true
		}
	}

	return conditionOperator == 1
}

func splitString(input string) []string {
	// Define the regular expression pattern to match Chinese comma, English comma, and Chinese enumeration comma
	pattern := `[，,、]`
	re := regexp.MustCompile(pattern)
	// Split the input string based on the pattern
	return re.Split(input, -1)
}

func varReplace(s string, contactInfo *ent.Contact) string {
	nickname := ""
	var cname, carea, cbirthday, cbirtharea, cidcard_no, ctitle, sex, cage string
	if contactInfo != nil {
		nickname = contactInfo.Nickname
		carea = contactInfo.Carea
		cname = contactInfo.Cname
		cbirthday = contactInfo.Cbirthday
		cbirtharea = contactInfo.Cbirtharea
		cidcard_no = contactInfo.CidcardNo
		ctitle = contactInfo.Ctitle
		if contactInfo.Sex == 1 {
			sex = "男"
		} else if contactInfo.Sex == 2 {
			sex = "女"
		}
		age := contactInfo.Cage
		if age > 0 {
			cage = strconv.Itoa(age)
		}
	}

	s = strings.Replace(s, "${nickname}", nickname, -1)
	s = strings.Replace(s, "${cname}", cname, -1)
	s = strings.Replace(s, "${carea}", carea, -1)
	s = strings.Replace(s, "${cbirthday}", cbirthday, -1)
	s = strings.Replace(s, "${cbirtharea}", cbirtharea, -1)
	s = strings.Replace(s, "${cidcard_no}", cidcard_no, -1)
	s = strings.Replace(s, "${ctitle}", ctitle, -1)
	s = strings.Replace(s, "${sex}", sex, -1)
	s = strings.Replace(s, "${cage}", cage, -1)
	return s
}
