package backup_export_udm

import (
	"encoding/json"
	"fmt"
	"path/filepath"
	"runtime"
	"time"

	"be.ems/src/framework/cron"
	"be.ems/src/framework/logger"
	"be.ems/src/framework/utils/file"
	neModel "be.ems/src/modules/ne/model"
	neService "be.ems/src/modules/ne/service"
	neDataModel "be.ems/src/modules/ne_data/model"
	neDataService "be.ems/src/modules/ne_data/service"
)

var NewProcessor = &BackupExportUDMProcessor{
	count:              0,
	neInfoService:      neService.NewNeInfo,
	backupService:      neDataService.NewBackup,
	udmAuthService:     neDataService.NewUDMAuthUser,
	udmSubService:      neDataService.NewUDMSubUser,
	udmVOIPService:     neDataService.NewUDMVOIPUser,
	udmVolteIMSService: neDataService.NewUDMVolteIMSUser,
}

// BackupExportUDM 队列任务处理
type BackupExportUDMProcessor struct {
	count              int                            // 执行次数
	neInfoService      *neService.NeInfo              // 网元信息服务
	backupService      *neDataService.Backup          // 备份相关服务
	udmAuthService     *neDataService.UDMAuthUser     // UDM鉴权信息服务
	udmSubService      *neDataService.UDMSubUser      // UDM签约信息服务
	udmVOIPService     *neDataService.UDMVOIPUser     // UDMVOIP信息服务
	udmVolteIMSService *neDataService.UDMVolteIMSUser // UDMVolteIMS信息服务
}

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

	var params struct {
		DataType []string `json:"dataType"` // 类型支持 auth/sub/voip/volte
		FileType string   `json:"fileType"` // 文件类型 csv/txt
	}
	if err := json.Unmarshal([]byte(sysJob.TargetParams), &params); err != nil {
		return nil, err
	}
	if !(params.FileType == "csv" || params.FileType == "txt") {
		return nil, fmt.Errorf("file type error, only support csv,txt")
	}

	neList := s.neInfoService.Find(neModel.NeInfo{NeType: "UDM"}, false, false)
	for _, neInfo := range neList {
		for _, v := range params.DataType {
			switch v {
			case "auth":
				result[fmt.Sprintf("%s-%s", neInfo.NeId, v)] = s.exportAuth(neInfo.NeId, params.FileType)
			case "sub":
				result[fmt.Sprintf("%s-%s", neInfo.NeId, v)] = s.exportSub(neInfo.NeId, params.FileType)
			case "voip":
				result[fmt.Sprintf("%s-%s", neInfo.NeId, v)] = s.exportVOIP(neInfo.NeId, params.FileType)
			case "volte":
				result[fmt.Sprintf("%s-%s", neInfo.NeId, v)] = s.exportVolte(neInfo.NeId, params.FileType)
			}
		}
	}

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

// exportAuth 导出鉴权用户数据
func (s BackupExportUDMProcessor) exportAuth(neId, fileType string) string {
	rows := s.udmAuthService.Find(neDataModel.UDMAuthUser{NeId: neId})
	if len(rows) <= 0 {
		return "no data"
	}

	// 导出文件名称
	dateStr := time.Now().Format("20060102150405")
	fileName := fmt.Sprintf("auth_%s_export_%d_%s.%s", neId, len(rows), dateStr, fileType)
	filePath := filepath.Join(s.backupService.BACKUP_DIR, "/udm/auth", fileName)
	if runtime.GOOS == "windows" {
		filePath = fmt.Sprintf("C:%s", filePath)
	}

	if fileType == "csv" {
		// 转换数据
		data := [][]string{}
		data = append(data, []string{"imsi", "ki", "algo", "amf", "opc"})
		for _, v := range rows {
			opc := v.Opc
			if opc == "-" {
				opc = ""
			}
			data = append(data, []string{v.IMSI, v.Ki, v.AlgoIndex, v.Amf, opc})
		}
		// 输出到文件
		if err := file.WriterFileCSV(data, filePath); err != nil {
			return err.Error()
		}
	}

	if fileType == "txt" {
		// 转换数据
		data := [][]string{}
		for _, v := range rows {
			opc := v.Opc
			if opc == "-" {
				opc = ""
			}
			data = append(data, []string{v.IMSI, v.Ki, v.AlgoIndex, v.Amf, opc})
		}
		// 输出到文件
		if err := file.WriterFileTXTLine(data, ",", filePath); err != nil {
			return err.Error()
		}
	}

	// 上传到FTP服务器
	if err := s.backupService.FTPPushFile(filePath, "udm_data"); err != nil {
		return "ok, ftp err:" + err.Error()
	}
	return "ok"
}

