package mgmthttpcli

import (
	"context"
	"fmt"

	"github.com/go-resty/resty/v2"
	apiv1 "github.com/tidbcloud/infra-provider/api/tidbcloud/cluster-agent/v1"
	emptypb "google.golang.org/protobuf/types/known/emptypb"
)

type CDCAgentV1 interface {
	PauseReconcileV1(ctx context.Context, req *apiv1.CdcPauseTCReq) (*emptypb.Empty, error)
	DeletePodsAndResumeReconcileV1(ctx context.Context, req *apiv1.CdcDeleteAstsAndResumeTCReq) (*emptypb.Empty, error)
}

type cdcAgentV1 struct {
	core      *resty.Client
	clusterID string
}

func (c *cdcAgentV1) PauseReconcileV1(ctx context.Context, req *apiv1.CdcPauseTCReq) (*emptypb.Empty, error) {
	path := "/api/v1/cdcs:pause_tc"
	var resp emptypb.Empty

	restyReq := c.core.R().
		SetContext(ctx).
		SetBody(req).
		SetResult(&resp)

	_, err := c.do(resty.MethodPost, path, restyReq)
	return &resp, err
}

func (c *cdcAgentV1) DeletePodsAndResumeReconcileV1(ctx context.Context, req *apiv1.CdcDeleteAstsAndResumeTCReq) (*emptypb.Empty, error) {
	path := "/api/v1/cdcs:delete_asts_and_resume"
	var resp emptypb.Empty

	restyReq := c.core.R().
		SetContext(ctx).
		SetBody(req).
		SetResult(&resp)

	_, err := c.do(resty.MethodPost, path, restyReq)
	return &resp, err
}

func (c *cdcAgentV1) do(method, apiPath string, request *resty.Request) (*resty.Response, error) {
	request = request.SetPathParam("cluster_id", c.clusterID)
	prefix := "/proxy/clusters/{cluster_id}/cluster-agent/tidb{cluster_id}"
	url := prefix + apiPath

	resp, err := request.Execute(method, url)
	if err != nil {
		return nil, fmt.Errorf("call clusterServer failed: %w", err)
	}
	return resp, nil
}

type CDCAgentV2 interface {
	PauseReconcileV2(ctx context.Context, req *apiv1.PauseClusterReq) (*emptypb.Empty, error)
	DeletePodsAndResumeReconcileV2(ctx context.Context, req *apiv1.DeleteGroupInstancesAndResumeClusterReq) (*emptypb.Empty, error)
}

type cdcAgentV2 struct {
	core      *resty.Client
	clusterID string
}

func (c *cdcAgentV2) PauseReconcileV2(ctx context.Context, req *apiv1.PauseClusterReq) (*emptypb.Empty, error) {
	path := "/api/v1/opv2/namespace/{namespace}/cluster/{cluster_name}:pause"
	var resp emptypb.Empty

	restyReq := c.core.R().
		SetContext(ctx).
		SetBody(req).
		SetResult(&resp)

	_, err := c.do(resty.MethodPost, path, restyReq)
	return &resp, err
}

func (c *cdcAgentV2) DeletePodsAndResumeReconcileV2(ctx context.Context, req *apiv1.DeleteGroupInstancesAndResumeClusterReq) (*emptypb.Empty, error) {
	path := "/api/v1/opv2/namespace/{namespace}/cluster/{cluster_name}:delete_group_instances_and_resume"
	var resp emptypb.Empty

	restyReq := c.core.R().
		SetContext(ctx).
		SetBody(req).
		SetResult(&resp)

	_, err := c.do(resty.MethodPost, path, restyReq)
	return &resp, err
}

func (c *cdcAgentV2) do(method, apiPath string, request *resty.Request) (*resty.Response, error) {
	request = request.SetPathParam("cluster_id", c.clusterID)
	request = request.SetPathParam("namespace", fmt.Sprintf("tidb%s", c.clusterID))
	request = request.SetPathParam("cluster_name", "db") // FIX ME: here we use cluster id as cluster name, need to change to real cluster name
	prefix := "/proxy/clusters/{cluster_id}/cluster-agent/tidb{cluster_id}"
	url := prefix + apiPath

	resp, err := request.Execute(method, url)
	if err != nil {
		return nil, fmt.Errorf("call clusterServer failed: %w", err)
	}
	return resp, nil
}
