package flattens

import (
	"context"
	"fmt"

	"github.com/google/uuid"
	"github.com/hashicorp/terraform-plugin-framework/diag"
	"github.com/hashicorp/terraform-plugin-framework/types"
	"github.com/hashicorp/terraform-plugin-log/tflog"
	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vins"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/flattens"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vins/models"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/vins/utilities"
)

// VINSDataSource flattens data source for vins.
// Return error in case data source is not found on the platform.
// Flatten errors are added to tflog.
func VINSDataSource(ctx context.Context, state *models.DataSourceVINSModel, c *client.Client) diag.Diagnostics {
	tflog.Info(ctx, "Start flattens.VINSDataSource")

	diags := diag.Diagnostics{}

	vinsId := uint64(state.VinsID.ValueInt64())

	recordVins, diags := utilities.VINSDataSourceCheckPresence(ctx, vinsId, c)
	if diags.HasError() {
		return diags
	}

	tflog.Info(ctx, "flattens.VINSDataSource: before flatten", map[string]any{"vins_id": vinsId})

	id := uuid.New()
	*state = models.DataSourceVINSModel{
		VinsID: state.VinsID,

		Timeouts: state.Timeouts,

		VNFDev:             flattenVNFDev(ctx, &recordVins.VNFDev),
		AccountID:          types.Int64Value(int64(recordVins.AccountID)),
		AccountName:        types.StringValue(recordVins.AccountName),
		CreatedBy:          types.StringValue(recordVins.CreatedBy),
		CreatedTime:        types.Int64Value(int64(recordVins.CreatedTime)),
		DefaultGW:          types.StringValue(recordVins.DefaultGW),
		DefaultQOS:         flattenQOS(ctx, &recordVins.DefaultQOS),
		DeletedBy:          types.StringValue(recordVins.DeletedBy),
		DeletedTime:        types.Int64Value(int64(recordVins.DeletedTime)),
		Description:        types.StringValue(recordVins.Description),
		GID:                types.Int64Value(int64(recordVins.GID)),
		GUID:               types.Int64Value(int64(recordVins.GUID)),
		Id:                 types.StringValue(id.String()),
		LockStatus:         types.StringValue(recordVins.LockStatus),
		ManagerID:          types.Int64Value(int64(recordVins.ManagerID)),
		ManagerType:        types.StringValue(recordVins.ManagerType),
		Milestones:         types.Int64Value(int64(recordVins.Milestones)),
		Name:               types.StringValue(recordVins.Name),
		NetMask:            types.Int64Value(int64(recordVins.NetMask)),
		Network:            types.StringValue(recordVins.Network),
		PreReservationsNum: types.Int64Value(int64(recordVins.PreReservationsNum)),
		Redundant:          types.BoolValue(recordVins.Redundant),
		RGID:               types.Int64Value(int64(recordVins.RGID)),
		RGName:             types.StringValue(recordVins.RGName),
		SecVNFDevID:        types.Int64Value(int64(recordVins.SecVNFDevID)),
		Status:             types.StringValue(recordVins.Status),
		UpdatedBy:          types.StringValue(recordVins.UpdatedBy),
		UpdatedTime:        types.Int64Value(int64(recordVins.UpdatedTime)),
		UserManaged:        types.BoolValue(recordVins.UserManaged),
		VNFs:               flattenVNFs(ctx, &recordVins.VNFs),
		VXLANID:            types.Int64Value(int64(recordVins.VXLANID)),
	}

	tflog.Info(ctx, "flattens.VINSDataSource: after flatten", map[string]any{"vins_id": state.Id.ValueString()})

	tflog.Info(ctx, "End flattens.VINSDataSource", map[string]any{"vins_id": state.Id.ValueString()})
	return nil
}

