package cli

import (
	"fmt"
	"os"
	"path/filepath"
	initcmd "sunhpc/internal/cli/init"
	"sunhpc/pkg/config"
	"sunhpc/pkg/logger"

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

var (
	cfgFile string
	verbose bool
	noColor bool
)

func NewRootCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "sunhpc",
		Short: "SunHPC - HPC集群一体化运维工具",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			// 设置 CLI 参数
			config.CLIParams.Verbose = verbose
			config.CLIParams.NoColor = noColor
			config.CLIParams.Config = cfgFile

			// 初始化配置目录和默认文件
			if err := config.InitConfigs(); err != nil {
				fmt.Fprintf(os.Stderr, "初始化配置目录失败: %v\n", err)
				os.Exit(1)
			}

			// 加载配置（后续调用直接返回缓存)
			cfg, err := config.LoadConfig()
			if err != nil {
				fmt.Fprintf(os.Stderr, "加载配置失败: %v\n", err)
				os.Exit(1)
			}

			// 初始化日志
			logger.Init(cfg.Log)

			// 记录启动信息
			logger.Debugf("SunHPC 启动中...")
			logger.Debugf("配置文件: %s", viper.ConfigFileUsed())
			logger.Debugf("日志级别: %s", cfg.Log.Level)
			logger.Debugf("日志格式: %s", cfg.Log.Format)
			logger.Debugf("日志输出: %s", cfg.Log.Output)
			logger.Debugf("日志文件: %s", cfg.Log.LogFile)
			logger.Debugf("显示颜色: %v", cfg.Log.ShowColor)

			// 跳过数据库检查，仅在 init db 时检查
			if isInitDbCommand(cmd) {
				return
			}

			// 检查数据库文件是否存在
			dbPath := filepath.Join(cfg.Database.Path, cfg.Database.Name)
			if _, err := os.Stat(dbPath); os.IsNotExist(err) {
				logger.Warnf("数据库文件不存在: %s", dbPath)
				logger.Errorf("请先运行 sunhpc init db 初始化数据库")
				os.Exit(1)
			}
			logger.Debugf("数据库文件存在: %s", dbPath)
		},

		Run: func(cmd *cobra.Command, args []string) {
			cmd.Help()
		},
	}

	cmd.PersistentFlags().BoolVar(
		&verbose, "verbose", false,
		"启用详细日志输出")

	cmd.PersistentFlags().BoolVar(
		&noColor, "no-color", false,
		"禁用彩色输出")

	cmd.PersistentFlags().StringVar(
		&cfgFile, "config", "",
		"配置文件路径 (默认:/etc/sunhpc/config.yaml)")

	cmd.AddCommand(initcmd.NewInitCmd())
	return cmd
}

func Execute() error {
	return NewRootCmd().Execute()
}

func isInitDbCommand(cmd *cobra.Command) bool {
	// 检查当前命令是否是 db 子命令
	if cmd.Name() == "db" {
		// 检查父命令是否是 init
		if parent := cmd.Parent(); parent != nil {
			return parent.Name() == "init"
		}
	}
	return false
}
