// run_windows.go
//go:build windows
// +build windows

package spm

import (
	"fmt"

	"golang.org/x/sys/windows/registry"
)

// RegisterApp writes the necessary registry keys, making it appear as officially installed app
func RegisterApp() error {
	exePath, err := GetInstallDir()
	if err != nil {
		return fmt.Errorf("failed to get install directory: %w", err)
	}

	// 1. Create Uninstall/Modify entry
	uninstallKeyPath := `Software\Microsoft\Windows\CurrentVersion\Uninstall\SpitfireBrowser`
	uk, _, err := registry.CreateKey(registry.LOCAL_MACHINE, uninstallKeyPath, registry.ALL_ACCESS)
	if err != nil {
		return fmt.Errorf("failed to create uninstall key: %w", err)
	}
	defer uk.Close()

	if err := uk.SetStringValue("DisplayName", "Spitfire"); err != nil {
		return err
	}
	if err := uk.SetStringValue("UninstallString", exePath+" --uninstall"); err != nil {
		return err
	}
	if err := uk.SetStringValue("ModifyPath", exePath+" --modify"); err != nil {
		return err
	}
	if err := uk.SetStringValue("DisplayIcon", exePath); err != nil {
		return err
	}

	// 2. Register as a browser for default apps
	clientKeyPath := `Software\Clients\StartMenuInternet\SpitfireBrowser`
	ck, _, err := registry.CreateKey(registry.LOCAL_MACHINE, clientKeyPath, registry.ALL_ACCESS)
	if err != nil {
		return fmt.Errorf("failed to create client key: %w", err)
	}
	defer ck.Close()

	if err := ck.SetStringValue("", "Spitfire"); err != nil {
		return err
	}

	// Create Capabilities subkey
	capabilitiesKeyPath := clientKeyPath + `\Capabilities`
	capk, _, err := registry.CreateKey(registry.LOCAL_MACHINE, capabilitiesKeyPath, registry.ALL_ACCESS)
	if err != nil {
		return fmt.Errorf("failed to create capabilities key: %w", err)
	}
	defer capk.Close()

	if err := capk.SetStringValue("ApplicationName", "Spitfire"); err != nil {
		return err
	}
	if err := capk.SetStringValue("ApplicationDescription", "A custom browser"); err != nil {
		return err
	}

	// Set file associations
	assocKeyPath := capabilitiesKeyPath + `\FileAssociations`
	ak, _, err := registry.CreateKey(registry.LOCAL_MACHINE, assocKeyPath, registry.ALL_ACCESS)
	if err != nil {
		return fmt.Errorf("failed to create file associations key: %w", err)
	}
	defer ak.Close()

	associations := map[string]string{
		".html": "SpitfireBrowserHTML",
		"HTTP":  "SpitfireBrowserHTML",
		"HTTPS": "SpitfireBrowserHTML",
	}
	for ext, progID := range associations {
		if err := ak.SetStringValue(ext, progID); err != nil {
			return err
		}
	}

	return nil
}

// UnregisterApp removes the registry entries created by registerApp.
func UnregisterApp() error {
	// Remove the Uninstall/Modify entry.
	uninstallKeyPath := `Software\Microsoft\Windows\CurrentVersion\Uninstall\SpitfireBrowser`
	if err := deleteRegistryTree(registry.LOCAL_MACHINE, uninstallKeyPath); err != nil {
		return fmt.Errorf("failed to delete uninstall key: %w", err)
	}

	// Remove the browser registration entry.
	clientKeyPath := `Software\Clients\StartMenuInternet\SpitfireBrowser`
	if err := deleteRegistryTree(registry.LOCAL_MACHINE, clientKeyPath); err != nil {
		return fmt.Errorf("failed to delete client key: %w", err)
	}

	return nil
}

// deleteRegistryTree recursively deletes a registry key and all its subkeys.
func deleteRegistryTree(root registry.Key, path string) error {
	// Open the key with ALL_ACCESS permissions.
	key, err := registry.OpenKey(root, path, registry.ALL_ACCESS)
	if err != nil {
		// If the key does not exist, there's nothing to do.
		if err == registry.ErrNotExist {
			return nil
		}
		return err
	}
	// Read the names of all subkeys.
	subKeys, err := key.ReadSubKeyNames(-1)
	key.Close() // Close the key so it can be deleted later.
	if err != nil {
		return err
	}

	// Recursively delete each subkey.
	for _, subKey := range subKeys {
		subKeyPath := path + `\` + subKey
		if err := deleteRegistryTree(root, subKeyPath); err != nil {
			return err
		}
	}

	// Finally, delete the (now empty) key.
	return registry.DeleteKey(root, path)
}

// IsRegistered returns true if the application is registered (installed) in the registry.
func IsRegistered() bool {
	// Try to open the uninstall key with read-only access.
	key, err := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Windows\CurrentVersion\Uninstall\SpitfireBrowser`, registry.READ)
	if err != nil {
		// If the key cannot be opened, assume the app is not registered.
		return false
	}
	defer key.Close()
	return true
}