package subsonic

import (
	"testing"
	"time"

	"github.com/jackc/pgx/v5/pgtype"
)

func TestUUIDRoundTrip(t *testing.T) {
	cases := []string{
		"6ba7b810-9dad-11d1-80b4-00c04fd430c8",
		"00000000-0000-0000-0000-000000000001",
	}
	for _, in := range cases {
		u, ok := parseUUID(in)
		if !ok {
			t.Fatalf("parseUUID(%q) failed", in)
		}
		if got := uuidToID(u); got != in {
			t.Errorf("uuidToID(parseUUID(%q)) = %q", in, got)
		}
	}
}

func TestUUIDToIDZero(t *testing.T) {
	var u pgtype.UUID
	if got := uuidToID(u); got != "" {
		t.Errorf("zero uuid → %q, want empty", got)
	}
}

func TestParseUUIDInvalid(t *testing.T) {
	for _, in := range []string{"", "not-a-uuid", "xxx"} {
		if _, ok := parseUUID(in); ok {
			t.Errorf("parseUUID(%q) unexpectedly ok", in)
		}
	}
}

func TestIndexLetter(t *testing.T) {
	cases := map[string]string{
		"Radiohead":     "R",
		"the beatles":   "T",
		"  massive":     "M",
		"4 Non Blondes": "#",
		"":              "?",
		"*NSYNC":        "?",
		"Éowyn":         "?",
	}
	for in, want := range cases {
		if got := indexLetter(in); got != want {
			t.Errorf("indexLetter(%q) = %q, want %q", in, got, want)
		}
	}
}

func TestContentTypeForFormat(t *testing.T) {
	cases := map[string]string{
		"mp3":     "audio/mpeg",
		"MP3":     "audio/mpeg",
		"flac":    "audio/flac",
		"ogg":     "audio/ogg",
		"oga":     "audio/ogg",
		"opus":    "audio/opus",
		"m4a":     "audio/mp4",
		"aac":     "audio/mp4",
		"wav":     "audio/wav",
		"unknown": "application/octet-stream",
	}
	for in, want := range cases {
		if got := contentTypeForFormat(in); got != want {
			t.Errorf("contentTypeForFormat(%q) = %q, want %q", in, got, want)
		}
	}
}

func TestYearFromDate(t *testing.T) {
	d := pgtype.Date{Valid: true, Time: time.Date(1997, 6, 16, 0, 0, 0, 0, time.UTC)}
	if got := yearFromDate(d); got != 1997 {
		t.Errorf("yearFromDate = %d", got)
	}
	if got := yearFromDate(pgtype.Date{}); got != 0 {
		t.Errorf("yearFromDate(zero) = %d, want 0", got)
	}
}

func TestTimestamptzToRFC3339(t *testing.T) {
	ts := pgtype.Timestamptz{
		Valid: true,
		Time:  time.Date(2026, 1, 2, 3, 4, 5, 0, time.UTC),
	}
	if got := timestamptzToRFC3339(ts); got != "2026-01-02T03:04:05Z" {
		t.Errorf("rfc3339 = %q", got)
	}
	if got := timestamptzToRFC3339(pgtype.Timestamptz{}); got != "" {
		t.Errorf("rfc3339(zero) = %q, want empty", got)
	}
}

func TestAtoiDefault(t *testing.T) {
	cases := []struct {
		in   string
		def  int
		want int
	}{
		{"", 7, 7},
		{"42", 0, 42},
		{"  12 ", 0, 12},
		{"junk", 99, 99},
	}
	for _, c := range cases {
		if got := atoiDefault(c.in, c.def); got != c.want {
			t.Errorf("atoiDefault(%q,%d) = %d, want %d", c.in, c.def, got, c.want)
		}
	}
}

func TestClampInt(t *testing.T) {
	if got := clampInt(5, 1, 10); got != 5 {
		t.Errorf("in-range = %d", got)
	}
	if got := clampInt(-3, 1, 10); got != 1 {
		t.Errorf("below = %d", got)
	}
	if got := clampInt(99, 1, 10); got != 10 {
		t.Errorf("above = %d", got)
	}
}