// flattenVNFDev flattens vnfdev.
// Flatten errors are added to tflog.
func flattenVNFDev(ctx context.Context, vnfdev *vins.VNFDev) types.Object {
	tflog.Info(ctx, "Start flattenVNFDev")

	temp := models.RecordVNFDevModel{
		CKey:            types.StringValue(vnfdev.CKey),
		AccountID:       types.Int64Value(int64(vnfdev.AccountID)),
		Capabilities:    flattens.FlattenSimpleTypeToList(ctx, types.StringType, &vnfdev.Capabilities),
		Config:          flattenVNFDevConfig(ctx, &vnfdev.Config),
		ConfigSaved:     types.BoolValue(vnfdev.ConfigSaved),
		CustomPreConfig: types.BoolValue(vnfdev.CustomPreConfig),
		Description:     types.StringValue(vnfdev.Description),
		GID:             types.Int64Value(int64(vnfdev.GID)),
		GUID:            types.Int64Value(int64(vnfdev.GUID)),
		ID:              types.Int64Value(int64(vnfdev.ID)),
		Interfaces:      flattenInterfaces(ctx, &vnfdev.Interfaces),
		LockStatus:      types.StringValue(vnfdev.LockStatus),
		Meta:            flattens.FlattenSimpleTypeToList(ctx, types.StringType, &vnfdev.Meta),
		Milestones:      types.Int64Value(int64(vnfdev.Milestones)),
		Name:            types.StringValue(vnfdev.Name),
		Status:          types.StringValue(vnfdev.Status),
		TechStatus:      types.StringValue(vnfdev.TechStatus),
		Type:            types.StringValue(vnfdev.Type),
		VNCPassword:     types.StringValue(vnfdev.VNCPassword),
		VINS:            flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &vnfdev.VINS),
	}

	res, err := types.ObjectValueFrom(ctx, models.ItemVNFDev, temp)
	if err != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenVNFDev struct to obj", err))
	}

	tflog.Info(ctx, "End flattenVNFDev")
	return res
}

// flattenVNFDevConfig flattens config.
// Flatten errors are added to tflog.
func flattenVNFDevConfig(ctx context.Context, config *vins.Config) types.Object {
	tflog.Info(ctx, "Start flattenVNFDevConfig")

	temp := models.RecordVNFConfigModel{
		MGMT:      flattenMgmtVNFConfig(ctx, &config.MGMT),
		Resources: flattenResourcesVNFConfig(ctx, &config.Resources),
	}

	res, err := types.ObjectValueFrom(ctx, models.ItemVNFConfig, temp)
	if err != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenVNFDevConfig struct to obj", err))
	}

	tflog.Info(ctx, "End flattenVNFDevConfig")
	return res
}

// flattenMgmtVNFConfig flattens mgmt.
// Flatten errors are added to tflog.
func flattenMgmtVNFConfig(ctx context.Context, mgmt *vins.MGMT) types.Object {
	tflog.Info(ctx, "Start flattenMgmtVNFConfig")

	temp := models.RecordMGMTModel{
		IPAddress: types.StringValue(mgmt.IPAddress),
		Password:  types.StringValue(mgmt.Password),
		SSHKey:    types.StringValue(mgmt.SSHKey),
		User:      types.StringValue(mgmt.User),
	}

	res, err := types.ObjectValueFrom(ctx, models.ItemMgmt, temp)
	if err != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenMgmtVNFConfig struct to obj", err))
	}

	tflog.Info(ctx, "End flattenMgmtVNFConfig")
	return res
}

// flattenResourcesVNFConfig flattens resources.
// Flatten errors are added to tflog.
func flattenResourcesVNFConfig(ctx context.Context, resources *vins.Resources) types.Object {
	tflog.Info(ctx, "Start flattenResourcesVNFConfig")

	temp := models.RecordResourcesModel{
		CPU:     types.Int64Value(int64(resources.CPU)),
		RAM:     types.Int64Value(int64(resources.RAM)),
		StackID: types.Int64Value(int64(resources.StackID)),
		UUID:    types.StringValue(resources.UUID),
	}

	res, err := types.ObjectValueFrom(ctx, models.ItemResources, temp)
	if err != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenResourcesVNFConfig struct to obj", err))
	}

	tflog.Info(ctx, "End flattenResourcesVNFConfig")
	return res
}

