package config

import (
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"log"
	"os"
	"strings"
)

// SecretsManager handles secure secret management
type SecretsManager struct {
	jwtSecret string
}

// NewSecretsManager creates a new secrets manager
func NewSecretsManager() *SecretsManager {
	return &SecretsManager{}
}

// GetJWTSecret retrieves JWT secret from environment or generates a secure one
func (sm *SecretsManager) GetJWTSecret() string {
	if sm.jwtSecret != "" {
		return sm.jwtSecret
	}

	// Try to get from environment
	secret := os.Getenv("JWT_SECRET")

	// Validate secret strength
	if secret == "" {
		log.Fatal("❌ CRITICAL: JWT_SECRET environment variable is not set!")
	}

	if len(secret) < 32 {
		log.Fatal("❌ CRITICAL: JWT_SECRET must be at least 32 characters long!")
	}

	// Check for weak/default secrets
	weakSecrets := []string{
		"secret",
		"password",
		"12345678",
		"change_this",
		"super-secret-value",
		"your-secret-key",
	}

	for _, weak := range weakSecrets {
		if secret == weak {
			log.Fatal("❌ CRITICAL: JWT_SECRET is using a weak/default value! Please use a strong random secret.")
		}
	}

	sm.jwtSecret = secret
	return sm.jwtSecret
}

// GenerateSecureSecret generates a cryptographically secure random secret
func GenerateSecureSecret(length int) (string, error) {
	if length < 32 {
		length = 32
	}

	bytes := make([]byte, length)
	if _, err := rand.Read(bytes); err != nil {
		return "", fmt.Errorf("failed to generate secure secret: %w", err)
	}

	return base64.URLEncoding.EncodeToString(bytes), nil
}

// ValidateSecretStrength checks if a secret meets security requirements
func ValidateSecretStrength(secret string) error {
	if len(secret) < 32 {
		return fmt.Errorf("secret must be at least 32 characters long")
	}

	// Check for common weak patterns
	weakPatterns := []string{
		"12345",
		"password",
		"secret",
		"admin",
		"qwerty",
	}

	secretLower := strings.ToLower(secret)
	for _, pattern := range weakPatterns {
		if len(secretLower) > 0 && len(pattern) > 0 {
			// Simple substring check
			found := false
			for i := 0; i <= len(secretLower)-len(pattern); i++ {
				if secretLower[i:i+len(pattern)] == pattern {
					found = true
					break
				}
			}
			if found {
				return fmt.Errorf("secret contains weak pattern: %s", pattern)
			}
		}
	}

	return nil
}

// PrintSecretGenerationInstructions prints instructions for generating a secure secret
func PrintSecretGenerationInstructions() {
	fmt.Println("\n" + strings.Repeat("=", 60))
	fmt.Println("🔐 JWT SECRET GENERATION INSTRUCTIONS")
	fmt.Println(strings.Repeat("=", 60))
	fmt.Println("\nTo generate a secure JWT secret, run one of these commands:")
	fmt.Println("\n1. Using OpenSSL:")
	fmt.Println("   openssl rand -base64 64")
	fmt.Println("\n2. Using Go:")
	fmt.Println("   go run -c 'import \"crypto/rand\"; import \"encoding/base64\"; b := make([]byte, 64); rand.Read(b); fmt.Println(base64.URLEncoding.EncodeToString(b))'")
	fmt.Println("\n3. Using this program:")

	secret, err := GenerateSecureSecret(64)
	if err != nil {
		fmt.Printf("   Error: %v\n", err)
	} else {
		fmt.Printf("   %s\n", secret)
	}

	fmt.Println("\nThen add it to your .env file:")
	fmt.Println("   JWT_SECRET=<your-generated-secret>")
	fmt.Println("\n" + strings.Repeat("=", 60) + "\n")
}

// Global secrets manager instance
var globalSecretsManager = NewSecretsManager()

// GetGlobalSecretsManager returns the global secrets manager
func GetGlobalSecretsManager() *SecretsManager {
	return globalSecretsManager
}
