package flattens

import (
	"context"

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

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

	diags := diag.Diagnostics{}

	resourceItem, err := utilities.RGGetResourceConsumptionCheckPresence(ctx, state, c)
	if err != nil {
		diags.AddError("Cannot get info about resource group get resource consumption", err.Error())
		return diags
	}

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

	id := uuid.New()
	*state = models.DataSourceRGGetResourceConsumptionModel{
		RGID:     state.RGID,
		Timeouts: state.Timeouts,
		Id:       types.StringValue(id.String()),

		Consumed: &models.ResourceModel{
			CPU:         types.Int64Value(resourceItem.Consumed.CPU),
			DiskSize:    types.Float64Value(resourceItem.Consumed.DiskSize),
			DiskSizeMax: types.Float64Value(resourceItem.Consumed.DiskSizeMax),
			ExtIPs:      types.Int64Value(resourceItem.Consumed.ExtIPs),
			ExtTraffic:  types.Int64Value(resourceItem.Consumed.ExtTraffic),
			GPU:         types.Int64Value(resourceItem.Consumed.GPU),
			RAM:         types.Int64Value(resourceItem.Consumed.RAM),
		},
		Reserved: &models.ResourceModel{
			CPU:         types.Int64Value(resourceItem.Reserved.CPU),
			DiskSize:    types.Float64Value(resourceItem.Reserved.DiskSize),
			DiskSizeMax: types.Float64Value(resourceItem.Reserved.DiskSizeMax),
			ExtIPs:      types.Int64Value(resourceItem.Reserved.ExtIPs),
			ExtTraffic:  types.Int64Value(resourceItem.Reserved.ExtTraffic),
			GPU:         types.Int64Value(resourceItem.Reserved.GPU),
			RAM:         types.Int64Value(resourceItem.Reserved.RAM),
		},
		ResourceLimits: &models.ResourceLimitsModel{
			CUC:      types.Float64Value(resourceItem.ResourceLimits.CUC),
			CUD:      types.Float64Value(resourceItem.ResourceLimits.CUD),
			CUDM:     types.Float64Value(resourceItem.ResourceLimits.CUDM),
			CUI:      types.Float64Value(resourceItem.ResourceLimits.CUI),
			CUM:      types.Float64Value(resourceItem.ResourceLimits.CUM),
			CUNP:     types.Float64Value(resourceItem.ResourceLimits.CUNP),
			GPUUnits: types.Float64Value(resourceItem.ResourceLimits.GPUUnits),
		},
	}

	sepsConsumed := make([]models.SEPsModel, 0, len(resourceItem.Consumed.SEPs))
	for sepId, data := range resourceItem.Consumed.SEPs {
		for dataName, diskData := range data {
			sepItem := models.SEPsModel{
				SepID:       types.StringValue(sepId),
				DataName:    types.StringValue(dataName),
				DiskSize:    types.Float64Value(diskData.DiskSize),
				DiskSizeMax: types.Float64Value(diskData.DiskSizeMax),
			}
			sepsConsumed = append(sepsConsumed, sepItem)
		}
	}
	state.Consumed.SEPs = sepsConsumed

	sepsReserved := make([]models.SEPsModel, 0, len(resourceItem.Reserved.SEPs))
	for sepId, data := range resourceItem.Reserved.SEPs {
		for dataName, diskData := range data {
			sepItem := models.SEPsModel{
				SepID:       types.StringValue(sepId),
				DataName:    types.StringValue(dataName),
				DiskSize:    types.Float64Value(diskData.DiskSize),
				DiskSizeMax: types.Float64Value(diskData.DiskSizeMax),
			}
			sepsReserved = append(sepsReserved, sepItem)
		}
	}
	state.Reserved.SEPs = sepsReserved

	tflog.Info(ctx, "flattens.RGGetResourceConsumptionDataSource: after flatten")

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