package ngoperation

import (
	"context"
	"fmt"
	"strconv"

	nextgenv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"

	opent "github.com/tidbcloud/devops/entity/operation"
	"github.com/tidbcloud/devops/pkg/service/operation/actions"
)

var (
	ActionDeleteResourcePool = opent.ActionMetadata{
		Name: "DeleteResourcePool",
		Type: opent.ActionTypeAuto,
	}
)

var (
	_ actions.Action = &DeleteResourcePool{}
)

type DeleteResourcePool struct {
	actions.BaseAction
	comps *actions.Components
}

func NewDeleteResourcePool(comps *actions.Components) actions.AutoAction {
	return &DeleteResourcePool{comps: comps}
}

func (a *DeleteResourcePool) Metadata() opent.ActionMetadata {
	return ActionDeleteResourcePool
}

func (a *DeleteResourcePool) PreCheck(ctx context.Context, instance *opent.Instance) error {
	delReq, err := a.getParam(instance)
	if err != nil {
		return err
	}
	resp, err := a.comps.CoreSvc.Mgmt.ResourcePool.GetResourcePool(ctx, &nextgenv1.GetResourcePoolRequest{
		ResourcePoolId: delReq.GetResourcePoolId(),
		ShowDeleted:    false,
	})
	if err != nil {
		return fmt.Errorf("failed to find resource pool %d before deletion: %w", delReq.GetResourcePoolId(), err)
	}

	tenantIDRaw, hasTenantID := instance.GetParam(opent.ParamTenantID)
	if !hasTenantID || tenantIDRaw == "0" {
		if resp.GetResourcePool().GetOwnerType() != nextgenv1.ResourcePool_SHARED {
			return fmt.Errorf("resource pool %d is not a shared resource pool", delReq.GetResourcePoolId())
		}
		return nil
	}

	tenantID, err := strconv.ParseUint(tenantIDRaw, 10, 64)
	if err != nil {
		return fmt.Errorf("invalid tenant_id %q: %w", tenantIDRaw, err)
	}
	if resp.GetResourcePool().GetOwnerType() != nextgenv1.ResourcePool_ORGANIZATION {
		return fmt.Errorf("resource pool %d is not an organization resource pool", delReq.GetResourcePoolId())
	}
	if resp.GetResourcePool().GetOwnerId() != tenantID {
		return fmt.Errorf("resource pool %d owner mismatch: expected tenant %d, got %d", delReq.GetResourcePoolId(), tenantID, resp.GetResourcePool().GetOwnerId())
	}

	return nil
}

func (a *DeleteResourcePool) Start(ctx context.Context, instance *opent.Instance) (*actions.ActionResult, error) {
	req, err := a.getParam(instance)
	if err != nil {
		return actions.FailedActionResult(err), nil
	}

	resp, err := a.comps.CoreSvc.Mgmt.ResourcePool.DeleteResourcePool(ctx, req)
	if err != nil {
		return actions.FailedActionResult(err), nil
	}

	return actions.RunningActionResult(fmt.Sprintf("sent request to delete resource pool: %d", resp.GetId()), nil), nil
}

func (a *DeleteResourcePool) Result(ctx context.Context, instance *opent.Instance) (*actions.ActionResult, error) {
	return actions.SucceededActionResult(nil), nil
}

func (a *DeleteResourcePool) getParam(instance *opent.Instance) (*nextgenv1.DeleteResourcePoolRequest, error) {
	poolIDStr, exist := instance.GetParam(opent.ParamResourcePoolID)
	if !exist {
		return nil, fmt.Errorf("missing resource pool ID")
	}
	poolID, err := strconv.ParseUint(poolIDStr, 10, 64)
	if err != nil {
		return nil, fmt.Errorf("invalid resource pool ID: %w", err)
	}
	return &nextgenv1.DeleteResourcePoolRequest{
		ResourcePoolId: poolID,
	}, nil
}
