package flattens

import (
	"context"
	"fmt"

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

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

	diags := diag.Diagnostics{}

	accountId := uint64(state.AccountID.ValueInt64())

	record, err := utilities.AccountGetResourceConsumptionDataSourceCheckPresence(ctx, accountId, c)
	if err != nil {
		diags.AddError(fmt.Sprintf("Cannot get info about account with ID %v", accountId), err.Error())
		return diags
	}

	tflog.Info(ctx, "flattens.AccountGetResourceConsumptionDataSource: before flatten", map[string]any{"account_id": accountId, "record": record})

	*state = models.AccountGetResourceConsumptionModel{
		AccountID: state.AccountID,
		Timeouts:  state.Timeouts,

		Consumed: &models.ResourceConsumptionModel{
			CPU:         types.Int64Value(record.Consumed.CPU),
			DiskSize:    types.Float64Value(record.Consumed.DiskSize),
			DiskSizeMax: types.Float64Value(record.Consumed.DiskSizeMax),
			ExtIPs:      types.Int64Value(record.Consumed.ExtIPs),
			ExtTraffic:  types.Int64Value(record.Consumed.ExtTraffic),
			GPU:         types.Int64Value(record.Consumed.GPU),
			RAM:         types.Int64Value(record.Consumed.RAM),
			SEPs:        flattenResourceConsumptionSep(ctx, record.Consumed.SEPs),
		},
		Limits: &models.ResourceConsumptionLimitsModel{
			CUC:      types.Float64Value(record.ResourceLimits.CuC),
			CUD:      types.Float64Value(record.ResourceLimits.CuD),
			CUI:      types.Float64Value(record.ResourceLimits.CuI),
			CUM:      types.Float64Value(record.ResourceLimits.CuM),
			CUDM:     types.Float64Value(record.ResourceLimits.CuDM),
			CUNP:     types.Float64Value(record.ResourceLimits.CuNP),
			GPUUnits: types.Float64Value(record.ResourceLimits.GPUUnits),
		},
		Reserved: &models.ResourceConsumptionModel{
			CPU:         types.Int64Value(record.Reserved.CPU),
			DiskSize:    types.Float64Value(record.Reserved.DiskSize),
			DiskSizeMax: types.Float64Value(record.Reserved.DiskSizeMax),
			ExtIPs:      types.Int64Value(record.Reserved.ExtIPs),
			ExtTraffic:  types.Int64Value(record.Reserved.ExtTraffic),
			GPU:         types.Int64Value(record.Reserved.GPU),
			RAM:         types.Int64Value(record.Reserved.RAM),
			SEPs:        flattenResourceConsumptionSep(ctx, record.Reserved.SEPs),
		},
	}

	tflog.Info(ctx, "flattens.AccountGetResourceConsumptionDataSource: after flatten", map[string]any{"account_id": state.AccountID.ValueInt64()})

	tflog.Info(ctx, "End flattens.AccountGetResourceConsumptionDataSource", map[string]any{"account_id": state.AccountID.ValueInt64()})
	return nil
}

func flattenResourceConsumptionSep(ctx context.Context, seps map[string]map[string]account.DiskUsage) []models.ResourceConsumptionSepModel {
	tflog.Info(ctx, "Start flattenResourceConsumption")
	res := make([]models.ResourceConsumptionSepModel, 0, len(seps))
	for sepId := range seps {
		for poolName, diskData := range seps[sepId] {
			s := models.ResourceConsumptionSepModel{
				SepID:       types.StringValue(sepId),
				PoolName:    types.StringValue(poolName),
				DiskSize:    types.Float64Value(diskData.DiskSize),
				DiskSizeMax: types.Float64Value(diskData.DiskSizeMax),
			}
			res = append(res, s)
		}
	}
	tflog.Info(ctx, "End flattenResourceConsumption")
	return res
}
