package regionalapi

import (
	"context"
	"net/url"

	ticdc_v1 "github.com/tidbcloud/cluster-service-ng/api/tidbcloud/ticdc-service/v1"
	"github.com/tidbcloud/pkgv2/bizerr"
)

const (
	regionalApiPrefix    = "/ticdc-service"
	createChangefeedPath = "/api/v1/ticdcClusters/{ticdc_cluster_id}/changefeeds"
	listChangefeedPath   = "/api/v1/ticdcClusters/{ticdc_cluster_id}/changefeeds"
	getChangefeedPath    = "/api/v1/ticdcClusters/{ticdc_cluster_id}/changefeeds/{changefeed_id}"
	pauseChangefeedPath  = "/api/v1/ticdcClusters/{ticdc_cluster_id}/changefeeds/{changefeed_id}:pause"
	resumeChangefeedPath = "/api/v1/ticdcClusters/{ticdc_cluster_id}/changefeeds/{changefeed_id}:resume"
	updateChangefeedPath = "/api/v1/ticdcClusters/{ticdc_cluster_id}/changefeeds/{changefeed_id}"
	deleteChangefeedPath = "/api/v1/ticdcClusters/{ticdc_cluster_id}/changefeeds/{changefeed_id}"
)

const (
	changefeedIDPathParam   = "changefeed_id"
	changefeedIDQueryParam  = "changefeedId"
	tidbClusterIDQueryParam = "tidbClusterId"
)

type ChangefeedClientImpl struct {
	regionalCli RegionalClient
}

func NewChangefeedClient(regionalCli RegionalClient) ChangefeedClient {
	return &ChangefeedClientImpl{
		regionalCli: regionalCli,
	}
}

func (m *ChangefeedClientImpl) CreateChangefeed(
	ctx context.Context, region *Region, req *ticdc_v1.CreateChangefeedRequest,
) (*ticdc_v1.Changefeed, bizerr.BizError) {
	pathParams := map[string]string{
		ticdcClusterIDPathParam: req.TicdcClusterId,
	}
	queryParams := make(url.Values)
	queryParams.Set(changefeedIDQueryParam, req.ChangefeedId)
	queryParams.Set(tidbClusterIDQueryParam, req.TidbClusterId)
	changefeed := new(ticdc_v1.Changefeed)
	if err := m.regionalCli.Post(
		ctx, region, createChangefeedPath, pathParams, queryParams, req.Changefeed, changefeed); err != nil {
		return nil, err
	}
	return changefeed, nil
}

func (m *ChangefeedClientImpl) ListChangefeeds(
	ctx context.Context, region *Region, req *ticdc_v1.ListChangefeedsRequest,
) (*ticdc_v1.ListChangefeedsResponse, bizerr.BizError) {
	pathParams := map[string]string{
		ticdcClusterIDPathParam: req.TicdcClusterId,
	}
	queryParams := make(url.Values)
	queryParams.Set(tidbClusterIDQueryParam, req.TidbClusterId)
	resp := new(ticdc_v1.ListChangefeedsResponse)
	if err := m.regionalCli.Get(ctx, region, listChangefeedPath, pathParams, queryParams, resp); err != nil {
		return nil, err
	}
	return resp, nil
}

func (m *ChangefeedClientImpl) GetChangefeed(
	ctx context.Context, region *Region, req *ticdc_v1.GetChangefeedRequest,
) (*ticdc_v1.Changefeed, bizerr.BizError) {
	pathParams := map[string]string{
		ticdcClusterIDPathParam: req.TicdcClusterId,
		changefeedIDPathParam:   req.ChangefeedId,
	}
	queryParams := make(url.Values)
	queryParams.Set(tidbClusterIDQueryParam, req.TidbClusterId)
	changefeed := new(ticdc_v1.Changefeed)
	if err := m.regionalCli.Get(ctx, region, getChangefeedPath, pathParams, queryParams, changefeed); err != nil {
		return nil, err
	}
	return changefeed, nil
}

func (m *ChangefeedClientImpl) PauseChangefeed(
	ctx context.Context, region *Region, req *ticdc_v1.PauseChangefeedRequest,
) bizerr.BizError {
	pathParams := map[string]string{
		ticdcClusterIDPathParam: req.TicdcClusterId,
		changefeedIDPathParam:   req.ChangefeedId,
	}
	queryParams := make(url.Values)
	queryParams.Set(tidbClusterIDQueryParam, req.TidbClusterId)
	return m.regionalCli.Post(ctx, region, pauseChangefeedPath, pathParams, queryParams, req, nil)
}

func (m *ChangefeedClientImpl) ResumeChangefeed(
	ctx context.Context, region *Region, req *ticdc_v1.ResumeChangefeedRequest,
) bizerr.BizError {
	pathParams := map[string]string{
		ticdcClusterIDPathParam: req.TicdcClusterId,
		changefeedIDPathParam:   req.ChangefeedId,
	}
	queryParams := make(url.Values)
	queryParams.Set(tidbClusterIDQueryParam, req.TidbClusterId)
	return m.regionalCli.Post(ctx, region, resumeChangefeedPath, pathParams, queryParams, req.Config, nil)
}

func (m *ChangefeedClientImpl) UpdateChangefeed(
	ctx context.Context, region *Region, req *ticdc_v1.UpdateChangefeedRequest,
) bizerr.BizError {
	pathParams := map[string]string{
		ticdcClusterIDPathParam: req.TicdcClusterId,
		changefeedIDPathParam:   req.ChangefeedId,
	}
	queryParams := make(url.Values)
	queryParams.Set(tidbClusterIDQueryParam, req.TidbClusterId)
	return m.regionalCli.Put(ctx, region, updateChangefeedPath, pathParams, queryParams, req.Changefeed, nil)
}

func (m *ChangefeedClientImpl) DeleteChangefeed(
	ctx context.Context, region *Region, req *ticdc_v1.DeleteChangefeedRequest,
) bizerr.BizError {
	pathParams := map[string]string{
		ticdcClusterIDPathParam: req.TicdcClusterId,
		changefeedIDPathParam:   req.ChangefeedId,
	}
	queryParams := make(url.Values)
	queryParams.Set(tidbClusterIDQueryParam, req.TidbClusterId)
	return m.regionalCli.Delete(ctx, region, deleteChangefeedPath, pathParams, queryParams)
}
