package main

import "testing"

func TestMatchLineExact(t *testing.T) {
	if !matchLine("hello", "hello") {
		t.Error("exact match should pass")
	}
	if matchLine("hello", "world") {
		t.Error("exact mismatch should fail")
	}
}

func TestMatchLineInlineWildcard(t *testing.T) {
	if !matchLine("Homebrew 5...", "Homebrew 5.1.0") {
		t.Error("trailing wildcard should match")
	}
	if !matchLine("...world", "hello world") {
		t.Error("leading wildcard should match")
	}
	if !matchLine("a...b...c", "aXXbYYc") {
		t.Error("multiple wildcards should match")
	}
	if matchLine("a...c", "aXXd") {
		t.Error("should not match when suffix differs")
	}
}

func TestMatchLinePreservesLiteralDots(t *testing.T) {
	if !matchLine("match ...", "match ...") {
		t.Error("literal ... should match itself")
	}
}

func TestMatchOutputEmpty(t *testing.T) {
	if !matchOutput(nil, nil) {
		t.Error("both empty should match")
	}
	if !matchOutput([]string{}, []string{}) {
		t.Error("both empty slices should match")
	}
}

func TestMatchOutputExact(t *testing.T) {
	if !matchOutput([]string{"hello", "world"}, []string{"hello", "world"}) {
		t.Error("exact match should pass")
	}
	if matchOutput([]string{"hello"}, []string{"world"}) {
		t.Error("mismatch should fail")
	}
}

func TestMatchOutputExtraActual(t *testing.T) {
	if matchOutput([]string{"hello"}, []string{"hello", "world"}) {
		t.Error("extra actual lines should fail")
	}
}

func TestMatchOutputExtraExpected(t *testing.T) {
	if matchOutput([]string{"hello", "world"}, []string{"hello"}) {
		t.Error("extra expected lines should fail")
	}
}

func TestMatchOutputMultilineWildcard(t *testing.T) {
	if !matchOutput([]string{"first", "...", "last"}, []string{"first", "a", "b", "c", "last"}) {
		t.Error("multiline wildcard should match multiple lines")
	}
	if !matchOutput([]string{"first", "...", "last"}, []string{"first", "last"}) {
		t.Error("multiline wildcard should match zero lines")
	}
	if !matchOutput([]string{"..."}, []string{"a", "b", "c"}) {
		t.Error("standalone wildcard should match anything")
	}
	if !matchOutput([]string{"..."}, nil) {
		t.Error("standalone wildcard should match empty")
	}
}

func TestMatchOutputMixed(t *testing.T) {
	expected := []string{"one", "...", "three"}
	actual := []string{"one", "two", "three"}
	if !matchOutput(expected, actual) {
		t.Error("mixed wildcard should match")
	}
}

func TestMatchOutputWildcardAtEnd(t *testing.T) {
	if !matchOutput([]string{"start", "..."}, []string{"start", "a", "b"}) {
		t.Error("trailing wildcard should match remaining lines")
	}
}

func TestMatchOutputInlineAndMultiline(t *testing.T) {
	expected := []string{"Homebrew 5...", "..."}
	actual := []string{"Homebrew 5.1.0", "extra line"}
	if !matchOutput(expected, actual) {
		t.Error("inline + multiline wildcards should work together")
	}
}

func TestDiffBasic(t *testing.T) {
	d := diff([]string{"hello"}, []string{"world"})
	if len(d) != 2 {
		t.Fatalf("expected 2 diff lines, got %d", len(d))
	}
	if d[0].Kind != "expected" || d[0].Text != "hello" {
		t.Errorf("d[0] = %+v", d[0])
	}
	if d[1].Kind != "actual" || d[1].Text != "world" {
		t.Errorf("d[1] = %+v", d[1])
	}
}

func TestDiffEqual(t *testing.T) {
	d := diff([]string{"hello"}, []string{"hello"})
	if len(d) != 1 || d[0].Kind != "equal" {
		t.Errorf("expected equal, got %+v", d)
	}
}

func TestDiffContext(t *testing.T) {
	d := diff([]string{"..."}, []string{"a", "b"})
	if len(d) != 3 {
		t.Fatalf("expected 3 diff lines, got %d: %+v", len(d), d)
	}
	if d[0].Kind != "context" || d[0].Text != "..." {
		t.Errorf("d[0] = %+v", d[0])
	}
	if d[1].Kind != "context" || d[1].Text != "a" {
		t.Errorf("d[1] = %+v", d[1])
	}
	if d[2].Kind != "context" || d[2].Text != "b" {
		t.Errorf("d[2] = %+v", d[2])
	}
}