// flattenInterfaces flattens interfaces.
// Flatten errors are added to tflog.
func flattenInterfaces(ctx context.Context, items *vins.ListInterfaces) types.List {
	tflog.Info(ctx, "Start flattenInterfaces")
	diags := diag.Diagnostics{}

	tempSlice := make([]types.Object, 0, len(*items))
	for _, item := range *items {
		temp := models.VNFInterfaceModel{
			ConnID:      types.Int64Value(int64(item.ConnID)),
			ConnType:    types.StringValue(item.ConnType),
			DefGW:       types.StringValue(item.DefGW),
			Enabled:     types.BoolValue(item.Enabled),
			FLIPGroupID: types.Int64Value(int64(item.FLIPGroupID)),
			GUID:        types.StringValue(item.GUID),
			IPAddress:   types.StringValue(item.IPAddress),
			ListenSSH:   types.BoolValue(item.ListenSSH),
			MAC:         types.StringValue(item.MAC),
			Name:        types.StringValue(item.Name),
			NetID:       types.Int64Value(int64(item.NetID)),
			NetMask:     types.Int64Value(int64(item.NetMask)),
			NetType:     types.StringValue(item.NetType),
			NodeID:      types.Int64Value(int64(item.NodeID)),
			PCISlot:     types.Int64Value(int64(item.PCISlot)),
			QOS:         flattenQOS(ctx, &item.QOS),
			Target:      types.StringValue(item.Target),
			Type:        types.StringValue(item.Type),
		}

		temp.VNFs, diags = types.ListValueFrom(ctx, types.Int64Type, item.VNFs)
		if diags.HasError() {
			tflog.Error(ctx, fmt.Sprint("flattens.flattenInterfaces: cannot flatten item.VNFs to temp.VNFs", diags))
		}

		obj, err := types.ObjectValueFrom(ctx, models.ItemInterface, temp)
		if err != nil {
			tflog.Error(ctx, fmt.Sprint("Error flattenInterfaces struct to obj", err))
		}
		tempSlice = append(tempSlice, obj)
	}

	res, err := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: models.ItemInterface}, tempSlice)
	if err != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenInterfaces", err))
	}

	tflog.Info(ctx, "End flattenInterfaces")
	return res
}

// flattenQOS flattens QOS.
// Flatten errors are added to tflog.
func flattenQOS(ctx context.Context, qos *vins.QOS) types.Object {
	tflog.Info(ctx, "Start flattenQOS")

	temp := models.QOSModel{
		ERate:   types.Int64Value(int64(qos.ERate)),
		GUID:    types.StringValue(qos.GUID),
		InBurst: types.Int64Value(int64(qos.InBurst)),
		InRate:  types.Int64Value(int64(qos.InRate)),
	}

	res, err := types.ObjectValueFrom(ctx, models.ItemQOS, temp)
	if err != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenQOS struct to obj", err))
	}

	tflog.Info(ctx, "End flattenQOS")
	return res
}

// flattenVNFs flattens vnfs.
func flattenVNFs(ctx context.Context, vnfs *vins.RecordVNFs) types.Object {
	tflog.Info(ctx, "Start flattenVNFs")

	temp := models.RecordVNFsModel{
		DHCP: flattenDHCP(ctx, &vnfs.DHCP),
		GW:   flattenGW(ctx, &vnfs.GW),
		NAT:  flattenNAT(ctx, &vnfs.NAT),
	}

	res, err := types.ObjectValueFrom(ctx, models.ItemVNFs, temp)
	if err != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenVNFs struct to obj", err))
	}

	tflog.Info(ctx, "End flattenVNFs")
	return res
}

// flattenDHCP flattens dhcp.
// Flatten errors are added to tflog.
func flattenDHCP(ctx context.Context, dhcp *vins.RecordDHCP) types.Object {
	tflog.Info(ctx, "Start flattenDHCP")

	temp := models.RecordDHCPModel{
		CKey:        types.StringValue(dhcp.CKey),
		AccountID:   types.Int64Value(int64(dhcp.AccountID)),
		Config:      flattenDHCPConfig(ctx, &dhcp.Config),
		CreatedTime: types.Int64Value(int64(dhcp.CreatedTime)),
		Devices:     flattenDevices(ctx, &dhcp.Devices),
		GID:         types.Int64Value(int64(dhcp.GID)),
		GUID:        types.Int64Value(int64(dhcp.GUID)),
		DHCPID:      types.Int64Value(int64(dhcp.ID)),
		LockStatus:  types.StringValue(dhcp.LockStatus),
		Milestones:  types.Int64Value(int64(dhcp.Milestones)),
		OwnerID:     types.Int64Value(int64(dhcp.OwnerID)),
		OwnerType:   types.StringValue(dhcp.OwnerType),
		PureVirtual: types.BoolValue(dhcp.PureVirtual),
		Routes:      flattenRoutes(ctx, &dhcp.Routes),
		Status:      types.StringValue(dhcp.Status),
		TechStatus:  types.StringValue(dhcp.TechStatus),
		Type:        types.StringValue(dhcp.Type),
	}

	res, diags := types.ObjectValueFrom(ctx, models.ItemDHCP, temp)
	if diags != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenDHCP struct to obj", diags))
	}

	tflog.Info(ctx, "End flattenDHCP")
	return res
}

