// Package robot -----------------------------
// @file      : robot.go
// @author    : JJXu
// @contact   : wavingbear@163.com
// @time      : 2025/6/13 17:41
// -------------------------------------------
package robot

import (
	"context"
	"fmt"
	"fonchain-fiee/api/accountFiee"
	"fonchain-fiee/pkg/common/ws"
	"fonchain-fiee/pkg/service"
	"fonchain-fiee/pkg/service/asChat/chatCache"
	"fonchain-fiee/pkg/service/asChat/consts"
	"fonchain-fiee/pkg/service/asChat/dto"
	"log"
	"sync"
	"time"
)

func NewRobot(cache *chatCache.ChatCache) *Robot {
	ctx := context.Background()
	robotQuery, err := service.AccountFieeProvider.GetChatUserList(ctx, &accountFiee.GetChatUserListRequest{
		Query: &accountFiee.ChatUserData{Role: 3},
		Page:  1, PageSize: 1,
	})
	if err != nil {
		panic("聊天机器人初始化失败,err:" + err.Error())
	}
	var robotInfo *accountFiee.ChatUserData
	if robotQuery.Total > 0 {
		robotInfo = robotQuery.List[0]
	} else {
		robotInfo = &accountFiee.ChatUserData{
			NickName: "阿泰",
			Role:     3,
			Origin:   "fontree",
		}
		createChatUserResp, errs := service.AccountFieeProvider.CreateChatUser(ctx, robotInfo)
		if errs != nil {
			panic("聊天机器人创建失败,err:" + errs.Error())
		}
		robotInfo = createChatUserResp.Data
	}
	r := &Robot{
		Info: robotInfo,
		EventListener: &ws.EventListener{
			Name: "robot1",
			ListenEvents: []ws.ListenEvent{ //只监听消息推送事件
				{ws.EventUserJoin, ws.EventProgressAfter},
				{ws.EventChatMessage, ws.EventProgressBefore},
			},
			Chan: make(ws.ListenEventChan),
		},
		cache: cache,
	}
	err = r.ReloadRules(ctx)
	fmt.Println("机器人规则加载完成,结果:", err)
	consts.ChatRoom.RegisterEventListener(r.EventListener)
	go r.Run()
	return r
}

type Robot struct {
	Info                                               *accountFiee.ChatUserData //机器人信息
	joinSessionRules, keywordsRules, noReplyAfterRules []IRobotTask              //自动回复规则
	DelayTask                                          []IRobotTask              //延时任务
	ticker                                             *time.Ticker              //定时器
	stopChan                                           chan struct{}             //停止管道
	isRunning                                          bool                      //运行状态
	mu                                                 sync.Mutex
	*ws.EventListener
	cache *chatCache.ChatCache
}

//func (r *Robot) Listen(record *accountFiee.ChatRecordData) {
//	for _, replyRules := range r.Rules {
//		for _, rule := range replyRules.Rules {
//			hit, runTime, function := rule.Hit(record)
//			if hit && function != nil {
//				if runTime.IsZero() {
//					go func() {
//						err := function(r.Info.ID, replyRules.Response)
//						if err != nil {
//							log.Printf("聊天机器人[%d]回复消息失败:%v", r.Info.ID, err)
//						}
//					}()
//				} else {
//					r.mu.Lock()
//					r.DelayTask = append(r.DelayTask, RobotTask{
//						RunTime:  runTime,
//						Run:      function,
//						Response: replyRules.Response,
//					})
//					r.mu.Unlock()
//					// 添加任务后启动定时任务(如果未运行)
//					if !r.isRunning {
//						go r.Run()
//					}
//				}
//				break
//			}
//		}
//	}
//}

