package ne_alarm_state_check_license

import (
	"encoding/json"
	"fmt"
	"math"
	"time"

	"be.ems/src/framework/constants"
	"be.ems/src/framework/cron"
	"be.ems/src/framework/logger"
	"be.ems/src/framework/utils/parse"

	neDataModel "be.ems/src/modules/network_data/model"
	neDataService "be.ems/src/modules/network_data/service"
	neModel "be.ems/src/modules/network_element/model"
	neService "be.ems/src/modules/network_element/service"
	wsService "be.ems/src/modules/ws/service"
)

var NewProcessor = &NeAlarmStateCheckLicenseProcessor{
	neConfigBackupService: neService.NewNeConfigBackup,
	neInfoService:         neService.NewNeInfo,
	alarmService:          neDataService.NewAlarm,
	wsSendService:         wsService.NewWSSend,
	count:                 0,
}

// NeAlarmStateCheckLicenseProcessor 网元告警License到期检查
type NeAlarmStateCheckLicenseProcessor struct {
	neConfigBackupService *neService.NeConfigBackup // 网元配置文件备份记录服务
	neInfoService         *neService.NeInfo         // 网元信息服务
	alarmService          *neDataService.Alarm      // 告警信息服务
	wsSendService         *wsService.WSSend         // ws发送服务
	count                 int                       // 执行次数
}

// alarmParams 告警参数
type alarmParams struct {
	AlarmTitle        string `json:"alarmTitle"`        // NE State Check Alarm License
	AlarmType         string `json:"alarmType"`         // EquipmentAlarm=2
	OrigSeverity      string `json:"origSeverity"`      // Major=2
	SpecificProblem   string `json:"specificProblem"`   // Alarm Cause: License received from target NE is about to expire
	SpecificProblemID string `json:"specificProblemId"` // AC10200
	AddInfo           string `json:"addInfo"`           // 告警补充信息
	DayLt             int64  `json:"dayLt"`             // 天数小于，默认30天

	// === 非参数字段 ===
	AlarmId string // 告警ID
}

func (s *NeAlarmStateCheckLicenseProcessor) Execute(data any) (any, error) {
	s.count++ // 执行次数加一
	options := data.(cron.JobData)
	sysJob := options.SysJob
	logger.Infof("重复:%v 任务ID:%s  执行次数:%d", options.Repeat, sysJob.JobID, s.count)
	// 返回结果，用于记录执行结果
	result := map[string]any{
		"count": s.count,
	}

	// 读取参数值
	var params alarmParams
	err := json.Unmarshal([]byte(sysJob.TargetParams), &params)
	if err != nil {
		return nil, fmt.Errorf("json params err: %v", err)
	}
	// 检查参数值
	if params.DayLt == 0 {
		params.DayLt = 30
	}

	neList := s.neInfoService.SelectList(neModel.NeInfo{}, true, false)
	for _, neInfo := range neList {
		if neInfo.CreateTime == 0 {
			continue
		}

		// 网元在线状态
		isOnline := parse.Boolean(neInfo.ServerState["online"])
		if !isOnline {
			continue
		}

		// 检查状态
		err := s.serverState(neInfo.ServerState, params.DayLt)
		if err == nil {
			continue
		}
		if params.AddInfo != "" {
			params.AddInfo = params.AddInfo + ", " + err.Error()
		} else {
			params.AddInfo = err.Error()
		}

		neTypeAndId := fmt.Sprintf("%s_%s", neInfo.NeType, neInfo.NeId)
		// 告警ID
		params.AlarmId = fmt.Sprintf("%d%d", constants.ALARM_LICENSE_CHECK, neInfo.CreateTime)
		// 检查网元告警ID是否唯一
		alarmIdArr := s.alarmService.Find(neDataModel.Alarm{
			NeType:  neInfo.NeType,
			NeId:    neInfo.RmUID,
			AlarmId: params.AlarmId,
		})
		// 告警状态, 存在的需要手动清除
		alarmStatus := ""
		if len(alarmIdArr) > 0 {
			alarmStatus = fmt.Sprint(alarmIdArr[0].AlarmStatus)
		}
		//  活动告警进行清除
		if alarmStatus == "1" {
			clearAlarm, err := s.alarmClear(neInfo, alarmIdArr[0])
			if err != nil {
				result[neTypeAndId] = err.Error()
				continue
			}
			groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId)
			s.wsSendService.ByGroupID(groupID, clearAlarm)
			result[neTypeAndId] = "alarm clear"
			alarmStatus = "" // 标记为未记录再次发起新告警
		}
		// 未记录
		if alarmStatus == "" {
			addInfo := params.AddInfo
			if params.AddInfo != "" {
				params.AddInfo = params.AddInfo + ", " + err.Error()
			} else {
				params.AddInfo = err.Error()
			}
			// 进行新增
			newAlarm, err := s.alarmNew(neInfo, params)
			params.AddInfo = addInfo // 恢复附加信息
			if err != nil {
				result[neTypeAndId] = err.Error()
				continue
			}
			groupID := fmt.Sprintf("%s_%s_%s", wsService.GROUP_ALARM, neInfo.NeType, neInfo.NeId)
			s.wsSendService.ByGroupID(groupID, newAlarm)
			result[neTypeAndId] = "alarm new"
		}
	}

	// 返回结果，用于记录执行结果
	return result, nil
}

