package container

import (
	"fmt"
	"strings"
	"time"

	data_pipeline_impl "github.com/tidbcloud/dataflow-service-ng/app/models/data_pipeline/impl"
	service_config "github.com/tidbcloud/dataflow-service-ng/internal/config"
	"github.com/tidbcloud/dataflow-service-ng/pkg/lake"
)

type dataPipelineClock struct{}

func (dataPipelineClock) Now() time.Time { return time.Now() }

func initDataPipeline(container *GlobalContainer) error {
	cfg := service_config.Global().DataPipeline
	if err := cfg.ValidateRuntime(); err != nil {
		return fmt.Errorf("validate data pipeline runtime configuration: %w", err)
	}

	lakeClient, err := newDataPipelineLakeClient(cfg)
	if err != nil {
		return err
	}
	clock := dataPipelineClock{}
	exportClient := container.MgmtSvcGrpcClient.ExportClient()
	validator := data_pipeline_impl.NewExternalResourceValidator(
		container.BizChangefeedModel,
		lakeClient,
	)

	container.DataPipelineConfig = cfg
	container.DataPipelineExportClient = exportClient
	container.DataPipelineLakeClient = lakeClient
	container.DataPipelineValidator = validator
	container.DataPipelineLifecycleCoordinator = data_pipeline_impl.NewLifecycleCoordinator(
		container.DataPipelineRepo,
		exportClient,
		container.BizChangefeedModel,
		lakeClient,
		container.Encryptor,
		clock,
	)
	container.DataPipelineModel = data_pipeline_impl.NewDataPipelineModel(
		container.DataPipelineRepo,
		container.MgmtSvcGrpcClient,
		container.BizChangefeedModel,
		lakeClient,
		validator,
		container.Encryptor,
		container.WorkflowModel,
		data_pipeline_impl.RuntimeConfig{
			Environment: service_config.Global().Env,
		},
		clock,
	)
	container.DataPipelineObservationModel = data_pipeline_impl.NewObservationModel(
		container.DataPipelineRepo,
		exportClient,
		container.BizChangefeedModel,
		lakeClient,
		clock,
		data_pipeline_impl.ObservationConfig{
			StaleThreshold: time.Duration(cfg.ObservationStaleSeconds) * time.Second,
		},
	)
	return nil
}

func newDataPipelineLakeClient(
	cfg service_config.DataPipelineConfig,
) (lake.Client, error) {
	// A write kill switch must not remove dependencies needed to pause or
	// delete an existing pipeline. Initialize Lake whenever complete settings
	// remain available; disabled deployments with absent or partial optional
	// settings still start safely.
	hmacSecret := strings.TrimSpace(cfg.LakeHMACSecret.Reveal())
	if strings.TrimSpace(cfg.LakeBaseURL) == "" || hmacSecret == "" {
		return nil, nil
	}
	client, err := lake.NewHTTPClient(lake.HTTPClientConfig{
		BaseURL:    strings.TrimSpace(cfg.LakeBaseURL),
		HMACSecret: lake.NewSecret(hmacSecret),
	})
	if err != nil {
		return nil, fmt.Errorf("initialize data pipeline Lake client: %w", err)
	}
	return client, nil
}
