package account

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

func flattenAccount(d *schema.ResourceData, acc account.RecordAccount) error {
	d.Set("dc_location", acc.DCLocation)
	d.Set("desc", acc.Description)
	d.Set("acl", flattenAccAcl(acc.ACL))
	d.Set("company", acc.Company)
	d.Set("companyurl", acc.CompanyURL)
	d.Set("compute_features", acc.ComputeFeatures)
	d.Set("created_by", acc.CreatedBy)
	d.Set("created_time", acc.CreatedTime)
	d.Set("deactivation_time", acc.DeactivationTime)
	d.Set("desc", acc.Description)
	d.Set("deleted_by", acc.DeletedBy)
	d.Set("deleted_time", acc.DeletedTime)
	d.Set("displayname", acc.DisplayName)
	d.Set("enable", flattenEnabled(acc.Status))
	d.Set("guid", acc.GUID)
	d.Set("account_id", acc.ID)
	d.Set("account_name", acc.Name)
	d.Set("resource_limits", flattenAccResourceLimits(acc.ResourceLimits))
	d.Set("send_access_emails", acc.SendAccessEmails)
	d.Set("status", acc.Status)
	d.Set("updated_by", acc.UpdatedBy)
	d.Set("updated_time", acc.UpdatedTime)
	d.Set("version", acc.Version)
	d.Set("vins", acc.VINS)
	d.Set("vinses", acc.VINSes)
	d.Set("computes", flattenAccComputes(acc.Computes))
	d.Set("machines", flattenAccMachines(acc.Machines))
	d.Set("cpu_allocation_parameter", acc.CPUAllocationParameter)
	d.Set("cpu_allocation_ratio", acc.CPUAllocationRatio)
	d.Set("default_zone_id", acc.DefaultZoneID)
	d.Set("storage_policy_ids", acc.StoragePolicyIDs)
	d.Set("zone_ids", flattenZones(acc.ZoneIDs))

	if username, ok := d.GetOk("username"); ok {
		d.Set("username", username)
	} else {
		d.Set("username", acc.ACL[0].UgroupID)
	}

	return nil
}

func flattenAccountResource(d *schema.ResourceData, acc account.RecordAccount) error {
	d.Set("dc_location", acc.DCLocation)
	d.Set("desc", acc.Description)
	d.Set("acl", flattenAccAcl(acc.ACL))
	d.Set("company", acc.Company)
	d.Set("companyurl", acc.CompanyURL)
	d.Set("compute_features", acc.ComputeFeatures)
	d.Set("created_by", acc.CreatedBy)
	d.Set("created_time", acc.CreatedTime)
	d.Set("deactivation_time", acc.DeactivationTime)
	d.Set("desc", acc.Description)
	d.Set("deleted_by", acc.DeletedBy)
	d.Set("deleted_time", acc.DeletedTime)
	d.Set("displayname", acc.DisplayName)
	d.Set("enable", flattenEnabled(acc.Status))
	d.Set("guid", acc.GUID)
	d.Set("account_id", acc.ID)
	d.Set("account_name", acc.Name)
	d.Set("resource_limits", flattenAccResourceLimits(acc.ResourceLimits))
	d.Set("send_access_emails", acc.SendAccessEmails)
	d.Set("status", acc.Status)
	d.Set("updated_by", acc.UpdatedBy)
	d.Set("updated_time", acc.UpdatedTime)
	d.Set("version", acc.Version)
	d.Set("vins", acc.VINS)
	d.Set("vinses", acc.VINSes)
	d.Set("computes", flattenAccComputes(acc.Computes))
	d.Set("machines", flattenAccMachines(acc.Machines))
	d.Set("cpu_allocation_parameter", acc.CPUAllocationParameter)
	d.Set("cpu_allocation_ratio", acc.CPUAllocationRatio)
	d.Set("default_zone_id", acc.DefaultZoneID)
	d.Set("storage_policy_ids", acc.StoragePolicyIDs)
	d.Set("zone_ids", flattenZonesInResource(acc.ZoneIDs))

	return nil
}

func flattenEnabled(status string) bool {
	return status == "CONFIRMED"
}

