package resourcemanager

import (
	"context"

	helmv2 "github.com/fluxcd/helm-controller/api/v2"
	prometheusv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
	promapiv1 "github.com/prometheus/client_golang/api/prometheus/v1"
	prommodel "github.com/prometheus/common/model"
	v1 "github.com/tidbcloud/observability/api/regionalserver/resourceworker/v1"
	"github.com/tidbcloud/observability/pkg/common/message"
	"github.com/tidbcloud/observability/pkg/common/structs"
	batchv1 "k8s.io/api/batch/v1"
	corev1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

type IAMReaderWriter interface {
	CreateRole(ctx context.Context, data *v1.IAM) error
	DeleteRole(ctx context.Context, roleName string, ns string) error
	DeleteRoles(ctx context.Context, ns string, labelSelector map[string]string) error
	GetRoles(ctx context.Context, ns string, labelSelector map[string]string) (*v1.IAMList, error)
	UpdateRole(ctx context.Context, data *v1.IAM) error
	IsRoleExists(ctx context.Context, roleName string, ns string) (bool, error)
	GetRole(ctx context.Context, roleName string, ns string) (*v1.IAM, error)
}

type ClusterReaderWriter interface {
	CreateCluster(ctx context.Context, data *v1.Cluster) error
	GetCluster(ctx context.Context, id string) (data *v1.Cluster, err error)
	IsClusterIDExists(ctx context.Context, id string) (bool, error)
	IsClusterExists(ctx context.Context, tenantID, projectID, applicationID, bizType string) (bool, error)
	QueryClusters(ctx context.Context, tenantID, projectID, applicationID, bizType string, cr message.ContinueRequest) (*v1.ClusterList, error)
	ListClusters(ctx context.Context, opts ...client.ListOption) (*v1.ClusterList, error)
	QueryClustersByRuleTemplateID(ctx context.Context, ruleTemplateID string, cr message.ContinueRequest) (*v1.ClusterList, error)
	SoftDeleteCluster(ctx context.Context, id string) (err error)
	DeleteCluster(ctx context.Context, id string) (err error)
	UpdateCluster(ctx context.Context, data *v1.Cluster) error
	SoftPauseCluster(ctx context.Context, data *v1.Cluster) (err error)
	PauseCluster(ctx context.Context, data *v1.Cluster) (err error)
	ResumeCluster(ctx context.Context, data *v1.Cluster) (err error)
}

type ObjectStorageReaderWriter interface {
	CreateObjectStorage(ctx context.Context, data *v1.S3) error
	IsObjectStorageExisted(ctx context.Context, bucketName string) (bool, error)
	GetObjectStorage(ctx context.Context, bucketName string) (data *v1.S3, err error)
}

type NamespaceReaderWriter interface {
	Create(ctx context.Context, namespace *corev1.Namespace) error
	Update(ctx context.Context, namespace *corev1.Namespace) error
	CreateServiceAccount(ctx context.Context, namespaceName string, roleArn string) error
	IsNamespaceExisted(ctx context.Context, namespace string) (bool, error)
	Get(ctx context.Context, name string) (*corev1.Namespace, error)
}

type DataAccountReaderWriter interface {
	UniqueInt32ForCluster(ctx context.Context) (int32, error)
}

type DataAccountReaderWriterFactory interface {
	GetReaderWriter(namespace string) DataAccountReaderWriter
}

type PrometheusRuleReaderWriter interface {
	Create(ctx context.Context, data *prometheusv1.PrometheusRule) error
	IsPrometheusRuleIDExists(ctx context.Context, id string) (bool, error)
	UpdatePrometheusRule(ctx context.Context, data *prometheusv1.PrometheusRule) error
	GetPrometheusRule(ctx context.Context, id string) (data *prometheusv1.PrometheusRule, err error)
	DeletePrometheusRules(ctx context.Context, id string) (err error)
	ListPrometheusRulesInNs(ctx context.Context, ns string) (rules []*prometheusv1.PrometheusRule, err error)
}

type ClusterRoleBindingReaderWriter interface {
	Create(ctx context.Context, data *rbacv1.ClusterRoleBinding) error
	Delete(ctx context.Context, name string) error
}

type SubscriptionReaderWriter interface {
	IsSubscriptionIDExists(ctx context.Context, id string) (bool, error)
	Create(ctx context.Context, subs *v1.Subscription) error
	Update(ctx context.Context, subs *v1.Subscription) error
	Query(ctx context.Context, tenantID, projectID string) ([]v1.Subscription, error)
	Get(ctx context.Context, name string) (*v1.Subscription, error)
	Delete(ctx context.Context, name string) error
}

type PVCReaderWriter interface {
	Create(ctx context.Context, ns string, name string, req string) error
	Get(ctx context.Context, ns string, name string) (*corev1.PersistentVolumeClaim, error)
	Update(ctx context.Context, ns string, pvc *corev1.PersistentVolumeClaim) error
	Delete(ctx context.Context, ns string, name string) (*corev1.PersistentVolumeClaim, error)
}

type ArchivedClusterReaderWriter interface {
	Archive(ctx context.Context, bucket string, uniqueKey structs.ClusterUniqueKey, archived structs.ArchivedClusterInfo) error
	Get(ctx context.Context, bucket string, uniqueKey structs.ClusterUniqueKey) (structs.ArchivedClusterInfo, error)
}

type JobReaderWriter interface {
	Create(ctx context.Context, job *batchv1.Job) error
	Get(ctx context.Context, ns, name string) (*batchv1.Job, error)
	IsJobExists(ctx context.Context, ns, name string) (bool, error)
	Delete(ctx context.Context, ns string, name string) (*batchv1.Job, error)
}

type PrometheusAPIClient interface {
	Alerts(url string, ctx context.Context) (promapiv1.AlertsResult, error)
	QueryRange(url string, ctx context.Context, query string, r promapiv1.Range, opts ...promapiv1.Option) (prommodel.Value, promapiv1.Warnings, error)
}

type ConfigMapReaderWriter interface {
	Get(ctx context.Context, namespace, name string) (*corev1.ConfigMap, error)
	Create(ctx context.Context, configMap *corev1.ConfigMap) error
	Update(ctx context.Context, configMap *corev1.ConfigMap) error
	CreateOrUpdate(ctx context.Context, configMap *corev1.ConfigMap) error
}

type IntegrationTaskReaderWriter interface {
	IsIntegrationTaskExists(ctx context.Context, key client.ObjectKey) (bool, error)
	CreateIntegrationTask(ctx context.Context, task *v1.IntegrationTask) error
	UpdateIntegrationTask(ctx context.Context, task *v1.IntegrationTask) error
	GetIntegrationTask(ctx context.Context, key client.ObjectKey) (*v1.IntegrationTask, error)
	GetIntegrationTaskByID(ctx context.Context, clusterId, taskId string) (*v1.IntegrationTask, error)
	DeleteIntegrationTask(ctx context.Context, key client.ObjectKey) error
	QueryIntegrationTasks(ctx context.Context, filters map[string]string, cr message.ContinueRequest) (*v1.IntegrationTaskList, error)
}

type HelmReleaseReaderWriter interface {
	Create(ctx context.Context, helmRelease *helmv2.HelmRelease) error
	Get(ctx context.Context, namespace, name string) (*helmv2.HelmRelease, error)
	List(ctx context.Context, namespace string, cr message.ContinueRequest) (*helmv2.HelmReleaseList, error)
	ListAll(ctx context.Context, cr message.ContinueRequest) (*helmv2.HelmReleaseList, error)
	Update(ctx context.Context, helmRelease *helmv2.HelmRelease) error
	Delete(ctx context.Context, namespace, name string) error
	IsHelmReleaseExists(ctx context.Context, namespace, name string) (bool, error)
}

type UpgradeOperationReaderWriter interface {
	Create(ctx context.Context, op *v1.ClusterUpgradeOperation) error
	Get(ctx context.Context, namespace, name string) (*v1.ClusterUpgradeOperation, error)
	List(ctx context.Context, namespace string, cr message.ContinueRequest) (*v1.ClusterUpgradeOperationList, error)
	Update(ctx context.Context, op *v1.ClusterUpgradeOperation) error
	Delete(ctx context.Context, namespace, name string) error
	IsOperationExists(ctx context.Context, namespace, name string) (bool, error)
	GetClient() client.Client
}
