package flattens

import (
	"context"
	"fmt"
	"strings"

	"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/cloudapi/compute"
	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/k8s"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/k8s/models"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/k8s/utilities"
)

func DataSourceK8sWgList(ctx context.Context, state *models.K8SWgListModel, c *client.Client) diag.Diagnostics {
	tflog.Info(ctx, "Start FlattenDataSourceK8sWgList")

	diags := diag.Diagnostics{}

	k8SID := uint64(state.K8SID.ValueInt64())

	cluster, err := utilities.K8SCPResourceCheckPresence(ctx, k8SID, c)
	if err != nil {
		diags.AddError(fmt.Sprintf("Cannot get info about cluster with ID %d", k8SID), err.Error())
		return diags
	}

	workersComputeList := make(map[uint64][]*compute.RecordCompute)
	for _, worker := range cluster.K8SGroups.Workers {
		workersComputeList[worker.ID] = make([]*compute.RecordCompute, 0, len(worker.DetailedInfo))
		for _, info := range worker.DetailedInfo {
			compute, err := utilities.ComputeCheckPresence(ctx, info.ID, c)
			if err != nil {
				diags.AddError(fmt.Sprintf("Cannot get info about workerNode with ID %d", info.ID), err.Error())
				return diags
			}
			workersComputeList[worker.ID] = append(workersComputeList[worker.ID], compute)
		}
	}

	id := uuid.New()

	*state = models.K8SWgListModel{
		K8SID:    state.K8SID,
		Timeouts: state.Timeouts,
		Id:       types.StringValue(id.String()),
		Items:    flattenK8sWg(ctx, &cluster.K8SGroups.Workers, workersComputeList),
	}

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

func flattenK8sWg(ctx context.Context, k8SGroupList *k8s.ListK8SGroups, workers map[uint64][]*compute.RecordCompute) []models.ItemWgListModel {
	tflog.Info(ctx, "Start flattenK8sWg")

	res := make([]models.ItemWgListModel, 0, len(*k8SGroupList))
	var diags diag.Diagnostics
	for _, k8sGroup := range *k8SGroupList {
		labels := make([]string, 0)
		for _, label := range k8sGroup.Labels {
			if strings.HasPrefix(label, "workersGroupName") {
				continue
			}
			labels = append(labels, label)
		}
		computes := workers[k8sGroup.ID]
		temp := models.ItemWgListModel{
			CPU:             types.Int64Value(int64(k8sGroup.CPU)),
			DetailedInfo:    flattenDetailedInfoWgList(ctx, &k8sGroup.DetailedInfo, computes),
			Disk:            types.Int64Value(int64(k8sGroup.Disk)),
			WorkerGroupID:   types.Int64Value(int64(k8sGroup.ID)),
			WorkerGroupName: types.StringValue(k8sGroup.Name),
			Num:             types.Int64Value(int64(k8sGroup.Num)),
			RAM:             types.Int64Value(int64(k8sGroup.RAM)),
		}
		temp.Annotations, diags = types.ListValueFrom(ctx, types.StringType, k8sGroup.Annotations)
		if diags != nil {
			tflog.Error(ctx, fmt.Sprint("Error flattenAnnotations", diags))
		}
		temp.Labels, diags = types.ListValueFrom(ctx, types.StringType, labels)
		if diags != nil {
			tflog.Error(ctx, fmt.Sprint("Error flattenLabels", diags))
		}
		temp.Taints, diags = types.ListValueFrom(ctx, types.StringType, k8sGroup.Taints)
		if diags != nil {
			tflog.Error(ctx, fmt.Sprint("Error flattenTaints", diags))
		}
		res = append(res, temp)
	}

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

func flattenDetailedInfoWgList(ctx context.Context, di *k8s.ListDetailedInfo, computes []*compute.RecordCompute) []models.ItemDetailedInfoDataSourceModel {
	tflog.Info(ctx, "Start flattenDetailedInfoWgList")

	res := make([]models.ItemDetailedInfoDataSourceModel, 0, len(*di))
	for i, detailedInfo := range *di {
		temp := models.ItemDetailedInfoDataSourceModel{
			ComputeId:          types.Int64Value(int64(detailedInfo.ID)),
			Name:               types.StringValue(detailedInfo.Name),
			Status:             types.StringValue(detailedInfo.Status),
			TechStatus:         types.StringValue(detailedInfo.TechStatus),
			Interfaces:         flattenInterfacesWgList(ctx, &computes[i].Interfaces),
			NatableVinsIp:      types.StringValue(computes[i].NatableVINSIP),
			NatableVinsNetwork: types.StringValue(computes[i].NatableVINSNetwork),
		}
		res = append(res, temp)
	}

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

func flattenInterfacesWgList(ctx context.Context, interfaces *compute.ListInterfaces) []models.ItemInterfacesDataSourceModel {
	tflog.Info(ctx, "Start flattenInterfacesWgList")

	res := make([]models.ItemInterfacesDataSourceModel, 0, len(*interfaces))
	for _, interfaceCompute := range *interfaces {
		temp := models.ItemInterfacesDataSourceModel{
			DefGw:     types.StringValue(interfaceCompute.DefGW),
			IpAddress: types.StringValue(interfaceCompute.IPAddress),
		}
		res = append(res, temp)
	}

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