// Copyright © 2023 Cisco Systems, Inc. and its affiliates.
// All rights reserved.
//
// Licensed under the Mozilla Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	https://mozilla.org/MPL/2.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: MPL-2.0
package provider

// RESOURCE NORMAL
import (
	"context"
	"strconv"

	"log"

	merakigosdk "github.com/meraki/dashboard-api-go/v5/sdk"

	"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
	"github.com/hashicorp/terraform-plugin-framework/path"
	"github.com/hashicorp/terraform-plugin-framework/resource"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
	"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
	"github.com/hashicorp/terraform-plugin-framework/schema/validator"
	"github.com/hashicorp/terraform-plugin-framework/types"
	"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
)

var (
	_ resource.Resource              = &NetworksApplianceTrafficShapingUplinkSelectionResource{}
	_ resource.ResourceWithConfigure = &NetworksApplianceTrafficShapingUplinkSelectionResource{}
)

func NewNetworksApplianceTrafficShapingUplinkSelectionResource() resource.Resource {
	return &NetworksApplianceTrafficShapingUplinkSelectionResource{}
}

type NetworksApplianceTrafficShapingUplinkSelectionResource struct {
	client *merakigosdk.Client
}

func (r *NetworksApplianceTrafficShapingUplinkSelectionResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
	if req.ProviderData == nil {
		return
	}
	client := req.ProviderData.(MerakiProviderData).Client
	r.client = client
}

// Metadata returns the data source type name.
func (r *NetworksApplianceTrafficShapingUplinkSelectionResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
	resp.TypeName = req.ProviderTypeName + "_networks_appliance_traffic_shaping_uplink_selection"
}