// flattenDHCPConfig flattens dhcp config.
// Flatten errors are added to tflog.
func flattenDHCPConfig(ctx context.Context, config *vins.VNFsConfig) types.Object {
	tflog.Info(ctx, "Start flattenDHCPConfig")
	diags := diag.Diagnostics{}

	temp := models.RecordDHCPConfigModel{
		DefaultGW:    types.StringValue(config.DefaultGW),
		IPEnd:        types.StringValue(config.IPEnd),
		IPStart:      types.StringValue(config.IPStart),
		Lease:        types.Int64Value(int64(config.Lease)),
		NetMask:      types.Int64Value(int64(config.NetMask)),
		Network:      types.StringValue(config.Network),
		Reservations: flattenReservations(ctx, &config.Reservations),
	}

	temp.DNS, diags = types.ListValueFrom(ctx, types.StringType, config.DNS)
	if diags.HasError() {
		tflog.Error(ctx, fmt.Sprint("flattens.flattenDHCPConfig: cannot flatten config.DNS to temp.DNS", diags))
	}

	res, diags := types.ObjectValueFrom(ctx, models.ItemDHCPConfig, temp)
	if diags.HasError() {
		tflog.Error(ctx, fmt.Sprint("Error flattenDHCPConfig struct to obj", diags))
	}

	tflog.Info(ctx, "End flattenDHCPConfig")
	return res
}

// flattenReservations flattens dhcp config reservations.
// Flatten errors are added to tflog.
func flattenReservations(ctx context.Context, items *vins.ListReservations) types.List {
	tflog.Info(ctx, "Start flattenReservations")

	tempSlice := make([]types.Object, 0, len(*items))
	for _, item := range *items {
		temp := models.ReservationModel{
			AccountID: types.Int64Value(int64(item.AccountID)),
			IP:        types.StringValue(item.IP),
			MAC:       types.StringValue(item.MAC),
			Type:      types.StringValue(item.Type),
			VMID:      types.Int64Value(int64(item.VMID)),
		}

		obj, diags := types.ObjectValueFrom(ctx, models.ItemReservations, temp)
		if diags.HasError() {
			tflog.Error(ctx, fmt.Sprint("Error flattenReservations struct to obj", diags))
		}
		tempSlice = append(tempSlice, obj)
	}

	res, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: models.ItemReservations}, tempSlice)
	if diags.HasError() {
		tflog.Error(ctx, fmt.Sprint("Error flattenReservations", diags))
	}

	tflog.Info(ctx, "End flattenReservations")
	return res
}

// flattenDevices flattens devices.
// Flatten errors are added to tflog.
func flattenDevices(ctx context.Context, devices *vins.Devices) types.Object {
	tflog.Info(ctx, "Start flattenDevices")

	temp := models.DevicesModel{
		Primary: flattenPrimaryDevices(ctx, &devices.Primary),
	}

	res, diags := types.ObjectValueFrom(ctx, models.ItemDevices, temp)
	if diags.HasError() {
		tflog.Error(ctx, fmt.Sprint("Error flattenDevices struct to obj", diags))
	}

	tflog.Info(ctx, "End flattenDevices")
	return res
}

