package service

import (
	"fmt"
	"strconv"
	"time"

	"github.com/tsmask/go-oam"
	"github.com/tsmask/go-oam/framework/utils/parse"

	"be.ems/src/framework/constants"
	"be.ems/src/framework/i18n"
	"be.ems/src/framework/utils/date"
	"be.ems/src/framework/utils/file"
	"be.ems/src/modules/ne_data/model"
	"be.ems/src/modules/ne_data/repository"
	sysService "be.ems/src/modules/system/service"
)

// 实例化数据层 Alarm 结构体
var NewAlarm = &Alarm{
	alarmRepository: repository.NewAlarm,
}

// Alarm 告警 服务层处理
type Alarm struct {
	alarmRepository *repository.Alarm // 告警数据信息
}

// FindByPage 根据条件分页查询
func (r Alarm) FindByPage(query model.AlarmQuery) ([]model.Alarm, int64) {
	return r.alarmRepository.SelectByPage(query)
}

// Find 查询
func (r Alarm) Find(param model.Alarm) []model.Alarm {
	return r.alarmRepository.Select(param)
}

// Insert 新增信息
func (s Alarm) Insert(param model.Alarm) int64 {
	return s.alarmRepository.Insert(param)
}

// Update 修改信息
func (s Alarm) Update(param model.Alarm) int64 {
	return s.alarmRepository.Update(param)
}

// DeleteByIds 批量删除信息
func (r Alarm) DeleteByIds(ids []int64) (int64, error) {
	// 检查是否存在
	data := r.alarmRepository.SelectByIds(ids)
	if len(data) <= 0 {
		return 0, fmt.Errorf("no data")
	}

	if len(data) == len(ids) {
		rows := r.alarmRepository.DeleteByIds(ids)
		return rows, nil
	}
	// 删除信息失败！
	return 0, fmt.Errorf("delete fail")
}

// FindAlarmSeqLast 查询网元告警最后一条序号
func (s Alarm) FindAlarmSeqLast(neType, neId string) int64 {
	return s.alarmRepository.SelectAlarmSeqLast(neType, neId)
}

// ClearByIds 批量清除告警信息
func (r Alarm) ClearByIds(ids []int64, clearUser, clearType string) (int64, error) {
	// 检查是否存在
	arr := r.alarmRepository.SelectByIds(ids)
	if len(arr) <= 0 {
		return 0, fmt.Errorf("no data")
	}

	if len(arr) == len(ids) {
		var rows int64 = 0
		for _, v := range arr {
			// 状态检查AlarmCode变更告警ID
			if v.AlarmCode == constants.ALARM_STATE_CHECK || v.AlarmCode == constants.ALARM_CMD_CHECK || v.AlarmCode == constants.ALARM_LICENSE_CHECK {
				v.AlarmId = fmt.Sprintf("%d%d", v.AlarmCode, v.EventTime)
			}
			v.AlarmStatus = oam.ALARM_STATUS_CLEAR
			// 告警清除
			v.ClearType = clearType
			v.ClearUser = clearUser
			v.ClearTime = time.Now().UnixMilli()
			rows += r.alarmRepository.Update(v)
		}
		return rows, nil
	}
	return 0, fmt.Errorf("clear fail")
}

// AckByIds 批量确认清除告警信息
func (r Alarm) AckByIds(ids []int64, ackUser, ackState string) (int64, error) {
	// 检查是否存在
	arr := r.alarmRepository.SelectByIds(ids)
	if len(arr) <= 0 {
		return 0, fmt.Errorf("no data")
	}

	if len(arr) == len(ids) {
		var rows int64 = 0
		for _, v := range arr {
			v.AckState = ackState
			v.AckTime = time.Now().UnixMilli()
			v.AckUser = ackUser
			rows += r.alarmRepository.Update(v)
		}
		return rows, nil
	}
	return 0, fmt.Errorf("ack fail")
}

// CountType 告警类别数量
func (s Alarm) CountType(alarmStatus string) []map[string]any {
	data := []map[string]any{}
	alarmTypeArr := []string{
		oam.ALARM_TYPE_COMMUNICATION_ALARM,
		oam.ALARM_TYPE_EQUIPMENT_ALARM,
		oam.ALARM_TYPE_PROCESSING_FAILURE,
		oam.ALARM_TYPE_ENVIRONMENTAL_ALARM,
		oam.ALARM_TYPE_QUALITY_OF_SERVICE_ALARM,
	}
	for _, v := range alarmTypeArr {
		data = append(data, map[string]any{
			"alarmType": v,
			"total":     0,
		})
	}

	// 告警类别数量
	rows := s.alarmRepository.GroupTotal(alarmStatus, "alarm_type", -1)
	for _, item := range data {
		for _, v := range rows {
			str := fmt.Sprint(v["alarm_type"])
			if str == item["alarmType"] {
				item["alarmType"] = str
				item["total"] = parse.Number(v["total"])
			}
		}
	}
	return data
}