func (r *NetworksApplianceTrafficShapingUplinkSelectionResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
	resp.Schema = schema.Schema{
		Attributes: map[string]schema.Attribute{
			"active_active_auto_vpn_enabled": schema.BoolAttribute{
				MarkdownDescription: `Whether active-active AutoVPN is enabled`,
				Optional:            true,
				PlanModifiers: []planmodifier.Bool{
					boolplanmodifier.UseStateForUnknown(),
				},
			},
			"default_uplink": schema.StringAttribute{
				MarkdownDescription: `The default uplink. Must be one of: 'wan1' or 'wan2'
                                  Allowed values: [wan1,wan2]`,
				Optional: true,
				PlanModifiers: []planmodifier.String{
					stringplanmodifier.UseStateForUnknown(),
				},
				Validators: []validator.String{
					stringvalidator.OneOf(
						"wan1",
						"wan2",
					),
				},
			},
			"failover_and_failback": schema.SingleNestedAttribute{
				MarkdownDescription: `WAN failover and failback`,
				Optional:            true,
				PlanModifiers: []planmodifier.Object{
					objectplanmodifier.UseStateForUnknown(),
				},
				Attributes: map[string]schema.Attribute{

					"immediate": schema.SingleNestedAttribute{
						MarkdownDescription: `Immediate WAN failover and failback`,
						Optional:            true,
						PlanModifiers: []planmodifier.Object{
							objectplanmodifier.UseStateForUnknown(),
						},
						Attributes: map[string]schema.Attribute{

							"enabled": schema.BoolAttribute{
								MarkdownDescription: `Whether immediate WAN failover and failback is enabled`,
								Optional:            true,
								PlanModifiers: []planmodifier.Bool{
									boolplanmodifier.UseStateForUnknown(),
								},
							},
						},
					},
				},
			},
			"load_balancing_enabled": schema.BoolAttribute{
				MarkdownDescription: `Whether load balancing is enabled`,
				Optional:            true,
				PlanModifiers: []planmodifier.Bool{
					boolplanmodifier.UseStateForUnknown(),
				},
			},
			"network_id": schema.StringAttribute{
				MarkdownDescription: `networkId path parameter. Network ID`,
				Required:            true,
			},
			"vpn_traffic_uplink_preferences": schema.ListNestedAttribute{
				MarkdownDescription: `Uplink preference rules for VPN traffic`,
				Optional:            true,
				PlanModifiers: []planmodifier.List{
					listplanmodifier.UseStateForUnknown(),
				},
				NestedObject: schema.NestedAttributeObject{
					Attributes: map[string]schema.Attribute{

						"fail_over_criterion": schema.StringAttribute{
							MarkdownDescription: `Fail over criterion for uplink preference rule. Must be one of: 'poorPerformance' or 'uplinkDown'
                                        Allowed values: [poorPerformance,uplinkDown]`,
							Optional: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							Validators: []validator.String{
								stringvalidator.OneOf(
									"poorPerformance",
									"uplinkDown",
								),
							},
						},
						"performance_class": schema.SingleNestedAttribute{
							MarkdownDescription: `Performance class setting for uplink preference rule`,
							Optional:            true,
							PlanModifiers: []planmodifier.Object{
								objectplanmodifier.UseStateForUnknown(),
							},
							Attributes: map[string]schema.Attribute{

								"builtin_performance_class_name": schema.StringAttribute{
									MarkdownDescription: `Name of builtin performance class. Must be present when performanceClass type is 'builtin' and value must be one of: 'VoIP'
                                              Allowed values: [VoIP]`,
									Optional: true,
									PlanModifiers: []planmodifier.String{
										stringplanmodifier.UseStateForUnknown(),
									},
									Validators: []validator.String{
										stringvalidator.OneOf(
											"VoIP",
										),
									},
								},
								"custom_performance_class_id": schema.StringAttribute{
									MarkdownDescription: `ID of created custom performance class, must be present when performanceClass type is "custom"`,
									Optional:            true,
									PlanModifiers: []planmodifier.String{
										stringplanmodifier.UseStateForUnknown(),
									},
								},
								"type": schema.StringAttribute{
									MarkdownDescription: `Type of this performance class. Must be one of: 'builtin' or 'custom'
                                              Allowed values: [builtin,custom]`,
									Optional: true,
									PlanModifiers: []planmodifier.String{
										stringplanmodifier.UseStateForUnknown(),
									},
									Validators: []validator.String{
										stringvalidator.OneOf(
											"builtin",
											"custom",
										),
									},
								},
							},
						},
						"preferred_uplink": schema.StringAttribute{
							MarkdownDescription: `Preferred uplink for uplink preference rule. Must be one of: 'wan1', 'wan2', 'bestForVoIP', 'loadBalancing' or 'defaultUplink'
                                        Allowed values: [bestForVoIP,defaultUplink,loadBalancing,wan1,wan2]`,
							Optional: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							Validators: []validator.String{
								stringvalidator.OneOf(
									"bestForVoIP",
									"defaultUplink",
									"loadBalancing",
									"wan1",
									"wan2",
								),
							},
						},
						"traffic_filters": schema.ListNestedAttribute{
							MarkdownDescription: `Traffic filters`,
							Optional:            true,
							PlanModifiers: []planmodifier.List{
								listplanmodifier.UseStateForUnknown(),
							},
							NestedObject: schema.NestedAttributeObject{
								Attributes: map[string]schema.Attribute{

									"type": schema.StringAttribute{
										MarkdownDescription: `Traffic filter type. Must be one of: 'applicationCategory', 'application' or 'custom'
                                              Allowed values: [application,applicationCategory,custom]`,
										Optional: true,
										PlanModifiers: []planmodifier.String{
											stringplanmodifier.UseStateForUnknown(),
										},
										Validators: []validator.String{
											stringvalidator.OneOf(
												"application",
												"applicationCategory",
												"custom",
											),
										},
									},
									"value": schema.SingleNestedAttribute{
										MarkdownDescription: `Value of traffic filter`,
										Optional:            true,
										PlanModifiers: []planmodifier.Object{
											objectplanmodifier.UseStateForUnknown(),
										},
										Attributes: map[string]schema.Attribute{

											"destination": schema.SingleNestedAttribute{
												MarkdownDescription: `Destination of 'custom' type traffic filter`,
												Optional:            true,
												PlanModifiers: []planmodifier.Object{
													objectplanmodifier.UseStateForUnknown(),
												},
												Attributes: map[string]schema.Attribute{

													"cidr": schema.StringAttribute{
														MarkdownDescription: `CIDR format address (e.g."192.168.10.1", which is the same as "192.168.10.1/32"), or "any". Cannot be used in combination with the "vlan" or "fqdn" property`,
														Optional:            true,
														PlanModifiers: []planmodifier.String{
															stringplanmodifier.UseStateForUnknown(),
														},
													},
													"fqdn": schema.StringAttribute{
														MarkdownDescription: `FQDN format address. Cannot be used in combination with the "cidr" or "fqdn" property and is currently only available in the "destination" object of the "vpnTrafficUplinkPreference" object. E.g.: "www.google.com"`,
														Optional:            true,
														PlanModifiers: []planmodifier.String{
															stringplanmodifier.UseStateForUnknown(),
														},
													},
													"host": schema.Int64Attribute{
														MarkdownDescription: `Host ID in the VLAN. Should not exceed the VLAN subnet capacity. Must be used along with the "vlan" property and is currently only available under a template network.`,
														Optional:            true,
														PlanModifiers: []planmodifier.Int64{
															int64planmodifier.UseStateForUnknown(),
														},
													},
													"network": schema.StringAttribute{
														MarkdownDescription: `Meraki network ID. Currently only available under a template network, and the value should be ID of either same template network, or another template network currently. E.g.: "L_12345678".`,
														Optional:            true,
														PlanModifiers: []planmodifier.String{
															stringplanmodifier.UseStateForUnknown(),
														},
													},
													"port": schema.StringAttribute{
														MarkdownDescription: `E.g.: "any", "0" (also means "any"), "8080", "1-1024"`,
														Optional:            true,
														PlanModifiers: []planmodifier.String{
															stringplanmodifier.UseStateForUnknown(),
														},
													},
													"vlan": schema.Int64Attribute{
														MarkdownDescription: `VLAN ID of the configured VLAN in the Meraki network. Cannot be used in combination with the "cidr" or "fqdn" property and is currently only available under a template network.`,
														Optional:            true,
														PlanModifiers: []planmodifier.Int64{
															int64planmodifier.UseStateForUnknown(),
														},
													},
												},
											},
											"id": schema.StringAttribute{
												MarkdownDescription: `ID of 'applicationCategory' or 'application' type traffic filter`,
												Optional:            true,
												PlanModifiers: []planmodifier.String{
													stringplanmodifier.UseStateForUnknown(),
												},
											},
											"protocol": schema.StringAttribute{
												MarkdownDescription: `Protocol of 'custom' type traffic filter. Must be one of: 'tcp', 'udp', 'icmp', 'icmp6' or 'any'
                                                    Allowed values: [any,icmp,icmp6,tcp,udp]`,
												Optional: true,
												PlanModifiers: []planmodifier.String{
													stringplanmodifier.UseStateForUnknown(),
												},
												Validators: []validator.String{
													stringvalidator.OneOf(
														"any",
														"icmp",
														"icmp6",
														"tcp",
														"udp",
													),
												},
											},
											"source": schema.SingleNestedAttribute{
												MarkdownDescription: `Source of 'custom' type traffic filter`,
												Optional:            true,
												PlanModifiers: []planmodifier.Object{
													objectplanmodifier.UseStateForUnknown(),
												},
												Attributes: map[string]schema.Attribute{

													"cidr": schema.StringAttribute{
														MarkdownDescription: `CIDR format address (e.g."192.168.10.1", which is the same as "192.168.10.1/32"), or "any". Cannot be used in combination with the "vlan" property`,
														Optional:            true,
														PlanModifiers: []planmodifier.String{
															stringplanmodifier.UseStateForUnknown(),
														},
													},
													"host": schema.Int64Attribute{
														MarkdownDescription: `Host ID in the VLAN. Should not exceed the VLAN subnet capacity. Must be used along with the "vlan" property and is currently only available under a template network.`,
														Optional:            true,
														PlanModifiers: []planmodifier.Int64{
															int64planmodifier.UseStateForUnknown(),
														},
													},
													"network": schema.StringAttribute{
														MarkdownDescription: `Meraki network ID. Currently only available under a template network, and the value should be ID of either same template network, or another template network currently. E.g.: "L_12345678".`,
														Optional:            true,
														PlanModifiers: []planmodifier.String{
															stringplanmodifier.UseStateForUnknown(),
														},
													},
													"port": schema.StringAttribute{
														MarkdownDescription: `E.g.: "any", "0" (also means "any"), "8080", "1-1024"`,
														Optional:            true,
														PlanModifiers: []planmodifier.String{
															stringplanmodifier.UseStateForUnknown(),
														},
													},
													"vlan": schema.Int64Attribute{
														MarkdownDescription: `VLAN ID of the configured VLAN in the Meraki network. Cannot be used in combination with the "cidr" property and is currently only available under a template network.`,
														Optional:            true,
														PlanModifiers: []planmodifier.Int64{
															int64planmodifier.UseStateForUnknown(),
														},
													},
												},
											},
										},
									},
								},
							},
						},
					},
				},
			},
			"wan_traffic_uplink_preferences": schema.ListNestedAttribute{
				MarkdownDescription: `Uplink preference rules for WAN traffic`,
				Optional:            true,
				PlanModifiers: []planmodifier.List{
					listplanmodifier.UseStateForUnknown(),
				},
				NestedObject: schema.NestedAttributeObject{
					Attributes: map[string]schema.Attribute{

						"preferred_uplink": schema.StringAttribute{
							MarkdownDescription: `Preferred uplink for uplink preference rule. Must be one of: 'wan1' or 'wan2'
                                        Allowed values: [wan1,wan2]`,
							Optional: true,
							PlanModifiers: []planmodifier.String{
								stringplanmodifier.UseStateForUnknown(),
							},
							Validators: []validator.String{
								stringvalidator.OneOf(
									"wan1",
									"wan2",
								),
							},
						},
						"traffic_filters": schema.ListNestedAttribute{
							MarkdownDescription: `Traffic filters`,
							Optional:            true,
							PlanModifiers: []planmodifier.List{
								listplanmodifier.UseStateForUnknown(),
							},
							NestedObject: schema.NestedAttributeObject{
								Attributes: map[string]schema.Attribute{

									"type": schema.StringAttribute{
										MarkdownDescription: `Traffic filter type. Must be "custom"
                                              Allowed values: [custom]`,
										Optional: true,
										PlanModifiers: []planmodifier.String{
											stringplanmodifier.UseStateForUnknown(),
										},
										Validators: []validator.String{
											stringvalidator.OneOf(
												"custom",
											),
										},
									},
									"value": schema.SingleNestedAttribute{
										MarkdownDescription: `Value of traffic filter`,
										Optional:            true,
										PlanModifiers: []planmodifier.Object{
											objectplanmodifier.UseStateForUnknown(),
										},
										Attributes: map[string]schema.Attribute{

											"destination": schema.SingleNestedAttribute{
												MarkdownDescription: `Destination of 'custom' type traffic filter`,
												Optional:            true,
												PlanModifiers: []planmodifier.Object{
													objectplanmodifier.UseStateForUnknown(),
												},
												Attributes: map[string]schema.Attribute{

													"applications": schema.ListNestedAttribute{
														MarkdownDescription: `list of application objects (either majorApplication or nbar)`,
														Computed:            true,
														NestedObject: schema.NestedAttributeObject{
															Attributes: map[string]schema.Attribute{

																"id": schema.StringAttribute{
																	MarkdownDescription: `Id of the major application, or a list of NBAR Application Category or Application selections`,
																	Computed:            true,
																},
																"name": schema.StringAttribute{
																	MarkdownDescription: `Name of the major application or application category selected`,
																	Computed:            true,
																},
																"type": schema.StringAttribute{
																	MarkdownDescription: `app type (major or nbar)`,
																	Computed:            true,
																},
															},
														},
													},
													"cidr": schema.StringAttribute{
														MarkdownDescription: `CIDR format address (e.g."192.168.10.1", which is the same as "192.168.10.1/32"), or "any"`,
														Optional:            true,
														PlanModifiers: []planmodifier.String{
															stringplanmodifier.UseStateForUnknown(),
														},
													},
													"port": schema.StringAttribute{
														MarkdownDescription: `E.g.: "any", "0" (also means "any"), "8080", "1-1024"`,
														Optional:            true,
														PlanModifiers: []planmodifier.String{
															stringplanmodifier.UseStateForUnknown(),
														},
													},
												},
											},
											"protocol": schema.StringAttribute{
												MarkdownDescription: `Protocol of 'custom' type traffic filter. Must be one of: 'tcp', 'udp', 'icmp6' or 'any'
                                                    Allowed values: [any,icmp6,tcp,udp]`,
												Optional: true,
												PlanModifiers: []planmodifier.String{
													stringplanmodifier.UseStateForUnknown(),
												},
												Validators: []validator.String{
													stringvalidator.OneOf(
														"any",
														"icmp6",
														"tcp",
														"udp",
													),
												},
											},
											"source": schema.SingleNestedAttribute{
												MarkdownDescription: `Source of 'custom' type traffic filter`,
												Optional:            true,
												PlanModifiers: []planmodifier.Object{
													objectplanmodifier.UseStateForUnknown(),
												},
												Attributes: map[string]schema.Attribute{

													"cidr": schema.StringAttribute{
														MarkdownDescription: `CIDR format address (e.g."192.168.10.1", which is the same as "192.168.10.1/32"), or "any". Cannot be used in combination with the "vlan" property`,
														Optional:            true,
														PlanModifiers: []planmodifier.String{
															stringplanmodifier.UseStateForUnknown(),
														},
													},
													"host": schema.Int64Attribute{
														MarkdownDescription: `Host ID in the VLAN. Should not exceed the VLAN subnet capacity. Must be used along with the "vlan" property and is currently only available under a template network.`,
														Optional:            true,
														PlanModifiers: []planmodifier.Int64{
															int64planmodifier.UseStateForUnknown(),
														},
													},
													"port": schema.StringAttribute{
														MarkdownDescription: `E.g.: "any", "0" (also means "any"), "8080", "1-1024"`,
														Optional:            true,
														PlanModifiers: []planmodifier.String{
															stringplanmodifier.UseStateForUnknown(),
														},
													},
													"vlan": schema.Int64Attribute{
														MarkdownDescription: `VLAN ID of the configured VLAN in the Meraki network. Cannot be used in combination with the "cidr" property and is currently only available under a template network.`,
														Optional:            true,
														PlanModifiers: []planmodifier.Int64{
															int64planmodifier.UseStateForUnknown(),
														},
													},
												},
											},
										},
									},
								},
							},
						},
					},
				},
			},
		},
	}
}

