package pipeline

import (
	"fmt"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"textmachine/backend/internal/obs"
)

// runner_pairpack_test.go is the end-to-end proof of the pair-keyed prompt seam (D39 слой 2): a book
// whose LangPair() is NOT in a stage's pair pack FAILS LOUD at loadTemplates (closing the latent bug
// where a ja book rode the zh-parataxis prompt), while a book of the populated pair resolves cleanly.

// setupPairPackProject writes a minimal project whose stages use a pair-keyed `prompts` pack carrying
// ONLY zh-ru, with the book's source_lang set to srcLang. Returns the book.yaml path.
func setupPairPackProject(t *testing.T, srcLang string) string {
	t.Helper()
	dir := t.TempDir()
	writeFile(t, filepath.Join(dir, "prompts", "translator.md"), "Переводи.\n---USER---\n{{text}}")
	writeFile(t, filepath.Join(dir, "prompts", "editor.md"), "Редактируй.\n---USER---\n{{text}}\n{{draft}}")
	writeFile(t, filepath.Join(dir, "models.yaml"), fmt.Sprintf(`
prices_checked: %q
default_model: fake-model
providers:
  fake: { kind: openai, base_url: http://127.0.0.1:0 }
models:
  fake-model: { provider: fake, price: { input_per_m: 1.0, output_per_m: 2.0 } }
`, time.Now().UTC().Format("2006-01-02")))
	// Pair-keyed pack — ONLY zh-ru is populated.
	writeFile(t, filepath.Join(dir, "pipeline.yaml"), `
core: C1
version: 1
defaults: { max_output_ratio: 2.0, min_max_tokens: 512 }
stages:
  - name: draft
    role: translator
    model: fake-model
    prompts: { zh-ru: prompts/translator.md }
    prompt_version: v-test
    reasoning: "off"
  - name: edit
    role: editor
    model: fake-model
    prompts: { zh-ru: prompts/editor.md }
    prompt_version: v-test
    reasoning: "off"
`)
	writeFile(t, filepath.Join(dir, "source.txt"), "四代族长 вошёл в зал.")
	writeFile(t, filepath.Join(dir, "book.yaml"), fmt.Sprintf(`
book_id: pairpack
title: Тест
source_lang: %s
target_lang: ru
genre: ранобэ
audience: тест
venuti: 0.5
honorifics: keep
transcription: polivanov
pipeline: pipeline.yaml
models: models.yaml
source_file: source.txt
ceilings: { book_usd: 1.0, day_usd: 2.0 }
`, srcLang))
	return filepath.Join(dir, "book.yaml")
}

func TestPairPackJaBookFailsLoud(t *testing.T) {
	// A ja→ru book against a zh-ru-only pack must STOP at loadTemplates, not silently run zh prompts.
	_, err := NewRunner(setupPairPackProject(t, "ja"), obs.NewLogger())
	if err == nil {
		t.Fatal("a ja book against a zh-ru-only prompt pack must fail loud (D39 слой 2)")
	}
	if !strings.Contains(err.Error(), "ja-ru") {
		t.Errorf("fail-loud error must name the missing pair ja-ru, got: %v", err)
	}
}

func TestPairPackZhBookResolves(t *testing.T) {
	// A zh→ru book of the populated pair resolves the pack cleanly (prod path, behaviour-neutral).
	r, err := NewRunner(setupPairPackProject(t, "zh"), obs.NewLogger())
	if err != nil {
		t.Fatalf("a zh book must resolve the zh-ru pack: %v", err)
	}
	defer r.Close()
	if len(r.templates) != 2 {
		t.Errorf("expected both stage templates loaded, got %d", len(r.templates))
	}
}
