package services

import (
	"testing"

	"github.com/google/uuid"
)

// TestBookMatchingService_QueryBooks tests the book query functionality
func TestBookMatchingService_QueryBooks(t *testing.T) {
	// This is a placeholder test that would need a mock database
	// For now, we'll test the matching priority logic structure

	t.Run("Priority 1: Bookhoard UUID match", func(t *testing.T) {
		// Test that UUID matching returns highest confidence
		req := &BookQueryRequest{
			Identifiers: []string{"uuid:550e8400-e29b-41d4-a716-446655440000"},
		}

		// Would need mock DB to test actual matching
		_ = req
		t.Log("UUID matching test placeholder - requires mock database")
	})

	t.Run("Priority 2: OPF UUID match", func(t *testing.T) {
		req := &BookQueryRequest{
			Identifiers: []string{"opf_uuid:550e8400-e29b-41d4-a716-446655440000"},
		}

		_ = req
		t.Log("OPF UUID matching test placeholder - requires mock database")
	})

	t.Run("Priority 3: SHA-256 match", func(t *testing.T) {
		req := &BookQueryRequest{
			SHA256: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
		}

		_ = req
		t.Log("SHA-256 matching test placeholder - requires mock database")
	})

	t.Run("Priority 7: Title + author + size match", func(t *testing.T) {
		req := &BookQueryRequest{
			Title:    "Test Book",
			Author:   "Test Author",
			FileSize: 1024000,
		}

		_ = req
		t.Log("Title+author+size matching test placeholder - requires mock database")
	})
}

// TestBookMatch_ConfidenceLevels tests confidence scoring
func TestBookMatch_ConfidenceLevels(t *testing.T) {
	tests := []struct {
		name       string
		match      BookMatch
		confidence float64
		method     string
	}{
		{
			name: "UUID match - highest confidence",
			match: BookMatch{
				Confidence:  1.0,
				MatchMethod: "uuid_match",
			},
			confidence: 1.0,
			method:     "uuid_match",
		},
		{
			name: "SHA-256 match - high confidence",
			match: BookMatch{
				Confidence:  0.9,
				MatchMethod: "sha256_match",
			},
			confidence: 0.9,
			method:     "sha256_match",
		},
		{
			name: "ISBN match - medium confidence",
			match: BookMatch{
				Confidence:  0.8,
				MatchMethod: "isbn_match",
			},
			confidence: 0.8,
			method:     "isbn_match",
		},
		{
			name: "Title+author+size match - lower confidence",
			match: BookMatch{
				Confidence:  0.5,
				MatchMethod: "title_author_size_match",
			},
			confidence: 0.5,
			method:     "title_author_size_match",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if tt.match.Confidence != tt.confidence {
				t.Errorf("Expected confidence %f, got %f", tt.confidence, tt.match.Confidence)
			}

			if tt.match.MatchMethod != tt.method {
				t.Errorf("Expected method %s, got %s", tt.method, tt.match.MatchMethod)
			}
		})
	}
}

// TestBookQueryResponse_ActionDetermination tests action logic
func TestBookQueryResponse_ActionDetermination(t *testing.T) {
	tests := []struct {
		name     string
		response BookQueryResponse
		action   string
	}{
		{
			name: "No matches",
			response: BookQueryResponse{
				Matches: []BookMatch{},
			},
			action: "no_match",
		},
		{
			name: "Single high-confidence match",
			response: BookQueryResponse{
				Matches: []BookMatch{
					{Confidence: 0.9, MatchMethod: "sha256_match"},
				},
			},
			action: "auto_link",
		},
		{
			name: "Single low-confidence match",
			response: BookQueryResponse{
				Matches: []BookMatch{
					{Confidence: 0.5, MatchMethod: "title_author_size_match"},
				},
			},
			action: "multiple_matches",
		},
		{
			name: "Multiple matches",
			response: BookQueryResponse{
				Matches: []BookMatch{
					{Confidence: 0.8, MatchMethod: "isbn_match"},
					{Confidence: 0.5, MatchMethod: "title_match"},
				},
			},
			action: "multiple_matches",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Determine action
			var action string
			if len(tt.response.Matches) == 0 {
				action = "no_match"
			} else if len(tt.response.Matches) == 1 && tt.response.Matches[0].Confidence > 0.7 {
				action = "auto_link"
			} else {
				action = "multiple_matches"
			}

			if action != tt.action {
				t.Errorf("Expected action %s, got %s", tt.action, action)
			}
		})
	}
}

