package web

import (
	"encoding/json"
	"net/http/httptest"
	"path/filepath"
	"strconv"
	"strings"
	"testing"
	"time"

	"pete/internal/config"
	"pete/internal/storage"
)

// TestReaderCardDataAndArticleAPI exercises the reader-mode path end to end: a
// classified story renders a card carrying its id + headline data attributes,
// and /api/article returns the stored full text for that id.
func TestReaderCardDataAndArticleAPI(t *testing.T) {
	storage.Close()
	if err := storage.Init(filepath.Join(t.TempDir(), "reader.db")); err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { storage.Close() })

	story := &storage.Story{
		GUID:       "reader-e2e",
		Headline:   "A Distinctive Reader Headline",
		Lede:       "The lede.",
		Content:    "Opening paragraph of the piece.\n\nA second paragraph with more detail.",
		ArticleURL: "https://example.com/story",
		Source:     "Example Wire",
		Channel:    "tech",
		Classified: true,
		SeenAt:     time.Now().Unix(),
	}
	if err := storage.InsertStory(story); err != nil {
		t.Fatal(err)
	}
	var id int64
	if err := storage.Get().QueryRow(`SELECT id FROM stories WHERE guid = ?`, story.GUID).Scan(&id); err != nil {
		t.Fatal(err)
	}

	s, err := New(config.WebConfig{SiteTitle: "Pete", ListenAddr: ":0"}, nil, true, config.AdventureConfig{}, nil)
	if err != nil {
		t.Fatal(err)
	}

	// Index page renders the card with the reader data attributes.
	rw := httptest.NewRecorder()
	s.handleIndex(rw, httptest.NewRequest("GET", "/", nil))
	body := rw.Body.String()
	if rw.Code != 200 {
		t.Fatalf("index status = %d", rw.Code)
	}
	for _, want := range []string{
		`data-id="` + strconv.FormatInt(id, 10) + `"`,
		`data-headline="A Distinctive Reader Headline"`,
		`data-story-card`,
	} {
		if !strings.Contains(body, want) {
			t.Errorf("index HTML missing %q", want)
		}
	}

	// The article endpoint returns the stored content for that id.
	rw2 := httptest.NewRecorder()
	s.handleArticle(rw2, httptest.NewRequest("GET", "/api/article?id="+strconv.FormatInt(id, 10), nil))
	if rw2.Code != 200 {
		t.Fatalf("article status = %d body=%s", rw2.Code, rw2.Body.String())
	}
	var got struct {
		Content string `json:"content"`
		Lede    string `json:"lede"`
	}
	if err := json.Unmarshal(rw2.Body.Bytes(), &got); err != nil {
		t.Fatalf("decode: %v", err)
	}
	if got.Content != story.Content {
		t.Errorf("content = %q, want %q", got.Content, story.Content)
	}

	// A bad id is a 400, an unknown id is a 404.
	for _, tc := range []struct {
		q    string
		code int
	}{{"id=0", 400}, {"id=abc", 400}, {"id=999999", 404}} {
		w := httptest.NewRecorder()
		s.handleArticle(w, httptest.NewRequest("GET", "/api/article?"+tc.q, nil))
		if w.Code != tc.code {
			t.Errorf("article?%s status = %d, want %d", tc.q, w.Code, tc.code)
		}
	}
}