// CountSeverity 告警级别数量
func (s Alarm) CountSeverity(alarmStatus string) []map[string]any {
	data := []map[string]any{}
	alarmTypeArr := []string{
		oam.ALARM_SEVERITY_CRITICAL,
		oam.ALARM_SEVERITY_MAJOR,
		oam.ALARM_SEVERITY_MINOR,
		oam.ALARM_SEVERITY_WARNING,
	}
	for _, v := range alarmTypeArr {
		data = append(data, map[string]any{
			"severity": v,
			"total":    0,
		})
	}

	// 数量
	rows := s.alarmRepository.GroupTotal(alarmStatus, "perceived_severity", -1)
	for _, item := range data {
		for _, v := range rows {
			str := fmt.Sprint(v["perceived_severity"])
			if str == item["severity"] {
				item["severity"] = str
				item["total"] = parse.Number(v["total"])
			}
		}
	}
	return data
}

// CountNe 告警状态前几排名
func (s Alarm) CountNe(alarmStatus string, top int) []map[string]any {
	data := s.alarmRepository.GroupTotal(alarmStatus, "ne_type", top)
	for _, v := range data {
		v["neType"] = fmt.Sprint(v["ne_type"])
		v["total"] = parse.Number(v["total"])
		delete(v, "ne_type")
	}
	return data
}

// ExportXlsx 导出数据到 xlsx 文件
func (r Alarm) ExportXlsx(rows []model.Alarm, fileName, language, alarmStatus string) (string, error) {
	// 第一行表头标题
	headerCells := map[string]string{
		"A1": i18n.TKey(language, "alarm.export.alarmType"),
		"B1": i18n.TKey(language, "alarm.export.origSeverity"),
		"C1": i18n.TKey(language, "alarm.export.alarmTitle"),
		"D1": i18n.TKey(language, "alarm.export.eventTime"),
		"E1": i18n.TKey(language, "alarm.export.alarmId"),
		"F1": i18n.TKey(language, "alarm.export.alarmCode"),
		"G1": i18n.TKey(language, "ne.common.neType"),
		"H1": i18n.TKey(language, "ne.common.neName"),
		"I1": i18n.TKey(language, "ne.common.neId"),
	}
	if alarmStatus == "0" {
		headerCells["J1"] = i18n.TKey(language, "alarm.export.clearUser")
		headerCells["K1"] = i18n.TKey(language, "alarm.export.clearTime")
		headerCells["L1"] = i18n.TKey(language, "alarm.export.clearType")
	}
	// 读取字典数据 告警原始严重程度
	dictActiveAlarmType := sysService.NewSysDictData.FindByType("active_alarm_type")
	// 读取字典数据 告警类型
	dictActiveClearType := sysService.NewSysDictData.FindByType("active_clear_type")
	// 读取字典数据 告警确认类型
	dictActiveAlarmSeverity := sysService.NewSysDictData.FindByType("active_alarm_severity")
	// 从第二行开始的数据
	dataCells := make([]map[string]any, 0)
	for i, row := range rows {
		idx := strconv.Itoa(i + 2)

		// 原始严重程度
		origSeverity := "-"
		for _, v := range dictActiveAlarmSeverity {
			if row.OrigSeverity == v.DataValue {
				origSeverity = i18n.TKey(language, v.DataLabel)
				break
			}
		}
		// 活动告警类型
		alarmType := "-"
		for _, v := range dictActiveAlarmType {
			if row.AlarmType == v.DataValue {
				alarmType = i18n.TKey(language, v.DataLabel)
				break
			}
		}
		// 告警清除类型
		clearType := "-"
		for _, v := range dictActiveClearType {
			if fmt.Sprint(row.ClearType) == v.DataValue {
				clearType = i18n.TKey(language, v.DataLabel)
				break
			}
		}
		eventTimeStr := date.ParseDateToStr(row.EventTime, date.YYYY_MM_DDTHH_MM_SSZ)

		cells := map[string]any{
			"A" + idx: alarmType,
			"B" + idx: origSeverity,
			"C" + idx: row.AlarmTitle,
			"D" + idx: eventTimeStr,
			"E" + idx: row.AlarmId,
			"F" + idx: row.AlarmCode,
			"G" + idx: row.NeType,
			"H" + idx: row.NeName,
			"I" + idx: row.NeId,
		}
		if alarmStatus == "0" {
			clearTimeStr := date.ParseDateToStr(row.ClearTime, date.YYYY_MM_DDTHH_MM_SSZ)
			cells["J"+idx] = row.ClearUser
			cells["K"+idx] = clearType
			cells["L"+idx] = clearTimeStr
		}
		dataCells = append(dataCells, cells)
	}

	// 导出数据表格
	return file.WriteSheet(headerCells, dataCells, fileName, "")
}
