package booking

import (
	"testing"
	"time"

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

func TestService_All(t *testing.T) {
	tests := []struct {
		name     string
		mockData []*Line
	}{
		{
			name:     "returns empty list when no bookings",
			mockData: []*Line{},
		},
		{
			name: "returns list of bookings",
			mockData: []*Line{
				{
					Id:           1,
					CustomerName: "John Doe",
					From:         time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
					To:           time.Date(2024, 1, 5, 0, 0, 0, 0, time.UTC),
					Platform:     "Airbnb",
					Total:        500.0,
					Canceled:     false,
				},
				{
					Id:           2,
					CustomerName: "Jane Smith",
					From:         time.Date(2024, 2, 1, 0, 0, 0, 0, time.UTC),
					To:           time.Date(2024, 2, 3, 0, 0, 0, 0, time.UTC),
					Platform:     "Booking.com",
					Total:        300.0,
					Canceled:     true,
				},
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Create mocks
			mockStore := new(MockStore)
			mockCalendar := new(MockCalendarClient)
			mockPDF := new(MockPDFClient)

			// Set up expectations
			mockStore.On("All").Return(tt.mockData)

			// Create service with mocks
			service, err := NewService(mockStore, nil, mockCalendar, mockPDF)
			assert.NoError(t, err)

			// Call the method
			result := service.All()

			// Assert expectations
			assert.Equal(t, tt.mockData, result)
			mockStore.AssertExpectations(t)
		})
	}
}

func TestService_Search(t *testing.T) {
	sampleBookings := []*Line{
		{
			Id:           1,
			CustomerName: "John Doe",
			From:         time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
			To:           time.Date(2024, 1, 5, 0, 0, 0, 0, time.UTC),
			Platform:     "Airbnb",
			Total:        500.0,
			Canceled:     false,
		},
		{
			Id:           2,
			CustomerName: "Jane Smith",
			From:         time.Date(2024, 2, 1, 0, 0, 0, 0, time.UTC),
			To:           time.Date(2024, 2, 3, 0, 0, 0, 0, time.UTC),
			Platform:     "Booking.com",
			Total:        300.0,
			Canceled:     true,
		},
	}

	tests := []struct {
		name           string
		searchQuery    string
		expectedLines  []*Line
		expectedCalled bool
	}{
		{
			name:           "empty search query returns no results",
			searchQuery:    "",
			expectedLines:  []*Line{},
			expectedCalled: false,
		},
		{
			name:        "search for 'John' returns matching booking",
			searchQuery: "John",
			expectedLines: []*Line{
				sampleBookings[0],
			},
			expectedCalled: true,
		},
		{
			name:        "search for 'Smith' returns matching booking",
			searchQuery: "Smith",
			expectedLines: []*Line{
				sampleBookings[1],
			},
			expectedCalled: true,
		},
		{
			name:           "search for non-existent name returns empty list",
			searchQuery:    "NonExistent",
			expectedLines:  []*Line{},
			expectedCalled: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Create mocks
			mockStore := new(MockStore)
			mockCalendar := new(MockCalendarClient)
			mockPDF := new(MockPDFClient)

			// Set up expectations
			mockStore.On("Search", tt.searchQuery).Return(tt.expectedLines)

			// Create service with mocks
			service, err := NewService(mockStore, nil, mockCalendar, mockPDF)
			assert.NoError(t, err)

			// Call the method
			result := service.Search(tt.searchQuery)

			// Assert expectations
			assert.Equal(t, tt.expectedLines, result)
			mockStore.AssertExpectations(t)
		})
	}
}