func (r *NetworksApplianceTrafficShapingUplinkSelectionResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
	// Retrieve values from plan
	var data NetworksApplianceTrafficShapingUplinkSelectionRs

	var item types.Object
	resp.Diagnostics.Append(req.Plan.Get(ctx, &item)...)
	if resp.Diagnostics.HasError() {
		return
	}

	resp.Diagnostics.Append(item.As(ctx, &data, basetypes.ObjectAsOptions{
		UnhandledNullAsEmpty:    true,
		UnhandledUnknownAsEmpty: true,
	})...)

	if resp.Diagnostics.HasError() {
		return
	}
	// Has Paths
	vvNetworkID := data.NetworkID.ValueString()
	//Has Item and not has items

	// UPDATE NO CREATE
	dataRequest := data.toSdkApiRequestUpdate(ctx)
	response, restyResp2, err := r.client.Appliance.UpdateNetworkApplianceTrafficShapingUplinkSelection(vvNetworkID, dataRequest)
	//Update
	if err != nil || restyResp2 == nil || response == nil {
		if restyResp2 != nil {
			resp.Diagnostics.AddError(
				"Failure when executing UpdateNetworkApplianceTrafficShapingUplinkSelection",
				"Status: "+strconv.Itoa(restyResp2.StatusCode())+"\n"+restyResp2.String(),
			)
			return
		}
		resp.Diagnostics.AddError(
			"Failure when executing UpdateNetworkApplianceTrafficShapingUplinkSelection",
			err.Error(),
		)
		return
	}

	// Assign data
	resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)

}

