package system

import (
	"os"
	"path/filepath"
	"sunhpc/internal/config"
	"sunhpc/internal/log"
)

// Context 系统配置上下文，包含所有命令行参数
type Context struct {
	Force   bool   // 强制模式
	DryRun  bool   // 干运行模式
	Verbose bool   // 详细输出
	Timeout int    // 超时时间
	Backup  string // 备份路径
	YesMode bool   // 自动确认
}

// ApplyAll 应用所有系统配置
func ApplyAll(cfg *config.SunHPCConfig) error {
	log.Info("开始应用系统配置...")

	if err := SetHostnameWithContext(cfg.Hostname, nil); err != nil {
		log.Warnf("设置主机名失败: %v", err)
	}

	if err := SetMOTDWithContext(cfg.MOTD, nil); err != nil {
		log.Warnf("设置 MOTD 失败: %v", err)
	}

	if err := ConfigureSysctlWithContext(cfg.Sysctl, nil); err != nil {
		log.Warnf("配置 sysctl 失败: %v", err)
	}

	if err := ConfigureSELinuxWithContext(cfg.SELinux, nil); err != nil {
		log.Warnf("配置 SELinux 失败: %v", err)
	}

	if err := ConfigureSSHWithContext(cfg.SSH, nil); err != nil {
		log.Warnf("配置 SSH 失败: %v", err)
	}

	log.Info("系统配置应用完成")
	return nil
}

// SetHostnameWithContext 设置系统主机名，带上下文参数
func SetHostnameWithContext(hostname string, ctx *Context) error {
	if ctx != nil && ctx.DryRun {
		log.Infof("[干运行] 设置主机名为: %s", hostname)
		return nil
	}

	if hostname == "" {
		return nil
	}

	// 检查是否需要强制设置
	current, _ := os.Hostname()
	if current == hostname && (ctx == nil || !ctx.Force) {
		log.Infof("主机名已是 '%s'，跳过设置", hostname)
		return nil
	}

	log.Infof("设置主机名为: %s", hostname)
	return SetHostname(hostname)
}

// SetMOTDWithContext 设置 MOTD，带上下文参数
func SetMOTDWithContext(content string, ctx *Context) error {
	if ctx != nil && ctx.DryRun {
		log.Info("[干运行] 设置 MOTD")
		return nil
	}

	if content == "" {
		return nil
	}

	// 备份现有文件
	if ctx != nil && ctx.Backup != "" {
		backupMOTD(ctx.Backup)
	}

	log.Info("更新 /etc/motd")
	return SetMOTD(content)
}

// ConfigureSysctlWithContext 配置内核参数，带上下文参数
func ConfigureSysctlWithContext(params map[string]string, ctx *Context) error {
	if ctx != nil && ctx.DryRun {
		log.Info("[干运行] 配置 sysctl 参数")
		return nil
	}

	if len(params) == 0 {
		return nil
	}

	// 备份现有配置
	if ctx != nil && ctx.Backup != "" {
		backupSysctl(ctx.Backup)
	}

	return ConfigureSysctl(params)
}

// ConfigureSELinuxWithContext 配置 SELinux，带上下文参数
func ConfigureSELinuxWithContext(mode string, ctx *Context) error {
	if ctx != nil && ctx.DryRun {
		log.Infof("[干运行] 设置 SELinux 模式为: %s", mode)
		return nil
	}

	if mode == "" {
		return nil
	}

	// 检查当前模式
	current, _ := GetSELinuxMode()
	if current == mode && (ctx == nil || !ctx.Force) {
		log.Infof("SELinux 已是 '%s' 模式，跳过设置", mode)
		return nil
	}

	log.Infof("设置 SELinux 模式为: %s", mode)
	return ConfigureSELinux(mode)
}

// ConfigureSSHWithContext 配置 SSH，带上下文参数
func ConfigureSSHWithContext(cfg config.SSHConfig, ctx *Context) error {
	if ctx != nil && ctx.DryRun {
		log.Info("[干运行] 配置 SSH 服务")
		return nil
	}

	// 备份配置文件
	if ctx != nil && ctx.Backup != "" {
		backupSSHConfig(ctx.Backup)
	}

	log.Info("配置 SSH 服务")
	return ConfigureSSH(cfg)
}

// 备份函数
func backupMOTD(backupDir string) error {
	backupPath := filepath.Join(backupDir, "motd."+filepath.Base(os.Args[0])+".bak")
	if err := os.MkdirAll(backupDir, 0755); err != nil {
		return err
	}
	return copyFile("/etc/motd", backupPath)
}

func backupSysctl(backupDir string) error {
	backupPath := filepath.Join(backupDir, "sysctl.conf.bak")
	if err := os.MkdirAll(backupDir, 0755); err != nil {
		return err
	}
	return copyFile("/etc/sysctl.conf", backupPath)
}

func backupSSHConfig(backupDir string) error {
	backupPath := filepath.Join(backupDir, "sshd_config.bak")
	if err := os.MkdirAll(backupDir, 0755); err != nil {
		return err
	}
	return copyFile("/etc/ssh/sshd_config", backupPath)
}

func copyFile(src, dst string) error {
	data, err := os.ReadFile(src)
	if err != nil {
		return err
	}
	return os.WriteFile(dst, data, 0644)
}
