package system

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
)

// ConfigureSELinux 设置 SELinux 模式
// 参数: mode - enforcing, permissive, disabled
// 返回: error - 配置错误
func ConfigureSELinux(mode string) error {
	if mode == "" {
		return nil
	}

	// 验证输入
	mode = strings.ToLower(strings.TrimSpace(mode))
	validModes := map[string]bool{
		"enforcing":  true,
		"permissive": true,
		"disabled":   true,
	}

	if !validModes[mode] {
		return fmt.Errorf("无效的 SELinux 模式: %s (可选: enforcing, permissive, disabled)", mode)
	}

	// 检查 SELinux 是否可用
	if _, err := os.Stat("/selinux/enforce"); os.IsNotExist(err) {
		if _, err := os.Stat("/sys/fs/selinux/enforce"); os.IsNotExist(err) {
			return fmt.Errorf("系统不支持 SELinux 或未启用")
		}
	}

	// 临时生效
	if mode != "disabled" { // disabled 需要重启才能完全生效
		cmd := exec.Command("setenforce", mode)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		if err := cmd.Run(); err != nil {
			return fmt.Errorf("setenforce %s 失败: %v", mode, err)
		}
	}

	// 持久化配置
	return persistSELinuxMode(mode)
}

// persistSELinuxMode 修改 /etc/selinux/config 实现持久化
func persistSELinuxMode(mode string) error {
	const selinuxConfig = "/etc/selinux/config"

	// 读取配置文件
	content, err := os.ReadFile(selinuxConfig)
	if err != nil {
		// 如果文件不存在，创建默认配置
		if os.IsNotExist(err) {
			defaultConfig := fmt.Sprintf(`# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=%s
# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted
`, mode)
			return os.WriteFile(selinuxConfig, []byte(defaultConfig), 0644)
		}
		return err
	}

	// 替换 SELINUX= 行
	lines := strings.Split(string(content), "\n")
	for i, line := range lines {
		if strings.HasPrefix(line, "SELINUX=") {
			lines[i] = fmt.Sprintf("SELINUX=%s", mode)
			break
		}
	}

	return os.WriteFile(selinuxConfig, []byte(strings.Join(lines, "\n")), 0644)
}

// GetSELinuxMode 获取当前 SELinux 模式
func GetSELinuxMode() (string, error) {
	cmd := exec.Command("getenforce")
	output, err := cmd.Output()
	if err != nil {
		return "", err
	}
	return strings.ToLower(strings.TrimSpace(string(output))), nil
}
