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 DataSourceK8sWg(ctx context.Context, state *models.K8SWgModel, c *client.Client) diag.Diagnostics {
	tflog.Info(ctx, "Start FlattenDataSourceK8sWg", map[string]any{"k8s_id": state.K8SID.ValueInt64(), "worker_group_id": state.WorkerGroupID.ValueInt64()})

	diags := diag.Diagnostics{}

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

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

	curWg := k8s.ItemK8SGroup{}
	for _, wg := range cluster.K8SGroups.Workers {
		if wg.ID == wgID {
			curWg = wg
			break
		}
	}
	if curWg.ID == 0 {
		diags.AddError(fmt.Sprintf("WG with id %v in k8s cluster %v not found", wgID, k8SID), err.Error())
		return diags
	}

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

	id := uuid.New()

	*state = models.K8SWgModel{
		K8SID:           state.K8SID,
		Timeouts:        state.Timeouts,
		WorkerGroupID:   state.WorkerGroupID,
		Id:              types.StringValue(id.String()),
		CPU:             types.Int64Value(int64(curWg.CPU)),
		DetailedInfo:    flattenDetailedInfoWg(ctx, &curWg.DetailedInfo, workersComputeList),
		Disk:            types.Int64Value(int64(curWg.Disk)),
		GUID:            types.StringValue(curWg.GUID),
		WorkerGroupName: types.StringValue(curWg.Name),
		Num:             types.Int64Value(int64(curWg.Num)),
		RAM:             types.Int64Value(int64(curWg.RAM)),
	}
	labels := make([]string, 0)
	for _, label := range curWg.Labels {
		if strings.HasPrefix(label, "workersGroupName") {
			continue
		}
		labels = append(labels, label)
	}
	state.Annotations, diags = types.ListValueFrom(ctx, types.StringType, curWg.Annotations)
	if diags != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenAnnotations", diags))
	}
	state.Labels, diags = types.ListValueFrom(ctx, types.StringType, labels)
	if diags != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenLabels", diags))
	}
	state.Taints, diags = types.ListValueFrom(ctx, types.StringType, curWg.Taints)
	if diags != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenTaints", diags))
	}
	tflog.Info(ctx, "End FlattenDataSourceK8sWg", map[string]any{"k8s_id": state.K8SID.ValueInt64(), "worker_group_id": state.WorkerGroupID.ValueInt64()})
	return nil
}

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

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

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

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

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

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