package utilities

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

	"github.com/hashicorp/terraform-plugin-framework/diag"
	"github.com/hashicorp/terraform-plugin-log/tflog"
	"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/lb"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/service/cloudapi/lb/models"
)

func CreateResourceLBBackend(ctx context.Context, plan *models.ResourceLBBackendModel, c *client.Client) diag.Diagnostics {
	tflog.Info(ctx, fmt.Sprintf("Start create ResourceLBBackend: backend_name %s", plan.Name.ValueString()))

	diags := diag.Diagnostics{}

	createReq := lb.BackendCreateRequest{
		LBID:        uint64(plan.LBID.ValueInt64()),
		BackendName: plan.Name.ValueString(),
	}

	if !plan.Algorithm.IsUnknown() { // Algorithm is optional & computed
		createReq.Algorithm = plan.Algorithm.ValueString()
	}

	if !plan.Inter.IsUnknown() { // Inter is optional & computed
		createReq.Inter = uint64(plan.Inter.ValueInt64())
	}

	if !plan.DownInter.IsUnknown() { // DownInter is optional & computed
		createReq.DownInter = uint64(plan.DownInter.ValueInt64())
	}

	if !plan.Rise.IsUnknown() { // Rise is optional & computed
		createReq.Rise = uint64(plan.Rise.ValueInt64())
	}

	if !plan.Fall.IsUnknown() { // Fall is optional & computed
		createReq.Fall = uint64(plan.Fall.ValueInt64())
	}

	if !plan.SlowStart.IsUnknown() { // SlowStart is optional & computed
		createReq.SlowStart = uint64(plan.SlowStart.ValueInt64())
	}

	if !plan.MaxConn.IsUnknown() { // MaxConn is optional & computed
		createReq.MaxConn = uint64(plan.MaxConn.ValueInt64())
	}

	if !plan.MaxQueue.IsUnknown() { // MaxQueue is optional & computed
		createReq.MaxQueue = uint64(plan.MaxQueue.ValueInt64())
	}

	if !plan.Weight.IsUnknown() { // Weight is optional & computed
		createReq.Weight = uint64(plan.Weight.ValueInt64())
	}

	tflog.Info(ctx, "CreateResourceLBBackend: before call CloudAPI().LB().BackendCreate", map[string]any{"req": createReq})

	resp, err := c.CloudAPI().LB().BackendCreate(ctx, createReq)
	if err != nil {
		diags.AddError("CreateResourceLBBackend: unable to create LB Backend", err.Error())
		return diags
	}
	tflog.Info(ctx, "CreateResourceLBBackend: LB Backend created", map[string]any{"responce": resp, "name": plan.Name.ValueString()})

	return nil
}

func LBBackendResourceCheckPresence(ctx context.Context, plan *models.ResourceLBBackendModel, c *client.Client) (*lb.ItemBackend, diag.Diagnostics) {
	tflog.Info(ctx, fmt.Sprintf("LBBackendCheckPresence: Get info about LB Backend with ID - %v", plan.ID.ValueString()))

	diags := diag.Diagnostics{}
	req := lb.GetRequest{}
	bName := plan.Name.ValueString()

	if !plan.LBID.IsNull() {
		req.LBID = uint64(plan.LBID.ValueInt64())
	} else {
		parameters := strings.Split(plan.ID.ValueString(), "#")
		if len(parameters) != 2 {
			diags.AddError("LBBackendResourceCheckPresence: broken state id",
				fmt.Sprintf("state id expected: <lb_id>#<backend_name>, got: %v", plan.ID.ValueString()))
			return nil, diags
		}
		lbId, _ := strconv.ParseUint(parameters[0], 10, 64)
		req.LBID = lbId
		bName = parameters[1]
	}

	lb, err := c.CloudAPI().LB().Get(ctx, req)
	if err != nil {
		diags.AddError(fmt.Sprintf("Cannot get info about lb with ID %v", req.LBID), err.Error())
		return nil, diags
	}

	backends := lb.Backends
	for _, b := range backends {
		if b.Name == bName {
			return &b, diags
		}
	}

	diags.AddError(fmt.Sprintf("can not find backend with name: %s for lb: %d", bName, lb.ID), "")
	return nil, diags
}

func UpdateLBBackend(ctx context.Context, plan, state *models.ResourceLBBackendModel, c *client.Client) diag.Diagnostics {
	tflog.Info(ctx, fmt.Sprintf("UpdateLBBackend: Start edit lb backend with ID - %v", state.ID.ValueString()))

	diags := diag.Diagnostics{}

	req := lb.BackendUpdateRequest{
		LBID:        uint64(plan.LBID.ValueInt64()),
		BackendName: plan.Name.ValueString(),
	}

	if !plan.Algorithm.IsUnknown() {
		req.Algorithm = plan.Algorithm.ValueString()
	}

	if !plan.Inter.IsUnknown() {
		req.Inter = uint64(plan.Inter.ValueInt64())
	}

	if !plan.DownInter.IsUnknown() {
		req.DownInter = uint64(plan.DownInter.ValueInt64())
	}

	if !plan.Rise.IsUnknown() {
		req.Rise = uint64(plan.Rise.ValueInt64())
	}

	if !plan.Fall.IsUnknown() {
		req.Fall = uint64(plan.Fall.ValueInt64())
	}

	if !plan.SlowStart.IsUnknown() {
		req.SlowStart = uint64(plan.SlowStart.ValueInt64())
	}

	if !plan.MaxConn.IsUnknown() {
		req.MaxConn = uint64(plan.MaxConn.ValueInt64())
	}

	if !plan.MaxQueue.IsUnknown() {
		req.MaxQueue = uint64(plan.MaxQueue.ValueInt64())
	}

	if !plan.Weight.IsUnknown() {
		req.Weight = uint64(plan.Weight.ValueInt64())
	}

	_, err := c.CloudAPI().LB().BackendUpdate(ctx, req)
	if err != nil {
		diags.AddError("UpdateLBBackend: cannot edit lb backend", err.Error())
		return diags
	}

	tflog.Info(ctx, fmt.Sprintf("UpdateLBBackend: Finish edit lb backend with name - %v", req.BackendName))

	return nil
}
