package jdenticon

import (
	"context"
	"strings"
	"testing"
)

func TestGenerate(t *testing.T) {
	tests := []struct {
		name    string
		input   string
		size    int
		wantErr bool
	}{
		{
			name:    "valid_email",
			input:   "user@example.com",
			size:    64,
			wantErr: false,
		},
		{
			name:    "valid_username",
			input:   "johndoe",
			size:    128,
			wantErr: false,
		},
		{
			name:    "empty_input",
			input:   "",
			size:    64,
			wantErr: true,
		},
		{
			name:    "zero_size",
			input:   "test",
			size:    0,
			wantErr: true,
		},
		{
			name:    "negative_size",
			input:   "test",
			size:    -1,
			wantErr: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			icon, err := Generate(context.Background(), tt.input, tt.size)

			if tt.wantErr {
				if err == nil {
					t.Errorf("Generate(context.Background(), ) expected error for %s, but got none", tt.name)
				}
				return
			}

			if err != nil {
				t.Errorf("Generate(context.Background(), ) unexpected error for %s: %v", tt.name, err)
				return
			}

			if icon == nil {
				t.Errorf("Generate(context.Background(), ) returned nil icon for %s", tt.name)
				return
			}
		})
	}
}

func TestToSVG(t *testing.T) {
	input := "test@example.com"
	size := 64

	svg, err := ToSVG(context.Background(), input, size)
	if err != nil {
		t.Fatalf("ToSVG(context.Background(), ) failed: %v", err)
	}

	if svg == "" {
		t.Error("ToSVG() returned empty string")
	}

	// Basic SVG validation
	if !strings.HasPrefix(svg, "<svg") {
		t.Error("ToSVG() output doesn't start with <svg")
	}

	if !strings.HasSuffix(svg, "</svg>") {
		t.Error("ToSVG() output doesn't end with </svg>")
	}

	if !strings.Contains(svg, "xmlns") {
		t.Error("ToSVG() output missing xmlns attribute")
	}
}

func TestToPNG(t *testing.T) {
	input := "test@example.com"
	size := 64

	png, err := ToPNG(context.Background(), input, size)
	if err != nil {
		t.Fatalf("ToPNG(context.Background(), ) failed: %v", err)
	}

	if len(png) == 0 {
		t.Error("ToPNG() returned empty byte slice")
	}

	// Basic PNG validation - check PNG signature
	if len(png) < 8 {
		t.Error("ToPNG() output too short to be valid PNG")
		return
	}

	// PNG signature: 89 50 4E 47 0D 0A 1A 0A
	expectedSignature := []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}
	for i, expected := range expectedSignature {
		if png[i] != expected {
			t.Errorf("ToPNG(context.Background(), ) invalid PNG signature at byte %d: expected %02x, got %02x", i, expected, png[i])
		}
	}
}

func TestDeterminism(t *testing.T) {
	input := "determinism-test"
	size := 64

	// Generate the same input multiple times
	svg1, err1 := ToSVG(context.Background(), input, size)
	svg2, err2 := ToSVG(context.Background(), input, size)

	if err1 != nil || err2 != nil {
		t.Fatalf("ToSVG(context.Background(), ) failed: err1=%v, err2=%v", err1, err2)
	}

	if svg1 != svg2 {
		t.Error("ToSVG() not deterministic: same input produced different output")
	}

	png1, err1 := ToPNG(context.Background(), input, size)
	png2, err2 := ToPNG(context.Background(), input, size)

	if err1 != nil || err2 != nil {
		t.Fatalf("ToPNG(context.Background(), ) failed: err1=%v, err2=%v", err1, err2)
	}

	if len(png1) != len(png2) {
		t.Error("ToPNG() not deterministic: same input produced different length output")
		return
	}

	for i := range png1 {
		if png1[i] != png2[i] {
			t.Errorf("ToPNG(context.Background(), ) not deterministic: difference at byte %d", i)
			break
		}
	}
}
