package resourcemanager

import (
	"context"

	v1 "github.com/tidbcloud/observability/api/regionalserver/resourceworker/v1"
	"github.com/tidbcloud/observability/pkg/common/message"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

type clusterUpgradeOperationReaderWriter struct {
	cli     client.Client
	readCli client.Reader
}

// Create creates a new ClusterUpgradeOperation CR
func (c clusterUpgradeOperationReaderWriter) Create(ctx context.Context, op *v1.ClusterUpgradeOperation) error {
	err := c.cli.Create(ctx, op)
	return WrapClientError(err)
}

// Get retrieves a specific ClusterUpgradeOperation CR by namespace and name
func (c clusterUpgradeOperationReaderWriter) Get(ctx context.Context, namespace, name string) (*v1.ClusterUpgradeOperation, error) {
	op := &v1.ClusterUpgradeOperation{}
	err := c.cli.Get(ctx, client.ObjectKey{
		Namespace: namespace,
		Name:      name,
	}, op)

	if err != nil {
		return nil, WrapClientError(err)
	}

	return op, nil
}

// List retrieves ClusterUpgradeOperation CRs in a specific namespace with pagination
func (c clusterUpgradeOperationReaderWriter) List(ctx context.Context, namespace string, cr message.ContinueRequest) (*v1.ClusterUpgradeOperationList, error) {
	ops := &v1.ClusterUpgradeOperationList{}

	opts := []client.ListOption{
		client.InNamespace(namespace),
	}

	// Add pagination options if provided
	if cr.Limit > 0 {
		opts = append(opts, client.Limit(cr.Limit))
	}
	if cr.ContinueToken != "" {
		opts = append(opts, client.Continue(cr.ContinueToken))
	}

	err := c.readCli.List(ctx, ops, opts...)
	if err != nil {
		return nil, WrapClientError(err)
	}

	return ops, nil
}

// Update updates an existing ClusterUpgradeOperation CR
func (c clusterUpgradeOperationReaderWriter) Update(ctx context.Context, op *v1.ClusterUpgradeOperation) error {
	err := c.cli.Update(ctx, op)
	return WrapClientError(err)
}

// Delete removes a ClusterUpgradeOperation CR by namespace and name
func (c clusterUpgradeOperationReaderWriter) Delete(ctx context.Context, namespace, name string) error {
	op := &v1.ClusterUpgradeOperation{
		ObjectMeta: metav1.ObjectMeta{
			Name:      name,
			Namespace: namespace,
		},
	}

	err := c.cli.Delete(ctx, op)
	return WrapClientError(err)
}

// IsOperationExists checks if a ClusterUpgradeOperation CR exists
func (c clusterUpgradeOperationReaderWriter) IsOperationExists(ctx context.Context, namespace, name string) (bool, error) {
	op := &v1.ClusterUpgradeOperation{}
	err := c.cli.Get(ctx, client.ObjectKey{
		Namespace: namespace,
		Name:      name,
	}, op)

	if err != nil {
		if client.IgnoreNotFound(err) == nil {
			return false, nil
		}
		return false, WrapClientError(err)
	}

	return true, nil
}

// GetClient returns the client for K8s operations (e.g. listing nodes for nodegroup version)
func (c clusterUpgradeOperationReaderWriter) GetClient() client.Client {
	return c.cli
}
