package service

import (
	"encoding/json"
	"fmt"
	"strings"

	"be.ems/src/framework/constants/cachekey"
	"be.ems/src/framework/redis"
	"be.ems/src/modules/network_element/model"
	"be.ems/src/modules/network_element/repository"
)

// 实例化服务层 NeInfoImpl 结构体
var NewNeInfoImpl = &NeInfoImpl{
	neInfoRepository: repository.NewNeInfoImpl,
	neHostRepository: repository.NewNeHostImpl,
}

// 网元信息 服务层处理
type NeInfoImpl struct {
	// 网元信息数据信息
	neInfoRepository repository.INeInfo
	// 网元主机连接表
	neHostRepository repository.INeHost
}

// SelectNeInfoByNeTypeAndNeID 通过ne_type和ne_id查询网元信息
func (r *NeInfoImpl) SelectNeInfoByNeTypeAndNeID(neType, neID string) model.NeInfo {
	var neInfo model.NeInfo
	key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, neType, neID)
	jsonStr, _ := redis.Get("", key)
	if len(jsonStr) > 7 {
		err := json.Unmarshal([]byte(jsonStr), &neInfo)
		if err != nil {
			neInfo = model.NeInfo{}
		}
	} else {
		neInfo = r.neInfoRepository.SelectNeInfoByNeTypeAndNeID(neType, neID)
		if neInfo.NeId == neID {
			redis.Del("", key)
			values, _ := json.Marshal(neInfo)
			redis.Set("", key, string(values))
		}
	}
	return neInfo
}

// RefreshByNeTypeAndNeID 通过ne_type和ne_id刷新redis中的缓存
func (r *NeInfoImpl) RefreshByNeTypeAndNeID(neType, neID string) model.NeInfo {
	var neInfo model.NeInfo
	key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, neType, neID)
	redis.Del("", key)
	neInfo = r.neInfoRepository.SelectNeInfoByNeTypeAndNeID(neType, neID)
	if neInfo.NeId == neID {
		values, _ := json.Marshal(neInfo)
		redis.Set("", key, string(values))
	}
	return neInfo
}

// ClearNeCacheByNeType 清除网元类型缓存
func (r *NeInfoImpl) ClearNeCacheByNeType(neType string) bool {
	key := fmt.Sprintf("%s*", cachekey.NE_KEY)
	if neType != "*" {
		key = fmt.Sprintf("%s%s*", cachekey.NE_KEY, neType)
	}
	keys, err := redis.GetKeys("", key)
	if err != nil {
		return false
	}
	delOk, _ := redis.DelKeys("", keys)
	return delOk
}

// SelectNeInfoByRmuid 通过rmUID查询网元信息
func (r *NeInfoImpl) SelectNeInfoByRmuid(rmUid string) model.NeInfo {
	var neInfo model.NeInfo
	cacheKeys, _ := redis.GetKeys("", cachekey.NE_KEY+"*")
	if len(cacheKeys) > 0 {
		for _, key := range cacheKeys {
			var v model.NeInfo
			jsonStr, _ := redis.Get("", key)
			if len(jsonStr) > 7 {
				json.Unmarshal([]byte(jsonStr), &v)
			}
			if v.RmUID == rmUid {
				neInfo = v
				break
			}
		}
	} else {
		neInfos := r.SelectList(neInfo, false)
		for _, v := range neInfos {
			key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, v.NeType, v.NeId)
			redis.Del("", key)
			values, _ := json.Marshal(v)
			redis.Set("", key, string(values))
			if v.RmUID == rmUid {
				neInfo = v
			}
		}
	}
	return neInfo
}

// SelectPage 根据条件分页查询
//
// bandStatus 带状态信息
func (r *NeInfoImpl) SelectPage(query map[string]any, bandStatus bool) map[string]any {
	data := r.neInfoRepository.SelectPage(query)

	// 网元直连读取网元服务状态
	if bandStatus {
		rows := data["rows"].([]model.NeInfo)
		arr := &rows
		for i := range *arr {
			v := (*arr)[i]
			result, err := NeState(v)
			if err != nil {
				(*arr)[i].ServerState = map[string]any{
					"online": false,
				}
				// 网元状态设置为离线
				if v.Status != "1" {
					v.Status = "1"
					r.neInfoRepository.Update(v)
				}
				continue
			}
			result["online"] = true
			(*arr)[i].ServerState = result
			// 网元状态设置为在线
			if v.Status != "0" {
				// 下发网管配置信息给网元
				_, err = NeConfigOMC(v)
				if err != nil {
					v.Status = "3"
				} else {
					v.Status = "0"
				}
				r.neInfoRepository.Update(v)
			}
		}
	}

	return data
}

