package MessageHandlers

import (
	"context"
	"encoding/json"
	"entgo.io/ent/dialect/sql"
	"github.com/zeromicro/go-zero/core/logx"
	"strconv"
	"strings"
	"time"
	"wechat-api/ent"
	"wechat-api/ent/label"
	"wechat-api/ent/labellog"
	"wechat-api/ent/labelrelationship"
	"wechat-api/ent/wx"
	"wechat-api/internal/pkg/wechat_ws"
	"wechat-api/internal/svc"
	"wechat-api/workphone"
)

type FriendPushNoticeHandler struct {
	svcCtx *svc.ServiceContext
}

func NewFriendPushNoticeHandler(svcCtx *svc.ServiceContext) *FriendPushNoticeHandler {
	return &FriendPushNoticeHandler{
		svcCtx: svcCtx,
	}
}

func (f *FriendPushNoticeHandler) Handler(msg *wechat_ws.MsgJsonObject) error {
	if msg.MsgType == "FriendPushNotice" {
		message := workphone.FriendPushNoticeMessage{}
		err := json.Unmarshal([]byte(msg.Message), &message)
		if err != nil {
			return err
		}
		// 拿到租户 id
		wx_info, err := f.svcCtx.DB.Wx.Query().
			Where(
				wx.WxidEQ(message.WeChatId), // Additional filter by organizationId
			).
			Only(context.TODO())
		//hookClient := hook.NewHook("", "", "")
		for _, friend := range message.Friends {
			friendType := 1
			//if friend.Type == 1 {
			//	friendType = 2
			//	_ = hookClient.RequestChatRoomInfo(friend.FriendId, message.WeChatId)
			//} else {
			//	friendType = 1
			//}
			_, err = f.svcCtx.DB.Contact.Create().
				SetWxWxid(message.WeChatId).
				SetType(friendType).
				SetWxid(friend.FriendId).
				SetAccount(friend.FriendNo).
				SetNickname(friend.FriendNick).
				SetMarkname(friend.Memo).
				SetHeadimg(friend.Avatar).
				//SetSex(cast.ToInt(friend.Gender)).
				SetOrganizationID(wx_info.OrganizationID).
				OnConflict().
				UpdateNewValues().
				SetType(friendType).
				SetOrganizationID(wx_info.OrganizationID).
				ID(context.TODO())

			if err != nil {
				logx.Error("Contact.Create: ", wx_info.OrganizationID)
				return err
			}
		}
	}
	return nil
}

type FriendPushNoticeTypeHandler struct {
	svcCtx *svc.ServiceContext
}

func NewFriendPushNoticeTypeHandler(svcCtx *svc.ServiceContext) *FriendPushNoticeTypeHandler {
	return &FriendPushNoticeTypeHandler{
		svcCtx: svcCtx,
	}
}

