package services

import (
	"bookhoard/internal/database"
	"testing"

	"github.com/google/uuid"
	"github.com/jackc/pgx/v5/pgtype"
	"github.com/stretchr/testify/assert"
)

func TestContinueSeriesRowToMediaItems_FieldsMappedCorrectly(t *testing.T) {
	itemUUID := uuid.New()
	libUUID := uuid.New()
	adminUUID := uuid.New()

	row := database.GetContinueSeriesItemsRow{
		ID:             pgtype.UUID{Bytes: itemUUID, Valid: true},
		LibraryID:      pgtype.UUID{Bytes: libUUID, Valid: true},
		Title:          "Test Book",
		Author:         pgtype.Text{String: "Test Author", Valid: true},
		Isbn:           pgtype.Text{String: "978-1234567890", Valid: true},
		Description:    pgtype.Text{String: "A test book", Valid: true},
		FilePath:       "/books/test.epub",
		FileSize:       pgtype.Int8{Int64: 1024, Valid: true},
		MimeType:       pgtype.Text{String: "application/epub+zip", Valid: true},
		CoverImagePath: pgtype.Text{String: "/covers/test.jpg", Valid: true},
		Series:         pgtype.Text{String: "Test Series", Valid: true},
		SeriesNumber:   pgtype.Int4{Int32: 3, Valid: true},
		Tags:           []string{"fantasy", "adventure"},
		FormatGroup:    "epub",
		AddedByAdminID: pgtype.UUID{Bytes: adminUUID, Valid: true},
	}

	result := continueSeriesRowToMediaItems(row)

	assert.Equal(t, pgtype.UUID{Bytes: itemUUID, Valid: true}, result.ID, "ID should match")
	assert.Equal(t, pgtype.UUID{Bytes: libUUID, Valid: true}, result.LibraryID, "LibraryID should match")
	assert.Equal(t, "Test Book", result.Title, "Title should match")
	assert.Equal(t, pgtype.Text{String: "Test Author", Valid: true}, result.Author, "Author should match")
	assert.Equal(t, pgtype.Text{String: "978-1234567890", Valid: true}, result.Isbn, "ISBN should match")
	assert.Equal(t, "/books/test.epub", result.FilePath, "FilePath should match")
	assert.Equal(t, pgtype.Text{String: "application/epub+zip", Valid: true}, result.MimeType, "MimeType should match")
	assert.Equal(t, pgtype.Text{String: "/covers/test.jpg", Valid: true}, result.CoverImagePath, "CoverImagePath should match")
	assert.Equal(t, pgtype.Text{String: "Test Series", Valid: true}, result.Series, "Series should match")
	assert.Equal(t, pgtype.Int4{Int32: 3, Valid: true}, result.SeriesNumber, "SeriesNumber should match")
	assert.Equal(t, []string{"fantasy", "adventure"}, result.Tags, "Tags should match")
	assert.Equal(t, "epub", result.FormatGroup, "FormatGroup should match")
}

func TestContinueSeriesRowToMediaItems_NullFieldsHandled(t *testing.T) {
	itemUUID := uuid.New()
	libUUID := uuid.New()

	row := database.GetContinueSeriesItemsRow{
		ID:             pgtype.UUID{Bytes: itemUUID, Valid: true},
		LibraryID:      pgtype.UUID{Bytes: libUUID, Valid: true},
		Title:          "No Metadata Book",
		Author:         pgtype.Text{Valid: false},
		Isbn:           pgtype.Text{Valid: false},
		Description:    pgtype.Text{Valid: false},
		FilePath:       "/books/nometa.epub",
		FileSize:       pgtype.Int8{Valid: false},
		MimeType:       pgtype.Text{Valid: false},
		CoverImagePath: pgtype.Text{Valid: false},
		Series:         pgtype.Text{Valid: false},
		SeriesNumber:   pgtype.Int4{Valid: false},
		Tags:           nil,
		FormatGroup:    "epub",
	}

	result := continueSeriesRowToMediaItems(row)

	assert.Equal(t, "No Metadata Book", result.Title)
	assert.False(t, result.Author.Valid, "Author should be invalid/null")
	assert.False(t, result.Series.Valid, "Series should be invalid/null")
	assert.False(t, result.SeriesNumber.Valid, "SeriesNumber should be invalid/null")
	assert.Nil(t, result.Tags, "Tags should be nil")
}