func flattenAccComputes(acs account.Computes) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"started": acs.Started,
		"stopped": acs.Stopped,
	}
	res = append(res, temp)
	return res
}

func flattenAccMachines(ams account.Machines) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"running": ams.Running,
		"halted":  ams.Halted,
	}
	res = append(res, temp)
	return res
}

func flattenAccAcl(acls []account.RecordACL) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	for _, acls := range acls {
		temp := map[string]interface{}{
			"can_be_deleted": acls.CanBeDeleted,
			"explicit":       acls.IsExplicit,
			"guid":           acls.GUID,
			"right":          acls.Rights,
			"status":         acls.Status,
			"type":           acls.Type,
			"emails":         acls.Emails,
			"user_group_id":  acls.UgroupID,
		}
		res = append(res, temp)
	}
	return res
}

func flattenResourceConsumption(d *schema.ResourceData, acc *account.RecordResourceConsumption) {
	d.Set("account_id", acc.AccountID)
	d.Set("consumed", flattenAccResource(acc.Consumed))
	d.Set("reserved", flattenAccResource(acc.Reserved))
	d.Set("resource_limits", flattenAccResourceLimits(acc.ResourceLimits))
}

func flattenAccResourceLimits(rl account.ResourceLimits) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"cu_c":           rl.CUC,
		"cu_d":           rl.CUD,
		"cu_dm":          rl.CUDM,
		"cu_i":           rl.CUI,
		"cu_m":           rl.CUM,
		"gpu_units":      rl.GPUUnits,
		"storage_policy": flattenSTPolicy(rl.StoragePolicy),
	}
	res = append(res, temp)
	return res

}

func flattenSTPolicy(ast []account.StoragePolicyItem) []map[string]interface{} {
	res := make([]map[string]interface{}, 0, len(ast))
	for _, item := range ast {
		temp := map[string]interface{}{
			"id":    item.ID,
			"limit": item.Limit,
		}
		res = append(res, temp)
	}
	return res
}

func flattenAccountSeps(seps map[string]map[string]account.DiskUsage) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	for sepKey, sepVal := range seps {
		for dataKey, dataVal := range sepVal {
			temp := map[string]interface{}{
				"sep_id":        sepKey,
				"data_name":     dataKey,
				"disk_size":     dataVal.DiskSize,
				"disk_size_max": dataVal.DiskSizeMax,
			}
			res = append(res, temp)
		}
	}
	return res
}

func flattenAccResource(r account.Resource) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	temp := map[string]interface{}{
		"cpu":           r.CPU,
		"disk_size":     r.DiskSize,
		"disk_size_max": r.DiskSizeMax,
		"ext_ips":       r.ExtIPs,
		"gpu":           r.GPU,
		"ram":           r.RAM,
		"seps":          flattenAccountSeps(r.SEPs),
		"policies":      flattenAccountPolicies(r.Policies),
	}
	res = append(res, temp)
	return res
}

func flattenAccountPolicies(policies map[string]account.Policy) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	for k, dataVal := range policies {
		temp := map[string]interface{}{
			"id":            k,
			"disk_size":     dataVal.DiskSize,
			"disk_size_max": dataVal.DiskSizeMax,
			"seps":          flattenAccountSeps(dataVal.SEPs),
		}
		res = append(res, temp)
	}
	return res
}

func flattenAccResourceConsumption(lrc *account.ListResourceConsumption) []map[string]interface{} {
	res := make([]map[string]interface{}, 0, len(lrc.Data))
	for _, rc := range lrc.Data {
		temp := map[string]interface{}{
			"consumed":   flattenAccResource(rc.Consumed),
			"reserved":   flattenAccResource(rc.Reserved),
			"account_id": rc.AccountID,
		}
		res = append(res, temp)
	}
	return res
}

func flattenZones(zones []account.ZoneID) []map[string]interface{} {
	res := make([]map[string]interface{}, 0)
	for _, zone := range zones {
		temp := map[string]interface{}{
			"id":   zone.ID,
			"name": zone.Name,
		}
		res = append(res, temp)
	}
	return res
}

func flattenZonesInResource(zones []account.ZoneID) []int64 {
	res := make([]int64, 0)
	for _, zone := range zones {
		res = append(res, zone.ID)
	}
	return res
}