// exportSub 导出签约用户数据
func (s BackupExportUDMProcessor) exportSub(neId, fileType string) string {
	rows := s.udmSubService.Find(neDataModel.UDMSubUser{NeId: neId})
	if len(rows) <= 0 {
		return "no data"
	}

	// 导出文件名称
	dateStr := time.Now().Format("20060102150405")
	fileName := fmt.Sprintf("sub_%s_export_%d_%s.%s", neId, len(rows), dateStr, fileType)
	filePath := filepath.Join(s.backupService.BACKUP_DIR, "/udm/sub", fileName)
	if runtime.GOOS == "windows" {
		filePath = fmt.Sprintf("C:%s", filePath)
	}

	if fileType == "csv" {
		// 转换数据
		data := [][]string{}
		data = append(data, []string{"IMSI", "MSISDN", "UeAmbrTpl", "NssaiTpl", "AreaForbiddenTpl", "ServiceAreaRestrictionTpl", "RatRestrictions", "CnTypeRestrictions", "SmfSel", "SmData", "EPSDat"})
		for _, v := range rows {
			epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
			data = append(data, []string{v.IMSI, v.MSISDN, v.UeAmbrTpl, v.NssaiTpl, v.AreaForbiddenTpl, v.ServiceAreaRestrictionTpl, v.RatRestrictions, v.CnTypeRestrictions, v.SmfSel, v.SmData, epsDat})
		}
		// 输出到文件
		if err := file.WriterFileCSV(data, filePath); err != nil {
			return err.Error()
		}
	}

	if fileType == "txt" {
		// 转换数据
		data := [][]string{}
		for _, v := range rows {
			epsDat := fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s", v.EpsFlag, v.EpsOdb, v.HplmnOdb, v.Ard, v.Epstpl, v.ContextId, v.ApnContext, v.StaticIp)
			data = append(data, []string{v.IMSI, v.MSISDN, v.UeAmbrTpl, v.NssaiTpl, v.AreaForbiddenTpl, v.ServiceAreaRestrictionTpl, v.RatRestrictions, v.CnTypeRestrictions, v.SmfSel, v.SmData, epsDat})
		}
		// 输出到文件
		if err := file.WriterFileTXTLine(data, ",", filePath); err != nil {
			return err.Error()
		}
	}

	// 上传到FTP服务器
	if err := s.backupService.FTPPushFile(filePath, "udm_data"); err != nil {
		return "ok, ftp err:" + err.Error()
	}
	return "ok"
}

// exportVOIP 导出VOIP用户数据
func (s BackupExportUDMProcessor) exportVOIP(neId, fileType string) string {
	rows := s.udmVOIPService.Find(neDataModel.UDMVOIPUser{NeId: neId})
	if len(rows) <= 0 {
		return "no data"
	}

	// 导出文件名称
	dateStr := time.Now().Format("20060102150405")
	fileName := fmt.Sprintf("voip_%s_export_%d_%s.%s", neId, len(rows), dateStr, fileType)
	filePath := filepath.Join(s.backupService.BACKUP_DIR, "/udm/voip", fileName)
	if runtime.GOOS == "windows" {
		filePath = fmt.Sprintf("C:%s", filePath)
	}

	if fileType == "csv" {
		// 转换数据
		data := [][]string{}
		data = append(data, []string{"username", "password"})
		for _, v := range rows {
			data = append(data, []string{v.UserName, v.Password})
		}
		// 输出到文件
		if err := file.WriterFileCSV(data, filePath); err != nil {
			return err.Error()
		}
	}

	if fileType == "txt" {
		// 转换数据
		data := [][]string{}
		for _, v := range rows {
			data = append(data, []string{v.UserName, v.Password})
		}
		// 输出到文件
		if err := file.WriterFileTXTLine(data, ",", filePath); err != nil {
			return err.Error()
		}
	}

	// 上传到FTP服务器
	if err := s.backupService.FTPPushFile(filePath, "udm_data"); err != nil {
		return "ok, ftp err:" + err.Error()
	}
	return "ok"
}

// exportVolte 导出Volte用户数据
func (s BackupExportUDMProcessor) exportVolte(neId, fileType string) string {
	rows := s.udmVolteIMSService.Find(neDataModel.UDMVolteIMSUser{NeId: neId})
	if len(rows) <= 0 {
		return "no data"
	}

	// 导出文件名称
	dateStr := time.Now().Format("20060102150405")
	fileName := fmt.Sprintf("volte_%s_export_%d_%s.%s", neId, len(rows), dateStr, fileType)
	filePath := filepath.Join(s.backupService.BACKUP_DIR, "/udm/volte", fileName)
	if runtime.GOOS == "windows" {
		filePath = fmt.Sprintf("C:%s", filePath)
	}

	if fileType == "csv" {
		// 转换数据
		data := [][]string{}
		data = append(data, []string{"IMSI", "MSISDN", "TAG", "VNI"})
		for _, v := range rows {
			data = append(data, []string{v.IMSI, v.MSISDN, v.Tag, v.VNI})
		}
		// 输出到文件
		if err := file.WriterFileCSV(data, filePath); err != nil {
			return err.Error()
		}
	}

	if fileType == "txt" {
		// 转换数据
		data := [][]string{}
		for _, v := range rows {
			data = append(data, []string{v.IMSI, v.MSISDN, v.Tag, v.VNI})
		}
		// 输出到文件
		if err := file.WriterFileTXTLine(data, ",", filePath); err != nil {
			return err.Error()
		}
	}

	// 上传到FTP服务器
	if err := s.backupService.FTPPushFile(filePath, "udm_data"); err != nil {
		return "ok, ftp err:" + err.Error()
	}
	return "ok"
}
