package flattens

import (
	"context"

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

func NodeListDataSource(ctx context.Context, state *models.DataSourceNodeList, c *client.Client) diag.Diagnostics {
	tflog.Info(ctx, "Start flattens.NodeDataListSource")

	diags := diag.Diagnostics{}

	recordList, diags := utilities.NodeListDataSourceCheckPresence(ctx, state, c)
	if diags.HasError() {
		return diags
	}

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

	id := uuid.New()

	*state = models.DataSourceNodeList{
		ByID:     state.ByID,
		Name:     state.Name,
		Version:  state.Version,
		Release:  state.Release,
		SepID:    state.SepID,
		Role:     state.Role,
		Status:   state.Status,
		SortBy:   state.SortBy,
		Page:     state.Page,
		Size:     state.Size,
		Timeouts: state.Timeouts,

		Id:         types.StringValue(id.String()),
		Items:      flattenItemsList(ctx, recordList),
		EntryCount: types.Int64Value(int64(recordList.EntryCount)),
	}

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

func flattenItemsList(ctx context.Context, recordList *node.ListNodes) []models.ItemNodeModel {
	tflog.Info(ctx, "Start flattenItemsList")

	res := make([]models.ItemNodeModel, 0, len(recordList.Data))

	for _, item := range recordList.Data {
		temp := models.ItemNodeModel{
			AdditionalPkgs:   flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.AdditionalPkgs),
			CpuInfo:          flattenCpuInfo(ctx, &item.CpuInfo),
			Description:      types.StringValue(item.Description),
			DPDK:             flattenDPDK(ctx, &item.DPDK),
			GID:              types.Int64Value(int64(item.GID)),
			GUID:             types.StringValue(item.GUID),
			HostKey:          types.StringValue(item.HostKey),
			IPAddr:           flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.IPAddr),
			IsolatedCPUs:     flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.IsolatedCpus),
			LastCheck:        types.Int64Value(int64(item.LastCheck)),
			MachineGUID:      types.StringValue(item.MachineGUID),
			MainboardSN:      types.StringValue(item.MainboardSN),
			Memory:           types.Int64Value(int64(item.Memory)),
			Milestones:       types.Int64Value(int64(item.Milestones)),
			Model:            types.StringValue(item.Model),
			Name:             types.StringValue(item.Name),
			NeedReboot:       types.BoolValue(item.NeedReboot),
			NetAddr:          flattenNetAddr(ctx, item.NetAddr),
			NetworkMode:      types.StringValue(item.NetworkMode),
			NicInfo:          flattenNicInfo(ctx, item.NicInfo),
			NodeUUID:         types.StringValue(item.NodeUUID),
			NodeID:           types.Int64Value(int64(item.ID)),
			NumaTopology:     flattenNumaTopology(ctx, &item.NumaTopology),
			PeerBackup:       types.Int64Value(int64(item.PeerBackup)),
			PeerLog:          types.Int64Value(int64(item.PeerLog)),
			PeerStats:        types.Int64Value(int64(item.PeerStats)),
			Pgpus:            flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.Pgpus),
			PublicKeys:       flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.PublicKeys),
			Release:          types.StringValue(item.Release),
			ReservedCPUs:     flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.ReservedCPUs),
			Roles:            flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.Roles),
			SEPs:             flattens.FlattenSimpleTypeToList(ctx, types.Int64Type, &item.Seps),
			SerialNum:        types.StringValue(item.SerialNum),
			SriovEnabled:     types.BoolValue(item.SriovEnabled),
			StackId:          types.Int64Value(int64(item.StackID)),
			Status:           types.StringValue(item.Status),
			Tags:             flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.Tags),
			Type:             types.StringValue(item.Type),
			UEFIFirmwareFile: types.StringValue(item.UEFIFirmwareFile),
			Version:          types.StringValue(item.Version),
		}
		res = append(res, temp)
	}

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

func flattenNetAddr(ctx context.Context, netAddr node.ListNetAddr) []models.NetAddrModel {
	tflog.Info(ctx, "Start flattenNetAddr")

	res := make([]models.NetAddrModel, 0, len(netAddr))

	for _, item := range netAddr {
		temp := models.NetAddrModel{
			CIDR:  flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.CIDR),
			Index: types.Int64Value(int64(item.Index)),
			IP:    flattens.FlattenSimpleTypeToList(ctx, types.StringType, &item.IP),
			MAC:   types.StringValue(item.Mac),
			MTU:   types.Int64Value(int64(item.MTU)),
			Name:  types.StringValue(item.Name),
		}

		res = append(res, temp)
	}

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