func (r *Robot) Run() {
	r.mu.Lock()
	if r.isRunning {
		r.mu.Unlock()
		return
	}
	r.isRunning = true
	r.ticker = time.NewTicker(time.Second)
	r.stopChan = make(chan struct{})
	r.mu.Unlock()

	defer func() {
		r.mu.Lock()
		r.isRunning = false
		if r.ticker != nil {
			r.ticker.Stop()
			r.ticker = nil
		}
		r.stopChan = nil
		r.mu.Unlock()
	}()

	for {
		select {
		default:
			time.Sleep(200 * time.Millisecond)
		case <-r.ticker.C:
			r.mu.Lock()
			if len(r.DelayTask) == 0 {
				r.mu.Unlock()
				break
				//return // 没有任务时退出
			}
			now := time.Now()
			var remainingTasks []IRobotTask
			for _, task := range r.DelayTask {
				if now.After(task.RunTime()) {
					// 执行任务
					go func() {
						err := task.Run(r.cache)
						if err != nil {
							log.Printf("聊天机器人[%d]延时回复消息失败:%v", r.Info.ID, err)
						} else {
							log.Printf("聊天机器人[%d]延时回复消息成功", r.Info.ID)
						}
					}()
				} else {
					// 保留未到期的任务
					remainingTasks = append(remainingTasks, task)
				}
			}
			r.DelayTask = remainingTasks
			r.mu.Unlock()
		case <-r.stopChan:
			return
		case event := <-r.EventListener.Chan:
			fmt.Printf("robot listen event:%#v\n", event)
			r.mu.Lock()
			//加入聊天室规则
			hasHit := false
			for _, rule := range r.joinSessionRules {
				rule := rule
				hit := rule.Hit(event, r.Info)
				fmt.Printf("规则【%s】校验结果:%v\n", rule.GetTitle(), hit)
				if hit {
					hasHit = true
					if rule.RunTime().IsZero() {
						go func() {
							err := rule.Run(r.cache)
							if err != nil {
								log.Printf("robot 执行任务失败:%v\n", err)
							}
						}()
					} else {
						r.RegisterDelayTask(rule)
					}
				}
			}
			if !hasHit {
				for _, rule := range r.keywordsRules {
					rule := rule
					hit := rule.Hit(event, r.Info)
					fmt.Printf("规则【%s】校验结果:%v\n", rule.GetTitle(), hit)
					if hit {
						hasHit = true
						fmt.Println("命中规则:", rule.GetTitle())
						if rule.RunTime().IsZero() {
							go func() {
								err := rule.Run(r.cache)
								if err != nil {
									log.Printf("robot 执行任务失败:%v\n", err)
								}
							}()
						} else {
							r.RegisterDelayTask(rule)
						}
					}
				}
			}
			if !hasHit {
				for _, rule := range r.noReplyAfterRules {
					rule := rule
					hit := rule.Hit(event, r.Info)
					fmt.Printf("规则【%s】校验结果:%v\n", rule.GetTitle(), hit)
					if hit {
						hasHit = true
						fmt.Println("命中规则:", rule.GetTitle())
						if rule.RunTime().IsZero() {
							go func() {
								err := rule.Run(r.cache)
								if err != nil {
									log.Printf("robot 执行任务失败:%v\n", err)
								}
							}()
						} else {
							r.RegisterDelayTask(rule)
						}
					}
				}
			}
			r.mu.Unlock()
		}
	}
}

// Stop 主动停止机器人的定时任务
func (r *Robot) Stop() {
	r.mu.Lock()
	if r.stopChan != nil {
		close(r.stopChan)
	}
	r.mu.Unlock()
}
func (r *Robot) RegisterDelayTask(task IRobotTask) {
	if task.Run == nil {
		return
	}
	r.DelayTask = append(r.DelayTask, task)
}

// 重载回复规则
func (r *Robot) ReloadRules(ctx context.Context) error {
	r.mu.Lock()
	defer r.mu.Unlock()
	r.joinSessionRules = []IRobotTask{}
	r.keywordsRules = []IRobotTask{}
	r.noReplyAfterRules = []IRobotTask{}
	ruleListRes, err := service.AccountFieeProvider.GetChatAutoReplyRulerList(ctx, &accountFiee.GetChatAutoReplyRulerListRequest{
		Query:    &accountFiee.ChatAutoReplyRulerData{Status: 1},
		Page:     1,
		PageSize: -1,
	})
	if err != nil {
		log.Printf("robot 查询回复规则失败:%v\n", err)
		return fmt.Errorf("robot 查询回复规则失败:%v\n", err)
	} else {
		var data []*dto.ChatAutoReplyData
		for _, v := range ruleListRes.List {
			tmp := dto.ChatAutoReplyData{}
			tmp.Parse(v)
			data = append(data, &tmp)
		}
		r.joinSessionRules, r.keywordsRules, r.noReplyAfterRules = ParseReplyRule(data)
	}
	return nil
}