package api

import (
	"testing"

	"drivervault/apiserver/internal/models"
)

// The garage arrangement is a per-user list of car ids, so it has to cope with
// lists that no longer line up with the cars the user actually has: a car sold
// since the last drag leaves a stale id, a car added or shared since leaves an
// id missing. These cover both directions plus the input cleaning.

func ids(cars []models.Car) []string {
	out := make([]string, len(cars))
	for i, c := range cars {
		out[i] = c.ID
	}
	return out
}

func carsWithIDs(list ...string) []models.Car {
	out := make([]models.Car, len(list))
	for i, id := range list {
		out[i] = models.Car{ID: id}
	}
	return out
}

func TestApplyCarOrder(t *testing.T) {
	for _, tc := range []struct {
		name  string
		cars  []string
		order []string
		want  []string
	}{
		{"arranged", []string{"a", "b", "c"}, []string{"c", "a", "b"}, []string{"c", "a", "b"}},
		{"no arrangement keeps default order", []string{"a", "b", "c"}, nil, []string{"a", "b", "c"}},
		{
			// A car added or shared since the last drag isn't in the list; it
			// belongs at the end rather than jumping into the middle.
			"unarranged cars go last in their existing order",
			[]string{"a", "b", "new1", "new2"}, []string{"b", "a"},
			[]string{"b", "a", "new1", "new2"},
		},
		{
			// A car that was sold since the last drag just drops out.
			"stale ids are ignored",
			[]string{"a", "b"}, []string{"gone", "b", "a"},
			[]string{"b", "a"},
		},
		{"single car is untouched", []string{"a"}, []string{"b", "a"}, []string{"a"}},
	} {
		t.Run(tc.name, func(t *testing.T) {
			cars := carsWithIDs(tc.cars...)
			applyCarOrder(cars, tc.order)
			got := ids(cars)
			if len(got) != len(tc.want) {
				t.Fatalf("order = %v, want %v", got, tc.want)
			}
			for i := range got {
				if got[i] != tc.want[i] {
					t.Fatalf("order = %v, want %v", got, tc.want)
				}
			}
		})
	}
}

func TestNormalizeCarOrder(t *testing.T) {
	got, err := normalizeCarOrder([]string{" a ", "", "b", "a", "   ", "c"})
	if err != nil {
		t.Fatalf("normalizeCarOrder: %v", err)
	}
	want := []string{"a", "b", "c"} // trimmed, blanks dropped, first "a" wins
	if len(got) != len(want) {
		t.Fatalf("normalized = %v, want %v", got, want)
	}
	for i := range got {
		if got[i] != want[i] {
			t.Fatalf("normalized = %v, want %v", got, want)
		}
	}

	tooLong := make([]string, maxCarOrder+1)
	for i := range tooLong {
		tooLong[i] = "c"
	}
	if _, err := normalizeCarOrder(tooLong); err == nil {
		t.Error("normalizeCarOrder accepted a list over the cap, want an error")
	}
}
