// Input checks
package ic

import (
	"context"
	"fmt"

	account "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/account"
	extnet "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/extnet"
	grid "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/grid"
	image "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/image"
	lb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/lb"
	rg "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/rg"
	vins "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/vins"
	"repository.basistech.ru/BASIS/terraform-provider-dynamix/internal/client"
)

func ExistRG(ctx context.Context, rgId uint64, c *client.Client) error {
	req := rg.ListRequest{
		ByID:           rgId,
		IncludeDeleted: false,
	}

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

	if len(rgList.Data) == 0 {
		return fmt.Errorf("RG with id %v not found", rgId)
	}

	return nil
}

func ExistAccount(ctx context.Context, accountId uint64, c *client.Client) error {
	req := account.ListRequest{
		ByID: accountId,
	}

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

	if len(accountList.Data) == 0 {
		return fmt.Errorf("account with id %d not found", accountId)
	}

	return nil
}

func ExistAccounts(ctx context.Context, accountIds []uint64, c *client.Client) error {
	req := account.ListRequest{}

	accountList, err := c.CloudBroker().Account().List(ctx, req)
	if err != nil {
		return err
	}
	if len(accountList.Data) == 0 {
		return fmt.Errorf("you have not been granted access to any account")
	}

	notFound := make([]uint64, 0, len(accountIds))

	for _, accID := range accountIds {
		found := false

		for _, acc := range accountList.Data {
			if accID == acc.ID {
				found = true
				break
			}
		}

		if !found {
			notFound = append(notFound, accID)
		}
	}

	if len(notFound) > 0 {
		return fmt.Errorf("Accounts with ids %v not found", notFound)
	}

	return nil
}

func ExistRGs(ctx context.Context, rgIDs []uint64, c *client.Client) error {
	req := rg.ListRequest{
		IncludeDeleted: false,
	}

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

	if len(rgList.Data) == 0 {
		return fmt.Errorf("you have not been granted access to any resource group")
	}

	notFound := make([]uint64, 0, len(rgIDs))

	for _, rgID := range rgIDs {
		found := false

		for _, rg := range rgList.Data {
			if rgID == rg.ID {
				found = true
				break
			}
		}

		if !found {
			notFound = append(notFound, rgID)
		}
	}

	if len(notFound) > 0 {
		return fmt.Errorf("RGs with ids %v not found", notFound)
	}

	return nil
}

func ExistLB(ctx context.Context, lbId uint64, c *client.Client) error {
	req := lb.ListRequest{
		ByID: lbId,
	}

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

	if len(lbList.Data) == 0 {
		return fmt.Errorf("LB with ID %v not found", lbId)
	}

	return nil
}

func ExistLBFrontend(ctx context.Context, lbId uint64, fName string, c *client.Client) error {
	lb, err := c.CloudBroker().LB().Get(ctx, lb.GetRequest{LBID: lbId})
	if err != nil {
		return err
	}

	frontends := lb.Frontends
	for _, f := range frontends {
		if f.Name == fName {
			return nil
		}
	}

	return fmt.Errorf("frontend with name %v not found", fName)
}

func ExistLBBackend(ctx context.Context, lbId uint64, bName string, c *client.Client) error {
	lb, err := c.CloudBroker().LB().Get(ctx, lb.GetRequest{LBID: lbId})
	if err != nil {
		return err
	}

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

	return fmt.Errorf("backend with name %v not found", bName)
}

func ExistExtNetInLb(ctx context.Context, extNetId uint64, c *client.Client) error {
	if extNetId == 0 {
		return nil
	}
	req := extnet.ListRequest{
		ByID: extNetId,
	}

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

	if len(extNetList.Data) == 0 {
		return fmt.Errorf("EXTNET with ID %v not found", extNetId)
	}

	return nil
}

func ExistVinsInLb(ctx context.Context, vinsId uint64, c *client.Client) error {
	if vinsId == 0 {
		return nil
	}

	req := vins.ListRequest{
		ByID: vinsId,
	}

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

	if len(vinsList.Data) == 0 {
		return fmt.Errorf("VINS with ID %v not found", vinsId)
	}

	return nil
}

func ExistExtNetInVins(ctx context.Context, extNetId int, c *client.Client) error {
	if extNetId == 0 || extNetId == -1 {
		return nil
	}
	req := extnet.ListRequest{
		ByID: uint64(extNetId),
	}

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

	if len(extNetList.Data) == 0 {
		return fmt.Errorf("EXTNET with ID %v not found", extNetId)
	}

	return nil
}

func ExistGID(ctx context.Context, gid uint64, c *client.Client) error {
	req := grid.ListRequest{}

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

	for _, grid := range gridList.Data {
		if grid.GID == gid {
			return nil
		}
	}

	return fmt.Errorf("GID with id %v not found", gid)
}

func ExistVins(ctx context.Context, vinsId uint64, c *client.Client) error {
	req := vins.ListRequest{
		ByID:           vinsId,
		IncludeDeleted: false,
	}

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

	if len(vinsList.Data) == 0 {
		return fmt.Errorf("vins with ID %v not found", vinsId)
	}

	return nil
}

func ExistImages(ctx context.Context, imageIDs []uint64, c *client.Client) error {
	req := image.ListRequest{}

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

	if len(listImages.Data) == 0 {
		return fmt.Errorf("you have not been granted access to any images")
	}

	notFound := make([]uint64, 0, len(imageIDs))

	for _, imageID := range imageIDs {
		found := false

		for _, image := range listImages.Data {
			if imageID == image.ID {
				found = true
				break
			}
		}

		if !found {
			notFound = append(notFound, imageID)
		}
	}

	if len(notFound) > 0 {
		return fmt.Errorf("images with ids %v not found", notFound)
	}

	return nil
}

func ExistExtNetInRG(ctx context.Context, extNetId, accountId uint64, c *client.Client) error {
	req := extnet.ListRequest{
		AccountID: accountId,
		ByID:      extNetId,
	}

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

	if len(listExtNet.Data) == 0 {
		return fmt.Errorf("EXTNET with ID %v not found for account with id %d", extNetId, accountId)
	}

	return nil
}
