package schedule

import (
	"context"
	"time"

	log "github.com/sirupsen/logrus"
	"github.com/tidbcloud/observability/o11ymetering/pkg/common/config"
	"github.com/tidbcloud/observability/o11ymetering/pkg/common/constants"
	"github.com/tidbcloud/observability/o11ymetering/pkg/common/models"
	"github.com/tidbcloud/observability/o11ymetering/pkg/facade"
	"github.com/tidbcloud/observability/o11ymetering/pkg/service/statistic"
	"github.com/tidbcloud/observability/pkg/common/configs"
)

func StatisticMergeTask() Task {
	start := models.Period(config.GetPeriodConfig().FirstPeriod).StartTime().Unix()
	return Task{
		Name:          constants.StatisticMergeTaskName,
		start:         start,
		interval:      time.Duration(config.GetScheduleConfig().MergeStatisticIntervalHours) * time.Hour,
		immediately:   config.GetScheduleConfig().MergeStatisticImmediately,
		execute:       MergeStatistic,
		nextTimestamp: NextMonthlyTaskTimestamp,
		ready:         ReadyToMerge,
		uploadData:    true,
	}
}

func MergeStatistic(ctx context.Context, timestamp int64) error {
	facade.SwitchStatisticMergeReaderWriter(ctx, timestamp)

	latest, err := facade.GetCurrentStatisticMergeReaderWriter().LatestMergedRecordPeriod(ctx, configs.GetServiceInfo().Region)
	if err != nil {
		log.Errorf("LatestMergedRecordPeriod failed, err = %s", err)
		return err
	}

	var start = timestamp
	var end = firstTimestampOfNextMonth(ctx, timestamp+1)

	if len(latest) > 0 {
		latestTimestamp := models.Period(latest).StartTime().Unix()
		if latestTimestamp > timestamp {
			start = latestTimestamp
		}
	}

	for t := start; t < end; t += constants.StatisticStepSeconds {
		localFile, err := statistic.EnsureLocalData(ctx, constants.StatisticTaskName, t)
		if err != nil {
			return err
		}

		log.Infof("copy statistic records from localFile, %s", localFile)
		err = facade.GetCurrentStatisticMergeReaderWriter().CopyRecords(ctx, localFile, configs.GetServiceInfo().Region)
		if err != nil {
			return err
		}
	}
	return nil
}

func ReadyToMerge(ctx context.Context, timestamp int64) bool {
	// statistic not ready
	nextMonthTimestamp := firstTimestampOfNextMonth(ctx, timestamp+1)
	statisticCheckpoint, err := facade.GetCheckpointReaderWriter().GetCheckpoint(ctx, constants.StatisticTaskName)
	if err != nil {
		log.Errorf("get statistic checkpoint failed, err = %s, timestamp = %d, region = %s", err.Error(), timestamp, configs.GetServiceInfo().Region)
		return false
	}

	log.Infof("timestamp = %d, nextMonthTimestamp = %d, statisticCheckpoint = %d", timestamp, nextMonthTimestamp, statisticCheckpoint)
	if statisticCheckpoint < nextMonthTimestamp {
		log.Infof("statistic not ready for merge")
		return false
	}
	return time.Now().Add(-30*time.Minute).Unix() > timestamp
}
