package service

import (
	"encoding/json"
	"fmt"
	"nms_nbi/src/framework/constants/uploadsubpath"
	"nms_nbi/src/framework/logger"
	"nms_nbi/src/framework/utils/date"
	"nms_nbi/src/framework/utils/file"
	"nms_nbi/src/framework/utils/parse"
	"nms_nbi/src/modules/api_rest_cxy/model"
	"nms_nbi/src/modules/api_rest_cxy/utils/common"
	"nms_nbi/src/modules/api_rest_cxy/utils/kafka"
	neDataModel "nms_nbi/src/modules/network_data/model"
	neDataService "nms_nbi/src/modules/network_data/service"
)

// 实例化数据层 AlarmImpl 结构体
var NewAlarmImpl = &AlarmImpl{
	alarmService: neDataService.NewAlarmImpl,
	alarmLevel: map[string]int64{
		"Critical": 1,
		"Major":    2,
		"Minor":    3,
		"Warning":  4,
	},
}

// 告警数据处理服务 服务层处理
type AlarmImpl struct {
	// 告警信息服务
	alarmService neDataService.IAlarm
	// 原始告警级别 1：一级告警；2：二级告警；3：三级告警；4：四级告警
	alarmLevel map[string]int64
}

// SelectPage 根据条件分页查询
func (s *AlarmImpl) SelectPage(querys neDataModel.AlarmQuery) ([]model.Alarm, int64) {
	dataArr := []model.Alarm{}
	// 查询数据
	pageData := s.alarmService.SelectPage(querys)
	total := parse.Number(pageData["total"])
	rows, ok := pageData["rows"].([]neDataModel.Alarm)
	if !ok || len(rows) <= 0 {
		return dataArr, total
	}

	for _, v := range rows {
		item := s.parseAlarmData(v)
		dataArr = append(dataArr, item)
	}
	return dataArr, total
}

// parseAlarmData 解析转换为指定的告警对象
func (s *AlarmImpl) parseAlarmData(v neDataModel.Alarm) model.Alarm {
	alarmLevel, ok := s.alarmLevel[v.OrigSeverity]
	if !ok {
		alarmLevel = 0
	}
	return model.Alarm{
		AlarmSeq:        v.AlarmSeq,
		AlarmTitle:      v.AlarmTitle,
		AlarmStatus:     parse.Number(v.AlarmStatus),
		AlarmType:       v.AlarmType,
		AlarmLevel:      alarmLevel,
		EventTime:       date.ParseDateToStr(v.EventTime, date.YYYY_MM_DD_HH_MM_SS),
		AlarmId:         parse.Number(v.ID),
		CauseID:         v.AlarmCode,
		Cause:           v.SpecificProblem,
		NeRUID:          v.ObjectUid,
		NeUserLabel:     v.NeName,
		ObjectRUID:      v.AlarmId,
		ObjectUserLabel: v.ObjectName,
		AddInfo:         v.AddInfo,
	}
}

// KafkaPush 推送数据Kafka
func (s *AlarmImpl) KafkaPush(alarm neDataModel.Alarm) error {
	if alarm.AlarmTitle == "" {
		return nil
	}

	// 数据序列化
	data := s.parseAlarmData(alarm)
	bytes, err := json.Marshal(data)
	if err != nil {
		logger.Errorf("KafkaPush parseAlarmData err => %s", err.Error())
		return err
	}

	// 订阅topic，名称为：专业编码-厂商编码-OMC编号-数据类别（固定为FM）
	basePath := common.BasePath("-")
	topic := fmt.Sprintf("%s-FM", basePath)

	// 发送消息
	partition, offset, err := kafka.KInitConm.MessageSyncSend(topic, 0, string(bytes))
	if err != nil {
		logger.Errorf("KafkaPush MessageSyncSend err => %s", err.Error())
		return err
	}
	logger.Infof("KafkaPush MessageSyncSend Partition:%d, Offset:%d", partition, offset)
	return err
}

// AlarmDataToFile 告警数据写入文件
func (s *AlarmImpl) AlarmDataToFile(requestId, neType, rmUID, startTime, endTime string) (int64, string) {
	var pageNum int64 = 1
	var pageSize int64 = 20
	dataArr := []any{}

	// 查询数据
	pageData := s.alarmService.SelectPage(neDataModel.AlarmQuery{
		PageNum:   pageNum,
		PageSize:  pageSize,
		StartTime: startTime,
		EndTime:   endTime,
		RmUID:     rmUID,
		NeType:    neType,
	})

	total := parse.Number(pageData["total"])
	rows, ok := pageData["rows"].([]neDataModel.Alarm)
	if !ok || len(rows) <= 0 {
		return int64(len(dataArr)), ""
	}
	for _, v := range rows {
		dataArr = append(dataArr, s.parseAlarmData(v))
	}

	// 按总数分批遍历
	batchNum := total / pageSize
	for i := 1; i <= int(batchNum); i++ {
		// 查询数据
		pageData := s.alarmService.SelectPage(neDataModel.AlarmQuery{
			PageNum:   int64(i),
			PageSize:  pageSize,
			StartTime: startTime,
			EndTime:   endTime,
			RmUID:     rmUID,
			NeType:    neType,
		})
		rows, ok := pageData["rows"].([]neDataModel.Alarm)
		if !ok || len(rows) <= 0 {
			return int64(len(dataArr)), ""
		}
		for _, v := range rows {
			dataArr = append(dataArr, s.parseAlarmData(v))
		}
	}

	// 文件名
	dataSaveFileName := common.DataSaveFileName{
		RequestId: requestId,
	}
	fileName := dataSaveFileName.JSON()
	filePath := fmt.Sprintf("%s/%s", file.ParseUploadFileDir(uploadsubpath.EXPORT), fileName)
	err := file.WriterFileJSONLine(dataArr, filePath)
	if err != nil {
		return int64(len(dataArr)), ""
	}
	return int64(len(dataArr)), filePath
}
