package lts

import (
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

const (
	maxLogSize     = 10 * 1024 * 1024 // 10MB
	maxRotatedLogs = 2                // 除了request.log外，最多保留 3 个轮转文件
	logFileName    = "request.log"    // 日志文件名
)

// WriteCommandToLog 将命令写入日志文件，并处理日志轮转
func WriteCommandToLog(command string) error {
	// 检查日志文件大小，如果超过限制则轮转
	if shouldRotateLog(logFileName) {
		if err := rotateLog(logFileName); err != nil {
			return fmt.Errorf("日志轮转失败: %v", err)
		}
	}

	// 打开日志文件（如果不存在则创建）
	file, err := os.OpenFile(logFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return fmt.Errorf("无法打开日志文件: %v", err)
	}
	defer file.Close()

	// 写入当前时间与命令
	currentTime := time.Now().Format(time.RFC3339)
	logEntry := fmt.Sprintf("%s - %s\n", currentTime, command)

	if _, err = file.WriteString(logEntry); err != nil {
		return fmt.Errorf("写入日志文件失败: %v", err)
	}

	return nil
}

// shouldRotateLog 检查日志文件是否需要轮转
func shouldRotateLog(filePath string) bool {
	fileInfo, err := os.Stat(filePath)
	if err != nil {
		// 如果文件不存在，不需要轮转
		if os.IsNotExist(err) {
			return false
		}
		// 其他错误直接返回 false
		return false
	}

	// 如果文件大小超过限制，需要轮转
	return fileInfo.Size() > maxLogSize
}

// rotateLog 执行日志轮转
func rotateLog(filePath string) error {
	// 生成带时间戳的新文件名
	timestamp := time.Now().Format("20060102-150405")
	rotatedFilePath := fmt.Sprintf("request_%s.log", timestamp)

	// 重命名当前日志文件
	if err := os.Rename(filePath, rotatedFilePath); err != nil {
		return fmt.Errorf("重命名日志文件失败: %v", err)
	}

	// 清理旧的轮转文件
	if err := cleanupRotatedLogs(); err != nil {
		return fmt.Errorf("清理旧日志文件失败: %v", err)
	}

	return nil
}

// cleanupRotatedLogs 清理旧的轮转文件，保留最多 maxRotatedLogs 个
func cleanupRotatedLogs() error {
	// 获取所有轮转文件
	files, err := filepath.Glob("request_*.log")
	if err != nil {
		return fmt.Errorf("获取轮转文件列表失败: %v", err)
	}

	// 按文件名排序（时间戳在文件名中，排序后旧文件在前）
	sort.Strings(files)

	// 删除多余的旧文件
	if len(files) > maxRotatedLogs {
		for i := 0; i < len(files)-maxRotatedLogs; i++ {
			if err := os.Remove(files[i]); err != nil {
				return fmt.Errorf("删除旧日志文件失败: %v", err)
			}
			fmt.Printf("删除旧日志文件: %s\n", files[i])
		}
	}

	return nil
}

// 记录命令
// func WriteCommandToLog(command string) error {
// 	// 确保目录存在，如果需要的话可以创建目录
// 	logFile := "request.log"
// 	f, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
// 	if err != nil {
// 		return fmt.Errorf("无法打开日志文件:request.log, %v", err)
// 	}
// 	defer f.Close()

// 	// 写入当前时间与命令
// 	currentTime := time.Now().Format(time.RFC3339)
// 	logEntry := fmt.Sprintf("%s - %s\n", currentTime, command)

// 	if _, err = f.WriteString(logEntry); err != nil {
// 		return fmt.Errorf("写入日志文件失败: %v", err)
// 	}

// 	return nil
// }

func BuildLogCommand(cmd *cobra.Command) string {
	var args []string

	cmd.Flags().Visit(func(f *pflag.Flag) {
		if !f.Changed { // 更精确的Visit方法替代VisitAll
			return
		}

		switch f.Value.Type() {
		case "string":
			args = append(args, fmt.Sprintf("--%s=%s", f.Name, f.Value.String()))
		case "int", "int64":
			args = append(args, fmt.Sprintf("--%s=%s", f.Name, f.Value.String()))
		case "float64":
			args = append(args, fmt.Sprintf("--%s=%s", f.Name, f.Value.String()))
		case "bool":
			// 修正布尔值判断逻辑
			boolValue, _ := cmd.Flags().GetBool(f.Name)
			args = append(args, fmt.Sprintf("--%s=%t", f.Name, boolValue))
		default:
			// 处理未识别的类型
			args = append(args, fmt.Sprintf("--%s=%v", f.Name, f.Value.String()))
		}
	})
	use := cmd.Use
	command := "ctglts log " + use + " " + strings.Join(args, " ")
	WriteCommandToLog(command)
	return command
}

// 从config.yaml 中加载参数配置
func LoadConfig(cmd *cobra.Command, configName string) (ak, sk, endpoint, region_id string) {
	ak, _ = cmd.Flags().GetString("ak")
	sk, _ = cmd.Flags().GetString("sk")
	endpoint, _ = cmd.Flags().GetString("endpoint")
	region_id, _ = cmd.Flags().GetString("region_id")

	if configName != "" {
		config := viper.GetStringMapString("config." + configName)
		if ak == "" {
			ak = config["ak"]
		}
		if sk == "" {
			sk = config["sk"]
		}
		if endpoint == "" {
			endpoint = config["endpoint"]
		}
		if region_id == "" {
			region_id = config["region_id"]
		}
	}
	return
}

// 校验命令参数是否为空
func ValidateRequiredParams(cmd *cobra.Command, params map[string]string) bool {
	var missing []string
	for name, value := range params {
		if value == "" {
			missing = append(missing, name)
		}
	}

	if len(missing) > 0 {
		fmt.Fprintf(os.Stderr, "Error: Missing required parameters: %s\n",
			strings.Join(missing, ", "))
		cmd.Usage() // 更简洁的用法提示
		return false
	}
	return true
}
