package repository

import (
	"context"
	"dataservices/commons/errs"
	"dataservices/commons/utils"
	"dataservices/internal/entity"
	"time"

	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

func RecordEtlEndpointRegion(ctx context.Context, record *entity.EtlEndpointRegion) error {
	err := MustFromContext(ctx).Table(entity.TableEtlEndpointRegion).Where("dataapp_id=? AND endpoint_id=?", record.DataappID, record.EndpointID).FirstOrCreate(record).Error
	if err != nil {
		return errs.WrapGORMError(err, "failed to create execpoint execute record")
	}
	return nil
}

func RecordEtlCombinedData(ctx context.Context, record *entity.EtlCombinedData) error {
	value := record.Value
	err := MustFromContext(ctx).Table(entity.TableEtlCombinedData).
		Where("job_type=? AND record_timestamp=? AND key1=? AND key2=? AND key3=? AND key4=?", record.JobType, record.RecordTimestamp, record.Key1, record.Key2, record.Key3, record.Key4).
		First(record).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			MustFromContext(ctx).Table(entity.TableEtlCombinedData).Create(record)
		} else {
			tilog.Info(ctx, "scan record failed.", zap.Any("err", err))
			return errs.WrapGORMError(err, "failed to create execpoint execute record")
		}
	} else {
		tilog.Info(ctx, "update record", zap.Any("RECORD", record))
		err = MustFromContext(ctx).Table(entity.TableEtlCombinedData).
			Where("job_type=? AND record_timestamp=? AND key1=? AND key2=? AND key3=? AND key4=?", record.JobType, record.RecordTimestamp, record.Key1, record.Key2, record.Key3, record.Key4).
			Update("Value", value).Error
		if err != nil {
			tilog.Info(ctx, "Update record failed.", zap.Any("err", err))
			return errs.WrapGORMError(err, "failed to create execpoint execute record")

		}
	}

	return nil
}

func DeleteEtlCombinedData(ctx context.Context, jobType string, recordTime time.Time) error {
	if err := MustFromContext(ctx).
		Table(entity.TableEtlCombinedData).Where("job_type=? and record_timestamp=? ", jobType, recordTime).
		Delete(&entity.EtlCombinedData{}).Error; err != nil {
		return errs.WrapGORMError(err, "Failed to DeleteEtlCombinedData: %s ", jobType)
	}
	return nil
}

func CountEtlCombinedData(ctx context.Context, jobType string, recordTime time.Time) (int64, error) {
	var count int64
	if err := MustFromContext(ctx).
		Table(entity.TableEtlCombinedData).Where("job_type=? and record_timestamp=? ", jobType, recordTime).
		Count(&count).Error; err != nil {
		return 0, errs.WrapGORMError(err, "Failed to CountEtlCombinedData: %s ", jobType)
	}
	return count, nil
}

func RecordEtlActiveUser(ctx context.Context, appType string, email string, activeTime time.Time) error {
	record := entity.EtlActiveUser{}
	err := MustFromContext(ctx).Table(entity.TableEtlActiveUser).
		Where("email=? and app_type=?", email, appType).First(&record).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			record.Email = email
			record.AppType = appType
			record.CreatedAt.Time = activeTime
			record.UpdatedAt.Time = activeTime
			record.EmailType = utils.GetExternalTypeByEmail(email)
			err = MustFromContext(ctx).Table(entity.TableEtlActiveUser).Create(record).Error
			if err != nil {
				return errs.WrapGORMError(err, "failed to RecordEtlActiveUser")
			}
		} else {
			return errs.WrapGORMError(err, "failed to RecordEtlActiveUser")
		}
	} else {
		if activeTime.Before(record.CreatedAt.Time) {
			err = MustFromContext(ctx).Table(entity.TableEtlActiveUser).Where("email=? AND app_type=?", email, appType).Update("created_at", activeTime).Error
			if err != nil {
				return errs.WrapGORMError(err, "failed to RecordEtlActiveUser")
			}
		}
		if !activeTime.Equal(record.UpdatedAt.Time) {
			err = MustFromContext(ctx).Table(entity.TableEtlActiveUser).Where("email=? AND app_type=?", email, appType).Update("updated_at", activeTime).Error
			if err != nil {
				return errs.WrapGORMError(err, "failed to RecordEtlActiveUser")
			}
		}
	}
	return nil
}

func CountActiveUserNum(ctx context.Context, filter entity.EtlActiveUserCountInput) ([]entity.AnalysisStrStrKKVResult, error) {
	db := MustFromContext(ctx).Table(entity.TableEtlActiveUser).
		Select("email_type as `key1`, app_type as `key2`, COUNT(1) as value")
	if filter.CreatedRange {
		startTimeObj := time.Unix(filter.CreatedStartSec, 0)
		endTimeObj := time.Unix(filter.CreatedEndSec, 0)
		db = db.Where("created_at >= ? and created_at < ?", startTimeObj, endTimeObj)
	}
	if filter.UpdatedRange {
		startTimeObj := time.Unix(filter.UpdatedStartSec, 0)
		endTimeObj := time.Unix(filter.UpdatedEndSec, 0)
		db = db.Where("updated_at >= ? and updated_at < ?", startTimeObj, endTimeObj)
	}

	var results []entity.AnalysisStrStrKKVResult
	err := db.Group("email_type, app_type").Scan(&results).Error
	if err != nil {
		return results, errs.WrapGORMError(err, "failed to CountEndpointExecRecord")
	}
	return results, nil
}
