package kvmvm

import (
	"context"
	"fmt"
	"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/terraform-provider-dynamix/internal/client"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/ic"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/kvmvm/models"
)

// resourceComputeInputChecks checks if rg_id and image_id are valid.
func resourceComputeInputChecks(ctx context.Context, plan *models.ResourceComputeModel, c *client.Client) diag.Diagnostics {
	diags := diag.Diagnostics{}

	rgID := uint64(plan.RGID.ValueInt64())
	tflog.Info(ctx, "resourceComputeInputChecks: exist resource rg", map[string]any{"rg_id": rgID})
	err := ic.ExistRG(ctx, rgID, c)
	if err != nil {
		diags.AddError(fmt.Sprintf("Cannot get info about rg with ID %v", rgID), err.Error())
	}

	var imageID uint64

	if plan.WithoutBootDisk.IsNull() || !plan.WithoutBootDisk.ValueBool() {
		if plan.ImageID.IsNull() {
			diags.AddError(fmt.Sprintf("imageId must be specified if the compute with boot disk is to be created"), "")
		} else {
			imageID = uint64(plan.ImageID.ValueInt64())
		}
		tflog.Info(ctx, "resourceComputeInputChecks: exist image", map[string]any{"image_id": imageID})
		err = ic.ExistImage(ctx, imageID, c)
		if err != nil {
			diags.AddError(fmt.Sprintf("Cannot get info about image with ID %v", imageID), err.Error())
		}
	}

	if !plan.Network.IsNull() {
		networkList := plan.Network.Elements()
		for _, elem := range networkList {
			objVal := elem.(types.Object)
			elemMap := objVal.Attributes()
			netType := strings.ToUpper(elemMap["net_type"].(types.String).ValueString())
			switch netType {
			case "VINS":
				vinsId := uint64(elemMap["net_id"].(types.Int64).ValueInt64())
				err = ic.ExistVins(ctx, vinsId, c)
				if err != nil {
					diags.AddError(fmt.Sprintf("Cannot create compute because vins ID %d is not allowed or does not exist", vinsId), err.Error())
				}
			case "EXTNET":
				extNetId := uint64(elemMap["net_id"].(types.Int64).ValueInt64())
				err = ic.ExistExtNet(ctx, extNetId, c)
				if err != nil {
					diags.AddError(fmt.Sprintf("Cannot create compute because extnet ID %d is not allowed or does not exist", extNetId), err.Error())
				}
			case "VFNIC":
				vfpoolId := uint64(elemMap["net_id"].(types.Int64).ValueInt64())
				err = ic.ExistVFPool(ctx, vfpoolId, c)
				if err != nil {
					diags.AddError(fmt.Sprintf("Cannot create compute because vfpool ID %d is not allowed or does not exist", vfpoolId), err.Error())
				}
			case "DPDK":
				dpdkId := uint64(elemMap["net_id"].(types.Int64).ValueInt64())
				err = ic.ExistDPDK(ctx, dpdkId, c)
				if err != nil {
					diags.AddError(fmt.Sprintf("Cannot create compute because DPDK net ID %d is not allowed or does not exist", dpdkId), err.Error())
				}
			}
		}
	}

	if !plan.Pool.IsUnknown() && plan.SepId.IsUnknown() {
		diags.AddError("sep_id required if pool name enable", "")
	}

	if plan.WithoutBootDisk.ValueBool() && (!plan.BootDiskSize.IsUnknown() || !plan.Pool.IsUnknown() || !plan.SepId.IsUnknown()) {
		diags.AddError("pool, boot_disk_size and sep_id should be empty if without_boot_disk is true", "")
	}

	return diags
}