func (r *NetworksApplianceTrafficShapingUplinkSelectionResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
	var data NetworksApplianceTrafficShapingUplinkSelectionRs

	diags := req.State.Get(ctx, &data)
	if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
		return
	}

	//Has Paths
	// Has Item2

	vvNetworkID := data.NetworkID.ValueString()
	responseGet, restyRespGet, err := r.client.Appliance.GetNetworkApplianceTrafficShapingUplinkSelection(vvNetworkID)
	if err != nil || restyRespGet == nil {
		if restyRespGet != nil {
			if restyRespGet.StatusCode() == 404 {
				resp.Diagnostics.AddWarning(
					"Resource not found",
					"Deleting resource",
				)
				resp.State.RemoveResource(ctx)
				return
			}
			resp.Diagnostics.AddError(
				"Failure when executing GetNetworkApplianceTrafficShapingUplinkSelection",
				restyRespGet.String(),
			)
			return
		}
		resp.Diagnostics.AddError(
			"Failure when executing GetNetworkApplianceTrafficShapingUplinkSelection",
			err.Error(),
		)
		return
	}
	//entro aqui 2
	data = ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionItemToBodyRs(data, responseGet, true)
	resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
func (r *NetworksApplianceTrafficShapingUplinkSelectionResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
	resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("network_id"), req.ID)...)
}

func (r *NetworksApplianceTrafficShapingUplinkSelectionResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
	var plan NetworksApplianceTrafficShapingUplinkSelectionRs
	merge(ctx, req, resp, &plan)

	if resp.Diagnostics.HasError() {
		return
	}
	//Path Params
	vvNetworkID := plan.NetworkID.ValueString()
	dataRequest := plan.toSdkApiRequestUpdate(ctx)
	response, restyResp2, err := r.client.Appliance.UpdateNetworkApplianceTrafficShapingUplinkSelection(vvNetworkID, dataRequest)
	if err != nil || restyResp2 == nil || response == nil {
		if restyResp2 != nil {
			resp.Diagnostics.AddError(
				"Failure when executing UpdateNetworkApplianceTrafficShapingUplinkSelection",
				"Status: "+strconv.Itoa(restyResp2.StatusCode())+"\n"+restyResp2.String(),
			)
			return
		}
		resp.Diagnostics.AddError(
			"Failure when executing UpdateNetworkApplianceTrafficShapingUplinkSelection",
			err.Error(),
		)
		return
	}
	resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
}

func (r *NetworksApplianceTrafficShapingUplinkSelectionResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
	//missing delete
	resp.Diagnostics.AddWarning("Error deleting NetworksApplianceTrafficShapingUplinkSelection", "This resource has no delete method in the meraki lab, the resource was deleted only in terraform.")
	resp.State.RemoveResource(ctx)
}

