package log

import (
	"context"
	"io/fs"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"slices"
	"strings"
	"time"
)

type AutoClear struct {
	LogPath   string        // 日志存放路径
	CycleTime time.Duration // 循环等待时间
	SaveDays  int           // 保留的天数
	Suffix    []string      // 需要清理的后缀, 例如 .log
}

func (ac *AutoClear) initConfig() {
	if ac.CycleTime <= 0 {
		ac.CycleTime = 12 * time.Hour
	}
	if ac.SaveDays <= 0 {
		ac.SaveDays = 7
	}
	if len(ac.Suffix) == 0 {
		ac.Suffix = []string{".log", ".out"} // 日志与 PProf
	}
	if ac.LogPath == "" {
		log.Panic("LogPath is required")
	}
	ac.LogPath = filepath.Join(ac.LogPath)
}

func (ac *AutoClear) convertDateStrToTime(dateStr string) (time.Time, error) {
	return time.Parse("20060102", dateStr)
}

func (ac *AutoClear) runAs(dateRegex *regexp.Regexp) {
	currentDate := time.Now()
	currentDateStr := currentDate.Format("20060102")
	err := filepath.WalkDir(ac.LogPath, func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		hasSuffix := slices.ContainsFunc(ac.Suffix, func(suffix string) bool {
			return strings.HasSuffix(d.Name(), suffix)
		})
		if !d.IsDir() && hasSuffix {
			matches := dateRegex.FindStringSubmatch(path)
			if len(matches) > 0 {
				// 转换 YYYY_MM_DD 为 YYYYMMDD 格式
				fileDateStr := matches[1] + matches[2] + matches[3]
				fileDate, err := ac.convertDateStrToTime(fileDateStr)
				if err != nil {
					log.Printf("log.AutoClear: Failed to parse date from %s: %v\n", path, err)
					return nil
				}
				deltaDays := int(currentDate.Sub(fileDate).Hours() / 24)
				// 删除 SaveDays 之前的文件
				if deltaDays > ac.SaveDays {
					if err = os.Remove(path); err != nil {
						log.Printf("log.AutoClear: Failed to delete %s: %v\n", path, err)
						return nil
					}
					log.Printf("log.AutoClear: deleted old log file: %s\n", path)
				}
			}
		}
		return nil
	})
	if err != nil {
		log.Printf("log.AutoClear: Error walking directory: %v", err)
		return
	}
	log.Printf("log.AutoClear: %s old log files deletion process completed.\n", currentDateStr)
}

func (ac *AutoClear) Start(ctx context.Context) {
	ac.initConfig()
	// 匹配 YYYY_MM_DD 格式的日期
	dateRegex, err := regexp.Compile(`(\d{4})_(\d{2})_(\d{2})`)
	if err != nil {
		log.Panicf("log.AutoClear: Failed to compile regex: %v\n", err)
	}
	timer := time.NewTimer(ac.CycleTime)
	defer timer.Stop()
	for {
		select {
		case <-ctx.Done():
			return
		case <-timer.C:
			ac.runAs(dateRegex)
			timer.Reset(ac.CycleTime)
		}
	}
}
