package handlers

import (
	"testing"
	"time"

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

func TestGetMostRecentSource_KOReaderMoreRecent(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source:    "koreader",
			Timestamp: time.Date(2026, 1, 30, 20, 10, 0, 0, time.UTC),
			Data: map[string]interface{}{
				"percentage": 0.45,
				"epubcfi":    "epubcfi(/6/4/2:15)",
			},
		},
		"kobo": {
			Source:    "kobo",
			Timestamp: time.Date(2026, 1, 30, 20, 5, 0, 0, time.UTC),
			Data: map[string]interface{}{
				"percentage": 0.42,
				"page":       float64(89),
			},
		},
	}

	source, data := handler.getMostRecentSource(conflictData)
	assert.Equal(t, "koreader", source)
	assert.Equal(t, 0.45, data["percentage"])
}

func TestGetMostRecentSource_KoboMoreRecent(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source:    "koreader",
			Timestamp: time.Date(2026, 1, 30, 20, 5, 0, 0, time.UTC),
			Data: map[string]interface{}{
				"percentage": 0.45,
			},
		},
		"kobo": {
			Source:    "kobo",
			Timestamp: time.Date(2026, 1, 30, 20, 15, 0, 0, time.UTC),
			Data: map[string]interface{}{
				"percentage": 0.42,
			},
		},
	}

	source, data := handler.getMostRecentSource(conflictData)
	assert.Equal(t, "kobo", source)
	assert.Equal(t, 0.42, data["percentage"])
}

func TestGetMostRecentSource_SingleSource(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source:    "koreader",
			Timestamp: time.Date(2026, 1, 30, 20, 10, 0, 0, time.UTC),
			Data: map[string]interface{}{
				"percentage": 0.50,
			},
		},
	}

	source, data := handler.getMostRecentSource(conflictData)
	assert.Equal(t, "koreader", source)
	assert.Equal(t, 0.50, data["percentage"])
}

func TestGetMostRecentSource_SameTimestamp(t *testing.T) {
	handler := &ConflictHandler{}

	ts := time.Date(2026, 1, 30, 20, 10, 0, 0, time.UTC)
	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source:    "koreader",
			Timestamp: ts,
			Data: map[string]interface{}{
				"percentage": 0.45,
			},
		},
		"kobo": {
			Source:    "kobo",
			Timestamp: ts,
			Data: map[string]interface{}{
				"percentage": 0.42,
			},
		},
	}

	source, _ := handler.getMostRecentSource(conflictData)
	assert.Contains(t, []string{"koreader", "kobo"}, source)
}

func TestGetMostRecentSource_EmptyData(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{}

	source, data := handler.getMostRecentSource(conflictData)
	assert.Equal(t, "", source)
	assert.Nil(t, data)
}

func TestGetHighestProgressSource_KOReaderHigher(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source: "koreader",
			Data: map[string]interface{}{
				"percentage": 0.75,
			},
		},
		"kobo": {
			Source: "kobo",
			Data: map[string]interface{}{
				"percentage": 0.42,
			},
		},
	}

	source, data := handler.getHighestProgressSource(conflictData)
	assert.Equal(t, "koreader", source)
	assert.Equal(t, 0.75, data["percentage"])
}

func TestGetHighestProgressSource_KoboHigher(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source: "koreader",
			Data: map[string]interface{}{
				"percentage": 0.30,
			},
		},
		"kobo": {
			Source: "kobo",
			Data: map[string]interface{}{
				"percentage": 0.90,
			},
		},
	}

	source, data := handler.getHighestProgressSource(conflictData)
	assert.Equal(t, "kobo", source)
	assert.Equal(t, 0.90, data["percentage"])
}

func TestGetHighestProgressSource_SingleSource(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source: "koreader",
			Data: map[string]interface{}{
				"percentage": 0.50,
			},
		},
	}

	source, data := handler.getHighestProgressSource(conflictData)
	assert.Equal(t, "koreader", source)
	assert.Equal(t, 0.50, data["percentage"])
}

func TestGetHighestProgressSource_EmptyData(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{}

	source, data := handler.getHighestProgressSource(conflictData)
	assert.Equal(t, "", source)
	assert.Nil(t, data)
}

func TestGetHighestProgressSource_NoPercentageField(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source: "koreader",
			Data:   map[string]interface{}{},
		},
	}

	source, data := handler.getHighestProgressSource(conflictData)
	assert.Equal(t, "", source)
	assert.Nil(t, data)
}

func TestGetHighestProgressSource_MixedPercentageTypes(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source: "koreader",
			Data: map[string]interface{}{
				"percentage": 0.60,
			},
		},
		"kobo": {
			Source: "kobo",
			Data: map[string]interface{}{
				"percentage": float64(0.80),
			},
		},
	}

	source, data := handler.getHighestProgressSource(conflictData)
	assert.Equal(t, "kobo", source)
	assert.Equal(t, float64(0.80), data["percentage"])
}

func TestGetHighestProgressSource_BothZero(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source: "koreader",
			Data: map[string]interface{}{
				"percentage": 0.0,
			},
		},
		"kobo": {
			Source: "kobo",
			Data: map[string]interface{}{
				"percentage": 0.0,
			},
		},
	}

	source, data := handler.getHighestProgressSource(conflictData)
	assert.NotEmpty(t, source)
	assert.NotNil(t, data)
	assert.Equal(t, 0.0, data["percentage"])
}

func TestGetHighestProgressSource_ThreeWayConflict(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source: "koreader",
			Data: map[string]interface{}{
				"percentage": 0.45,
			},
		},
		"kobo": {
			Source: "kobo",
			Data: map[string]interface{}{
				"percentage": 0.92,
			},
		},
		"web": {
			Source: "web",
			Data: map[string]interface{}{
				"percentage": 0.70,
			},
		},
	}

	source, data := handler.getHighestProgressSource(conflictData)
	assert.Equal(t, "kobo", source)
	assert.Equal(t, 0.92, data["percentage"])
}

func TestGetMostRecentSource_ThreeWayConflict(t *testing.T) {
	handler := &ConflictHandler{}

	conflictData := map[string]ConflictSourceData{
		"koreader": {
			Source:    "koreader",
			Timestamp: time.Date(2026, 1, 30, 20, 5, 0, 0, time.UTC),
			Data: map[string]interface{}{
				"percentage": 0.45,
			},
		},
		"kobo": {
			Source:    "kobo",
			Timestamp: time.Date(2026, 1, 30, 20, 20, 0, 0, time.UTC),
			Data: map[string]interface{}{
				"percentage": 0.92,
			},
		},
		"web": {
			Source:    "web",
			Timestamp: time.Date(2026, 1, 30, 20, 10, 0, 0, time.UTC),
			Data: map[string]interface{}{
				"percentage": 0.70,
			},
		},
	}

	source, data := handler.getMostRecentSource(conflictData)
	assert.Equal(t, "kobo", source)
	assert.Equal(t, 0.92, data["percentage"])
}
