// Package process provides process isolation and resource limiting for HIPAA compliance.
// Implements Worker Process Isolation controls.
package process

import (
	"fmt"
	"os"
	"runtime"
	"syscall"
)

// IsolationConfig holds process isolation parameters
type IsolationConfig struct {
	MaxProcesses int  // Fork bomb protection (RLIMIT_NPROC on Linux)
	MaxOpenFiles int  // FD exhaustion protection (RLIMIT_NOFILE)
	DisableSwap  bool // Prevent swap exfiltration
	OOMScoreAdj  int  // OOM killer priority adjustment (Linux only)
}

// ApplyIsolation applies process isolation controls to the current process.
// This should be called after forking but before execing the target command.
func ApplyIsolation(cfg IsolationConfig) error {
	// Apply resource limits (platform-specific)
	if err := applyResourceLimits(cfg); err != nil {
		return err
	}

	// OOM score adjustment (only on Linux)
	if cfg.OOMScoreAdj != 0 && runtime.GOOS == "linux" {
		if err := setOOMScoreAdj(cfg.OOMScoreAdj); err != nil {
			return fmt.Errorf("failed to set OOM score adjustment: %w", err)
		}
	}

	// Disable swap (Linux only) - requires CAP_SYS_RESOURCE or root
	if cfg.DisableSwap && runtime.GOOS == "linux" {
		if err := disableSwap(); err != nil {
			// Log but don't fail - swap disabling requires privileges
			// This is best-effort security hardening
		}
	}

	return nil
}

// setOOMScoreAdj adjusts the OOM killer score (Linux only)
// Lower values = less likely to be killed (negative is "never kill")
// Higher values = more likely to be killed
func setOOMScoreAdj(score int) error {
	// Write to /proc/self/oom_score_adj
	path := "/proc/self/oom_score_adj"
	data := []byte(fmt.Sprintf("%d\n", score))
	return os.WriteFile(path, data, 0644)
}

// IsolatedExec runs a command with process isolation applied.
// This is a helper for container execution that applies limits before exec.
func IsolatedExec(argv []string, cfg IsolationConfig) error {
	if err := ApplyIsolation(cfg); err != nil {
		return err
	}
	return syscall.Exec(argv[0], argv, os.Environ())
}
