package flattens

import (
	"context"
	"fmt"

	"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/decort-golang-sdk/pkg/cloudbroker/rg"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/rg/models"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudbroker/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:       flattenResource(ctx, &resourceItem.Consumed),
		Reserved:       flattenResource(ctx, &resourceItem.Reserved),
		ResourceLimits: flattenResourceLimits(ctx, &resourceItem.ResourceLimits),
	}

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

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

func flattenResource(ctx context.Context, item *rg.Reservation) types.Object {
	tflog.Info(ctx, "Start flattenResource")
	temp := models.ResourceModel{
		CPU:         types.Int64Value(item.CPU),
		DiskSize:    types.Float64Value(item.DiskSize),
		DiskSizeMax: types.Float64Value(item.DiskSizeMax),
		ExtIPs:      types.Int64Value(item.ExtIPs),
		ExtTraffic:  types.Int64Value(item.ExtTraffic),
		GPU:         types.Int64Value(item.GPU),
		RAM:         types.Int64Value(item.RAM),
		SEPs:        flattenSEPs(ctx, item.SEPs),
	}
	res, diags := types.ObjectValueFrom(ctx, models.ItemResource, temp)
	if diags != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenResource struct to obj", diags))
	}

	tflog.Info(ctx, "End flattenResource")
	return res
}

func flattenSEPs(ctx context.Context, seps map[string]map[string]rg.DiskUsage) types.List {
	tflog.Info(ctx, "Start flattenSEPs")
	tempSlice := make([]types.Object, 0, len(seps))
	for sepId, data := range 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),
			}
			obj, err := types.ObjectValueFrom(ctx, models.ItemSEPs, sepItem)
			if err != nil {
				tflog.Error(ctx, fmt.Sprint("Error flattenSEPs struct to obj", err))
			}
			tempSlice = append(tempSlice, obj)
		}
	}

	res, err := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: models.ItemSEPs}, tempSlice)
	if err != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenSEPs", err))
	}

	tflog.Info(ctx, "End flattenSEPs")
	return res
}
