package scenarios_service

import (
	"context"
	"testing"

	"evening_detective_server/internal/modules/storytelling"
)

// TestMapStoryPrefixesEvidence — улики получают полный URL (домен + имя),
// как картинки точек и аудио введения; префиксация идемпотентна, внешние
// URL не трогаются; file_type деривируется при пустом значении.
func TestMapStoryPrefixesEvidence(t *testing.T) {
	storyJSON := `{
		"introduction": {"text": "Вступление", "audio": "intro.mp3"},
		"places": [{
			"code": "p1",
			"name": "Место",
			"text": "Текст",
			"image": "place.png",
			"applications": [
				{"name": "Договор", "image": "contract.pdf"},
				{"name": "Фото", "image": "https://external.example.com/pic.jpg", "file_type": "image"}
			]
		}]
	}`

	story, err := mapStory(storyJSON, testDomain)
	if err != nil {
		t.Fatalf("mapStory: %v", err)
	}

	if story.Introduction.Audio != testDomain+"intro.mp3" {
		t.Errorf("Audio = %q, want %q", story.Introduction.Audio, testDomain+"intro.mp3")
	}
	place := story.Places[0]
	if place.Image != testDomain+"place.png" {
		t.Errorf("place.Image = %q, want %q", place.Image, testDomain+"place.png")
	}

	// Улика из хранилища: полный URL + деривированный file_type.
	app := place.Applications[0]
	if app.Image != testDomain+"contract.pdf" {
		t.Errorf("application.Image = %q, want %q", app.Image, testDomain+"contract.pdf")
	}
	if app.FileType != "pdf" {
		t.Errorf("application.FileType = %q, want pdf", app.FileType)
	}

	// Внешний URL не префиксуется, file_type сохраняется.
	external := place.Applications[1]
	if external.Image != "https://external.example.com/pic.jpg" {
		t.Errorf("external.Image = %q, want без изменений", external.Image)
	}
	if external.FileType != "image" {
		t.Errorf("external.FileType = %q, want image", external.FileType)
	}

	// Идемпотентность: повторный прогон не даёт двойного префикса.
	jsonOut, err := convertStory(story)
	if err != nil {
		t.Fatalf("convertStory: %v", err)
	}
	again, err := mapStory(jsonOut, testDomain)
	if err != nil {
		t.Fatalf("mapStory повторно: %v", err)
	}
	if again.Places[0].Applications[0].Image != testDomain+"contract.pdf" {
		t.Errorf("повторный mapStory: Image = %q, want %q", again.Places[0].Applications[0].Image, testDomain+"contract.pdf")
	}
}

// TestNormalizeFileType — невалидный file_type заменяется деривацией из
// расширения файла, известные значения сохраняются.
func TestNormalizeFileType(t *testing.T) {
	cases := []struct {
		fileType string
		image    string
		want     string
	}{
		{"banana", "http://domain/api/files/clue.pdf", "pdf"},
		{"banana", "clue", ""},
		{"", "clue.png", "image"},
		{"pdf", "clue.pdf", "pdf"},
		{"image", "clue.gif", "image"},
		{"audio", "clue.ogg", "audio"},
	}
	for _, c := range cases {
		if got := normalizeFileType(c.fileType, c.image); got != c.want {
			t.Errorf("normalizeFileType(%q, %q) = %q, want %q", c.fileType, c.image, got, c.want)
		}
	}
}

// TestNormalizeStoryBanana — файл-улика с невалидным file_type проходит
// normalizeStory и получает деривированный тип.
func TestNormalizeStoryBanana(t *testing.T) {
	story := &storytelling.Story{
		Places: []*storytelling.Place{
			{
				Code: "p1",
				Name: "Место",
				Applications: []*storytelling.Application{
					{Name: "Договор", Image: "clue.pdf", FileType: "banana"},
				},
			},
		},
	}

	jsonOut, err := normalizeStory(story)
	if err != nil {
		t.Fatalf("normalizeStory: %v", err)
	}

	parsed, err := mapStory(jsonOut, "")
	if err != nil {
		t.Fatalf("mapStory: %v", err)
	}
	if got := parsed.Places[0].Applications[0].FileType; got != "pdf" {
		t.Errorf("FileType = %q, want pdf", got)
	}
}

// TestUpdateStoryTrimsEvidenceDomain — сохранение истории снимает доменный
// префикс с улик (в БД хранятся относительные имена).
func TestUpdateStoryTrimsEvidenceDomain(t *testing.T) {
	repo := newFakeScenariosRepo()
	storage := newFakeStorage()
	svc := newTestService(repo, storage)

	// Сценарий с историей, где улика уже с доменным префиксом.
	scenario := seedScenario(t, repo, storage)
	scenario.Scenario = `{"places":[{"code":"p1","name":"Место","text":"","image":"place.png","applications":[{"name":"Договор","image":"http://storage.test/api/files/contract.pdf","file_type":"pdf"}]}]}`

	story := &storytelling.Story{
		Places: []*storytelling.Place{
			{
				Code:  "p1",
				Name:  "Место",
				Image: testDomain + "place.png",
				Text:  "Текст",
				Applications: []*storytelling.Application{
					{Name: "Договор", Image: testDomain + "contract.pdf", FileType: "pdf"},
				},
			},
		},
	}

	if err := svc.updateStory(context.Background(), scenario.ID, story); err != nil {
		t.Fatalf("updateStory: %v", err)
	}

	parsed, err := mapStory(scenario.Scenario, testDomain)
	if err != nil {
		t.Fatalf("mapStory: %v", err)
	}
	app := parsed.Places[0].Applications[0]
	if app.Image != testDomain+"contract.pdf" {
		t.Errorf("после trim+prefix Image = %q, want %q (без двойного префикса)", app.Image, testDomain+"contract.pdf")
	}
	if app.FileType != "pdf" {
		t.Errorf("FileType = %q, want pdf", app.FileType)
	}
}