// SelectList 查询列表
//
// bandStatus 带状态信息
func (r *NeInfoImpl) SelectList(ne model.NeInfo, bandStatus bool) []model.NeInfo {
	list := r.neInfoRepository.SelectList(ne)

	// 网元直连读取网元服务状态
	if bandStatus {
		neList := &list
		for i := range *neList {
			v := (*neList)[i]
			result, err := NeState(v)
			if err != nil {
				(*neList)[i].ServerState = map[string]any{
					"online": false,
				}
				// 网元状态设置为离线
				if v.Status != "1" {
					v.Status = "1"
					r.neInfoRepository.Update(v)
				}
				continue
			}
			result["online"] = true
			(*neList)[i].ServerState = result
			// 网元状态设置为在线
			if v.Status != "0" {
				// 下发网管配置信息给网元
				_, err = NeConfigOMC(v)
				if err != nil {
					v.Status = "3"
				} else {
					v.Status = "0"
				}
				r.neInfoRepository.Update(v)
			}
		}
	}

	return list
}

// SelectByIds 通过ID查询
//
// bandStatus 带主机信息
func (r *NeInfoImpl) SelectById(infoId string, bandHost bool) model.NeInfo {
	if infoId == "" {
		return model.NeInfo{}
	}
	neInfos := r.neInfoRepository.SelectByIds([]string{infoId})
	if len(neInfos) > 0 {
		neInfo := neInfos[0]
		// 带主机信息
		if neInfo.HostIDs != "" && bandHost {
			neInfo.Hosts = r.neHostRepository.SelectByIds(strings.Split(neInfo.HostIDs, ","))
		}
		return neInfo
	}
	return model.NeInfo{}
}

// Insert 新增信息
func (r *NeInfoImpl) Insert(neInfo model.NeInfo) string {
	// 主机信息新增
	if neInfo.Hosts != nil {
		var hostIDs []string
		for _, host := range neInfo.Hosts {
			host.Title = fmt.Sprintf("%s_%s_%d", strings.ToUpper(neInfo.NeType), neInfo.NeId, host.Port)
			host.GroupID = "1"
			hostId := r.neHostRepository.Insert(host)
			if hostId != "" {
				hostIDs = append(hostIDs, hostId)
			}
		}
		neInfo.HostIDs = strings.Join(hostIDs, ",")
	}

	insertId := r.neInfoRepository.Insert(neInfo)
	if insertId != "" {
		// 刷新缓存
		r.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
	}
	return insertId
}

// Update 修改信息
func (r *NeInfoImpl) Update(neInfo model.NeInfo) int64 {
	// 主机信息更新
	if neInfo.Hosts != nil {
		for _, host := range neInfo.Hosts {
			if host.HostID != "" {
				host.Title = fmt.Sprintf("%s_%s_%d", strings.ToUpper(neInfo.NeType), neInfo.NeId, host.Port)
				host.GroupID = "1"
				r.neHostRepository.Update(host)
			}
		}
	}

	num := r.neInfoRepository.Update(neInfo)
	if num > 0 {
		// 刷新缓存
		r.RefreshByNeTypeAndNeID(neInfo.NeType, neInfo.NeId)
	}
	return num
}

// DeleteByIds 批量删除信息
func (r *NeInfoImpl) DeleteByIds(infoIds []string) (int64, error) {
	// 检查是否存在
	infos := r.neInfoRepository.SelectByIds(infoIds)
	if len(infos) <= 0 {
		return 0, fmt.Errorf("neHostCmd.noData")
	}

	if len(infos) == len(infoIds) {
		for _, v := range infos {
			// 主机信息删除
			if v.HostIDs != "" {
				hostIds := strings.Split(v.HostIDs, ",")
				r.neHostRepository.DeleteByIds(hostIds)
			}
			// 缓存信息删除
			key := fmt.Sprintf("%s%s:%s", cachekey.NE_KEY, v.NeType, v.NeId)
			redis.Del("", key)
		}
		rows := r.neInfoRepository.DeleteByIds(infoIds)
		return rows, nil
	}
	// 删除信息失败！
	return 0, fmt.Errorf("delete fail")
}

// CheckUniqueNeTypeAndNeId 校验同类型下标识是否唯一
func (r *NeInfoImpl) CheckUniqueNeTypeAndNeId(neType, neId, infoId string) bool {
	uniqueId := r.neInfoRepository.CheckUniqueNeTypeAndNeId(model.NeInfo{
		NeType: neType,
		NeId:   neId,
	})
	if uniqueId == infoId {
		return true
	}
	return uniqueId == ""
}
