package cvt

import (
	"fmt"
	"time"

	"github.com/pingcap/errors"
	modelutil "github.com/tidbcloud/dataflow-service/internal/model/util"
	"google.golang.org/protobuf/types/known/timestamppb"

	"github.com/tidbcloud/core-svc/idl/pbgen/proto/core"
	"github.com/tidbcloud/dataflow-service/app/repo/entity"
	"github.com/tidbcloud/dataflow-service/idl/pbgen/proto/dataflow"
)

func DataflowBackupType2Entity(backupType dataflow.BackupType) entity.BackupType {
	switch backupType {
	case dataflow.BackupType_ALL:
		return entity.BackupTypeAll
	case dataflow.BackupType_AUTO:
		return entity.BackupTypeAuto
	case dataflow.BackupType_MANUAL:
		return entity.BackupTypeManual
	}
	panic(fmt.Sprintf("invalid backup type %s", backupType))
}

func LogBackupEntity2Dataflow(logBackup *entity.LogBackup) (*dataflow.LogBackup, error) {
	dfLogBackup := &dataflow.LogBackup{
		Id:               uint64(logBackup.ID),
		ClusterId:        uint64(logBackup.ClusterID),
		BackupScheduleId: uint64(logBackup.BackupScheduleID),
		Name:             logBackup.Name,
		CreatedAt:        timestamppb.New(logBackup.CreatedAt),
		Status:           LogBackupStatusEntity2Dataflow(logBackup.Status),
	}

	if logBackup.StartTS != nil {
		startTS, err := modelutil.ParseTSFromTSString(*logBackup.StartTS)
		if err != nil {
			return nil, errors.Annotatef(err, "parse start ts %s", *logBackup.StartTS)
		}
		dfLogBackup.StartTs = timestamppb.New(time.Unix(startTS, 0))
	}
	if logBackup.CheckpointTS != "" {
		checkpointTS, err := modelutil.ParseTSFromTSString(logBackup.CheckpointTS)
		if err != nil {
			return nil, errors.Annotatef(err, "parse checkpoint ts %s", logBackup.CheckpointTS)
		}
		dfLogBackup.CheckPointTs = timestamppb.New(time.Unix(checkpointTS, 0))
	}
	if logBackup.TruncateUntil != "" {
		truncateUntil, err := modelutil.ParseTSFromTSString(logBackup.TruncateUntil)
		if err != nil {
			return nil, errors.Annotatef(err, "parse truncate until %s", logBackup.TruncateUntil)
		}
		dfLogBackup.TruncateUntil = timestamppb.New(time.Unix(truncateUntil, 0))
	}

	return dfLogBackup, nil
}

func LogBackupStatusEntity2Dataflow(status entity.LogBackupStatus) dataflow.LogBackup_Status {
	switch status {
	case entity.LogBackupStatusScheduled:
		return dataflow.LogBackup_SCHEDULED
	case entity.LogBackupStatusPending:
		return dataflow.LogBackup_PENDING
	case entity.LogBackupStatusRunning:
		return dataflow.LogBackup_RUNNING
	case entity.LogBackupStatusPausing:
		return dataflow.LogBackup_PAUSING
	case entity.LogBackupStatusPaused:
		return dataflow.LogBackup_PAUSED
	case entity.LogBackupStatusResuming:
		return dataflow.LogBackup_RESUMING
	case entity.LogBackupStatusStopping:
		return dataflow.LogBackup_STOPPING
	case entity.LogBackupStatusStopped:
		return dataflow.LogBackup_STOPPED
	case entity.LogBackupStatusFailed:
		return dataflow.LogBackup_FAILED
	default:
		return dataflow.LogBackup_UNSPECIFIED
	}
}

func ConvertBackupScheduleDeployType(cluster *core.Cluster) entity.BackupClusterType {
	if cluster.IsDevTier {
		return entity.BackupClusterTypeServerless
	}
	return entity.BackupClusterTypeDedicated
}
