package storytelling

import (
	"evening_detective_server/internal/modules/cleaner"
	"testing"

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

func Test_story_GetStory(t *testing.T) {
	tests := []struct {
		name     string
		scenario *Story
		codes    []string
		want     *Story
	}{
		{
			name:     "Попытка получить несуществующую точку",
			scenario: &Story{},
			codes:    []string{"Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Не найдено",
						Text: "Такой точки не существует.",
					},
				},
			},
		},
		{
			name: "Введение передаётся в начале игры (без действий)",
			scenario: &Story{
				Introduction: &Introduction{
					Text:  "Текст введения.([Ы])",
					Audio: "intro.mp3",
				},
			},
			codes: []string{},
			want: &Story{
				Introduction: &Introduction{
					Text:  "Текст введения.",
					Audio: "intro.mp3",
				},
			},
		},
		{
			name: "Введение передаётся вместе с точками",
			scenario: &Story{
				Introduction: &Introduction{
					Text:  "Текст введения.",
					Audio: "intro.mp3",
				},
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
			codes: []string{"Ы"},
			want: &Story{
				Introduction: &Introduction{
					Text:  "Текст введения.",
					Audio: "intro.mp3",
				},
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
		},
		{
			name: "Получение точки",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
			codes: []string{"Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
		},
		{
			name: "Получение точки проверка регистра",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы-1",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
			codes: []string{"ы1"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы-1",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
		},
		{
			name: "Получение точки проверка очистки ссылок",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы-1",
						Name: "Название точки",
						Text: "Текст точки.([Ы-2])",
					},
				},
			},
			codes: []string{"Ы-1"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы-1",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
		},
		{
			name: "Получение 2 точек",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки Ы",
						Text: "Текст точки Ы.",
					},
					{
						Code: "Д",
						Name: "Название точки Д",
						Text: "Текст точки Д.",
					},
				},
			},
			codes: []string{"Ы", "Д"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки Ы",
						Text: "Текст точки Ы.",
					},
					{
						Code: "Д",
						Name: "Название точки Д",
						Text: "Текст точки Д.",
					},
				},
			},
		},
		{
			name: "Получение точки с картинкой",
			scenario: &Story{
				Places: []*Place{
					{
						Code:  "Ы",
						Name:  "Название точки",
						Text:  "Текст точки.",
						Image: "image.png",
					},
				},
			},
			codes: []string{"Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code:  "Ы",
						Name:  "Название точки",
						Text:  "Текст точки.",
						Image: "image.png",
					},
				},
			},
		},
		{
			name: "Попытка получить скрытую точку",
			scenario: &Story{
				Places: []*Place{
					{
						Code:   "Ы",
						Name:   "Название точки",
						Text:   "Текст точки.",
						Hidden: true,
					},
				},
			},
			codes: []string{"Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Не найдено",
						Text: "Такой точки не существует.",
					},
				},
			},
		},
		{
			name: "Получение точки с уликой",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Applications: []*Application{
							{
								Name:     "Название улики",
								Image:    "image.png",
								FileType: "image",
							},
						},
					},
				},
			},
			codes: []string{"Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Applications: []*Application{
							{
								Name:     "Название улики",
								Image:    "image.png",
								FileType: "image",
							},
						},
					},
				},
			},
		},
		{
			name: "Улики не повторяются",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Applications: []*Application{
							{
								Name:  "Название улики",
								Image: "image.png",
							},
						},
					},
				},
			},
			codes: []string{"Ы", "Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Applications: []*Application{
							{
								Name:  "Название улики",
								Image: "image.png",
							},
						},
					},
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
		},
		{
			name: "Получение точки с действием",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Ы-1",
								Name: "Действие 1",
							},
						},
					},
				},
			},
			codes: []string{"Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Ы-1",
								Name: "Действие 1",
							},
						},
					},
				},
			},
		},
		{
			name: "Не открываем скрытую точку действием",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Ы-1",
								Name: "Действие 1",
							},
						},
					},
					{
						Code: "Д",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
			codes: []string{"Ы", "Д"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Д",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
		},
		{
			name: "Открываем скрытую точку действием",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Ы-1",
								Name: "Действие 1",
							},
						},
					},
					{
						Code:   "Ы-1",
						Name:   "Название точки",
						Text:   "Текст точки.",
						Hidden: true,
					},
				},
			},
			codes: []string{"Ы", "Ы-1"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Ы-1",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
		},
		{
			name: "Не открываем скрытую точку действием, а потом возвращаемся",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Ы-1",
								Name: "Действие 1",
							},
						},
					},
					{
						Code: "Д",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
			codes: []string{"Ы", "Д", "Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Д",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Ы-1",
								Name: "Действие 1",
							},
						},
					},
				},
			},
		},
		{
			name: "Открываем скрытую точку действием, а потом возвращаемся",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Ы-1",
								Name: "Действие 1",
							},
						},
					},
					{
						Code:   "Ы-1",
						Name:   "Название точки",
						Text:   "Текст точки.",
						Hidden: true,
					},
				},
			},
			codes: []string{"Ы", "Ы-1", "Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Ы-1",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
		},
		{
			name: "Получение точки со скрытым действием",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Ы-1",
								Name: "Действие 1",
								Keys: []*Key{
									{
										Name: "ключ",
									},
								},
							},
						},
					},
				},
			},
			codes: []string{"Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
		},
		{
			name: "Получение точки с ключом",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Keys: []*Key{
							{
								Name: "ключ",
							},
						},
					},
				},
			},
			codes: []string{"Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
		},
		{
			name: "Получение ключа и открытие скрытого действия",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Keys: []*Key{
							{
								Name: "ключ",
							},
						},
					},
					{
						Code: "Д",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Ы-1",
								Name: "Действие 1",
								Keys: []*Key{
									{
										Name: "ключ",
									},
								},
							},
						},
					},
				},
			},
			codes: []string{"Ы", "Д"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Д",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Ы-1",
								Name: "Действие 1",
							},
						},
					},
				},
			},
		},
		{
			name: "После выбора одного из действий остальные не доступны",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Ы-1",
								Name: "Действие 1",
							},
							{
								Code: "Ы-2",
								Name: "Действие 1",
							},
						},
					},
					{
						Code:   "Ы-1",
						Name:   "Название точки",
						Text:   "Текст точки.",
						Hidden: true,
					},
					{
						Code:   "Ы-2",
						Name:   "Название точки",
						Text:   "Текст точки.",
						Hidden: true,
					},
				},
			},
			codes: []string{"Ы", "Ы-1", "Ы-2", "Ы", "Ы-2"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Ы-1",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Ы-2",
						Name: "Не найдено",
						Text: "Такой точки не существует.",
					},
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Ы-2",
						Name: "Не найдено",
						Text: "Такой точки не существует.",
					},
				},
			},
		},
		{
			name: "Если ключей не хватает то скрытые двери не видим",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы-1",
						Name: "Название точки",
						Text: "Текст точки.",
						Keys: []*Key{
							{
								Name: "ключ 1",
							},
						},
					},
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Д",
								Name: "Действие",
								Keys: []*Key{
									{
										Name: "ключ 1",
									},
									{
										Name: "ключ 2",
									},
								},
							},
						},
					},
				},
			},
			codes: []string{"Ы-1", "Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы-1",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
					},
				},
			},
		},
		{
			name: "Собираем ключи и видим скрытые двери",
			scenario: &Story{
				Places: []*Place{
					{
						Code: "Ы-1",
						Name: "Название точки",
						Text: "Текст точки.",
						Keys: []*Key{
							{
								Name: "ключ 1",
							},
						},
					},
					{
						Code: "Ы-2",
						Name: "Название точки",
						Text: "Текст точки.",
						Keys: []*Key{
							{
								Name: "ключ 2",
							},
						},
					},
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Д",
								Name: "Действие",
								Keys: []*Key{
									{
										Name: "ключ 1",
									},
									{
										Name: "ключ 2",
									},
								},
							},
						},
					},
				},
			},
			codes: []string{"Ы-1", "Ы-2", "Ы"},
			want: &Story{
				Places: []*Place{
					{
						Code: "Ы-1",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Ы-2",
						Name: "Название точки",
						Text: "Текст точки.",
					},
					{
						Code: "Ы",
						Name: "Название точки",
						Text: "Текст точки.",
						Doors: []*Door{
							{
								Code: "Д",
								Name: "Действие",
							},
						},
					},
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := NewStory(cleaner.NewCleaner()).GetStory(tt.scenario, tt.codes)
			assert.Equal(t, got, tt.want)
		})
	}
}