// flattenPrimaryDevices flattens primary devices.
// Flatten errors are added to tflog.
func flattenPrimaryDevices(ctx context.Context, primary *vins.Primary) types.Object {
	tflog.Info(ctx, "Start flattenPrimaryDevices")

	temp := models.PrimaryDevicesModel{
		DevID:   types.Int64Value(int64(primary.DevID)),
		IFace01: types.StringValue(primary.IFace01),
		IFace02: types.StringValue(primary.IFace02),
	}

	res, diags := types.ObjectValueFrom(ctx, models.ItemPrimaryDevices, temp)
	if diags.HasError() {
		tflog.Error(ctx, fmt.Sprint("Error flattenPrimaryDevices struct to obj", diags))
	}

	tflog.Info(ctx, "End flattenPrimaryDevices")
	return res
}

// flattenRoutes flattens routes.
// Flatten errors are added to tflog.
func flattenRoutes(ctx context.Context, items *vins.ListRoutes) types.List {
	tflog.Info(ctx, "Start flattenRoutes")
	diags := diag.Diagnostics{}

	tempSlice := make([]types.Object, 0, len(*items))
	for _, item := range *items {
		temp := models.RoutesModel{
			Destination: types.StringValue(item.Destination),
			Gateway:     types.StringValue(item.Gateway),
			GUID:        types.StringValue(item.GUID),
			RouteID:     types.Int64Value(int64(item.ID)),
			Netmask:     types.StringValue(item.Netmask),
		}

		temp.ComputeIds, diags = types.ListValueFrom(ctx, types.Int64Type, item.ComputeIds)
		if diags.HasError() {
			tflog.Error(ctx, fmt.Sprint("flattens.flattenRoutes: cannot flatten item.ComputeIds to temp.ComputeIds", diags))
		}

		obj, diags := types.ObjectValueFrom(ctx, models.ItemRoute, temp)
		if diags.HasError() {
			tflog.Error(ctx, fmt.Sprint("Error flattenRoutes struct to obj", diags))
		}
		tempSlice = append(tempSlice, obj)
	}

	res, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: models.ItemRoute}, tempSlice)
	if diags.HasError() {
		tflog.Error(ctx, fmt.Sprint("Error flattenRoutes", diags))
	}

	tflog.Info(ctx, "End flattenRoutes")
	return res
}

// flattenGW flattens gw.
// Flatten errors are added to tflog.
func flattenGW(ctx context.Context, gw *vins.RecordGW) types.Object {
	tflog.Info(ctx, "Start flattenGW")
	diags := diag.Diagnostics{}

	temp := models.RecordGWModel{
		CKey:        types.StringValue(gw.CKey),
		AccountID:   types.Int64Value(int64(gw.AccountID)),
		Config:      flattenGWConfig(ctx, &gw.Config),
		CreatedTime: types.Int64Value(int64(gw.CreatedTime)),
		Devices:     flattenDevices(ctx, &gw.Devices),
		GID:         types.Int64Value(int64(gw.GID)),
		GUID:        types.Int64Value(int64(gw.GUID)),
		GWID:        types.Int64Value(int64(gw.ID)),
		LockStatus:  types.StringValue(gw.LockStatus),
		Milestones:  types.Int64Value(int64(gw.Milestones)),
		OwnerID:     types.Int64Value(int64(gw.OwnerID)),
		OwnerType:   types.StringValue(gw.OwnerType),
		PureVirtual: types.BoolValue(gw.PureVirtual),
		Routes:      flattenRoutes(ctx, &gw.Routes),
		Status:      types.StringValue(gw.Status),
		TechStatus:  types.StringValue(gw.TechStatus),
		Type:        types.StringValue(gw.Type),
	}

	res, diags := types.ObjectValueFrom(ctx, models.ItemGW, temp)
	if diags != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenGW struct to obj", diags))
	}

	tflog.Info(ctx, "End flattenGW")
	return res
}

// flattenGWConfig flattens gw config.
// Flatten errors are added to tflog.
func flattenGWConfig(ctx context.Context, config *vins.GWConfig) types.Object {
	tflog.Info(ctx, "Start flattenGWConfig")
	diags := diag.Diagnostics{}

	temp := models.RecordGWConfigModel{
		DefaultGW:  types.StringValue(config.DefaultGW),
		ExtNetID:   types.Int64Value(int64(config.ExtNetID)),
		ExtNetIP:   types.StringValue(config.ExtNetIP),
		ExtNetMask: types.Int64Value(int64(config.ExtNetMask)),
		QOS:        flattenQOS(ctx, &config.QOS),
	}

	res, diags := types.ObjectValueFrom(ctx, models.ItemGWConfig, temp)
	if diags.HasError() {
		tflog.Error(ctx, fmt.Sprint("Error flattenGWConfig struct to obj", diags))
	}

	tflog.Info(ctx, "End flattenGWConfig")
	return res
}

