package utils

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestValidatePasswordStrength_ValidPassword(t *testing.T) {
	tests := []struct {
		name     string
		password string
	}{
		{
			name:     "valid password with all requirements",
			password: "SecurePass123!",
		},
		{
			name:     "valid password with special chars",
			password: "MyP@ssw0rd!",
		},
		{
			name:     "valid password with multiple special chars",
			password: "Test#123$Pass",
		},
		{
			name:     "valid password exactly 8 chars",
			password: "Test123!",
		},
		{
			name:     "valid password longer than 8 chars",
			password: "VerySecurePassword123!@#",
		},
		{
			name:     "valid password with parentheses",
			password: "Test(123)",
		},
		{
			name:     "valid password with comma",
			password: "Test,123",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := ValidatePasswordStrength(tt.password)
			assert.NoError(t, err, "Password should be valid: %s", tt.password)
		})
	}
}

func TestValidatePasswordStrength_InvalidLength(t *testing.T) {
	tests := []struct {
		name     string
		password string
		expected string
	}{
		{
			name:     "password too short",
			password: "Test123",
			expected: "password must be at least 8 characters",
		},
		{
			name:     "empty password",
			password: "",
			expected: "password must be at least 8 characters",
		},
		{
			name:     "password too long",
			password: string(make([]byte, 129)),
			expected: "password must be less than 128 characters",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := ValidatePasswordStrength(tt.password)
			assert.Error(t, err)
			assert.Contains(t, err.Error(), tt.expected)
		})
	}
}

func TestValidatePasswordStrength_MissingUpperCase(t *testing.T) {
	password := "test123!@#"
	err := ValidatePasswordStrength(password)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "uppercase letter")
}

func TestValidatePasswordStrength_MissingLowerCase(t *testing.T) {
	password := "TEST123!@#"
	err := ValidatePasswordStrength(password)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "lowercase letter")
}

func TestValidatePasswordStrength_MissingNumber(t *testing.T) {
	password := "TestPass!@#"
	err := ValidatePasswordStrength(password)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "number")
}

func TestValidatePasswordStrength_MissingSpecialChar(t *testing.T) {
	password := "TestPass123"
	err := ValidatePasswordStrength(password)
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "special character")
}

func TestValidatePasswordStrength_MultipleMissing(t *testing.T) {
	tests := []struct {
		name     string
		password string
		expected string
	}{
		{
			name:     "missing uppercase and number",
			password: "testpass!@#",
			expected: "uppercase letter",
		},
		{
			name:     "missing lowercase and special",
			password: "TESTPASS123",
			expected: "lowercase letter",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := ValidatePasswordStrength(tt.password)
			assert.Error(t, err)
			assert.Contains(t, err.Error(), tt.expected)
		})
	}
}

func TestValidatePasswordStrength_SpecialCharacters(t *testing.T) {
	specialChars := []string{"!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_", "+", "=", "[", "]", "{", "}", ";", ":", "'", "\"", "\\", "|", ",", ".", "<", ">", "/", "?"}

	for _, char := range specialChars {
		password := "Test123" + char
		err := ValidatePasswordStrength(password)
		assert.NoError(t, err, "Password with special char %s should be valid", char)
	}
}

func TestValidatePasswordStrength_EdgeCases(t *testing.T) {
	tests := []struct {
		name     string
		password string
		expected string
	}{
		{
			name:     "only uppercase letters",
			password: "TESTPASS",
			expected: "lowercase letter",
		},
		{
			name:     "only lowercase letters",
			password: "testpass",
			expected: "uppercase letter",
		},
		{
			name:     "only numbers",
			password: "12345678",
			expected: "uppercase letter",
		},
		{
			name:     "only special characters",
			password: "!@#$%^&*",
			expected: "uppercase letter",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := ValidatePasswordStrength(tt.password)
			assert.Error(t, err)
			assert.Contains(t, err.Error(), tt.expected)
		})
	}
}