// Handle 实现 MessageHandlerStrategy 接口
func (f *FriendPushNoticeTypeHandler) Handle(ctx context.Context, msg *wechat_ws.MsgJsonObject, svcCtx *svc.ServiceContext) error {
	message := workphone.FriendPushNoticeMessage{}
	err := json.Unmarshal([]byte(msg.Message), &message)
	logx.Infof("msg.Message 的内容是：%s", msg.Message)
	if err != nil {
		logx.Errorf("Unmarshal.fail")
		return err
	}
	// 拿到租户 id
	wxInfo, err := svcCtx.DB.Wx.Query().
		Where(
			wx.WxidEQ(message.WeChatId), // Additional filter by organizationId
		).Only(ctx)
	if err != nil {
		return err
	}
	var labelRelationshipCreates []*ent.LabelRelationshipCreate
	for _, friend := range message.Friends {
		var friendId uint64
		friendType := 1
		friendId, err = svcCtx.DB.Contact.Create().
			SetWxWxid(message.WeChatId).
			SetType(friendType).
			SetWxid(friend.FriendId).
			SetAccount(friend.FriendNo).
			SetNickname(friend.FriendNick).
			SetMarkname(friend.Memo).
			SetHeadimg(friend.Avatar).
			SetOrganizationID(wxInfo.OrganizationID).
			OnConflict().
			UpdateNewValues().
			SetType(friendType).
			SetOrganizationID(wxInfo.OrganizationID).
			ID(ctx)
		if err != nil {
			logx.Errorf("Contact.Create 失败, OrgID=%d, err=%v", wxInfo.OrganizationID, err)
			return err
		}
		//判断friend里的labelId="1,2,3,4,5"为空就不处理了，不为空的时候就查下label表里有没有这个labelId，没有就插入，有就跳过
		if friend.LabelIds == "" {
			logx.Infof("没有labelIds 失败, wx_wxId=%v", message.WeChatId)
			continue
		}
		//获取labelId,并且按照逗号去分割成数组
		labelIdsStr := friend.LabelIds
		var ids []int
		ids, err = ParseCSVToIntSlice(labelIdsStr)
		if err != nil {
			logx.Infof("labelstring切割失败, labelIds=%v", labelIdsStr)
			continue
		}

		//转换成labelIds的切片，去labelLog里 用labelId in 查下一下数据。
		//labelIds := strings.Split(labelIdsStr, ",")
		//ids, _ = ParseCSVToIntSlice(labelIdsStr)

		LabelLogs, err := svcCtx.DB.LabelLog.Query().
			Where(labellog.LabelIDIn(ids...)).
			Where(labellog.WxID(message.WeChatId)).
			All(ctx)

		if err != nil || len(LabelLogs) == 0 {
			logx.Error("labelLog.Query.fail: 跳过 || 或者查询失败", wxInfo.OrganizationID)
			continue
		}

		//映射本地的name + type + model + organization_id
		currentOrgID := wxInfo.OrganizationID
		for _, remoteLabel := range LabelLogs {
			labelInfo, err := svcCtx.DB.Label.Query().Where(
				label.NameEQ(remoteLabel.LabelName),
				//label.StatusEQ(remoteLabel.LabelName),
				label.OrganizationID(currentOrgID),
			).Only(ctx)
			if err != nil || ent.IsNotFound(err) {
				logx.Error("label not found.fail: ", wxInfo.OrganizationID)
				continue
			}

			//svcCtx.DB.LabelRelationship.Create().
			//	SetOrganizationID(wxInfo.OrganizationID).
			//	SetContactID(friendId).
			//	SetLabelID(labelInfo.ID).
			//	SetAccount(friend.FriendNo).
			//	SetNickname(friend.FriendNick).
			//	SetMarkname(friend.Memo).
			//	SetHeadimg(friend.Avatar).
			//	SetOrganizationID(wxInfo.OrganizationID).
			//	OnConflict().
			//	UpdateNewValues().
			//	SetType(friendType).
			//	SetOrganizationID(wxInfo.OrganizationID).
			//	ID(ctx)

			//生成批量的关系数据 待插入
			labelRelationshipCreates = append(labelRelationshipCreates,
				svcCtx.DB.LabelRelationship.Create().
					//SetID(int(label.LabelId)).
					SetOrganizationID(wxInfo.OrganizationID).
					SetContactID(friendId).
					SetStatus(1).
					SetLabelID(labelInfo.ID).
					SetCreatedAt(time.Now()).
					SetUpdatedAt(time.Now()),
			)
			//
		}
	}
	if len(labelRelationshipCreates) > 0 {
		errShip := svcCtx.DB.LabelRelationship.CreateBulk(labelRelationshipCreates...).
			OnConflict(
				sql.ConflictColumns(labelrelationship.FieldLabelID, labelrelationship.FieldContactID),
			).DoNothing().Exec(ctx)
		if errShip != nil {
			logx.Error("label_relationship.create.fail: ", wxInfo.OrganizationID, labelRelationshipCreates)
			return err
		}
	}
	return nil
}

func ParseCSVToIntSlice(csv string) ([]int, error) {
	if csv == "" {
		return nil, nil
	}
	parts := strings.Split(csv, ",")
	var result []int
	for _, p := range parts {
		trimmed := strings.TrimSpace(p)
		if trimmed == "" {
			continue // 忽略空字符串
		}
		n, err := strconv.Atoi(trimmed)
		if err != nil {
			logx.Error("无法将 %s 转换为整数: %v", trimmed, err)
			continue // 忽略无效字符
		}
		result = append(result, n)
	}
	return result, nil
}
