package promobot

import (
	"context"
	"io"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/go-telegram/bot/models"
	"go.uber.org/zap"
)

func TestPromoTextLocalization(t *testing.T) {
	const url = "https://telegram.me/bot/app?startapp=verudit_ru-scrabble_en"
	// The @username is rendered as a clickable deep link (the same target as the button),
	// not a plain mention, so tapping it opens the seeded Mini App.
	wantLink := `<a href="` + url + `">@ScrabbleBot</a>`

	en, enBtn := promoText("en", "ScrabbleBot", url)
	if !strings.Contains(en, wantLink) || !strings.Contains(en, "profile settings") {
		t.Errorf("en text = %q", en)
	}
	if enBtn != "🤩 I want to play!" {
		t.Errorf("en button = %q", enBtn)
	}

	ru, ruBtn := promoText("ru-RU", "ScrabbleBot", url)
	if !strings.Contains(ru, wantLink) || !strings.Contains(ru, "Откройте") {
		t.Errorf("ru text = %q", ru)
	}
	if ruBtn != "🤩 Хочу играть!" {
		t.Errorf("ru button = %q", ruBtn)
	}

	// An unknown language falls back to English, still with the linked mention.
	if got, _ := promoText("de", "B", url); !strings.Contains(got, "Open ") || !strings.Contains(got, `">@B</a>`) {
		t.Errorf("fallback text = %q, want English with a linked mention", got)
	}
}

func TestLaunchURLAppendsStartapp(t *testing.T) {
	b := &Bot{linkURL: "https://telegram.me/bot/app"}
	if got := b.launchURL(""); got != "https://telegram.me/bot/app" {
		t.Errorf("empty payload = %q, want the base link unchanged", got)
	}
	if got := b.launchURL("g123"); got != "https://telegram.me/bot/app?startapp=g123" {
		t.Errorf("launchURL = %q, want startapp=g123 appended", got)
	}
}

func TestLaunchMarkupIsURLButton(t *testing.T) {
	b := &Bot{linkURL: "https://telegram.me/bot/app"}
	btn := b.launchMarkup("Play", "f99").InlineKeyboard[0][0]
	if btn.WebApp != nil {
		t.Error("the promo button must not be a web_app button (it would sign initData with the promo token, which the main bot rejects)")
	}
	if !strings.Contains(btn.URL, "startapp=f99") {
		t.Errorf("button URL = %q, want startapp=f99", btn.URL)
	}
}

// fakeAPI answers getMe (so New succeeds offline) and records the last sendMessage.
type fakeAPI struct {
	chatID, text, replyMarkup string
}

func (f *fakeAPI) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch {
	case strings.HasSuffix(r.URL.Path, "/getMe"):
		io.WriteString(w, `{"ok":true,"result":{"id":1,"is_bot":true,"first_name":"t","username":"promo"}}`)
	case strings.HasSuffix(r.URL.Path, "/sendMessage"):
		f.chatID = r.FormValue("chat_id")
		f.text = r.FormValue("text")
		f.replyMarkup = r.FormValue("reply_markup")
		io.WriteString(w, `{"ok":true,"result":{"message_id":1}}`)
	default:
		io.WriteString(w, `{"ok":true,"result":true}`)
	}
}

func TestHandleStartReplies(t *testing.T) {
	api := &fakeAPI{}
	srv := httptest.NewServer(api)
	t.Cleanup(srv.Close)
	b, err := New(Config{Token: "1:2", APIBaseURL: srv.URL, BotUsername: "ScrabbleBot", BotLinkURL: "https://telegram.me/bot/app"}, zap.NewNop())
	if err != nil {
		t.Fatalf("new: %v", err)
	}

	b.handleStart(context.Background(), b.api, &models.Update{Message: &models.Message{
		Chat: models.Chat{ID: 42, Type: models.ChatTypePrivate},
		From: &models.User{LanguageCode: "ru"},
		Text: "/start f99",
	}})

	if api.chatID != "42" {
		t.Errorf("chat_id = %q, want 42", api.chatID)
	}
	if !strings.Contains(api.text, `<a href="https://telegram.me/bot/app?startapp=f99">@ScrabbleBot</a>`) {
		t.Errorf("text = %q, want the @mention linked to the startapp deep link", api.text)
	}
	if strings.Contains(api.replyMarkup, "web_app") {
		t.Errorf("reply_markup = %q has a web_app button; want a url button", api.replyMarkup)
	}
	if !strings.Contains(api.replyMarkup, "startapp=f99") {
		t.Errorf("reply_markup = %q, want startapp=f99 (the /start payload forwarded)", api.replyMarkup)
	}
}

func TestHandleStartIgnoresGroup(t *testing.T) {
	api := &fakeAPI{}
	srv := httptest.NewServer(api)
	t.Cleanup(srv.Close)
	b, err := New(Config{Token: "1:2", APIBaseURL: srv.URL, BotUsername: "B", BotLinkURL: "https://telegram.me/b/a"}, zap.NewNop())
	if err != nil {
		t.Fatalf("new: %v", err)
	}
	b.handleStart(context.Background(), b.api, &models.Update{Message: &models.Message{
		Chat: models.Chat{ID: -100, Type: models.ChatTypeSupergroup}, Text: "/start",
	}})
	if api.chatID != "" {
		t.Errorf("replied to a group message (chat=%q); want none", api.chatID)
	}
}
