// Package keyring provides secure password storage for sudo authentication
package keyring

import (
	"errors"
	"fmt"
	"runtime"

	"github.com/99designs/keyring"
)

// ErrNoBackend indicates no keyring backend is available
var ErrNoBackend = errors.New("no keyring backend available")

// ErrDaemonNotRunning indicates the keyring daemon is not running
var ErrDaemonNotRunning = errors.New("keyring daemon is not running")

// CheckDependencies checks if keyring dependencies are installed and functional
// Returns an error with installation instructions if dependencies are missing
func CheckDependencies() error {
	// Non-Linux platforms have native keyring support
	if runtime.GOOS != "linux" {
		return nil
	}

	status := DetectStatus()

	// Check if any backend is available
	if len(status.AvailableBackends) == 0 || status.ActiveBackend == BackendNone {
		return fmt.Errorf("%w\n\nInstall with: %s", ErrNoBackend, status.InstallHint)
	}

	// Check if daemon is running (not needed for file/pass backends)
	if status.ActiveBackend != BackendFile && status.ActiveBackend != BackendPass {
		if !status.DaemonRunning {
			return fmt.Errorf("%w\n\nThe %s daemon is not running. Please start it and try again.",
				ErrDaemonNotRunning, status.ActiveBackend)
		}
	}

	return nil
}

// NeedsInstallPrompt returns true if the user needs to install keyring dependencies
// This is used to show an installation prompt in the UI
func NeedsInstallPrompt() bool {
	// Non-Linux platforms have native keyring support
	if runtime.GOOS != "linux" {
		return false
	}

	status := DetectStatus()

	// Need to prompt if no backends at all
	if len(status.AvailableBackends) == 0 || status.ActiveBackend == BackendNone {
		return true
	}

	// If file backend is available, we can always work (no prompt needed)
	for _, backend := range status.AvailableBackends {
		if backend == BackendFile {
			return false
		}
	}

	// If active backend doesn't need a daemon, no prompt needed
	if status.ActiveBackend == BackendFile || status.ActiveBackend == BackendPass {
		return false
	}

	// For SecretService/KWallet, if daemon is running, no prompt needed
	if status.DaemonRunning {
		return false
	}

	// Daemon-based backend but daemon not running - show prompt
	return true
}

// CanUseKeyring returns true if keyring can be used for password storage
// This is a convenience function that combines dependency checking
func CanUseKeyring() bool {
	return CheckDependencies() == nil
}

// GetSetupInstructions returns human-readable setup instructions
// Returns an empty string if no setup is needed
func GetSetupInstructions() string {
	// Non-Linux platforms have native keyring support
	if runtime.GOOS != "linux" {
		return ""
	}

	status := DetectStatus()

	// No setup needed if backend is available and working
	if len(status.AvailableBackends) > 0 && status.ActiveBackend != BackendNone {
		if status.ActiveBackend == BackendFile || status.ActiveBackend == BackendPass {
			return ""
		}
		if status.DaemonRunning {
			return ""
		}
	}

	// Generate setup instructions based on detected environment
	var instructions string

	switch status.ActiveBackend {
	case BackendSecretService:
		instructions = fmt.Sprintf(
			"GNOME Keyring is installed but not running.\n\n"+
				"To start it automatically:\n"+
				"1. Ensure you're logged in with a display manager that supports PAM\n"+
				"2. Or run: eval $(gnome-keyring-daemon --start)\n"+
				"3. Then set: export SSH_AUTH_SOCK\n\n"+
				"Alternatively, install and configure: %s",
			status.InstallHint,
		)
	case BackendKWallet:
		instructions = fmt.Sprintf(
			"KWallet is installed but not running.\n\n"+
				"To start it:\n"+
				"1. Open KDE System Settings\n"+
				"2. Go to Account Details → KDE Wallet\n"+
				"3. Enable the wallet system\n\n"+
				"Alternatively, install: %s",
			status.InstallHint,
		)
	case BackendNone:
		instructions = fmt.Sprintf(
			"No keyring backend detected.\n\n"+
				"To enable secure password storage for sudo authentication:\n\n"+
				"%s\n\n"+
				"After installation, restart mpv-manager.",
			status.InstallHint,
		)
	default:
		instructions = fmt.Sprintf(
			"Keyring setup may be required.\n\n"+
				"Install with: %s",
			status.InstallHint,
		)
	}

	return instructions
}

// ValidateSetup checks the keyring setup and returns detailed status
// This is useful for diagnostics and troubleshooting
func ValidateSetup() (bool, string) {
	// Non-Linux platforms have native keyring support
	if runtime.GOOS != "linux" {
		return true, "Native keyring available on " + runtime.GOOS
	}

	status := DetectStatus()

	// Check backend availability
	if len(status.AvailableBackends) == 0 {
		return false, "No keyring backends detected. " + status.InstallHint
	}

	// Check daemon status for backends that require it
	if status.ActiveBackend != BackendFile && status.ActiveBackend != BackendPass {
		if !status.DaemonRunning {
			return false, fmt.Sprintf(
				"%s backend detected but daemon is not running.",
				status.ActiveBackend,
			)
		}
	}

	// Try to open the keyring to verify it works
	kr, err := Open()
	if err != nil {
		return false, "Failed to open keyring: " + err.Error()
	}

	// Try to set and get a test value
	testKey := "test-connection"
	testValue := "test-value-" + status.Distro

	err = kr.ring.Set(keyring.Item{
		Key:  testKey,
		Data: []byte(testValue),
	})
	if err != nil {
		return false, "Failed to write to keyring: " + err.Error()
	}

	// Clean up test value
	_ = kr.ring.Remove(testKey)

	return true, fmt.Sprintf(
		"Keyring is working. Active backend: %s, Desktop: %s, Distro: %s",
		status.ActiveBackend,
		status.DesktopEnv,
		status.Distro,
	)
}