// TestDetermineAction tests the action determination logic
func TestDetermineAction(t *testing.T) {
	tests := []struct {
		name     string
		matches  []BookMatch
		expected string
	}{
		{
			name:     "No matches",
			matches:  []BookMatch{},
			expected: "no_match",
		},
		{
			name: "Single high-confidence match",
			matches: []BookMatch{
				{Confidence: 0.9, MatchMethod: "sha256_match"},
			},
			expected: "auto_link",
		},
		{
			name: "Single low-confidence match",
			matches: []BookMatch{
				{Confidence: 0.5, MatchMethod: "title_match"},
			},
			expected: "multiple_matches",
		},
		{
			name: "Multiple matches",
			matches: []BookMatch{
				{Confidence: 0.8, MatchMethod: "isbn_match"},
				{Confidence: 0.7, MatchMethod: "asin_match"},
			},
			expected: "multiple_matches",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			service := &BookMatchingService{}
			result := service.determineAction(tt.matches)
			if result != tt.expected {
				t.Errorf("Expected action %s, got %s", tt.expected, result)
			}
		})
	}
}

// TestBookQueryRequest_Validation tests request validation
func TestBookQueryRequest_Validation(t *testing.T) {
	tests := []struct {
		name   string
		req    BookQueryRequest
		valid  bool
		reason string
	}{
		{
			name: "Valid UUID identifier",
			req: BookQueryRequest{
				Identifiers: []string{"uuid:550e8400-e29b-41d4-a716-446655440000"},
			},
			valid:  true,
			reason: "",
		},
		{
			name: "Valid ISBN identifier",
			req: BookQueryRequest{
				Identifiers: []string{"isbn:9783161484100"},
			},
			valid:  true,
			reason: "",
		},
		{
			name: "Valid SHA-256",
			req: BookQueryRequest{
				SHA256: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
			},
			valid:  true,
			reason: "",
		},
		{
			name: "Valid title+author+size",
			req: BookQueryRequest{
				Title:    "Test Book",
				Author:   "Test Author",
				FileSize: 1024000,
			},
			valid:  true,
			reason: "",
		},
		{
			name:   "Empty request",
			req:    BookQueryRequest{},
			valid:  false,
			reason: "No identifiers provided",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Basic validation logic
			valid := len(tt.req.Identifiers) > 0 ||
				tt.req.SHA256 != "" ||
				(tt.req.Title != "" && tt.req.Author != "")

			if valid != tt.valid {
				t.Errorf("Expected valid=%v, got valid=%v. Reason: %s", tt.valid, valid, tt.reason)
			}
		})
	}
}

// TestLinkBookRequest_Validation tests linking request validation
func TestLinkBookRequest_Validation(t *testing.T) {
	tests := []struct {
		name   string
		req    LinkBookRequest
		valid  bool
		reason string
	}{
		{
			name: "Valid link request",
			req: LinkBookRequest{
				MediaItemID:     uuid.New(),
				ConfidenceScore: 1.0,
				DeviceFile: struct {
					FilePath string `json:"file_path"`
					SHA256   string `json:"sha256"`
					Title    string `json:"title"`
				}{
					FilePath: "/path/to/book.epub",
					SHA256:   "abc123",
					Title:    "Test Book",
				},
			},
			valid:  true,
			reason: "",
		},
		{
			name: "Missing media item ID",
			req: LinkBookRequest{
				ConfidenceScore: 1.0,
			},
			valid:  false,
			reason: "MediaItemID is required",
		},
		{
			name: "Invalid confidence score",
			req: LinkBookRequest{
				MediaItemID:     uuid.New(),
				ConfidenceScore: 2.0, // Invalid, should be 0-1
			},
			valid:  false,
			reason: "Confidence score must be between 0 and 1",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Check if MediaItemID is valid
			valid := tt.req.MediaItemID != uuid.Nil &&
				tt.req.ConfidenceScore >= 0 &&
				tt.req.ConfidenceScore <= 1

			if valid != tt.valid {
				t.Errorf("Expected valid=%v, got valid=%v. Reason: %s", tt.valid, valid, tt.reason)
			}
		})
	}
}

// Example usage
func ExampleBookMatchingService_QueryBooks() {
	service := NewBookMatchingService(nil) // Would need real DB

	req := &BookQueryRequest{
		Identifiers: []string{
			"uuid:550e8400-e29b-41d4-a716-446655440000",
			"isbn:9783161484100",
		},
		SHA256:   "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
		Title:    "Test Book",
		Author:   "Test Author",
		FileSize: 1024000,
	}

	_ = service
	_ = req
	// response, err := service.QueryBooks(context.Background(), req)
	// fmt.Printf("Matches: %d, Action: %s\n", len(response.Matches), response.Action)
}
