package scheduler

import (
	"ALLinSSL/backend/internal/monitor"
	"ALLinSSL/backend/internal/report"
	"ALLinSSL/backend/public"
	"encoding/json"
	"fmt"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"
)

var (
	MonitorErrCount   = make(map[int64]int)
	monitorErrCountMu sync.Mutex
)

// 通知模板，先写死，后续做成配置
var MonitorErrTemplate = "监控名称：%v\n类型：%v\n域名：%v\n错误信息：%v\n请及时处理！\n检测时间：%v"

func Monitor() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("Monitor 主流程捕获 panic: %v\n", r)
		}
	}()

	s, err := monitor.GetSqlite()
	if err != nil {
		fmt.Println(err)
	}
	defer s.Close()
	s1, err := report.GetSqlite()
	if err != nil {
		fmt.Println(err)
		return
	}
	defer s1.Close()
	s1.TableName = "report"

	data, err := s.Select()
	if err != nil {
		fmt.Println(err)
	}
	now := time.Now()
	loc := now.Location()
	var wg sync.WaitGroup
	for _, v := range data {
		if v["active"].(int64) == 1 {
			lastTimeStr, ok := v["last_time"].(string)
			if !ok || lastTimeStr == "" {
				lastTimeStr = "1970-01-01 00:00:00"
			}
			lastTime, err := time.ParseInLocation("2006-01-02 15:04:05", lastTimeStr, loc)
			if err != nil {
				// fmt.Println(err)
				continue
			}
			monitorType, ok := v["monitor_type"].(string)
			if !ok {
				fmt.Println("监控类型错误")
				return
			}
			target, ok := v["target"].(string)
			if !ok {
				fmt.Println("监控目标错误")
				return
			}
			advanceDay, ok := v["advance_day"].(int64)
			if !ok {
				advanceDay = 30 // 默认提前30天
			}
			if now.Sub(lastTime).Minutes() >= float64(v["cycle"].(int64)) {
				wg.Add(1)
				go func(v map[string]any) {
					defer func() {
						if r := recover(); r != nil {
							fmt.Printf("监控任务发生错误: %v\n", r)
							// 打印堆栈
							buf := make([]byte, 1<<16) // 64KB
							n := runtime.Stack(buf, false)
							fmt.Println("堆栈信息:\n", string(buf[:n]))
						}
					}()
					defer wg.Done()
					gs := *s
					var (
						certInfo *monitor.CertInfo
						certJson string
						Err      error
						checkErr string
					)
					switch monitorType {
					case "https":
						certInfo, Err = monitor.CheckHttps(target, int(advanceDay))
					case "smtp":
						certInfo, Err = monitor.CheckSmtp(target, int(advanceDay))
					default:
						Err = fmt.Errorf("不支持的监控类型:%s", monitorType)
					}

					if Err != nil {
						checkErr = Err.Error()
					} else {
						if certInfo.VerifyError != "" && (!certInfo.Valid || certInfo.DaysLeft <= int(advanceDay)) {
							checkErr = certInfo.VerifyError
						}
						certBytes, err := json.Marshal(certInfo)
						if err == nil {
							certJson = string(certBytes)
						}
					}
					id := v["id"].(int64)

					// 此处应该发送错误邮件
					if checkErr != "" {
						// 更新监控记录
						valid := -1 // 状态为异常
						if certInfo != nil && certInfo.Valid {
							valid = 1 // 状态为正常
						}
						gs.Where("id=?", []interface{}{id}).Update(map[string]any{
							"last_time":       now.Format("2006-01-02 15:04:05"),
							"except_end_time": now.Format("2006-01-02 15:04:05"),
							"info":            certJson,
							"valid":           valid, // 状态为异常
						})
						// 新增错误记录
						if certInfo == nil || !certInfo.Valid {
							gs.TableName = "err_record"
							gs.Insert(map[string]any{
								"id":          public.GenerateUUID(),
								"monitor_id":  id,
								"create_time": now.Format("2006-01-02 15:04:05"),
								"msg":         checkErr,
								"info":        certJson,
							})
						}
						monitorErrCountMu.Lock()
						MonitorErrCount[id] += 1
						errCount := MonitorErrCount[id]
						monitorErrCountMu.Unlock()

						repeatSendGap, ok := v["repeat_send_gap"].(int64)
						if !ok {
							repeatSendGap = 10
						}
						reportTypes, ok := v["report_types"].(string)
						if ok && errCount == 1 {
							reportTypeArr := strings.Split(reportTypes, ",")
							for _, reportType := range reportTypeArr {
								if reportType == "" {
									continue
								}
								rdata, err := s1.Where("type=?", []interface{}{reportType}).Select()
								if err != nil {
									return
								}
								if len(rdata) <= 0 {
									return
								}
								report.Notify(map[string]any{
									"provider":    reportType,
									"provider_id": strconv.FormatInt(rdata[0]["id"].(int64), 10),
									"subject":     "ALLinSSL 监控通知",
									"body":        fmt.Sprintf(MonitorErrTemplate, v["name"], monitorType, v["target"], strings.Split(checkErr, "：")[0], now.Format("2006-01-02 15:04:05")),
								})
							}
						}
						monitorErrCountMu.Lock()
						if MonitorErrCount[id] >= int(repeatSendGap) {
							MonitorErrCount[id] = 0
						}
						monitorErrCountMu.Unlock()
					} else {
						// 更新监控记录
						gs.Where("id=?", []interface{}{id}).Update(map[string]any{
							"last_time": now.Format("2006-01-02 15:04:05"),
							"info":      certJson,
							"valid":     1, // 状态为正常
						})
						monitorErrCountMu.Lock()
						MonitorErrCount[id] = 0
						monitorErrCountMu.Unlock()
					}
				}(v)
			}
		}
	}
	wg.Wait()
}
