// internal/config/leveldb.go
package config

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

	"codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/pkg/storage/leveldb"
)

// LevelDB support functions - desktop-specific databases
// These functions return errors instead of using log.Fatalf to allow proper error handling.
//
// Storage is organized as follows:
// - Global storage (session): {appDir}/session/
// - User-specific storage: {appDir}/users/{emailHash}/{dbName}/
//
// This ensures:
// 1. Different users have isolated data
// 2. Dev and production modes have separate directories ({appName} vs {appName}-dev)
// 3. Email addresses are not exposed in directory names (hashed)

// getAppDir returns the application data directory path, creating it if needed.
// Uses 0700 permissions for security (owner read/write/execute only).
// The directory name is mode-aware: "maplefile-dev" for dev mode, "maplefile" for production.
func getAppDir() (string, error) {
	configDir, err := os.UserConfigDir()
	if err != nil {
		return "", fmt.Errorf("failed to get user config directory: %w", err)
	}

	appName := GetAppName()
	appDir := filepath.Join(configDir, appName)

	// Ensure the directory exists with restrictive permissions
	if err := os.MkdirAll(appDir, 0700); err != nil {
		return "", fmt.Errorf("failed to create app directory: %w", err)
	}

	return appDir, nil
}

// getUserDir returns the user-specific data directory, creating it if needed.
// Returns an error if userEmail is empty (no user logged in).
func getUserDir(userEmail string) (string, error) {
	if userEmail == "" {
		return "", fmt.Errorf("no user email provided - user must be logged in")
	}

	appName := GetAppName()
	userDir, err := GetUserSpecificDataDir(appName, userEmail)
	if err != nil {
		return "", fmt.Errorf("failed to get user data directory: %w", err)
	}

	return userDir, nil
}

// =============================================================================
// GLOBAL STORAGE PROVIDERS (not user-specific)
// =============================================================================

// NewLevelDBConfigurationProviderForSession returns a LevelDB configuration provider for user sessions.
// Session storage is GLOBAL (not per-user) because it stores the current login session.
func NewLevelDBConfigurationProviderForSession() (leveldb.LevelDBConfigurationProvider, error) {
	appDir, err := getAppDir()
	if err != nil {
		return nil, fmt.Errorf("session storage: %w", err)
	}
	return leveldb.NewLevelDBConfigurationProvider(appDir, "session"), nil
}

// =============================================================================
// USER-SPECIFIC STORAGE PROVIDERS
// These require a logged-in user's email to determine the storage path.
// =============================================================================

// NewLevelDBConfigurationProviderForLocalFilesWithUser returns a LevelDB configuration provider
// for local file metadata, scoped to a specific user.
func NewLevelDBConfigurationProviderForLocalFilesWithUser(userEmail string) (leveldb.LevelDBConfigurationProvider, error) {
	userDir, err := getUserDir(userEmail)
	if err != nil {
		return nil, fmt.Errorf("local files storage: %w", err)
	}
	return leveldb.NewLevelDBConfigurationProvider(userDir, "local_files"), nil
}

// NewLevelDBConfigurationProviderForSyncStateWithUser returns a LevelDB configuration provider
// for sync state, scoped to a specific user.
func NewLevelDBConfigurationProviderForSyncStateWithUser(userEmail string) (leveldb.LevelDBConfigurationProvider, error) {
	userDir, err := getUserDir(userEmail)
	if err != nil {
		return nil, fmt.Errorf("sync state storage: %w", err)
	}
	return leveldb.NewLevelDBConfigurationProvider(userDir, "sync_state"), nil
}

// NewLevelDBConfigurationProviderForCacheWithUser returns a LevelDB configuration provider
// for local cache, scoped to a specific user.
func NewLevelDBConfigurationProviderForCacheWithUser(userEmail string) (leveldb.LevelDBConfigurationProvider, error) {
	userDir, err := getUserDir(userEmail)
	if err != nil {
		return nil, fmt.Errorf("cache storage: %w", err)
	}
	return leveldb.NewLevelDBConfigurationProvider(userDir, "cache"), nil
}

// NewLevelDBConfigurationProviderForUserDataWithUser returns a LevelDB configuration provider
// for user-specific data, scoped to a specific user.
func NewLevelDBConfigurationProviderForUserDataWithUser(userEmail string) (leveldb.LevelDBConfigurationProvider, error) {
	userDir, err := getUserDir(userEmail)
	if err != nil {
		return nil, fmt.Errorf("user data storage: %w", err)
	}
	return leveldb.NewLevelDBConfigurationProvider(userDir, "user_data"), nil
}

// =============================================================================
// LEGACY FUNCTIONS (deprecated - use user-specific versions instead)
// These exist for backward compatibility during migration.
// =============================================================================

// NewLevelDBConfigurationProviderForCache returns a LevelDB configuration provider for local cache.
// Deprecated: Use NewLevelDBConfigurationProviderForCacheWithUser instead.
func NewLevelDBConfigurationProviderForCache() (leveldb.LevelDBConfigurationProvider, error) {
	appDir, err := getAppDir()
	if err != nil {
		return nil, fmt.Errorf("cache storage: %w", err)
	}
	return leveldb.NewLevelDBConfigurationProvider(appDir, "cache"), nil
}

// NewLevelDBConfigurationProviderForLocalFiles returns a LevelDB configuration provider for local file metadata.
// Deprecated: Use NewLevelDBConfigurationProviderForLocalFilesWithUser instead.
func NewLevelDBConfigurationProviderForLocalFiles() (leveldb.LevelDBConfigurationProvider, error) {
	appDir, err := getAppDir()
	if err != nil {
		return nil, fmt.Errorf("local files storage: %w", err)
	}
	return leveldb.NewLevelDBConfigurationProvider(appDir, "local_files"), nil
}

// NewLevelDBConfigurationProviderForSyncState returns a LevelDB configuration provider for sync state.
// Deprecated: Use NewLevelDBConfigurationProviderForSyncStateWithUser instead.
func NewLevelDBConfigurationProviderForSyncState() (leveldb.LevelDBConfigurationProvider, error) {
	appDir, err := getAppDir()
	if err != nil {
		return nil, fmt.Errorf("sync state storage: %w", err)
	}
	return leveldb.NewLevelDBConfigurationProvider(appDir, "sync_state"), nil
}

// NewLevelDBConfigurationProviderForUser returns a LevelDB configuration provider for user data.
// Deprecated: Use NewLevelDBConfigurationProviderForUserDataWithUser instead.
func NewLevelDBConfigurationProviderForUser() (leveldb.LevelDBConfigurationProvider, error) {
	appDir, err := getAppDir()
	if err != nil {
		return nil, fmt.Errorf("user storage: %w", err)
	}
	return leveldb.NewLevelDBConfigurationProvider(appDir, "user"), nil
}
