package utils

import (
	"testing"
)

func TestNewVersion(t *testing.T) {
	tests := []struct {
		name    string
		version string
		wantErr bool
	}{
		{
			name:    "valid version with v prefix",
			version: "v1.2.3",
			wantErr: false,
		},
		{
			name:    "invalid version without v prefix",
			version: "1.2.3",
			wantErr: true,
		},
		{
			name:    "valid version with additional text",
			version: "v1.2.3-beta",
			wantErr: false,
		},
		{
			name:    "invalid version",
			version: "invalid",
			wantErr: true,
		},
		{
			name:    "empty version",
			version: "",
			wantErr: true,
		},
		{
			name:    "version with only v",
			version: "v",
			wantErr: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := NewVersion(tt.version)
			if (err != nil) != tt.wantErr {
				t.Errorf("NewVersion() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !tt.wantErr && got == nil {
				t.Errorf("NewVersion() returned nil for valid version")
			}
		})
	}
}

func TestVersion_Lt(t *testing.T) {
	v1, _ := NewVersion("v1.2.3")
	v2, _ := NewVersion("v2.0.0")

	tests := []struct {
		name           string
		version        *Version
		anotherVersion string
		want           bool
		wantErr        bool
	}{
		{
			name:           "less than",
			version:        v1,
			anotherVersion: "v2.0.0-beta.1",
			want:           true,
			wantErr:        false,
		},
		{
			name:           "less than - same major version",
			version:        v1,
			anotherVersion: "v1.3.3",
			want:           true,
			wantErr:        false,
		},
		{
			name:           "not less than",
			version:        v2,
			anotherVersion: "v1.2.3",
			want:           false,
			wantErr:        false,
		},
		{
			name:           "equal versions",
			version:        v1,
			anotherVersion: "v1.2.3",
			want:           false,
			wantErr:        false,
		},
		{
			name:           "invalid another version",
			version:        v1,
			anotherVersion: "invalid",
			want:           false,
			wantErr:        true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := tt.version.Lt(tt.anotherVersion)
			if (err != nil) != tt.wantErr {
				t.Errorf("Version.Lt() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if got != tt.want {
				t.Errorf("Version.Lt() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestVersion_Lte(t *testing.T) {
	v1, _ := NewVersion("v1.2.3")
	v2, _ := NewVersion("v2.0.0")

	tests := []struct {
		name           string
		version        *Version
		anotherVersion string
		want           bool
		wantErr        bool
	}{
		{
			name:           "less than",
			version:        v1,
			anotherVersion: "v2.0.0-beta.1",
			want:           true,
			wantErr:        false,
		},
		{
			name:           "equal versions",
			version:        v1,
			anotherVersion: "v1.2.3",
			want:           true,
			wantErr:        false,
		},
		{
			name:           "not less than or equal",
			version:        v2,
			anotherVersion: "v1.2.3",
			want:           false,
			wantErr:        false,
		},
		{
			name:           "invalid another version",
			version:        v1,
			anotherVersion: "invalid",
			want:           false,
			wantErr:        true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := tt.version.Lte(tt.anotherVersion)
			if (err != nil) != tt.wantErr {
				t.Errorf("Version.Lte() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if got != tt.want {
				t.Errorf("Version.Lte() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestVersion_Gt(t *testing.T) {
	v1, _ := NewVersion("v1.2.3")
	v2, _ := NewVersion("v2.0.0")

	tests := []struct {
		name           string
		version        *Version
		anotherVersion string
		want           bool
		wantErr        bool
	}{
		{
			name:           "greater than",
			version:        v2,
			anotherVersion: "v1.2.3",
			want:           true,
			wantErr:        false,
		},
		{
			name:           "not greater than",
			version:        v1,
			anotherVersion: "v2.0.0-beta.1",
			want:           false,
			wantErr:        false,
		},
		{
			name:           "equal versions",
			version:        v1,
			anotherVersion: "v1.2.3",
			want:           false,
			wantErr:        false,
		},
		{
			name:           "invalid another version",
			version:        v1,
			anotherVersion: "invalid",
			want:           false,
			wantErr:        true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := tt.version.Gt(tt.anotherVersion)
			if (err != nil) != tt.wantErr {
				t.Errorf("Version.Gt() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if got != tt.want {
				t.Errorf("Version.Gt() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestVersion_Gte(t *testing.T) {
	v1, _ := NewVersion("v1.2.3")
	v2, _ := NewVersion("v2.0.0")

	tests := []struct {
		name           string
		version        *Version
		anotherVersion string
		want           bool
		wantErr        bool
	}{
		{
			name:           "greater than",
			version:        v2,
			anotherVersion: "v1.2.3",
			want:           true,
			wantErr:        false,
		},
		{
			name:           "equal versions",
			version:        v1,
			anotherVersion: "v1.2.3",
			want:           true,
			wantErr:        false,
		},
		{
			name:           "not greater than or equal",
			version:        v1,
			anotherVersion: "v2.0.0-beta.1",
			want:           false,
			wantErr:        false,
		},
		{
			name:           "invalid another version",
			version:        v1,
			anotherVersion: "invalid",
			want:           false,
			wantErr:        true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := tt.version.Gte(tt.anotherVersion)
			if (err != nil) != tt.wantErr {
				t.Errorf("Version.Gte() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if got != tt.want {
				t.Errorf("Version.Gte() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestNormalizeVersion(t *testing.T) {
	tests := []struct {
		name    string
		version string
		want    string
	}{
		{
			name:    "version with v prefix",
			version: "v1.2.3",
			want:    "v1.2.3",
		},
		{
			name:    "version without v prefix",
			version: "1.2.3",
			want:    "",
		},
		{
			name:    "version with additional text",
			version: "v1.2.3-beta",
			want:    "v1.2.3",
		},
		{
			name:    "version with additional text2",
			version: "v9.0.0-crr-advancer-final",
			want:    "v9.0.0",
		},
		{
			name:    "version with multiple dots",
			version: "v1.2.3.4",
			want:    "v1.2.3.4",
		},
		{
			name:    "version with single number",
			version: "v1",
			want:    "v1",
		},
		{
			name:    "version with two numbers",
			version: "v1.2",
			want:    "v1.2",
		},
		{
			name:    "no version pattern",
			version: "no version here",
			want:    "",
		},
		{
			name:    "empty string",
			version: "",
			want:    "",
		},
		{
			name:    "just v",
			version: "v",
			want:    "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := NormalizeVersion(tt.version); got != tt.want {
				t.Errorf("NormalizeVersion() = %v, want %v", got, tt.want)
			}
		})
	}
}
