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

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

	diags := diag.Diagnostics{}

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

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

	tflog.Info(ctx, "flattens.AccountDataSource: before flatten", map[string]any{"account_id": ID, "recordAccount": recordAccount})

	*state = models.DataSourceAccountModel{
		AccountID:              state.AccountID,
		Timeouts:               state.Timeouts,
		DCLocation:             types.StringValue(recordAccount.DCLocation),
		CKey:                   types.StringValue(recordAccount.CKey),
		ACL:                    flattenACLInAccount(ctx, recordAccount.ACL),
		Company:                types.StringValue(recordAccount.Company),
		CompanyURL:             types.StringValue(recordAccount.CompanyURL),
		CPUAllocationParameter: types.StringValue(recordAccount.CPUAllocationParameter),
		CPUAllocationRatio:     types.Float64Value(recordAccount.CPUAllocationRatio),
		CreatedBy:              types.StringValue(recordAccount.CreatedBy),
		CreatedTime:            types.Int64Value(int64(recordAccount.CreatedTime)),
		DeactivationTime:       types.Float64Value(recordAccount.DeactivationTime),
		DeletedBy:              types.StringValue(recordAccount.DeletedBy),
		DeletedTime:            types.Int64Value(int64(recordAccount.DeletedTime)),
		DisplayName:            types.StringValue(recordAccount.DisplayName),
		GUID:                   types.Int64Value(int64(recordAccount.GUID)),
		Name:                   types.StringValue(recordAccount.Name),
		ResourceLimits:         flattenResourceLimits(ctx, recordAccount.ResourceLimits),
		ResTypes:               flattens.FlattenSimpleTypeToList(ctx, types.StringType, recordAccount.ResTypes),
		SendAccessEmails:       types.BoolValue(recordAccount.SendAccessEmails),
		Status:                 types.StringValue(recordAccount.Status),
		UniqPools:              flattens.FlattenSimpleTypeToList(ctx, types.StringType, recordAccount.UniqPools),
		UpdatedTime:            types.Int64Value(int64(recordAccount.UpdatedTime)),
		Version:                types.Int64Value(int64(recordAccount.Version)),
		VINS:                   flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, recordAccount.VINS),
	}

	state.ComputeFeatures, diags = types.ListValueFrom(ctx, types.StringType, recordAccount.ComputeFeatures)
	if diags.HasError() {
		tflog.Error(ctx, fmt.Sprint("flattens.AccountListDeletedDataSource: cannot flatten recordAccount.ComputeFeatures to state.ComputeFeatures", diags))
	}

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

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

func flattenResourceLimits(ctx context.Context, limits account.ResourceLimits) *models.ResourceLimitsModel {
	tflog.Info(ctx, "Start flattenResourceLimits")
	res := models.ResourceLimitsModel{
		CuC:      types.Float64Value(limits.CuC),
		CuD:      types.Float64Value(limits.CuD),
		CuI:      types.Float64Value(limits.CuI),
		CuM:      types.Float64Value(limits.CuM),
		CuDM:     types.Float64Value(limits.CuDM),
		CuNP:     types.Float64Value(limits.CuNP),
		GPUUnits: types.Float64Value(limits.GPUUnits),
	}

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

func flattenACLInAccount(ctx context.Context, aclList []account.ACL) []models.ACLModel {
	tflog.Info(ctx, "Start flattenACLInAccount")
	res := make([]models.ACLModel, 0, len(aclList))
	for _, item := range aclList {
		temp := models.ACLModel{
			Explicit:    types.BoolValue(item.Explicit),
			GUID:        types.StringValue(item.GUID),
			Right:       types.StringValue(item.Right),
			Status:      types.StringValue(item.Status),
			Type:        types.StringValue(item.Type),
			UserGroupID: types.StringValue(item.UserGroupID),
		}
		res = append(res, temp)
	}

	return res
}
