package flattens

import (
	"context"
	"fmt"
	"strconv"

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

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

	diags := diag.Diagnostics{}

	vfPoolID := uint64(state.VFPoolID.ValueInt64())

	if vfPoolID == 0 {
		id, err := strconv.Atoi(state.ID.ValueString())
		if err != nil {
			diags.AddError(
				"flattens.VFPoolResource: cannot parse resource ID from state",
				err.Error())
			return diags
		}
		vfPoolID = uint64(id)
	}

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

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

	*state = models.ResourceItemVFPoolModel{
		//required fields
		Name: state.Name,

		//optional fields
		Description:   state.Description,
		AccountAccess: state.AccountAccess,
		RGAccess:      state.RGAccess,
		Config:        state.Config,
		Enable:        state.Enable,
		Timeouts:      state.Timeouts,

		//compute fields
		VFPoolID:    types.Int64Value(int64(record.ID)),
		CreatedTime: types.Int64Value(int64(record.CreatedTime)),
		GID:         types.Int64Value(int64(record.GID)),
		GUID:        types.Int64Value(int64(record.GUID)),
		Status:      types.StringValue(record.Status),
		UpdatedTime: types.Int64Value(int64(record.UpdatedTime)),
		VFS:         flattenVFS(ctx, record.VFS),
		ID:          types.StringValue(strconv.Itoa(int(vfPoolID))),
	}

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

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

func flattenVFS(ctx context.Context, items []vfpool.VFS) types.List {
	tflog.Info(ctx, "Start flattenVFS")
	tempSlice := make([]types.Object, 0, len(items))
	for _, v := range items {
		temp := models.ResourceIVFSModel{
			NodeID: types.Int64Value(int64(v.NodeID)),
			VFList: flattenVFList(ctx, v.VFList),
		}
		obj, diags := types.ObjectValueFrom(ctx, models.ResourceIVFS, temp)
		if diags != nil {
			tflog.Error(ctx, fmt.Sprint("Error flattenVFS struct to obj", diags))
		}
		tempSlice = append(tempSlice, obj)
	}

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

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

func flattenVFList(ctx context.Context, items vfpool.VFList) types.List {
	tflog.Info(ctx, "Start flattenVFList")
	tempSlice := make([]types.Object, 0, len(items))
	for _, v := range items {
		temp := models.ResourceIVFItemModel{
			NicName: types.StringValue(v.NicName),
			VFSInfo: flattenVFSInfo(ctx, v.VFSInfo),
		}
		obj, diags := types.ObjectValueFrom(ctx, models.ResourceIVFItem, temp)
		if diags != nil {
			tflog.Error(ctx, fmt.Sprint("Error flattenVFList struct to obj", diags))
		}
		tempSlice = append(tempSlice, obj)
	}

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

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

func flattenVFSInfo(ctx context.Context, items vfpool.VFSInfoList) types.List {
	tflog.Info(ctx, "Start flattenVFSInfo")
	tempSlice := make([]types.Object, 0, len(items))
	for _, v := range items {
		temp := models.ResourceIVFSInfoItemModel{
			ID:      types.Int64Value(int64(v.ID)),
			Claimed: types.BoolValue(v.Claimed),
			VMID:    types.Int64Value(int64(v.VMID)),
		}
		obj, diags := types.ObjectValueFrom(ctx, models.ResourceIVFSInfoItem, temp)
		if diags != nil {
			tflog.Error(ctx, fmt.Sprint("Error flattenVFSInfo struct to obj", diags))
		}
		tempSlice = append(tempSlice, obj)
	}

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

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