// flattenNAT flattens nat.
// Flatten errors are added to tflog.
func flattenNAT(ctx context.Context, nat *vins.RecordNAT) types.Object {
	tflog.Info(ctx, "Start flattenNAT")

	temp := models.RecordNATModel{
		CKey:        types.StringValue(nat.CKey),
		AccountID:   types.Int64Value(int64(nat.AccountID)),
		Config:      flattenNATConfig(ctx, &nat.Config),
		CreatedTime: types.Int64Value(int64(nat.CreatedTime)),
		Devices:     flattenDevices(ctx, &nat.Devices),
		GID:         types.Int64Value(int64(nat.GID)),
		GUID:        types.Int64Value(int64(nat.GUID)),
		NatID:       types.Int64Value(int64(nat.ID)),
		LockStatus:  types.StringValue(nat.LockStatus),
		Milestones:  types.Int64Value(int64(nat.Milestones)),
		OwnerID:     types.Int64Value(int64(nat.OwnerID)),
		OwnerType:   types.StringValue(nat.OwnerType),
		PureVirtual: types.BoolValue(nat.PureVirtual),
		Routes:      flattenRoutes(ctx, &nat.Routes),
		Status:      types.StringValue(nat.Status),
		TechStatus:  types.StringValue(nat.TechStatus),
		Type:        types.StringValue(nat.Type),
	}

	res, diags := types.ObjectValueFrom(ctx, models.ItemNAT, temp)
	if diags.HasError() {
		tflog.Error(ctx, fmt.Sprint("Error flattenNAT struct to obj", diags))
	}

	tflog.Info(ctx, "End flattenNAT")
	return res
}

// flattenRules flattens nat rules.
// Flatten errors are added to tflog.
func flattenRules(ctx context.Context, items *vins.ListNATRule) types.List {
	tflog.Info(ctx, "Start flattenRules")

	tempSlice := make([]types.Object, 0, len(*items))
	for _, item := range *items {
		temp := models.NATRuleModel{
			RuleID:          types.Int64Value(int64(item.ID)),
			LocalIP:         types.StringValue(item.LocalIP),
			LocalPort:       types.Int64Value(int64(item.LocalPort)),
			Protocol:        types.StringValue(item.Protocol),
			PublicPortEnd:   types.Int64Value(int64(item.PublicPortEnd)),
			PublicPortStart: types.Int64Value(int64(item.PublicPortStart)),
			VMID:            types.Int64Value(int64(item.VMID)),
			VMName:          types.StringValue(item.VMName),
		}

		obj, diags := types.ObjectValueFrom(ctx, models.ItemNATRule, temp)
		if diags.HasError() {
			tflog.Error(ctx, fmt.Sprint("Error flattenRules struct to obj", diags))
		}
		tempSlice = append(tempSlice, obj)
	}

	res, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: models.ItemNATRule}, tempSlice)
	if diags.HasError() {
		tflog.Error(ctx, fmt.Sprint("Error flattenRules", diags))
	}

	tflog.Info(ctx, "End flattenRules")
	return res
}

// flattenNATConfig flattens nat config.
// Flatten errors are added to tflog.
func flattenNATConfig(ctx context.Context, config *vins.NATConfig) types.Object {
	tflog.Info(ctx, "Start flattenNATConfig")
	diags := diag.Diagnostics{}

	temp := models.NATConfigModel{
		NetMask: types.Int64Value(int64(config.NetMask)),
		Network: types.StringValue(config.Network),
		Rules:   flattenRules(ctx, &config.Rules),
	}

	res, diags := types.ObjectValueFrom(ctx, models.ItemNATConfig, temp)
	if diags.HasError() {
		tflog.Error(ctx, fmt.Sprint("Error flattenNATConfig struct to obj", diags))
	}

	tflog.Info(ctx, "End flattenNATConfig")
	return res
}
