package cbDisks

import (
	"context"
	"fmt"

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

// resourceDiskReplicationInputChecks checks if user provided disk_id exist on the platform during disk replication.
func resourceDiskReplicationInputChecks(ctx context.Context, plan *models.ResourceRecordDiskReplicationModel, c *client.Client) diag.Diagnostics {
	diags := diag.Diagnostics{}

	diskId := uint64(plan.DiskId.ValueInt64())
	tflog.Info(ctx, "resourceDiskCreateInputChecks: exist disk check", map[string]any{"disk_id": diskId})
	err := CheckTatlinDiskID(ctx, diskId, c)
	if err != nil {
		diags.AddError(fmt.Sprintf("Cannot get info about disk with ID %v", diskId), err.Error())
	}

	return diags

}

// resourceDiskUpdateInputChecks checks if user provided:
// account_id and gid exist on the platform during disk creation,
// description, pool, sep_id, type are not attempted to be changed.
func resourceDiskUpdateInputChecks(ctx context.Context, plan, state *models.ResourceDiskModel, c *client.Client) diag.Diagnostics {
	diags := diag.Diagnostics{}

	// check accountId and gid
	diags.Append(resourceDiskCreateInputChecks(ctx, plan, c)...)

	// check description
	if !plan.Description.Equal(state.Description) && !plan.Description.IsUnknown() {
		diags.AddError(
			"resourceDiskUpdateInputChecks: description change is not allowed",
			fmt.Sprintf("cannot change description from %s to %s for disk id %s",
				state.Description.ValueString(),
				plan.Description.ValueString(),
				plan.Id.ValueString()))
	}

	// check pool
	if !plan.Pool.Equal(state.Pool) && !plan.Pool.IsUnknown() {
		diags.AddError(
			"resourceDiskUpdateInputChecks: pool change is not allowed",
			fmt.Sprintf("cannot change pool from %s to %s for disk id %s",
				state.Pool.ValueString(),
				plan.Pool.ValueString(),
				plan.Id.ValueString()))
	}

	// check sep_id
	if !plan.SEPID.Equal(state.SEPID) && !plan.SEPID.IsUnknown() {
		diags.AddError(
			"resourceDiskUpdateInputChecks: sep_id change is not allowed",
			fmt.Sprintf("cannot change sep_id from %d to %d for disk id %s",
				state.SEPID.ValueInt64(),
				plan.SEPID.ValueInt64(),
				plan.Id.ValueString()))
	}

	// check type
	if !plan.Type.Equal(state.Type) && !plan.Type.IsUnknown() {
		diags.AddError(
			"resourceDiskUpdateInputChecks: type change is not allowed",
			fmt.Sprintf("cannot change type from %s to %s for disk id %s",
				state.Type.ValueString(),
				plan.Type.ValueString(),
				plan.Id.ValueString()))
	}

	return diags
}

// resourceDiskCreateInputChecks checks if user provided account_id and gid exist on the platform during disk creation.
func resourceDiskCreateInputChecks(ctx context.Context, plan *models.ResourceDiskModel, c *client.Client) diag.Diagnostics {
	diags := diag.Diagnostics{}

	accountId := uint64(plan.AccountID.ValueInt64())
	tflog.Info(ctx, "resourceDiskCreateInputChecks: exist account check", map[string]any{"account_id": accountId})
	err := ic.ExistAccount(ctx, accountId, c)
	if err != nil {
		diags.AddError(fmt.Sprintf("Cannot get info about account with ID %v", accountId), err.Error())
	}

	gid := uint64(plan.GID.ValueInt64())
	tflog.Info(ctx, "resourceDiskCreateInputChecks: exist gid check", map[string]any{"gid": gid})
	err = ic.ExistGID(ctx, gid, c)
	if err != nil {
		diags.AddError(fmt.Sprintf("Cannot get info about GID %v", gid), err.Error())
	}
	return diags
}

func CheckTatlinDiskID(ctx context.Context, diskId uint64, c *client.Client) error {

	req := disks.ListRequest{
		ByID: diskId,
	}

	diskList, err := c.CloudBroker().Disks().List(ctx, req)
	if err != nil {
		return err
	}

	if len(diskList.Data) == 0 {
		return fmt.Errorf("DiskID %d is not allowed or does not exist", diskId)
	}

	if diskList.Data[0].SEPType != "TATLIN" {
		return fmt.Errorf("DiskID %d is not allowed or does not exist", diskId)
	}

	return nil
}
