package sync

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestDetectFormatGroup_Epub(t *testing.T) {
	tests := []struct {
		name     string
		mimetype string
		filePath string
		want     FormatGroup
	}{
		{
			name:     "EPUB by mimetype",
			mimetype: "application/epub+zip",
			filePath: "/path/to/book.epub",
			want:     FormatGroupReflowable,
		},
		{
			name:     "EPUB by extension",
			mimetype: "",
			filePath: "/path/to/book.epub",
			want:     FormatGroupReflowable,
		},
		{
			name:     "EPUB by uppercase extension",
			mimetype: "",
			filePath: "/path/to/book.EPUB",
			want:     FormatGroupReflowable,
		},
		{
			name:     "EPUB with mimetype priority",
			mimetype: "application/epub+zip",
			filePath: "/path/to/book.unknown",
			want:     FormatGroupReflowable,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := DetectFormatGroup(tt.mimetype, tt.filePath)
			assert.Equal(t, tt.want, got)
		})
	}
}

func TestDetectFormatGroup_Mobi(t *testing.T) {
	tests := []struct {
		name     string
		mimetype string
		filePath string
		want     FormatGroup
	}{
		{
			name:     "MOBI by mimetype",
			mimetype: "application/x-mobipocket-ebook",
			filePath: "/path/to/book.mobi",
			want:     FormatGroupReflowable,
		},
		{
			name:     "MOBI by extension",
			mimetype: "",
			filePath: "/path/to/book.mobi",
			want:     FormatGroupReflowable,
		},
		{
			name:     "AZW3 by extension",
			mimetype: "",
			filePath: "/path/to/book.azw3",
			want:     FormatGroupReflowable,
		},
		{
			name:     "FB2 by extension",
			mimetype: "",
			filePath: "/path/to/book.fb2",
			want:     FormatGroupReflowable,
		},
		{
			name:     "TXT by extension",
			mimetype: "",
			filePath: "/path/to/book.txt",
			want:     FormatGroupReflowable,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := DetectFormatGroup(tt.mimetype, tt.filePath)
			assert.Equal(t, tt.want, got)
		})
	}
}

func TestDetectFormatGroup_Pdf(t *testing.T) {
	tests := []struct {
		name     string
		mimetype string
		filePath string
		want     FormatGroup
	}{
		{
			name:     "PDF by mimetype",
			mimetype: "application/pdf",
			filePath: "/path/to/book.pdf",
			want:     FormatGroupFixedLayout,
		},
		{
			name:     "PDF by extension",
			mimetype: "",
			filePath: "/path/to/book.pdf",
			want:     FormatGroupFixedLayout,
		},
		{
			name:     "DJVU by extension",
			mimetype: "",
			filePath: "/path/to/book.djvu",
			want:     FormatGroupFixedLayout,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := DetectFormatGroup(tt.mimetype, tt.filePath)
			assert.Equal(t, tt.want, got)
		})
	}
}

func TestDetectFormatGroup_Comic(t *testing.T) {
	tests := []struct {
		name     string
		mimetype string
		filePath string
		want     FormatGroup
	}{
		{
			name:     "CBZ by mimetype",
			mimetype: "application/x-cbz",
			filePath: "/path/to/comic.cbz",
			want:     FormatGroupComicArchive,
		},
		{
			name:     "CBZ by extension",
			mimetype: "",
			filePath: "/path/to/comic.cbz",
			want:     FormatGroupComicArchive,
		},
		{
			name:     "CBR by extension",
			mimetype: "",
			filePath: "/path/to/comic.cbr",
			want:     FormatGroupComicArchive,
		},
		{
			name:     "CB7 by extension",
			mimetype: "",
			filePath: "/path/to/comic.cb7",
			want:     FormatGroupComicArchive,
		},
		{
			name:     "CBT by extension",
			mimetype: "",
			filePath: "/path/to/comic.cbt",
			want:     FormatGroupComicArchive,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := DetectFormatGroup(tt.mimetype, tt.filePath)
			assert.Equal(t, tt.want, got)
		})
	}
}

func TestDetectFormatGroup_Unknown(t *testing.T) {
	tests := []struct {
		name     string
		mimetype string
		filePath string
		want     FormatGroup
	}{
		{
			name:     "Unknown extension",
			mimetype: "",
			filePath: "/path/to/file.xyz",
			want:     FormatGroupUnknown,
		},
		{
			name:     "Unknown mimetype",
			mimetype: "application/unknown",
			filePath: "/path/to/file.unknown",
			want:     FormatGroupUnknown,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := DetectFormatGroup(tt.mimetype, tt.filePath)
			assert.Equal(t, tt.want, got)
		})
	}
}

func TestGetMimeType(t *testing.T) {
	tests := []struct {
		name     string
		filePath string
		want     string
	}{
		{
			name:     "EPUB mimetype",
			filePath: "book.epub",
			want:     "application/epub+zip",
		},
		{
			name:     "PDF mimetype",
			filePath: "document.pdf",
			want:     "application/pdf",
		},
		{
			name:     "CBZ mimetype",
			filePath: "comic.cbz",
			want:     "application/x-cbz",
		},
		{
			name:     "Unknown mimetype",
			filePath: "file.xyz",
			want:     "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := GetMimeType(tt.filePath)
			assert.Equal(t, tt.want, got)
		})
	}
}

func TestIsReflowable(t *testing.T) {
	assert.True(t, IsReflowable(FormatGroupReflowable))
	assert.False(t, IsReflowable(FormatGroupFixedLayout))
	assert.False(t, IsReflowable(FormatGroupComicArchive))
	assert.False(t, IsReflowable(FormatGroupUnknown))
}

func TestHasFixedLayout(t *testing.T) {
	assert.True(t, HasFixedLayout(FormatGroupFixedLayout))
	assert.False(t, HasFixedLayout(FormatGroupReflowable))
	assert.False(t, HasFixedLayout(FormatGroupComicArchive))
	assert.False(t, HasFixedLayout(FormatGroupUnknown))
}

func TestIsComicArchive(t *testing.T) {
	assert.True(t, IsComicArchive(FormatGroupComicArchive))
	assert.False(t, IsComicArchive(FormatGroupReflowable))
	assert.False(t, IsComicArchive(FormatGroupFixedLayout))
	assert.False(t, IsComicArchive(FormatGroupUnknown))
}
