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/message"
	"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 ReportTask() Task {
	start := models.Period(config.GetPeriodConfig().FirstPeriod).StartTime().Unix()
	return Task{
		Name:          constants.ReportTaskName,
		start:         start,
		interval:      time.Duration(config.GetScheduleConfig().GenerateStatisticReportIntervalHours) * time.Hour,
		immediately:   config.GetScheduleConfig().GenerateStatisticReportImmediately,
		execute:       GenerateStatisticReport,
		nextTimestamp: NextMonthlyTaskTimestamp,
		ready:         ReadyToReport,
		uploadData:    false,
	}
}

func GenerateStatisticReport(ctx context.Context, timestamp int64) error {
	_, err := statistic.Report(ctx, message.GenerateStatisticReportReq{
		// nolint:gosec
		Timestamp: int32(timestamp),
	})
	if err != nil {
		log.Errorf("statistic.Report failed, err = %s", err.Error())
		return err
	}

	return nil
}

func ReadyToReport(ctx context.Context, timestamp int64) bool {
	if timestamp > time.Now().Unix() {
		log.Infof("it’s time for task execution, task = %s", constants.ReportTaskName)
		return false
	}

	mergeCheckpoint, err := facade.GetCheckpointReaderWriter().GetCheckpoint(ctx, constants.StatisticMergeTaskName)
	if err != nil {
		log.Warnf("get merge_statistic checkpoint failed, err = %s, timestamp = %d, region = %s", err.Error(), timestamp, configs.GetServiceInfo().Region)
		return false
	}

	if mergeCheckpoint < timestamp {
		log.Infof("merge_statistic not ready")
		return false
	}
	// nolint:gosec
	costReady, err := facade.GetStatisticReportWriter().IfCostReady(ctx, int32(timestamp), configs.GetServiceInfo().Region)

	if err != nil {
		log.Errorf("IfCostReady failed, err = %s, timestamp = %d, region = %s", err.Error(), timestamp, configs.GetServiceInfo().Region)
		return false
	}

	if !costReady {
		log.Infof("cost data is not ready yet")
		return false
	}

	return true
}
