package random

import (
	"net"
	"strings"
	"testing"
)

func Test_RandPositiveInt(t *testing.T) {
	integer := RandPositiveInt(10)
	if integer > 10 {
		t.Error("Integer larger than 10")
	}
	if integer < 0 {
		t.Error("Positive integer less than 0")
	}
}

func Test_RandIntRange(t *testing.T) {
	integer := RandIntRange(-2, 10)
	if integer > 10 {
		t.Error("Integer larger than 10")
	}
	if integer < -2 {
		t.Error("Integer less than -2")
	}
}

func Test_RandLetters(t *testing.T) {
	letters := RandLetters(8)
	if len(letters) != 8 {
		t.Error("Failed to generate an 8 char string")
	}

	letters = RandLetters(1)
	if len(letters) != 1 {
		t.Error("Failed to generate a 1 char string")
	}

	letters = RandLetters(0)
	if len(letters) != 0 {
		t.Error("Failed to generate a 0 char string")
	}

	letters = RandLetters(64)
	if len(letters) != 64 {
		t.Error("Failed to generate a 64 char string")
	}

	for _, value := range letters {
		if (int(value) < 65 || int(value) > 90) && (int(value) < 97 || int(value) > 122) {
			t.Error("RandLetters used value outside of ascii letter ranges.")
		}
	}
}

func Test_RandLettersNoBadChars(t *testing.T) {
	// loop 100 times generating random letter strings and ensure
	// they don't contain a bad value.
	for range 100 {
		letters := RandLettersNoBadChars(12, []rune("abcd"))
		if len(letters) == 0 {
			t.Error("RandLettersNoBadChars created an empty string")
		}
		for _, value := range letters {
			if value == 'a' || value == 'b' || value == 'c' || value == 'd' {
				t.Error("Created a string with a badchar: " + letters)
			}
		}
	}
}

func Test_RandDigits(t *testing.T) {
	digits := RandDigits(8)
	if len(digits) != 8 {
		t.Error("Failed to generate an 8 char string")
	}

	if digits[0] == '0' {
		t.Error("Created a digit string that starts with zero")
	}

	for _, value := range digits {
		if int(value) < 48 || int(value) > 57 {
			t.Error("RandDigits used value outside of ascii digit ranges.")
		}
	}
}

func Test_RandHex(t *testing.T) {
	hex := RandHex(8)
	if len(hex) != 8 {
		t.Error("Failed to generate an 8 char string")
	}

	for _, value := range hex {
		if (int(value) < 48 || int(value) > 57) && (int(value) < 97 || int(value) > 102) {
			t.Error("RandHex used value outside of ascii hex ranges: " + string(value))
		}
	}
}

func Test_RandLettersRange(t *testing.T) {
	letters := RandLettersRange(2, 10)
	if len(letters) < 2 || len(letters) >= 10 {
		t.Error("Created a string outside of the [2,10) range")
	}

	for _, value := range letters {
		if (int(value) < 65 || int(value) > 90) && (int(value) < 97 || int(value) > 122) {
			t.Error("RandLettersRange used value outside of ascii letter ranges.")
		}
	}
}

func Test_RandHexRange(t *testing.T) {
	hex := RandHexRange(2, 10)
	if len(hex) < 2 || len(hex) >= 10 {
		t.Error("Created a string outside of the [2,10) range")
	}

	for _, value := range hex {
		if (int(value) < 48 || int(value) > 57) && (int(value) < 97 || int(value) > 102) {
			t.Error("RandHex used value outside of ascii hex ranges: " + string(value))
		}
	}
}

func Test_RandDigitsRange(t *testing.T) {
	digits := RandDigitsRange(2, 10)
	if len(digits) < 2 || len(digits) >= 10 {
		t.Error("Created a string outside of the [2,10) range")
	}

	if digits[0] == '0' {
		t.Error("Created a digit string that starts with zero")
	}

	for _, value := range digits {
		if int(value) < 48 || int(value) > 57 {
			t.Error("RandDigits used value outside of ascii digit ranges.")
		}
	}
}

func Test_RandDomain(t *testing.T) {
	for range 100 {
		r := RandDomain()
		if len(r) > 14 || len(r) < 8 {
			t.Error("Domain generated with an unexpected length: " + r)
		}
		if !strings.Contains(r, ".") {
			t.Error("Domain generated without expected characters: " + r)
		}
	}
}

func Test_RandMAC(t *testing.T) {
	for range 100 {
		r := RandMAC()
		if len(r) != 17 {
			t.Error("Mac address generated with an unexpected length: " + r)
		}
		if !strings.Contains(r, ":") {
			t.Error("Mac address generated without expected characters: " + r)
		}
	}
}

func Test_RandEmail(t *testing.T) {
	for range 100 {
		r := RandEmail()
		if len(r) > 23 || len(r) < 13 {
			t.Error("Domain generated with an unexpected length: " + r)
		}
		if !strings.Contains(r, ".") {
			t.Error("Domain generated without expected characters: " + r)
		}
	}
}

func TestRandIPv4(t *testing.T) {
	for range 100 {
		r := RandIPv4()
		parsed := net.ParseIP(r.String())
		if parsed == nil {
			t.Error("Generated IP is nil: " + r.String())
		}
		if parsed.To4() == nil {
			t.Error("Generated IP is not a valid IPv4 address: " + r.String())
		}
	}
}

func TestRandIPv6(t *testing.T) {
	for range 100 {
		r := RandIPv6()
		parsed := net.ParseIP(r.String())
		if parsed == nil {
			t.Error("Generated IP is nil: " + r.String())
		}
		if parsed.To4() != nil {
			t.Error("Generated IP is not a valid IPv6 address: " + r.String())
		}
	}
}

func TestRandIPv4Private(t *testing.T) {
	for range 100 {
		r := RandIPv4Private()
		parsed := net.ParseIP(r.String())
		if parsed == nil {
			t.Error("Generated IP is nil: " + r.String())
		}
		if parsed.To4() == nil {
			t.Error("Generated IP is not a valid IPv4 address: " + r.String())
		}

		// Check if the IP is private
		isPrivate := r.IsPrivate()

		if !isPrivate {
			t.Error("Generated IP is not in a private range: " + r.String())
		}
	}
}

func TestRandIPv4Loopback(t *testing.T) {
	for range 5 {
		r := RandIPv4Loopback()
		parsed := net.ParseIP(r.String())
		if parsed == nil {
			t.Error("Generated IP is nil: " + r.String())
		}
		if parsed.To4() == nil {
			t.Error("Generated IP is not a valid IPv4 address: " + r.String())
		}

		// Check if the IP is loopback
		isLoopback := r.IsLoopback()

		if !isLoopback {
			t.Error("Generated IP is not the expected loopback address:" + r.String())
		}
	}
}
