package workers

import (
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go/service/marketplacecommerceanalytics"
	"github.com/pingcap/dbaas/billing2/config"
	"github.com/pingcap/dbaas/billing2/handler/awshandler"
	"github.com/pingcap/dbaas/billing2/handler/workerhandler"
	"github.com/pingcap/dbaas/billing2/model/payment/reconciliation"
	"github.com/pingcap/dbaas/billing2/utils/log"
	"github.com/pingcap/dbaas/billing2/utils/timeutils"
	"go.uber.org/zap"
)

func GenerateAWSDailyReportWorker() error {
	if !config.Get().GetBool(config.AWSPaymentEnable) {
		log.Info("aws payment is not enabled")
		return nil
	}
	now := timeutils.GetNow()
	if now.Hour() < config.Get().GetInt(config.AWSMarketplaceDailyReportGenerateRunningOffsetHours) {
		log.Info("It's too early to generate data")
		return nil
	}
	workerName := "GenerateAWSDailyReportWorker"
	workerhandler.Get().DedupeRun(0, workerName, timeutils.DAY, now, func(tenantID uint, startTime time.Time) (interface{}, error) {
		date := timeutils.GetDayDate(now.AddDate(0, 0, -config.Get().GetInt(config.AWSMarketplaceDailyReportGenerateDelayDays)))
		commerce, err := awshandler.NewMarketPlaceCommerceAnalyticsClient()
		if err != nil {
			log.Error("failed to new MarketPlaceCommerceAnalyticsClient", zap.Error(err))
			return nil, err
		}
		var lastErr error
		for _, dataSetType := range config.Get().GetStringSlice(config.AWSMarketplaceDailyReportDataSetTypeList) {
			s3BucketName := config.Get().GetString(config.ReconciliationAWSS3BucketName)
			roleName := config.Get().GetString(config.ReconciliationAWSRoleNameArn)
			snsTopicArn := config.Get().GetString(config.ReconciliationAWSSNSTopicArn)
			prefix := fmt.Sprintf("%s/%s", config.Get().GetString(config.ENV), dataSetType)
			ret, err := commerce.GenerateDataSet(&marketplacecommerceanalytics.GenerateDataSetInput{
				DataSetType:             &dataSetType,
				DestinationS3BucketName: &s3BucketName,
				DestinationS3Prefix:     &prefix,
				DataSetPublicationDate:  &date,
				RoleNameArn:             &roleName,
				SnsTopicArn:             &snsTopicArn,
			})
			if err != nil {
				log.Error("failed to generate date set", zap.Error(err), zap.String("dataSetType", dataSetType), zap.Time("date", date))
				lastErr = err
				continue
			}
			log.Info("success to generate date set", zap.String("dataSetType", dataSetType), zap.Time("date", date), zap.String("DataSetRequestId", *ret.DataSetRequestId))
		}
		return nil, lastErr
	})
	return nil
}

func ReconciliationDailyWorker() error {
	now := timeutils.GetNow()
	workName := "ReconciliationDailyWorker"
	workerhandler.Get().DedupeRun(0, workName, timeutils.DAY, now, func(tenantID uint, startTime time.Time) (interface{}, error) {
		model := &reconciliation.Model{}
		err := model.DailyCheck()
		if err != nil {
			log.Error("failed to run ReconciliationDailyWorker", zap.Error(err))
			return nil, err
		}
		return nil, nil
	})
	return nil
}

func ReconciliationMonthlyWorker() error {
	now := timeutils.GetNow()
	workName := "ReconciliationMonthlyWorker"
	workerhandler.Get().DedupeRun(0, workName, timeutils.MONTH, now, func(tenantID uint, startTime time.Time) (interface{}, error) {
		model := &reconciliation.Model{}
		err := model.MonthlyReport()
		if err != nil {
			log.Error("failed to run ReconciliationMonthlyWorker", zap.Error(err))
			return nil, err
		}
		return nil, err
	})
	return nil
}
