// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package lunatask_test

import (
	"testing"

	lunatask "git.secluded.site/go-lunatask"
)

func TestAllMotivations(t *testing.T) {
	t.Parallel()

	motivations := lunatask.AllMotivations()

	// Check count
	if got := len(motivations); got != 4 {
		t.Fatalf("AllMotivations() returned %d values, want 4", got)
	}

	// Check order
	expected := []lunatask.Motivation{
		lunatask.MotivationUnknown,
		lunatask.MotivationMust,
		lunatask.MotivationShould,
		lunatask.MotivationWant,
	}
	for i, want := range expected {
		if motivations[i] != want {
			t.Errorf("AllMotivations()[%d] = %q, want %q", i, motivations[i], want)
		}
	}

	// Check roundtrip: each value should be parseable
	for _, motivation := range motivations {
		parsed, err := lunatask.ParseMotivation(motivation.String())
		if err != nil {
			t.Errorf("ParseMotivation(%q) failed: %v", motivation.String(), err)
		}

		if parsed != motivation {
			t.Errorf("ParseMotivation(%q) = %q, want %q", motivation.String(), parsed, motivation)
		}
	}
}

func TestParseMotivation(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name    string
		input   string
		want    lunatask.Motivation
		wantErr bool
	}{
		{"unknown_lower", "unknown", lunatask.MotivationUnknown, false},
		{"unknown_upper", "UNKNOWN", lunatask.MotivationUnknown, false},
		{"unknown_mixed", "UnKnOwN", lunatask.MotivationUnknown, false},
		{"must_lower", "must", lunatask.MotivationMust, false},
		{"must_upper", "MUST", lunatask.MotivationMust, false},
		{"should_lower", "should", lunatask.MotivationShould, false},
		{"should_upper", "SHOULD", lunatask.MotivationShould, false},
		{"want_lower", "want", lunatask.MotivationWant, false},
		{"want_upper", "WANT", lunatask.MotivationWant, false},
		{"want_mixed", "WaNt", lunatask.MotivationWant, false},
		{"invalid", "invalid", "", true},
		{"empty", "", "", true},
		{"numeric", "1", "", true},
		{"typo", "muust", "", true},
	}

	for _, testCase := range tests {
		t.Run(testCase.name, func(t *testing.T) {
			t.Parallel()

			got, err := lunatask.ParseMotivation(testCase.input)
			if (err != nil) != testCase.wantErr {
				t.Errorf("ParseMotivation(%q) error = %v, wantErr %v", testCase.input, err, testCase.wantErr)

				return
			}

			if !testCase.wantErr && got != testCase.want {
				t.Errorf("ParseMotivation(%q) = %q, want %q", testCase.input, got, testCase.want)
			}
		})
	}
}

func TestMotivation_String(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name  string
		value lunatask.Motivation
		want  string
	}{
		{"unknown", lunatask.MotivationUnknown, "unknown"},
		{"must", lunatask.MotivationMust, "must"},
		{"should", lunatask.MotivationShould, "should"},
		{"want", lunatask.MotivationWant, "want"},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			t.Parallel()

			if got := tc.value.String(); got != tc.want {
				t.Errorf("Motivation.String() = %q, want %q", got, tc.want)
			}
		})
	}
}
