package removeFile

import (
	"encoding/json"
	"os"
	"path/filepath"
	"sort"
	"time"

	"be.ems/lib/log"
	"be.ems/src/framework/cron"
)

var NewProcessor = &BarProcessor{
	progress: 0,
	count:    0,
}

// bar 队列任务处理
type BarProcessor struct {
	// 任务进度
	progress int
	// 执行次数
	count int
}

type BarParams struct {
	FilePath string `json:"filePath"` // file path
	MaxDays  int    `json:"maxDays"`
	MaxFiles *int   `json:"maxFiles"` // keep max files
	MaxSize  *int64 `json:"maxSize"`
	Extras   string `json:"extras"` // extras condition for where
}

type FileInfo struct {
	Path string
	Info os.FileInfo
}

func (s *BarProcessor) Execute(data any) (any, error) {
	s.count++

	options := data.(cron.JobData)
	sysJob := options.SysJob
	var params []BarParams

	err := json.Unmarshal([]byte(sysJob.TargetParams), &params)
	if err != nil {
		return nil, err
	}
	result := []map[string]any{}
	for _, param := range params {
		res, _ := s.ExecuteOne(param)
		result = append(result, res)
	}

	// 返回结果，用于记录执行结果
	return map[string]any{
		"result": result,
	}, nil
}

func (s *BarProcessor) ExecuteOne(params BarParams) (map[string]any, error) {
	var maxFiles int = 0
	var maxSize int64 = 0
	if params.MaxFiles != nil {
		maxFiles = *params.MaxFiles
	}
	if params.MaxSize != nil {
		maxSize = int64(*params.MaxSize * 1024 * 1024)
	}
	files, err := getFiles(params.FilePath)
	if err != nil {
		return map[string]any{
			"msg": "failed",
			"err": err.Error(),
		}, err
	}

	// 获取本地时区
	loc, err := time.LoadLocation("Local")
	if err != nil {
		return map[string]any{
			"msg": "failed",
			"err": err.Error(),
		}, err
	}
	cutoff := time.Now().In(loc).AddDate(0, 0, -params.MaxDays)

	var oldFiles []FileInfo
	for _, file := range files {
		if file.Info.ModTime().Before(cutoff) {
			oldFiles = append(oldFiles, file)
		}
	}

	// 按修改时间排序文件（最旧的在前）
	sort.Slice(oldFiles, func(i, j int) bool {
		return oldFiles[i].Info.ModTime().Before(oldFiles[j].Info.ModTime())
	})

	deleted, errorDel := 0, 0

	// 删除文件，直到满足文件总数不超过maxFiles个且总大小不超过maxSize的条件
	var totalSize int64
	for i, file := range oldFiles {
		if (maxFiles > 0 && i >= maxFiles) || (maxSize > 0 && totalSize+file.Info.Size() > maxSize) {
			break
		}
		err := os.Remove(file.Path)
		if err != nil {
			log.Error("Error deleting file:", file.Path, err)
			errorDel++
			continue
		}
		totalSize += file.Info.Size()
		deleted++
	}

	// 如果仍然有超过maxFiles个文件或总大小超过maxSize，继续删除最旧的文件
	remainingFiles := files
	sort.Slice(remainingFiles, func(i, j int) bool {
		return remainingFiles[i].Info.ModTime().Before(remainingFiles[j].Info.ModTime())
	})

	for (maxFiles > 0 && len(remainingFiles) > maxFiles) || (maxSize > 0 && totalSize > maxSize) {
		file := remainingFiles[0]
		err := os.Remove(file.Path)
		if err != nil {
			log.Error("Error deleting file:", file.Path, err)
			remainingFiles = remainingFiles[1:]
			continue
		}
		totalSize -= file.Info.Size()
		remainingFiles = remainingFiles[1:]
	}

	// 返回结果，用于记录执行结果
	return map[string]any{
		"msg":      "successed",
		"filePath": params.FilePath,
		"deleted":  deleted,
		"errorDel": errorDel,
	}, nil
}

func getFiles(dir string) ([]FileInfo, error) {
	var files []FileInfo
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() {
			files = append(files, FileInfo{Path: path, Info: info})
		}
		return nil
	})
	return files, err
}
