package main

import (
	"io"
	"net/http"
	"net/http/httptest"
	"regexp"
	"strings"
	"testing"
)

func TestRoutesServeSelfContainedV2Page(t *testing.T) {
	server, err := newDemoServer(demoConfig{
		GatewayBaseURL: "http://127.0.0.1:13000",
		AdminBaseURL:   "http://127.0.0.1:13100",
		WalletAddr:     "127.0.0.1:13004",
		LuckyGiftAddr:  "127.0.0.1:13013",
		AppCode:        "lalu",
		InitialCoins:   1_000_000,
	})
	if err != nil {
		t.Fatal(err)
	}
	defer server.Close()

	request := httptest.NewRequest(http.MethodGet, "/", nil)
	response := httptest.NewRecorder()
	server.Routes().ServeHTTP(response, request)
	if response.Code != http.StatusOK {
		t.Fatalf("status = %d, want %d", response.Code, http.StatusOK)
	}
	body, err := io.ReadAll(response.Result().Body)
	if err != nil {
		t.Fatal(err)
	}
	page := string(body)
	for _, required := range []string{
		`/api/v2/rooms/gift/send`,
		`/api/v1/activities/lucky-gifts/check`,
		`/__local/heartbeat`,
		`target_user_id`,
		`idempotent_replay`,
	} {
		if !strings.Contains(page, required) {
			t.Errorf("page does not contain %q", required)
		}
	}
	if strings.Contains(page, "admin123") {
		t.Fatal("page must never embed local administrator credentials")
	}
}

func TestFixtureEndpointsFailClosedBeforeSetup(t *testing.T) {
	server, err := newDemoServer(demoConfig{
		GatewayBaseURL: "http://127.0.0.1:13000",
		AdminBaseURL:   "http://127.0.0.1:13100",
		WalletAddr:     "127.0.0.1:13004",
		LuckyGiftAddr:  "127.0.0.1:13013",
		AppCode:        "lalu",
		InitialCoins:   1_000_000,
	})
	if err != nil {
		t.Fatal(err)
	}
	defer server.Close()

	for _, testCase := range []struct {
		method string
		path   string
	}{
		{method: http.MethodGet, path: "/__local/state"},
		{method: http.MethodPost, path: "/__local/heartbeat"},
	} {
		request := httptest.NewRequest(testCase.method, testCase.path, nil)
		response := httptest.NewRecorder()
		server.Routes().ServeHTTP(response, request)
		if response.Code != http.StatusConflict {
			t.Errorf("%s %s status = %d, want %d", testCase.method, testCase.path, response.Code, http.StatusConflict)
		}
	}
}

func TestCommandIDAndIntegerParsing(t *testing.T) {
	first := commandID("gift")
	second := commandID("gift")
	if first == second {
		t.Fatalf("command IDs must be unique: %q", first)
	}
	if !regexp.MustCompile(`^demo-gift-\d+-[0-9a-f]{12}$`).MatchString(first) {
		t.Fatalf("unexpected command ID: %q", first)
	}
	if value, err := parsePositiveInt64("9223372036854775807", "user_id"); err != nil || value <= 0 {
		t.Fatalf("parse max int64: value=%d err=%v", value, err)
	}
	for _, invalid := range []string{"", "0", "-1", "9007199254740992.0", "abc"} {
		if _, err := parsePositiveInt64(invalid, "user_id"); err == nil {
			t.Errorf("parsePositiveInt64(%q) unexpectedly succeeded", invalid)
		}
	}
}

func TestAdminCodeOK(t *testing.T) {
	for _, value := range []any{nil, float64(0), float64(200), "0", "200", "OK", "ok"} {
		if !adminCodeOK(value) {
			t.Errorf("adminCodeOK(%v) = false", value)
		}
	}
	for _, value := range []any{float64(500), "ERROR", true} {
		if adminCodeOK(value) {
			t.Errorf("adminCodeOK(%v) = true", value)
		}
	}
}
