//go:build windows

package update

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"
)

// Apply downloads the new exe and schedules replacement after exit (Windows).
func Apply(ctx context.Context, manifestURL string) (string, error) {
	latest, _, _, exe, tmp, err := prepareDownload(ctx, manifestURL)
	if err != nil {
		return "", err
	}
	dir := filepath.Dir(exe)
	bat := filepath.Join(dir, "navis-update.bat")

	script := "@echo off\r\n" +
		"setlocal EnableExtensions\r\n" +
		"cd /d \"" + dir + "\"\r\n" +
		"set \"EXE=" + exe + "\"\r\n" +
		"set \"NEW=" + tmp + "\"\r\n" +
		":wait\r\n" +
		"ping -n 2 127.0.0.1 >nul\r\n" +
		"del /f /q \"%EXE%\" >nul 2>&1\r\n" +
		"if exist \"%EXE%\" goto wait\r\n" +
		"move /y \"%NEW%\" \"%EXE%\" >nul\r\n" +
		"if not exist \"%EXE%\" exit /b 1\r\n" +
		"start \"\" \"%EXE%\"\r\n" +
		"exit /b 0\r\n"
	if err := os.WriteFile(bat, []byte(script), 0o755); err != nil {
		return "", err
	}

	cmd := exec.Command("cmd.exe", "/C", bat)
	cmd.Dir = dir
	cmd.SysProcAttr = &syscall.SysProcAttr{
		HideWindow:    true,
		CreationFlags: 0x00000008 | 0x00000200, // DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP
	}
	if err := cmd.Start(); err != nil {
		return "", fmt.Errorf("start updater: %w", err)
	}
	return latest, nil
}
