package flattens

import (
	"context"
	"fmt"
	"strconv"
	"strings"

	"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 K8SWGResource(ctx context.Context, plan *models.ResourceK8SWGModel, c *client.Client) diag.Diagnostics {
	tflog.Info(ctx, "Start FlattenK8SWGResource", map[string]any{"wg_id": plan.Id.ValueString()})

	diags := diag.Diagnostics{}

	wg, k8sId, err := utilities.K8SWGResourceCheckPresence(ctx, plan, c)
	if err != nil {
		diags.AddError("Cannot get info about wg ", err.Error())
		return diags
	}

	workersComputeList := make([]*compute.RecordCompute, 0, len(wg.DetailedInfo))
	for _, info := range wg.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 = append(workersComputeList, compute)
	}

	*plan = models.ResourceK8SWGModel{
		K8SID:         types.Int64Value(int64(k8sId)),
		Name:          types.StringValue(wg.Name),
		Num:           types.Int64Value(int64(wg.Num)),
		CPU:           types.Int64Value(int64(wg.CPU)),
		RAM:           types.Int64Value(int64(wg.RAM)),
		Disk:          types.Int64Value(int64(wg.Disk)),
		WorkerSEPID:   plan.WorkerSEPID,
		WorkerSEPPool: plan.WorkerSEPPool,
		CloudInit:     plan.CloudInit,
		Timeouts:      plan.Timeouts,
		Chipset:       plan.Chipset,
		Id:            types.StringValue(strconv.Itoa(int(wg.ID))),
		WorkerGroupId: types.Int64Value(int64(wg.ID)),
		LastUpdated:   plan.LastUpdated,
		DetailedInfo:  flattenDetailedInfoInK8sWG(ctx, &wg.DetailedInfo, workersComputeList),
		GUID:          types.StringValue(wg.GUID),
	}

	labels := make([]string, 0)
	for _, label := range wg.Labels {
		if strings.HasPrefix(label, "workersGroupName") {
			continue
		}
		labels = append(labels, label)
	}
	plan.Annotations, diags = types.ListValueFrom(ctx, types.StringType, wg.Annotations)
	if diags != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenAnnotations", diags))
	}
	plan.Labels, diags = types.ListValueFrom(ctx, types.StringType, labels)
	if diags != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenLabels", diags))
	}
	plan.Taints, diags = types.ListValueFrom(ctx, types.StringType, wg.Taints)
	if diags != nil {
		tflog.Error(ctx, fmt.Sprint("Error flattenTaints", diags))
	}

	tflog.Info(ctx, "End FlattenK8SWGResource", map[string]any{"wg_id": plan.Id.ValueString()})
	return nil
}

func flattenDetailedInfoInK8sWG(ctx context.Context, di *k8s.ListDetailedInfo, computes []*compute.RecordCompute) types.List {
	tflog.Info(ctx, "Start flattenDetailedInfoInK8sWG")

	tempSlice := make([]types.Object, 0, len(*di))
	for i, detailedInfo := range *di {
		temp := models.ItemDetailedInfoModel{
			ComputeId:          types.Int64Value(int64(detailedInfo.ID)),
			Name:               types.StringValue(detailedInfo.Name),
			Status:             types.StringValue(detailedInfo.Status),
			TechStatus:         types.StringValue(detailedInfo.TechStatus),
			Interfaces:         flattenInterfacesInK8sWG(ctx, &computes[i].Interfaces),
			NatableVinsIp:      types.StringValue(computes[i].NatableVINSIP),
			NatableVinsNetwork: types.StringValue(computes[i].NatableVINSNetwork),
		}
		obj, err := types.ObjectValueFrom(ctx, models.ItemDetailedInfo, temp)
		if err != nil {
			tflog.Error(ctx, fmt.Sprint("Error flattenDetailedInfoInK8sWG struct to obj", err))
		}

		tempSlice = append(tempSlice, obj)
	}

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

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

func flattenInterfacesInK8sWG(ctx context.Context, interfaces *compute.ListInterfaces) types.List {
	tflog.Info(ctx, "Start flattenInterfacesInK8sWG")

	tempSlice := make([]types.Object, 0, len(*interfaces))
	for _, interfaceCompute := range *interfaces {
		temp := models.ItemInterfacesModel{
			DefGw:     types.StringValue(interfaceCompute.DefGW),
			IpAddress: types.StringValue(interfaceCompute.IPAddress),
		}
		obj, err := types.ObjectValueFrom(ctx, models.ItemInterfaces, temp)
		if err != nil {
			tflog.Error(ctx, fmt.Sprint("Error flattenInterfacesInK8sWG struct to obj", err))
		}

		tempSlice = append(tempSlice, obj)
	}

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

	tflog.Info(ctx, "End flattenInterfacesInK8sWG")

	return res
}
