package flattens

import (
	"context"
	"fmt"

	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/rg"

	"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"
)

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

	diags := diag.Diagnostics{}

	rgListComputes, err := utilities.RGListComputesCheckPresence(ctx, state, c)
	if err != nil {
		diags.AddError("Cannot get info about resource group list computes", err.Error())
		return diags
	}

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

	id := uuid.New()
	*state = models.DataSourceRGListComputesModel{
		RGID:       state.RGID,
		ComputeID:  state.ComputeID,
		Name:       state.Name,
		AccountID:  state.AccountID,
		TechStatus: state.TechStatus,
		Status:     state.Status,
		IPAddress:  state.IPAddress,
		ExtNetName: state.ExtNetName,
		ExtNetID:   state.ExtNetID,
		SortBy:     state.SortBy,
		Page:       state.Page,
		Size:       state.Size,
		Timeouts:   state.Timeouts,

		Id: types.StringValue(id.String()),
	}

	items := make([]models.ItemsRGListComputeModel, 0, len(rgListComputes.Data))
	for _, compItem := range rgListComputes.Data {
		item := models.ItemsRGListComputeModel{
			AccountID:         types.Int64Value(int64(compItem.AccountID)),
			AccountName:       types.StringValue(compItem.AccountName),
			AffinityLabel:     types.StringValue(compItem.AffinityLabel),
			AffinityRules:     flattenAffinityRules(ctx, &compItem.AffinityRules),
			AffinityWeight:    types.Int64Value(int64(compItem.AffinityWeight)),
			AntiAffinityRules: flattenAffinityRules(ctx, &compItem.AntiAffinityRules),
			CPUs:              types.Int64Value(int64(compItem.CPUs)),
			CreatedBy:         types.StringValue(compItem.CreatedBy),
			CreatedTime:       types.Int64Value(int64(compItem.CreatedTime)),
			DeletedBy:         types.StringValue(compItem.DeletedBy),
			DeletedTime:       types.Int64Value(int64(compItem.DeletedTime)),
			ID:                types.Int64Value(int64(compItem.ID)),
			Name:              types.StringValue(compItem.Name),
			RAM:               types.Int64Value(int64(compItem.RAM)),
			Registered:        types.BoolValue(compItem.Registered),
			RGName:            types.StringValue(compItem.RGName),
			Status:            types.StringValue(compItem.Status),
			TechStatus:        types.StringValue(compItem.TechStatus),
			TotalDisksSize:    types.Int64Value(int64(compItem.TotalDisksSize)),
			UpdatedBy:         types.StringValue(compItem.UpdatedBy),
			UpdatedTime:       types.Int64Value(int64(compItem.UpdatedTime)),
			UserManaged:       types.BoolValue(compItem.UserManaged),
			VINSConnected:     types.Int64Value(int64(compItem.VINSConnected)),
		}

		items = append(items, item)
	}

	state.Items = items
	state.EntryCount = types.Int64Value(int64(rgListComputes.EntryCount))

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

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

func flattenAffinityRules(ctx context.Context, items *rg.ListRules) types.List {
	tflog.Info(ctx, "Start flattenAffinityRules")
	tempSlice := make([]types.Object, 0, len(*items))
	for _, ruleItem := range *items {
		temp := models.AffinityRuleModel{
			GUID:     types.StringValue(ruleItem.GUID),
			Key:      types.StringValue(ruleItem.Key),
			Mode:     types.StringValue(ruleItem.Mode),
			Policy:   types.StringValue(ruleItem.Policy),
			Topology: types.StringValue(ruleItem.Topology),
			Value:    types.StringValue(ruleItem.Value),
		}

		obj, diags := types.ObjectValueFrom(ctx, models.ItemAffinityRule, temp)
		if diags != nil {
			tflog.Error(ctx, fmt.Sprint("Error flattenAffinityRules struct to obj", diags))
		}
		tempSlice = append(tempSlice, obj)
	}

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

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