package logicalports

import (
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/sdn/logicalports"
)

func flattenLogicalPortResource(d *schema.ResourceData, logicalPort *logicalports.LogicalPort) {
	d.Set("id", logicalPort.ID)
	d.Set("access_group_id", logicalPort.AccessGroupID)
	d.Set("access_group_name", logicalPort.AccessGroupName)
	d.Set("adapter_mac", logicalPort.AdapterMAC)
	d.Set("address_detection", logicalPort.AddressDetection)
	d.Set("description", logicalPort.Description)
	d.Set("display_name", logicalPort.DisplayName)
	d.Set("enabled", logicalPort.Enabled)
	d.Set("external_network_id", logicalPort.ExternalNetworkID)
	d.Set("hypervisor", logicalPort.Hypervisor)
	d.Set("hypervisor_display_name", logicalPort.HypervisorDisplayName)
	d.Set("live_migration_target_hv", logicalPort.LiveMigrationTargetHV)
	d.Set("status", flattenStatus(logicalPort.Status))
	d.Set("unique_identifier", logicalPort.UniqueIdentifier)
	d.Set("version_id", logicalPort.VersionID)
	d.Set("bindings", flattenBindings(logicalPort.Bindings))
	d.Set("labels", flattenLabels(logicalPort.Labels))
	d.Set("created_at", logicalPort.CreatedAt)
}

func flattenLogicalPortList(lpl *logicalports.LogicalPortsList) []map[string]interface{} {
	res := make([]map[string]interface{}, 0, len(lpl.Ports))
	for _, v := range lpl.Ports {
		temp := map[string]interface{}{
			"id":                       v.ID,
			"access_group_id":          v.AccessGroupID,
			"access_group_name":        v.AccessGroupName,
			"adapter_mac":              v.AdapterMAC,
			"address_detection":        v.AddressDetection,
			"description":              v.Description,
			"display_name":             v.DisplayName,
			"enabled":                  v.Enabled,
			"hypervisor":               v.Hypervisor,
			"hypervisor_display_name":  v.HypervisorDisplayName,
			"external_network_id":      v.ExternalNetworkID,
			"live_migration_target_hv": v.LiveMigrationTargetHV,
			"status":                   flattenStatus(v.Status),
			"unique_identifier":        v.UniqueIdentifier,
			"version_id":               v.VersionID,
			"bindings":                 flattenBindings(v.Bindings),
			"labels":                   flattenLabels(v.Labels),
			"created_at":               v.CreatedAt,
			"updated_at":               v.UpdatedAt,
		}
		res = append(res, temp)
	}
	return res
}

func flattenLogicalPort(d *schema.ResourceData, logicalPort *logicalports.LogicalPort) {
	d.Set("id", logicalPort.ID)
	d.Set("access_group_id", logicalPort.AccessGroupID)
	d.Set("access_group_name", logicalPort.AccessGroupName)
	d.Set("adapter_mac", logicalPort.AdapterMAC)
	d.Set("address_detection", logicalPort.AddressDetection)
	d.Set("description", logicalPort.Description)
	d.Set("display_name", logicalPort.DisplayName)
	d.Set("enabled", logicalPort.Enabled)
	d.Set("external_network_id", logicalPort.ExternalNetworkID)
	d.Set("hypervisor", logicalPort.Hypervisor)
	d.Set("hypervisor_display_name", logicalPort.HypervisorDisplayName)
	d.Set("live_migration_target_hv", logicalPort.LiveMigrationTargetHV)
	d.Set("status", flattenStatus(logicalPort.Status))
	d.Set("unique_identifier", logicalPort.UniqueIdentifier)
	d.Set("version_id", logicalPort.VersionID)
	d.Set("bindings", flattenBindings(logicalPort.Bindings))
	d.Set("labels", flattenLabels(logicalPort.Labels))
	d.Set("created_at", logicalPort.CreatedAt)
	d.Set("updated_at", logicalPort.UpdatedAt)
}

func flattenLabels(labels logicalports.Labels) []map[string]interface{} {
	if labels.VMID == "" && labels.VMName == "" {
		return []map[string]interface{}{}
	}
	return []map[string]interface{}{
		{
			"vm_id":   labels.VMID,
			"vm_name": labels.VMName,
		},
	}
}

func flattenBindings(bindings logicalports.Bindings) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"id":                     bindings.ID,
		"segment_id":             bindings.SegmentID,
		"segment_display_name":   bindings.SegmentDisplayName,
		"port_security":          bindings.PortSecurity,
		"address_detection":      bindings.AddressDetection,
		"version_id":             bindings.VersionID,
		"created_at":             bindings.CreatedAt,
		"updated_at":             bindings.UpdatedAt,
		"logical_port_addresses": flattenLogicalPortAddresses(bindings.LogicalPortAddresses),
	}
	res = append(res, temp)
	return res
}

func flattenLogicalPortAddresses(addrs []logicalports.LogicalPortAddress) []map[string]interface{} {
	res := make([]map[string]interface{}, 0, len(addrs))
	for _, a := range addrs {
		res = append(res, map[string]interface{}{
			"ip":              a.IP,
			"ip_type":         a.IPType,
			"mac":             a.MAC,
			"id":              a.ID,
			"logical_port_id": a.LogicalPortID,
			"assigned_at":     a.AssignedAt,
			"is_discovered":   a.IsDiscovered,
			"is_primary":      a.IsPrimary,
		})
	}
	return res
}

func flattenStatus(status logicalports.Status) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"operation_status":  status.OperationStatus,
		"hypervisor_status": status.HypervisorStatus,
		"hypervisors":       flattenHypervisors(status.Hypervisors),
	}
	res = append(res, temp)
	return res
}

func flattenHypervisors(hv []logicalports.HypervisorStatus) []map[string]interface{} {
	res := make([]map[string]interface{}, 0, len(hv))
	for _, v := range hv {
		temp := map[string]interface{}{
			"operation_status":  v.OperationStatus,
			"name":              v.Name,
			"display_name":      v.DisplayName,
			"hypervisor_status": v.HypervisorStatus,
			"synced_at":         v.SyncedAt,
		}
		res = append(res, temp)
	}
	return res
}
