package regionalapi

import (
	"context"
	"net/url"

	ticdc_v1 "github.com/tidbcloud/infra-provider/api/tidbcloud/ticdc-service/v1"
	"github.com/tidbcloud/pkgv2/bizerr"
)

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

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

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)
	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,
	}
	resp := new(ticdc_v1.ListChangefeedsResponse)
	if err := m.regionalCli.Get(ctx, region, listChangefeedPath, pathParams, nil, 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,
	}
	changefeed := new(ticdc_v1.Changefeed)
	if err := m.regionalCli.Get(ctx, region, getChangefeedPath, pathParams, nil, 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,
	}
	return m.regionalCli.Post(ctx, region, pauseChangefeedPath, pathParams, nil, nil, 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,
	}
	return m.regionalCli.Post(ctx, region, resumeChangefeedPath, pathParams, nil, 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,
	}
	return m.regionalCli.Put(ctx, region, updateChangefeedPath, pathParams, 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,
	}
	return m.regionalCli.Delete(ctx, region, deleteChangefeedPath, pathParams, nil)
}
