package service_test

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/user-management-system/internal/service"
)

// =============================================================================
// Auth Service Password Strength Tests
// =============================================================================

func TestGetPasswordStrength_Empty(t *testing.T) {
	info := service.GetPasswordStrength("")
	assert.Equal(t, 0, info.Score)
	assert.Equal(t, 0, info.Length)
	assert.False(t, info.HasUpper)
	assert.False(t, info.HasLower)
	assert.False(t, info.HasDigit)
	assert.False(t, info.HasSpecial)
}

func TestGetPasswordStrength_OnlyLowercase(t *testing.T) {
	info := service.GetPasswordStrength("abcdef")
	assert.Equal(t, 1, info.Score)
	assert.Equal(t, 6, info.Length)
	assert.False(t, info.HasUpper)
	assert.True(t, info.HasLower)
	assert.False(t, info.HasDigit)
	assert.False(t, info.HasSpecial)
}

func TestGetPasswordStrength_OnlyUppercase(t *testing.T) {
	info := service.GetPasswordStrength("ABCDEF")
	assert.Equal(t, 1, info.Score)
	assert.Equal(t, 6, info.Length)
	assert.True(t, info.HasUpper)
	assert.False(t, info.HasLower)
	assert.False(t, info.HasDigit)
	assert.False(t, info.HasSpecial)
}

func TestGetPasswordStrength_OnlyDigits(t *testing.T) {
	info := service.GetPasswordStrength("123456")
	assert.Equal(t, 1, info.Score)
	assert.Equal(t, 6, info.Length)
	assert.False(t, info.HasUpper)
	assert.False(t, info.HasLower)
	assert.True(t, info.HasDigit)
	assert.False(t, info.HasSpecial)
}

func TestGetPasswordStrength_OnlySpecial(t *testing.T) {
	info := service.GetPasswordStrength("!@#$%")
	assert.Equal(t, 1, info.Score)
	assert.Equal(t, 5, info.Length)
	assert.False(t, info.HasUpper)
	assert.False(t, info.HasLower)
	assert.False(t, info.HasDigit)
	assert.True(t, info.HasSpecial)
}

func TestGetPasswordStrength_TwoTypes(t *testing.T) {
	// Upper + Lower
	info := service.GetPasswordStrength("Abcdef")
	assert.Equal(t, 2, info.Score)
	assert.True(t, info.HasUpper)
	assert.True(t, info.HasLower)

	// Upper + Digit
	info = service.GetPasswordStrength("A12345")
	assert.Equal(t, 2, info.Score)
	assert.True(t, info.HasUpper)
	assert.True(t, info.HasDigit)

	// Lower + Special
	info = service.GetPasswordStrength("abc!")
	assert.Equal(t, 2, info.Score)
	assert.True(t, info.HasLower)
	assert.True(t, info.HasSpecial)
}

func TestGetPasswordStrength_ThreeTypes(t *testing.T) {
	info := service.GetPasswordStrength("Abc123!")
	// When all 4 types are present, score is 4
	assert.Equal(t, 4, info.Score)
	assert.True(t, info.HasUpper)
	assert.True(t, info.HasLower)
	assert.True(t, info.HasDigit)
	assert.True(t, info.HasSpecial)
}

func TestGetPasswordStrength_FourTypes(t *testing.T) {
	info := service.GetPasswordStrength("Abc123!@")
	assert.Equal(t, 4, info.Score)
	assert.True(t, info.HasUpper)
	assert.True(t, info.HasLower)
	assert.True(t, info.HasDigit)
	assert.True(t, info.HasSpecial)
}

func TestGetPasswordStrength_Unicode(t *testing.T) {
	// Unicode characters
	info := service.GetPasswordStrength("测试密码123")
	assert.GreaterOrEqual(t, info.Length, 6)
	// Unicode is not counted as upper/lower/digit/special in the current implementation
}

// =============================================================================
// LoginRequest GetAccount Tests
// =============================================================================

func TestLoginRequest_GetAccount_Nil(t *testing.T) {
	var req *service.LoginRequest
	assert.Equal(t, "", req.GetAccount())
}

func TestLoginRequest_GetAccount_Empty(t *testing.T) {
	req := &service.LoginRequest{}
	assert.Equal(t, "", req.GetAccount())
}

func TestLoginRequest_GetAccount_Account(t *testing.T) {
	req := &service.LoginRequest{
		Account: "testuser",
	}
	assert.Equal(t, "testuser", req.GetAccount())
}

func TestLoginRequest_GetAccount_Username(t *testing.T) {
	req := &service.LoginRequest{
		Username: "testuser",
	}
	assert.Equal(t, "testuser", req.GetAccount())
}

func TestLoginRequest_GetAccount_Email(t *testing.T) {
	req := &service.LoginRequest{
		Email: "test@test.com",
	}
	assert.Equal(t, "test@test.com", req.GetAccount())
}

func TestLoginRequest_GetAccount_Phone(t *testing.T) {
	req := &service.LoginRequest{
		Phone: "+1234567890",
	}
	assert.Equal(t, "+1234567890", req.GetAccount())
}

func TestLoginRequest_GetAccount_Priority(t *testing.T) {
	// Account has priority
	req := &service.LoginRequest{
		Account:  "account",
		Username: "username",
		Email:    "email@test.com",
	}
	assert.Equal(t, "account", req.GetAccount())
}

func TestLoginRequest_GetAccount_Trimmed(t *testing.T) {
	// Whitespace should be trimmed
	req := &service.LoginRequest{
		Username: "  testuser  ",
	}
	assert.Equal(t, "testuser", req.GetAccount())
}

func TestLoginRequest_GetAccount_EmptyAfterTrim(t *testing.T) {
	// Only whitespace
	req := &service.LoginRequest{
		Username: "   ",
	}
	assert.Equal(t, "", req.GetAccount())
}
