package jobs

import (
	"gadmin/internal/cron/jobs/types"
	"gadmin/utility"
	"gadmin/utility/character"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/sirupsen/logrus"
	"github.com/spf13/cast"
)

var BackupEmail = new(jBackupEmail)

const EmailBackupPath = "/email/" // 备份二级路径

type jBackupEmail struct{}

func (j *jBackupEmail) Run() {
	logrus.WithField("source", "email").Info("BackupEmail Run.....")

	j.createDir()

	data, err := ioutil.ReadFile(os.Getenv("STORAGE_EMAILS"))
	if err != nil {
		logrus.WithField("source", "email").Errorf("Run read file err:%v", err.Error())
		return
	}

	if j.getLastMd5() != character.Md5Content(data) {
		dstFileName := j.backupPath() + time.Now().Format("2006-01-02-150405")
		j.copyFile(dstFileName, os.Getenv("STORAGE_EMAILS"))
		j.cleanupExpired()
		return
	}

	logrus.WithField("source", "email").Infof("neglect..")
}

func (j *jBackupEmail) getLastMd5() string {
	lastName := ""
	lastIndex := 0
	err := filepath.Walk(j.backupPath(), func(pat string, info os.FileInfo, err error) error {
		n := cast.ToInt(strings.ReplaceAll(info.Name(), "-", ""))
		if n > lastIndex {
			lastIndex = n
			lastName = info.Name()
		}
		return nil
	})

	if err != nil {
		logrus.WithField("source", "email").Errorf("getLastMd5 file err = %v\n", err)
	}

	if lastIndex == 0 {
		return ""
	}

	data, err := os.ReadFile(j.backupPath() + lastName)
	if err != nil {
		logrus.WithField("source", "email").Errorf("getLastMd5 read file err:%v", err.Error())
		return ""
	}

	return character.Md5Content(data)
}

func (j *jBackupEmail) copyFile(dstFileName string, srcFileName string) (written int64, err error) {
	srcFile, err := os.Open(srcFileName)
	if err != nil {
		logrus.WithField("source", "email").Errorf("open file err = %v\n", err)
		return
	}
	defer srcFile.Close()

	dstFile, err := os.Create(dstFileName)
	if err != nil {
		logrus.WithField("source", "email").Errorf("open file err = %v\n", err)
		return
	}

	defer dstFile.Close()
	return io.Copy(dstFile, srcFile)
}

func (j *jBackupEmail) cleanupExpired() {
	var files types.SrcFiles
	err := filepath.Walk(j.backupPath(), func(pat string, info os.FileInfo, err error) error {
		index := cast.ToInt(strings.ReplaceAll(info.Name(), "-", ""))
		if index > 0 {
			files = append(files, types.SrcFile{
				Name:  info.Name(),
				Index: index,
			})
		}
		return nil
	})
	if err != nil {
		logrus.WithField("source", "email").Errorf("getLastMd5 file err = %v\n", err)
	}

	// 倒序，最新的备份排在最前面
	sort.Sort(files)

	// 保留最新的100份，之前的加入到清理
	var cleanFiles types.SrcFiles
	for k, v := range files {
		if k+1 > 100 {
			cleanFiles = append(cleanFiles, v)
		}
	}

	if len(cleanFiles) == 0 {
		return
	}

	for _, v := range cleanFiles {
		path := j.backupPath() + v.Name
		logrus.WithField("source", "email").Infoln("清理邮件备份：", path)
		if err := os.Remove(path); err != nil {
			logrus.WithField("source", "email").Errorf("os.Remove err:%v", err)
		}
	}
}

func (j *jBackupEmail) createDir() {
	utility.CreateDir(j.backupPath())
}

func (j *jBackupEmail) backupPath() string {
	return os.Getenv("BACKUP_PATH") + EmailBackupPath
}
