package data_pipeline

import (
	"context"

	"github.com/tidbcloud/dataflow-service-ng/app/models/domain"
	"github.com/tidbcloud/pkgv2/bizerr"
)

// Model is the business boundary used by the Data Pipeline Console API.
//
//nolint:interfacebloat // The Console resource has one cohesive lifecycle API.
type Model interface {
	CreateDataPipeline(
		ctx context.Context, req *domain.CreateDataPipelineReq,
	) (*domain.CreateDataPipelineResp, bizerr.BizError)
	GetDataPipeline(
		ctx context.Context, req *domain.GetDataPipelineReq,
	) (*domain.GetDataPipelineResp, bizerr.BizError)
	ListDataPipelines(
		ctx context.Context, req *domain.ListDataPipelinesReq,
	) (*domain.ListDataPipelinesResp, bizerr.BizError)
	PauseDataPipeline(ctx context.Context, req *domain.PauseDataPipelineReq) bizerr.BizError
	EditDataPipeline(ctx context.Context, req *domain.EditDataPipelineReq) bizerr.BizError
	ScaleDataPipeline(ctx context.Context, req *domain.ScaleDataPipelineReq) bizerr.BizError
	ResumeDataPipeline(ctx context.Context, req *domain.ResumeDataPipelineReq) bizerr.BizError
	DeleteDataPipeline(ctx context.Context, req *domain.DeleteDataPipelineReq) bizerr.BizError
	ValidateDataPipelineSourceConnection(
		ctx context.Context, req *domain.ValidateDataPipelineSourceConnectionReq,
	) bizerr.BizError
	ValidateDataPipelineStaging(
		ctx context.Context, req *domain.ValidateDataPipelineStagingReq,
	) bizerr.BizError
	ValidateDataPipelineDestination(
		ctx context.Context, req *domain.ValidateDataPipelineDestinationReq,
	) bizerr.BizError
	GetDataPipelineStagingTrust(
		ctx context.Context, req *domain.GetDataPipelineStagingTrustReq,
	) (*domain.GetDataPipelineStagingTrustResp, bizerr.BizError)
}

// ValidationScope contains only the stable identity required to authenticate
// external validation calls. Runtime tokens and Lake organization slugs are
// deliberately absent and must be derived by the validator per call.
type ValidationScope struct {
	TenantID   uint64
	ClusterID  uint64
	PipelineID uint64
	UserID     uint64
	// Which Lake the destination calls are scoped to. Carried on the scope
	// rather than read from the Pipeline because staging is validated before
	// any Pipeline row exists.
	LakeOrgID string
}

// ExternalResourceValidator reuses the existing TiDB/Changefeed connection
// checks and the destination adapter without coupling the orchestration model
// to their wire request types.
type ExternalResourceValidator interface {
	// ValidateSource checks that the source account works and, when a filter
	// is supplied, that it parses. It also reports how many tables the
	// selection resolved to. That count is recorded on the Pipeline rather
	// than discarded: a filter matching nothing is allowed but is seldom what
	// was meant, and for a snapshot-only Pipeline it is the only place that
	// answer exists, since the destination's live table counters are written
	// by the CDC run.
	ValidateSource(
		ctx context.Context,
		clusterID uint64,
		source domain.DataPipelineSourceInput,
	) (int32, bizerr.BizError)
	ValidateStaging(
		ctx context.Context,
		scope ValidationScope,
		staging domain.DataPipelineStagingInput,
	) bizerr.BizError
	ValidateChangefeedSpecification(
		ctx context.Context,
		clusterID uint64,
		specification string,
	) bizerr.BizError
}

// LifecycleCoordinator owns idempotent child-resource operations. Fastflow
// actions remain thin and call one method per durable orchestration stage.
//
//nolint:interfacebloat // Explicit stages make retry and ordering contracts reviewable.
type LifecycleCoordinator interface {
	CreateExport(context.Context, uint64) bizerr.BizError
	CreateChangefeed(context.Context, uint64) bizerr.BizError
	WaitSnapshotReady(context.Context, uint64) bizerr.BizError
	CreateDestination(context.Context, uint64) bizerr.BizError
	StartDestination(context.Context, uint64) bizerr.BizError
	FinishCreate(context.Context, uint64) bizerr.BizError

	PauseChangefeed(context.Context, uint64) bizerr.BizError
	StopDestination(context.Context, uint64) bizerr.BizError
	FinishPause(context.Context, uint64) bizerr.BizError

	ApplyChangefeed(context.Context, uint64) bizerr.BizError
	ApplyDestination(context.Context, uint64) bizerr.BizError
	FinishEdit(context.Context, uint64) bizerr.BizError
	ResumeChangefeed(context.Context, uint64) bizerr.BizError
	FinishResume(context.Context, uint64) bizerr.BizError

	DeleteDestination(context.Context, uint64) bizerr.BizError
	DeleteChangefeed(context.Context, uint64) bizerr.BizError
	DeleteExport(context.Context, uint64) bizerr.BizError
	FinishDelete(context.Context, uint64) bizerr.BizError
}

type ObservationModel interface {
	SyncObservations(context.Context) bizerr.BizError
}
