package flattens

import (
	"context"

	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/account"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"

	"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/terraform-provider-dynamix/internal/service/cloudapi/account/models"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/account/utilities"
)

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

	diags := diag.Diagnostics{}

	rgList, err := utilities.AccountRGListCheckPresence(ctx, state, c)
	if err != nil {
		diags.AddError("Cannot get info about account rg list", err.Error())
		return diags
	}

	tflog.Info(ctx, "flattens.AccountRGListDataSource: before flatten")

	id := uuid.New()
	*state = models.DataSourceAccountRGListModel{
		AccountID: state.AccountID,
		RGID:      state.RGID,
		VinsID:    state.VinsID,
		VMID:      state.VMID,
		Name:      state.Name,
		Status:    state.Status,
		Page:      state.Page,
		Size:      state.Size,
		Timeouts:  state.Timeouts,
		SortBy:    state.SortBy,

		Id:         types.StringValue(id.String()),
		EntryCount: types.Int64Value(int64(rgList.EntryCount)),
	}

	items := make([]models.ItemAccountRGModel, 0, len(rgList.Data))
	for _, item := range rgList.Data {
		i := models.ItemAccountRGModel{
			Computes: &models.RGComputesModel{
				Started: types.Int64Value(int64(item.Computes.Started)),
				Stopped: types.Int64Value(int64(item.Computes.Stopped)),
			},
			Resources: &models.RGResourcesModel{
				Consumed: &models.ResourceModel{
					CPU:         types.Int64Value(item.Resources.Consumed.CPU),
					DiskSize:    types.Float64Value(item.Resources.Consumed.DiskSize),
					DiskSizeMax: types.Float64Value(item.Resources.Consumed.DiskSizeMax),
					ExtIPs:      types.Int64Value(item.Resources.Consumed.ExtIPs),
					ExtTraffic:  types.Int64Value(item.Resources.Consumed.ExtTraffic),
					GPU:         types.Int64Value(item.Resources.Consumed.GPU),
					RAM:         types.Int64Value(item.Resources.Consumed.RAM),
					SEPs:        flattenSep(item.Resources.Consumed.SEPs),
				},
				Limits: &models.LimitsRGModel{
					CPU:         types.Int64Value(item.Resources.Limits.CPU),
					DiskSize:    types.Int64Value(item.Resources.Limits.DiskSize),
					DiskSizeMax: types.Int64Value(item.Resources.Limits.DiskSizeMax),
					ExtIPs:      types.Int64Value(item.Resources.Limits.ExtIPs),
					ExtTraffic:  types.Int64Value(item.Resources.Limits.ExtTraffic),
					GPU:         types.Int64Value(item.Resources.Limits.GPU),
					RAM:         types.Int64Value(item.Resources.Limits.RAM),
					SEPs:        types.Int64Value(int64(item.Resources.Limits.SEPs)),
				},
				Reserved: &models.ResourceModel{
					CPU:         types.Int64Value(item.Resources.Reserved.CPU),
					DiskSize:    types.Float64Value(item.Resources.Reserved.DiskSize),
					DiskSizeMax: types.Float64Value(item.Resources.Reserved.DiskSizeMax),
					ExtIPs:      types.Int64Value(item.Resources.Reserved.ExtIPs),
					ExtTraffic:  types.Int64Value(item.Resources.Reserved.ExtTraffic),
					GPU:         types.Int64Value(item.Resources.Reserved.GPU),
					RAM:         types.Int64Value(item.Resources.Reserved.RAM),
					SEPs:        flattenSep(item.Resources.Reserved.SEPs),
				},
			},
			CreatedBy:   types.StringValue(item.CreatedBy),
			CreatedTime: types.Int64Value(int64(item.CreatedTime)),
			DeletedBy:   types.StringValue(item.DeletedBy),
			DeletedTime: types.Int64Value(int64(item.DeletedTime)),
			Desc:        types.StringValue(item.Description),
			RGID:        types.Int64Value(int64(item.RGID)),
			Milestones:  types.Int64Value(int64(item.Milestones)),
			RGName:      types.StringValue(item.RGName),
			Status:      types.StringValue(item.Status),
			UpdatedBy:   types.StringValue(item.UpdatedBy),
			UpdatedTime: types.Int64Value(int64(item.UpdatedTime)),
			VINSes:      types.Int64Value(int64(item.VINSes)),
		}

		items = append(items, i)
	}
	state.Items = items

	tflog.Info(ctx, "End flattens.AccountRGListDataSource")
	return nil
}

func flattenSep(seps map[string]map[string]account.DiskUsage) []models.SepModel {
	res := make([]models.SepModel, 0, len(seps))
	for sepId := range seps {
		for poolName, diskData := range seps[sepId] {
			s := models.SepModel{
				SepID:       types.StringValue(sepId),
				PoolName:    types.StringValue(poolName),
				DiskSize:    types.Float64Value(diskData.DiskSize),
				DiskSizeMax: types.Float64Value(diskData.DiskSizeMax),
			}
			res = append(res, s)
		}
	}
	return res
}