// TF Structs Schema
type NetworksApplianceTrafficShapingUplinkSelectionRs struct {
	NetworkID                   types.String                                                                                      `tfsdk:"network_id"`
	ActiveActiveAutoVpnEnabled  types.Bool                                                                                        `tfsdk:"active_active_auto_vpn_enabled"`
	DefaultUplink               types.String                                                                                      `tfsdk:"default_uplink"`
	FailoverAndFailback         *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackRs           `tfsdk:"failover_and_failback"`
	LoadBalancingEnabled        types.Bool                                                                                        `tfsdk:"load_balancing_enabled"`
	VpnTrafficUplinkPreferences *[]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesRs `tfsdk:"vpn_traffic_uplink_preferences"`
	WanTrafficUplinkPreferences *[]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesRs `tfsdk:"wan_traffic_uplink_preferences"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackRs struct {
	Immediate *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackImmediateRs `tfsdk:"immediate"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackImmediateRs struct {
	Enabled types.Bool `tfsdk:"enabled"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesRs struct {
	FailOverCriterion types.String                                                                                                    `tfsdk:"fail_over_criterion"`
	PerformanceClass  *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesPerformanceClassRs `tfsdk:"performance_class"`
	PreferredUplink   types.String                                                                                                    `tfsdk:"preferred_uplink"`
	TrafficFilters    *[]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersRs `tfsdk:"traffic_filters"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesPerformanceClassRs struct {
	BuiltinPerformanceClassName types.String `tfsdk:"builtin_performance_class_name"`
	CustomPerformanceClassID    types.String `tfsdk:"custom_performance_class_id"`
	Type                        types.String `tfsdk:"type"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersRs struct {
	Type  types.String                                                                                                       `tfsdk:"type"`
	Value *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueRs `tfsdk:"value"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueRs struct {
	Destination *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueDestinationRs `tfsdk:"destination"`
	ID          types.String                                                                                                                  `tfsdk:"id"`
	Protocol    types.String                                                                                                                  `tfsdk:"protocol"`
	Source      *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueSourceRs      `tfsdk:"source"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueDestinationRs struct {
	Cidr    types.String `tfsdk:"cidr"`
	Fqdn    types.String `tfsdk:"fqdn"`
	Host    types.Int64  `tfsdk:"host"`
	Network types.String `tfsdk:"network"`
	Port    types.String `tfsdk:"port"`
	VLAN    types.Int64  `tfsdk:"vlan"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueSourceRs struct {
	Cidr    types.String `tfsdk:"cidr"`
	Host    types.Int64  `tfsdk:"host"`
	Network types.String `tfsdk:"network"`
	Port    types.String `tfsdk:"port"`
	VLAN    types.Int64  `tfsdk:"vlan"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesRs struct {
	PreferredUplink types.String                                                                                                    `tfsdk:"preferred_uplink"`
	TrafficFilters  *[]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersRs `tfsdk:"traffic_filters"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersRs struct {
	Type  types.String                                                                                                       `tfsdk:"type"`
	Value *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueRs `tfsdk:"value"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueRs struct {
	Destination *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestinationRs `tfsdk:"destination"`
	Protocol    types.String                                                                                                                  `tfsdk:"protocol"`
	Source      *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueSourceRs      `tfsdk:"source"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestinationRs struct {
	Applications *[]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestinationApplicationsRs `tfsdk:"applications"`
	Cidr         types.String                                                                                                                                `tfsdk:"cidr"`
	Port         types.String                                                                                                                                `tfsdk:"port"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestinationApplicationsRs struct {
	ID   types.String `tfsdk:"id"`
	Name types.String `tfsdk:"name"`
	Type types.String `tfsdk:"type"`
}

type ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueSourceRs struct {
	Cidr types.String `tfsdk:"cidr"`
	Host types.Int64  `tfsdk:"host"`
	Port types.String `tfsdk:"port"`
	VLAN types.Int64  `tfsdk:"vlan"`
}

// FromBody
func (r *NetworksApplianceTrafficShapingUplinkSelectionRs) toSdkApiRequestUpdate(ctx context.Context) *merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelection {
	emptyString := ""
	activeActiveAutoVpnEnabled := new(bool)
	if !r.ActiveActiveAutoVpnEnabled.IsUnknown() && !r.ActiveActiveAutoVpnEnabled.IsNull() {
		*activeActiveAutoVpnEnabled = r.ActiveActiveAutoVpnEnabled.ValueBool()
	} else {
		activeActiveAutoVpnEnabled = nil
	}
	defaultUplink := new(string)
	if !r.DefaultUplink.IsUnknown() && !r.DefaultUplink.IsNull() {
		*defaultUplink = r.DefaultUplink.ValueString()
	} else {
		defaultUplink = &emptyString
	}
	var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailback *merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailback

	if r.FailoverAndFailback != nil {
		var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackImmediate *merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackImmediate

		if r.FailoverAndFailback.Immediate != nil {
			enabled := func() *bool {
				if !r.FailoverAndFailback.Immediate.Enabled.IsUnknown() && !r.FailoverAndFailback.Immediate.Enabled.IsNull() {
					return r.FailoverAndFailback.Immediate.Enabled.ValueBoolPointer()
				}
				return nil
			}()
			requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackImmediate = &merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackImmediate{
				Enabled: enabled,
			}
			//[debug] Is Array: False
		}
		requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailback = &merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailback{
			Immediate: requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackImmediate,
		}
		//[debug] Is Array: False
	}
	loadBalancingEnabled := new(bool)
	if !r.LoadBalancingEnabled.IsUnknown() && !r.LoadBalancingEnabled.IsNull() {
		*loadBalancingEnabled = r.LoadBalancingEnabled.ValueBool()
	} else {
		loadBalancingEnabled = nil
	}
	var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferences []merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferences

	if r.VpnTrafficUplinkPreferences != nil {
		for _, rItem1 := range *r.VpnTrafficUplinkPreferences {
			failOverCriterion := rItem1.FailOverCriterion.ValueString()
			var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesPerformanceClass *merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesPerformanceClass

			if rItem1.PerformanceClass != nil {
				builtinPerformanceClassName := rItem1.PerformanceClass.BuiltinPerformanceClassName.ValueString()
				customPerformanceClassID := rItem1.PerformanceClass.CustomPerformanceClassID.ValueString()
				typeR := rItem1.PerformanceClass.Type.ValueString()
				requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesPerformanceClass = &merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesPerformanceClass{
					BuiltinPerformanceClassName: builtinPerformanceClassName,
					CustomPerformanceClassID:    customPerformanceClassID,
					Type:                        typeR,
				}
				//[debug] Is Array: False
			}
			preferredUplink := rItem1.PreferredUplink.ValueString()

			log.Printf("[DEBUG] #TODO []RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFilters")
			var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFilters []merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFilters

			if rItem1.TrafficFilters != nil {
				for _, rItem2 := range *rItem1.TrafficFilters {
					typeR := rItem2.Type.ValueString()
					var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValue *merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValue

					if rItem2.Value != nil {
						var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueDestination *merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueDestination

						if rItem2.Value.Destination != nil {
							cidr := rItem2.Value.Destination.Cidr.ValueString()
							fqdn := rItem2.Value.Destination.Fqdn.ValueString()
							host := func() *int64 {
								if !rItem2.Value.Destination.Host.IsUnknown() && !rItem2.Value.Destination.Host.IsNull() {
									return rItem2.Value.Destination.Host.ValueInt64Pointer()
								}
								return nil
							}()
							network := rItem2.Value.Destination.Network.ValueString()
							port := rItem2.Value.Destination.Port.ValueString()
							vlan := func() *int64 {
								if !rItem2.Value.Destination.VLAN.IsUnknown() && !rItem2.Value.Destination.VLAN.IsNull() {
									return rItem2.Value.Destination.VLAN.ValueInt64Pointer()
								}
								return nil
							}()
							requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueDestination = &merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueDestination{
								Cidr:    cidr,
								Fqdn:    fqdn,
								Host:    int64ToIntPointer(host),
								Network: network,
								Port:    port,
								VLAN:    int64ToIntPointer(vlan),
							}
							//[debug] Is Array: False
						}
						id := rItem2.Value.ID.ValueString()
						protocol := rItem2.Value.Protocol.ValueString()
						var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueSource *merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueSource

						if rItem2.Value.Source != nil {
							cidr := rItem2.Value.Source.Cidr.ValueString()
							host := func() *int64 {
								if !rItem2.Value.Source.Host.IsUnknown() && !rItem2.Value.Source.Host.IsNull() {
									return rItem2.Value.Source.Host.ValueInt64Pointer()
								}
								return nil
							}()
							network := rItem2.Value.Source.Network.ValueString()
							port := rItem2.Value.Source.Port.ValueString()
							vlan := func() *int64 {
								if !rItem2.Value.Source.VLAN.IsUnknown() && !rItem2.Value.Source.VLAN.IsNull() {
									return rItem2.Value.Source.VLAN.ValueInt64Pointer()
								}
								return nil
							}()
							requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueSource = &merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueSource{
								Cidr:    cidr,
								Host:    int64ToIntPointer(host),
								Network: network,
								Port:    port,
								VLAN:    int64ToIntPointer(vlan),
							}
							//[debug] Is Array: False
						}
						requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValue = &merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValue{
							Destination: requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueDestination,
							ID:          id,
							Protocol:    protocol,
							Source:      requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueSource,
						}
						//[debug] Is Array: False
					}
					requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFilters = append(requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFilters, merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFilters{
						Type:  typeR,
						Value: requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValue,
					})
					//[debug] Is Array: True
				}
			}
			requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferences = append(requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferences, merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferences{
				FailOverCriterion: failOverCriterion,
				PerformanceClass:  requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesPerformanceClass,
				PreferredUplink:   preferredUplink,
				TrafficFilters: func() *[]merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFilters {
					if len(requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFilters) > 0 {
						return &requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFilters
					}
					return nil
				}(),
			})
			//[debug] Is Array: True
		}
	}
	var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferences []merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferences

	if r.WanTrafficUplinkPreferences != nil {
		for _, rItem1 := range *r.WanTrafficUplinkPreferences {
			preferredUplink := rItem1.PreferredUplink.ValueString()

			log.Printf("[DEBUG] #TODO []RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFilters")
			var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFilters []merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFilters

			if rItem1.TrafficFilters != nil {
				for _, rItem2 := range *rItem1.TrafficFilters {
					typeR := rItem2.Type.ValueString()
					var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValue *merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValue

					if rItem2.Value != nil {
						var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestination *merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestination

						if rItem2.Value.Destination != nil {
							cidr := rItem2.Value.Destination.Cidr.ValueString()
							port := rItem2.Value.Destination.Port.ValueString()
							requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestination = &merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestination{
								Cidr: cidr,
								Port: port,
							}
							//[debug] Is Array: False
						}
						protocol := rItem2.Value.Protocol.ValueString()
						var requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueSource *merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueSource

						if rItem2.Value.Source != nil {
							cidr := rItem2.Value.Source.Cidr.ValueString()
							host := func() *int64 {
								if !rItem2.Value.Source.Host.IsUnknown() && !rItem2.Value.Source.Host.IsNull() {
									return rItem2.Value.Source.Host.ValueInt64Pointer()
								}
								return nil
							}()
							port := rItem2.Value.Source.Port.ValueString()
							vlan := func() *int64 {
								if !rItem2.Value.Source.VLAN.IsUnknown() && !rItem2.Value.Source.VLAN.IsNull() {
									return rItem2.Value.Source.VLAN.ValueInt64Pointer()
								}
								return nil
							}()
							requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueSource = &merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueSource{
								Cidr: cidr,
								Host: int64ToIntPointer(host),
								Port: port,
								VLAN: int64ToIntPointer(vlan),
							}
							//[debug] Is Array: False
						}
						requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValue = &merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValue{
							Destination: requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestination,
							Protocol:    protocol,
							Source:      requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueSource,
						}
						//[debug] Is Array: False
					}
					requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFilters = append(requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFilters, merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFilters{
						Type:  typeR,
						Value: requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValue,
					})
					//[debug] Is Array: True
				}
			}
			requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferences = append(requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferences, merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferences{
				PreferredUplink: preferredUplink,
				TrafficFilters: func() *[]merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFilters {
					if len(requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFilters) > 0 {
						return &requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFilters
					}
					return nil
				}(),
			})
			//[debug] Is Array: True
		}
	}
	out := merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelection{
		ActiveActiveAutoVpnEnabled: activeActiveAutoVpnEnabled,
		DefaultUplink:              *defaultUplink,
		FailoverAndFailback:        requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailback,
		LoadBalancingEnabled:       loadBalancingEnabled,
		VpnTrafficUplinkPreferences: func() *[]merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferences {
			if len(requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferences) > 0 {
				return &requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferences
			}
			return nil
		}(),
		WanTrafficUplinkPreferences: func() *[]merakigosdk.RequestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferences {
			if len(requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferences) > 0 {
				return &requestApplianceUpdateNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferences
			}
			return nil
		}(),
	}
	return &out
}

// From gosdk to TF Structs Schema
func ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionItemToBodyRs(state NetworksApplianceTrafficShapingUplinkSelectionRs, response *merakigosdk.ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelection, is_read bool) NetworksApplianceTrafficShapingUplinkSelectionRs {
	itemState := NetworksApplianceTrafficShapingUplinkSelectionRs{
		ActiveActiveAutoVpnEnabled: func() types.Bool {
			if response.ActiveActiveAutoVpnEnabled != nil {
				return types.BoolValue(*response.ActiveActiveAutoVpnEnabled)
			}
			return types.Bool{}
		}(),
		DefaultUplink: func() types.String {
			if response.DefaultUplink != "" {
				return types.StringValue(response.DefaultUplink)
			}
			return types.String{}
		}(),
		FailoverAndFailback: func() *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackRs {
			if response.FailoverAndFailback != nil {
				return &ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackRs{
					Immediate: func() *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackImmediateRs {
						if response.FailoverAndFailback.Immediate != nil {
							return &ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionFailoverAndFailbackImmediateRs{
								Enabled: func() types.Bool {
									if response.FailoverAndFailback.Immediate.Enabled != nil {
										return types.BoolValue(*response.FailoverAndFailback.Immediate.Enabled)
									}
									return types.Bool{}
								}(),
							}
						}
						return nil
					}(),
				}
			}
			return nil
		}(),
		LoadBalancingEnabled: func() types.Bool {
			if response.LoadBalancingEnabled != nil {
				return types.BoolValue(*response.LoadBalancingEnabled)
			}
			return types.Bool{}
		}(),
		VpnTrafficUplinkPreferences: func() *[]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesRs {
			if response.VpnTrafficUplinkPreferences != nil {
				result := make([]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesRs, len(*response.VpnTrafficUplinkPreferences))
				for i, vpnTrafficUplinkPreferences := range *response.VpnTrafficUplinkPreferences {
					result[i] = ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesRs{
						FailOverCriterion: func() types.String {
							if vpnTrafficUplinkPreferences.FailOverCriterion != "" {
								return types.StringValue(vpnTrafficUplinkPreferences.FailOverCriterion)
							}
							return types.String{}
						}(),
						PerformanceClass: func() *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesPerformanceClassRs {
							if vpnTrafficUplinkPreferences.PerformanceClass != nil {
								return &ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesPerformanceClassRs{
									BuiltinPerformanceClassName: func() types.String {
										if vpnTrafficUplinkPreferences.PerformanceClass.BuiltinPerformanceClassName != "" {
											return types.StringValue(vpnTrafficUplinkPreferences.PerformanceClass.BuiltinPerformanceClassName)
										}
										return types.String{}
									}(),
									CustomPerformanceClassID: func() types.String {
										if vpnTrafficUplinkPreferences.PerformanceClass.CustomPerformanceClassID != "" {
											return types.StringValue(vpnTrafficUplinkPreferences.PerformanceClass.CustomPerformanceClassID)
										}
										return types.String{}
									}(),
									Type: func() types.String {
										if vpnTrafficUplinkPreferences.PerformanceClass.Type != "" {
											return types.StringValue(vpnTrafficUplinkPreferences.PerformanceClass.Type)
										}
										return types.String{}
									}(),
								}
							}
							return nil
						}(),
						PreferredUplink: func() types.String {
							if vpnTrafficUplinkPreferences.PreferredUplink != "" {
								return types.StringValue(vpnTrafficUplinkPreferences.PreferredUplink)
							}
							return types.String{}
						}(),
						TrafficFilters: func() *[]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersRs {
							if vpnTrafficUplinkPreferences.TrafficFilters != nil {
								result := make([]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersRs, len(*vpnTrafficUplinkPreferences.TrafficFilters))
								for i, trafficFilters := range *vpnTrafficUplinkPreferences.TrafficFilters {
									result[i] = ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersRs{
										Type: func() types.String {
											if trafficFilters.Type != "" {
												return types.StringValue(trafficFilters.Type)
											}
											return types.String{}
										}(),
										Value: func() *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueRs {
											if trafficFilters.Value != nil {
												return &ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueRs{
													Destination: func() *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueDestinationRs {
														if trafficFilters.Value.Destination != nil {
															return &ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueDestinationRs{
																Cidr: func() types.String {
																	if trafficFilters.Value.Destination.Cidr != "" {
																		return types.StringValue(trafficFilters.Value.Destination.Cidr)
																	}
																	return types.String{}
																}(),
																Fqdn: func() types.String {
																	if trafficFilters.Value.Destination.Fqdn != "" {
																		return types.StringValue(trafficFilters.Value.Destination.Fqdn)
																	}
																	return types.String{}
																}(),
																Host: func() types.Int64 {
																	if trafficFilters.Value.Destination.Host != nil {
																		return types.Int64Value(int64(*trafficFilters.Value.Destination.Host))
																	}
																	return types.Int64{}
																}(),
																Network: func() types.String {
																	if trafficFilters.Value.Destination.Network != "" {
																		return types.StringValue(trafficFilters.Value.Destination.Network)
																	}
																	return types.String{}
																}(),
																Port: func() types.String {
																	if trafficFilters.Value.Destination.Port != "" {
																		return types.StringValue(trafficFilters.Value.Destination.Port)
																	}
																	return types.String{}
																}(),
																VLAN: func() types.Int64 {
																	if trafficFilters.Value.Destination.VLAN != nil {
																		return types.Int64Value(int64(*trafficFilters.Value.Destination.VLAN))
																	}
																	return types.Int64{}
																}(),
															}
														}
														return nil
													}(),
													ID: func() types.String {
														if trafficFilters.Value.ID != "" {
															return types.StringValue(trafficFilters.Value.ID)
														}
														return types.String{}
													}(),
													Protocol: func() types.String {
														if trafficFilters.Value.Protocol != "" {
															return types.StringValue(trafficFilters.Value.Protocol)
														}
														return types.String{}
													}(),
													Source: func() *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueSourceRs {
														if trafficFilters.Value.Source != nil {
															return &ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionVpnTrafficUplinkPreferencesTrafficFiltersValueSourceRs{
																Cidr: func() types.String {
																	if trafficFilters.Value.Source.Cidr != "" {
																		return types.StringValue(trafficFilters.Value.Source.Cidr)
																	}
																	return types.String{}
																}(),
																Host: func() types.Int64 {
																	if trafficFilters.Value.Source.Host != nil {
																		return types.Int64Value(int64(*trafficFilters.Value.Source.Host))
																	}
																	return types.Int64{}
																}(),
																Network: func() types.String {
																	if trafficFilters.Value.Source.Network != "" {
																		return types.StringValue(trafficFilters.Value.Source.Network)
																	}
																	return types.String{}
																}(),
																Port: func() types.String {
																	if trafficFilters.Value.Source.Port != "" {
																		return types.StringValue(trafficFilters.Value.Source.Port)
																	}
																	return types.String{}
																}(),
																VLAN: func() types.Int64 {
																	if trafficFilters.Value.Source.VLAN != nil {
																		return types.Int64Value(int64(*trafficFilters.Value.Source.VLAN))
																	}
																	return types.Int64{}
																}(),
															}
														}
														return nil
													}(),
												}
											}
											return nil
										}(),
									}
								}
								return &result
							}
							return nil
						}(),
					}
				}
				return &result
			}
			return nil
		}(),
		WanTrafficUplinkPreferences: func() *[]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesRs {
			if response.WanTrafficUplinkPreferences != nil {
				result := make([]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesRs, len(*response.WanTrafficUplinkPreferences))
				for i, wanTrafficUplinkPreferences := range *response.WanTrafficUplinkPreferences {
					result[i] = ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesRs{
						PreferredUplink: func() types.String {
							if wanTrafficUplinkPreferences.PreferredUplink != "" {
								return types.StringValue(wanTrafficUplinkPreferences.PreferredUplink)
							}
							return types.String{}
						}(),
						TrafficFilters: func() *[]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersRs {
							if wanTrafficUplinkPreferences.TrafficFilters != nil {
								result := make([]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersRs, len(*wanTrafficUplinkPreferences.TrafficFilters))
								for i, trafficFilters := range *wanTrafficUplinkPreferences.TrafficFilters {
									result[i] = ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersRs{
										Type: func() types.String {
											if trafficFilters.Type != "" {
												return types.StringValue(trafficFilters.Type)
											}
											return types.String{}
										}(),
										Value: func() *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueRs {
											if trafficFilters.Value != nil {
												return &ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueRs{
													Destination: func() *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestinationRs {
														if trafficFilters.Value.Destination != nil {
															return &ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestinationRs{
																Applications: func() *[]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestinationApplicationsRs {
																	if trafficFilters.Value.Destination.Applications != nil {
																		result := make([]ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestinationApplicationsRs, len(*trafficFilters.Value.Destination.Applications))
																		for i, applications := range *trafficFilters.Value.Destination.Applications {
																			result[i] = ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueDestinationApplicationsRs{
																				ID: func() types.String {
																					if applications.ID != "" {
																						return types.StringValue(applications.ID)
																					}
																					return types.String{}
																				}(),
																				Name: func() types.String {
																					if applications.Name != "" {
																						return types.StringValue(applications.Name)
																					}
																					return types.String{}
																				}(),
																				Type: func() types.String {
																					if applications.Type != "" {
																						return types.StringValue(applications.Type)
																					}
																					return types.String{}
																				}(),
																			}
																		}
																		return &result
																	}
																	return nil
																}(),
																Cidr: func() types.String {
																	if trafficFilters.Value.Destination.Cidr != "" {
																		return types.StringValue(trafficFilters.Value.Destination.Cidr)
																	}
																	return types.String{}
																}(),
																Port: func() types.String {
																	if trafficFilters.Value.Destination.Port != "" {
																		return types.StringValue(trafficFilters.Value.Destination.Port)
																	}
																	return types.String{}
																}(),
															}
														}
														return nil
													}(),
													Protocol: func() types.String {
														if trafficFilters.Value.Protocol != "" {
															return types.StringValue(trafficFilters.Value.Protocol)
														}
														return types.String{}
													}(),
													Source: func() *ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueSourceRs {
														if trafficFilters.Value.Source != nil {
															return &ResponseApplianceGetNetworkApplianceTrafficShapingUplinkSelectionWanTrafficUplinkPreferencesTrafficFiltersValueSourceRs{
																Cidr: func() types.String {
																	if trafficFilters.Value.Source.Cidr != "" {
																		return types.StringValue(trafficFilters.Value.Source.Cidr)
																	}
																	return types.String{}
																}(),
																Host: func() types.Int64 {
																	if trafficFilters.Value.Source.Host != nil {
																		return types.Int64Value(int64(*trafficFilters.Value.Source.Host))
																	}
																	return types.Int64{}
																}(),
																Port: func() types.String {
																	if trafficFilters.Value.Source.Port != "" {
																		return types.StringValue(trafficFilters.Value.Source.Port)
																	}
																	return types.String{}
																}(),
																VLAN: func() types.Int64 {
																	if trafficFilters.Value.Source.VLAN != nil {
																		return types.Int64Value(int64(*trafficFilters.Value.Source.VLAN))
																	}
																	return types.Int64{}
																}(),
															}
														}
														return nil
													}(),
												}
											}
											return nil
										}(),
									}
								}
								return &result
							}
							return nil
						}(),
					}
				}
				return &result
			}
			return nil
		}(),
	}
	if is_read {
		return mergeInterfacesOnlyPath(state, itemState).(NetworksApplianceTrafficShapingUplinkSelectionRs)
	}
	return mergeInterfaces(state, itemState, true).(NetworksApplianceTrafficShapingUplinkSelectionRs)
}