// serverState 网元状态
func (s NeAlarmStateCheckLicenseProcessor) serverState(state map[string]any, dayLt int64) error {
	expire := fmt.Sprint(state["expire"])
	if expire == "" || expire == "<nil>" || expire == "-" || expire == "2099-12-31" {
		return nil
	}

	// 解析过期时间
	expireTime, err := time.Parse("2006-01-02", expire)
	if err != nil {
		return fmt.Errorf("parse expire time error: %v", err)
	}

	// 计算距离天数
	daysLeft := time.Until(expireTime).Hours() / 24
	expireDay := int64(math.Ceil(daysLeft))
	if expireDay <= dayLt {
		if expireDay <= 0 {
			return fmt.Errorf("license will expire after today")
		}
		return fmt.Errorf("license will expire in %d days", expireDay)
	}
	return nil
}

// alarmClear 清除告警
func (s NeAlarmStateCheckLicenseProcessor) alarmClear(neInfo neModel.NeInfo, v neDataModel.Alarm) (neDataModel.Alarm, error) {
	// 变更告警ID为告警清除ID
	v.AlarmId = fmt.Sprintf("%s%d", v.AlarmCode, v.EventTime.UnixMilli())
	v.AlarmStatus = "0"
	// 告警清除
	clearTime := time.UnixMilli(neInfo.UpdateTime)
	v.ClearType = "1"
	v.ClearTime = &clearTime
	v.ClearUser = "system"
	rows := s.alarmService.Update(v)
	if rows > 0 {
		return v, nil
	}
	return neDataModel.Alarm{}, fmt.Errorf("clear alarm fail")
}

// alarmNew 新增告警
func (s NeAlarmStateCheckLicenseProcessor) alarmNew(neInfo neModel.NeInfo, v alarmParams) (neDataModel.Alarm, error) {
	// seq 告警序号
	lastSeq := s.alarmService.FindAlarmSeqLast(neInfo.NeType, neInfo.RmUID)
	lastTime := neInfo.UpdateTime // 网元最后更新时间
	if lastTime < neInfo.CreateTime {
		lastTime = time.Now().UnixMilli()
	}
	alarm := neDataModel.Alarm{
		NeType:            neInfo.NeType,
		NeId:              neInfo.RmUID, // neInfo.NeId,
		NeName:            neInfo.NeName,
		Province:          neInfo.Province,
		PvFlag:            neInfo.PvFlag,
		AlarmSeq:          fmt.Sprint(lastSeq + 1),
		AlarmId:           v.AlarmId,
		AlarmTitle:        v.AlarmTitle,
		AlarmCode:         fmt.Sprint(constants.ALARM_LICENSE_CHECK),
		EventTime:         time.UnixMilli(lastTime),
		AlarmType:         v.AlarmType,
		OrigSeverity:      v.OrigSeverity,
		PerceivedSeverity: v.OrigSeverity,
		ObjectUid:         neInfo.RmUID,
		ObjectName:        "NE License",
		ObjectType:        "license",
		LocationInfo:      "NE License: Heartbeat",
		AlarmStatus:       "1", // 活动告警
		SpecificProblem:   v.SpecificProblem,
		SpecificProblemId: v.SpecificProblemID,
		AddInfo:           v.AddInfo,
		Counter:           "0",
		AckState:          "0",
		ClearType:         "0",
	}
	insertId := s.alarmService.InsertAndForword(alarm)
	if insertId != "" {
		alarm.ID = insertId
		return alarm, nil
	}
	return neDataModel.Alarm{}, fmt.Errorf("new alarm fail")
}