func TestContinueSeriesRowToMediaItems_AllFieldsMapped(t *testing.T) {
	itemUUID := uuid.New()
	libUUID := uuid.New()

	row := database.GetContinueSeriesItemsRow{
		ID:                 pgtype.UUID{Bytes: itemUUID, Valid: true},
		LibraryID:          pgtype.UUID{Bytes: libUUID, Valid: true},
		Title:              "Full Book",
		Author:             pgtype.Text{String: "Author", Valid: true},
		Isbn:               pgtype.Text{String: "ISBN", Valid: true},
		Description:        pgtype.Text{String: "Desc", Valid: true},
		FilePath:           "/book.epub",
		FileSize:           pgtype.Int8{Int64: 2048, Valid: true},
		MimeType:           pgtype.Text{String: "epub", Valid: true},
		CoverImagePath:     pgtype.Text{String: "/cover.jpg", Valid: true},
		Series:             pgtype.Text{String: "Series", Valid: true},
		SeriesNumber:       pgtype.Int4{Int32: 1, Valid: true},
		Tags:               []string{"tag1"},
		Asin:               pgtype.Text{String: "ASIN", Valid: true},
		Publisher:          pgtype.Text{String: "Pub", Valid: true},
		Language:           pgtype.Text{String: "en", Valid: true},
		Edition:            pgtype.Text{String: "1st", Valid: true},
		Genre:              pgtype.Text{String: "Fiction", Valid: true},
		FormatGroup:        "epub",
		FormatMimetype:     pgtype.Text{String: "application/epub+zip", Valid: true},
		IsReflowable:       pgtype.Bool{Bool: true, Valid: true},
		HasFixedLayout:     pgtype.Bool{Bool: false, Valid: true},
		TotalCharacters:    pgtype.Int8{Int64: 500000, Valid: true},
		ChapterCount:       pgtype.Int4{Int32: 20, Valid: true},
		MangaType:          pgtype.Text{String: "manga", Valid: true},
		ReadingDirection:   pgtype.Text{String: "rtl", Valid: true},
		SeriesCount:        pgtype.Int4{Int32: 10, Valid: true},
		Volume:             pgtype.Int4{Int32: 1, Valid: true},
		LibraryTypeName:    pgtype.Text{String: "ebooks", Valid: true},
		FileSha256:         pgtype.Text{String: "abc123", Valid: true},
	}

	result := continueSeriesRowToMediaItems(row)

	assert.Equal(t, pgtype.Text{String: "ASIN", Valid: true}, result.Asin)
	assert.Equal(t, pgtype.Text{String: "Pub", Valid: true}, result.Publisher)
	assert.Equal(t, pgtype.Text{String: "en", Valid: true}, result.Language)
	assert.Equal(t, pgtype.Text{String: "1st", Valid: true}, result.Edition)
	assert.Equal(t, pgtype.Text{String: "Fiction", Valid: true}, result.Genre)
	assert.Equal(t, pgtype.Text{String: "application/epub+zip", Valid: true}, result.FormatMimetype)
	assert.Equal(t, pgtype.Bool{Bool: true, Valid: true}, result.IsReflowable)
	assert.Equal(t, pgtype.Bool{Bool: false, Valid: true}, result.HasFixedLayout)
	assert.Equal(t, pgtype.Int8{Int64: 500000, Valid: true}, result.TotalCharacters)
	assert.Equal(t, pgtype.Int4{Int32: 20, Valid: true}, result.ChapterCount)
	assert.Equal(t, pgtype.Text{String: "manga", Valid: true}, result.MangaType)
	assert.Equal(t, pgtype.Text{String: "rtl", Valid: true}, result.ReadingDirection)
	assert.Equal(t, pgtype.Int4{Int32: 10, Valid: true}, result.SeriesCount)
	assert.Equal(t, pgtype.Int4{Int32: 1, Valid: true}, result.Volume)
	assert.Equal(t, pgtype.Text{String: "ebooks", Valid: true}, result.LibraryTypeName)
	assert.Equal(t, pgtype.Text{String: "abc123", Valid: true}, result.FileSha256)
}
