package main

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"

	cmschema "ems.agt/crontask/cm/schema"
	"ems.agt/lib/dborm"
	"ems.agt/lib/global"
	"ems.agt/lib/log"

	"gopkg.in/yaml.v3"
)

const (
	// Header is a generic XML header suitable for use with the output of Marshal.
	// This is not automatically added to any output of this package,
	// it is provided as a convenience.
	Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
)

const (
	AdminStateLocked       = "Locked"
	AdminStateUnlocked     = "Unlocked"
	AdminStateShuttingdown = "ShuttingDown"
	OperationStateDisabled = "Disabled"
	OperationStateEnabled  = "Enabled"
)

func (t *TaskFunc) GenCmXmlFile(uri, params, body string) {
	log.Debug("GenCmXmlFile processing ...")
	for _, neType := range neTypes {
		t.GenNFXmlFile(neType)
	}
}

func (t *TaskFunc) ReadCmYaml(cmfile string) (map[string]interface{}, error) {
	log.Debug("cmfile:", cmfile)
	file, err := os.ReadFile(cmfile)
	if err != nil {
		log.Error(err)
		return nil, err
	}
	log.Debug("file:", file)
	resultMap := make(map[string]interface{})
	err = yaml.Unmarshal(file, resultMap)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	log.Debug("resultMap:", resultMap)
	return resultMap, nil
}

func (t *TaskFunc) GenNFXmlFile(neType string) error {
	log.Info("GenNFXmlFile processing...")

	var nes []NeInfo
	_, err := XormGetNeInfoByType(neType, &nes)
	if err != nil {
		log.Error("Failed to get all ne info:", err)
		return err
	}

	cmfile := fmt.Sprintf("%s/cm-%s.yaml", yamlConfig.NBI.CM.CfgFileDir, strings.ToLower(neType))

	resultMap, _ := t.ReadCmYaml(cmfile)

	ti := time.Now()
	timestamp := ti.Format("2006-01-02 15:04:05")
	timefile := ti.Format("20060102150405")
	date := ti.Format("20060102")
	_, offset := ti.Zone()
	var tzOffset string
	if offset >= 0 {
		tzOffset = "UTC+" + strconv.Itoa(offset/3600)
	} else {
		tzOffset = "UTC" + strconv.Itoa(offset/3600)
	}

	nrmFile := new(cmschema.DataFile)
	//创建目录
	path := fmt.Sprintf("%s/HX/%s/%s/CM/%s", yamlConfig.OMC.Province, yamlConfig.OMC.Vendor, yamlConfig.OMC.Name, date)
	folderPath := global.CreateDir(path, yamlConfig.NBI.CM.XmlFileDir)

	nrmFile.FileHeader = cmschema.FileHeader{
		TimeStamp:   timestamp,
		TimeZone:    tzOffset,
		VendorName:  yamlConfig.OMC.Vendor,
		ElementType: neType,
		CmVersion:   yamlConfig.NBI.CM.Version,
	}

	nrmFile.XsiAttr = "http://www.w3.org/2001/XMLSchema-instance"
	nrmFile.XsiLoc = "file:///usr/loal/omc/etc/schema/cm-schema.xsd"

	for objectType, e := range resultMap {
		//objects := cmschema.Objects{ObjectType: objectType}
		objectData := cmschema.ObjectData{ObjectType: objectType}

		sortResult := make(map[string]string)
		keys := make([]string, 0)
		for key, value := range e.(map[string]interface{}) {
			sortResult[key] = fmt.Sprintf("%v", value)
			keys = append(keys, key)
		}

		sort.Strings(keys)
		for s, ne := range nes {
			cmResult, err := dborm.XormGetNorthboundCmLatestObject(neType, ne.NeId, objectType)
			if err != nil {
				log.Error("Failed to XormGetNorthboundCmLatestObject:", err)
				continue
			}
			log.Trace("cmResult:", cmResult)
			//dataMap := make(map[string]interface{})
			valueMap := make(map[string]interface{})
			if cmResult.ValueJSON != "" {
				err = json.Unmarshal([]byte(cmResult.ValueJSON), &valueMap)
				if err != nil {
					log.Error("Failed to json.Unmarshal:", err)
					continue
				}
			}

			log.Trace("valueMap:", valueMap)
			rmUID := ne.RmUID
			var object cmschema.Object
			if ne.PvFlag == "VNF" {
				vmId := fmt.Sprintf("kylin10.0-00%d-%s", s+1, neType)
				vnfInstanceID := fmt.Sprintf("2%xd55b4-%d018-41f4-af%d5-28b%d828788", s+10, s+6, s+4, s+3)
				object = cmschema.Object{RmUIDAttr: rmUID,
					DnAttr:        "DC=www.ruijie.com.cn,SubNetwork=10001,SubNetwork=114214,ManagedElement=325",
					UserLabelAttr: ne.NeName, PVFlagAttr: ne.PvFlag, VMIDAttr: vmId, VNFInstanceIDAttr: vnfInstanceID}
			} else {
				object = cmschema.Object{RmUIDAttr: rmUID,
					DnAttr:        "DC=www.ruijie.com.cn,SubNetwork=10001,SubNetwork=114214,ManagedElement=325",
					UserLabelAttr: ne.NeName, PVFlagAttr: ne.PvFlag}
			}

			i := 1
			for _, p := range keys {
				if s == 0 {
					//objects.FieldName.N = append(objects.FieldName.N, cmschema.N{IAttr: i, Value: p})
					objectData.FieldName.N = append(objectData.FieldName.N, cmschema.N{IAttr: i, Value: p})
				}
				var v string
				if valueMap[p] == nil || valueMap[p] == "" {
					v = "-"
				} else {
					v = fmt.Sprintf("%v", valueMap[p])
				}

				object.V = append(object.V, cmschema.V{IAttr: i, Value: v})
				i++
			}
			//objects.FieldValue.Object = append(objects.FieldValue.Object, object)
			objectData.FieldValue.Object = append(objectData.FieldValue.Object, object)
		}
		//nrmFile.Objects = append(nrmFile.Objects, objects)
		nrmFile.ObjectData = objectData

		x, _ := xml.MarshalIndent(nrmFile, "", "	")
		x = append([]byte(xml.Header), x...)

		xmlfile := fmt.Sprintf("%s/%s-CM-%s-%s-%s-%s-%s-001.xml",
			folderPath, yamlConfig.OMC.Province, neType, objectType, yamlConfig.OMC.HostNo, yamlConfig.NBI.CM.Version, timefile)
		tmpXmlfile := xmlfile + ".tmp"
		err := os.WriteFile(tmpXmlfile, x, 0664)
		if err != nil {
			log.Error("Failed to WriteFile xml file:", err)
			continue
		}
		err = os.Rename(tmpXmlfile, xmlfile)
		if err != nil {
			log.Error("Failed to Rename xml file:", err)
			continue
		}
		zipFile := xmlfile + ".zip"
		err = global.ZipOneFile(xmlfile, zipFile, false)
		if err != nil {
			log.Error("Failed to ZipOneFile:", err)
			continue
		}
		err = os.Remove(xmlfile)
		if err != nil {
			log.Error("Failed to delete file:", err)
			continue
		}
	}

	return nil
}
