package app

import (
	"context"
	"testing"
	"time"

	"hyapp/pkg/appcode"
	"hyapp/pkg/walletmq"
	messageservice "hyapp/services/activity-service/internal/service/message"
	"hyapp/services/activity-service/internal/testutil/mysqltest"
)

func TestVIPRebateAvailableEventFromWalletMessage(t *testing.T) {
	body := vipRebateWalletMessage(t, "VipDailyCoinRebateAvailable", 42, `{
        "rebate_id":"viprebate_fami_2027-01-15_42",
        "user_id":42,
        "task_day":"2027-01-15",
        "vip_level":9,
        "vip_name":"VIP9",
        "coin_amount":100000,
        "available_at_ms":1800000000000,
        "expires_at_ms":1800086400000,
        "config_version":7,
        "created_at_ms":1800000000100
    }`)
	event, ok, err := vipRebateAvailableEventFromWalletMessage(body)
	if err != nil || !ok {
		t.Fatalf("parse VIP rebate event failed: ok=%v event=%+v err=%v", ok, event, err)
	}
	if event.AppCode != "fami" || event.EventID != "wev-vip-rebate" || event.RebateID != "viprebate_fami_2027-01-15_42" || event.UserID != 42 || event.TaskDay != "2027-01-15" || event.VIPLevel != 9 || event.CoinAmount != 100000 || event.ExpiresAtMS != 1800086400000 || event.ConfigVersion != 7 {
		t.Fatalf("VIP rebate event mismatch: %+v", event)
	}
}

func TestVIPRebateWalletEventSkipsOtherFactsAndRejectsCorruptTarget(t *testing.T) {
	other := vipRebateWalletMessage(t, "WalletRechargeRecorded", 42, `{}`)
	if event, ok, err := vipRebateAvailableEventFromWalletMessage(other); err != nil || ok || event.EventID != "" {
		t.Fatalf("non-target event should be acknowledged: ok=%v event=%+v err=%v", ok, event, err)
	}
	corrupt := vipRebateWalletMessage(t, "VipDailyCoinRebateAvailable", 42, `{"rebate_id":"r1","user_id":99}`)
	if _, ok, err := vipRebateAvailableEventFromWalletMessage(corrupt); err == nil || ok {
		t.Fatalf("corrupt target event must fail for MQ retry: ok=%v err=%v", ok, err)
	}
}

func TestVIPRebateWalletEventCreatesOneIdempotentSystemNotice(t *testing.T) {
	ctx := appcode.WithContext(context.Background(), "fami")
	repository := mysqltest.NewRepository(t)
	service := messageservice.New(messageservice.Config{NodeID: "activity-test"}, repository)
	service.SetClock(func() time.Time { return time.UnixMilli(1800000000200) })
	event := vipRebateAvailableEvent{
		AppCode: "fami", EventID: "wev-vip-rebate", RebateID: "viprebate_fami_2027-01-15_42",
		UserID: 42, TaskDay: "2027-01-15", VIPLevel: 9, VIPName: "VIP9", CoinAmount: 100000,
		AvailableAtMS: 1800000000000, ExpiresAtMS: 1800086400000, ConfigVersion: 7, CreatedAtMS: 1800000000100,
	}
	if err := createVIPRebateSystemNotice(ctx, service, event); err != nil {
		t.Fatalf("create system notice failed: %v", err)
	}
	if err := createVIPRebateSystemNotice(ctx, service, event); err != nil {
		t.Fatalf("duplicate system notice should be idempotent: %v", err)
	}
	items, _, err := service.ListInboxMessages(ctx, 42, "system", 20, "")
	if err != nil || len(items) != 1 {
		t.Fatalf("system inbox mismatch: items=%+v err=%v", items, err)
	}
	item := items[0]
	wantSummary := "Your daily VIP cashback of 100000 coins is ready. Claim it before it expires."
	if item.Title != "VIP Coin Cashback" || item.Summary != wantSummary || item.Body != wantSummary || item.TemplateVersion != "v2" || item.AggregateID != event.RebateID || item.ExpireAtMS != event.ExpiresAtMS || len(item.Actions) != 1 {
		t.Fatalf("VIP rebate notice mismatch: %+v", item)
	}
	action := item.Actions[0]
	if action.Action != "claim" || action.Label != "Claim" || action.Style != "primary" || action.API.Method != "POST" || action.API.Path != "/api/v1/vip/coin-rebates/viprebate_fami_2027-01-15_42/claim" || action.API.Body == nil {
		t.Fatalf("VIP rebate action mismatch: %+v", action)
	}

	// 当天部署前已经落库的 v1 中文消息仍在有效窗口内；列表读取必须立即投影为同一英文文案。
	legacyActionParam := `{"coin_amount":88,"rebate_id":"viprebate_fami_2027-01-15_43"}`
	if _, err := service.CreateSystemNotice(ctx, messageservice.NoticeCommand{
		TargetUserID: 43, Producer: "wallet-service", ProducerEventID: "wev-vip-rebate-legacy",
		TemplateID: "vip_daily_coin_rebate_available", TemplateVersion: "v1",
		Title: "VIP金币返现", Summary: "尊敬的VIP用户，平台今日返现88金币，请及时领取。",
		Body: "尊敬的VIP用户，平台今日返现88金币，请及时领取。", ActionType: "vip_coin_rebate_claim",
		ActionParam: legacyActionParam, SentAtMS: event.AvailableAtMS, ExpireAtMS: event.ExpiresAtMS,
	}); err != nil {
		t.Fatalf("create legacy system notice failed: %v", err)
	}
	legacyItems, _, err := service.ListInboxMessages(ctx, 43, "system", 20, "")
	if err != nil || len(legacyItems) != 1 || legacyItems[0].Title != "VIP Coin Cashback" || legacyItems[0].Summary != "Your daily VIP cashback of 88 coins is ready. Claim it before it expires." || legacyItems[0].Body != legacyItems[0].Summary || legacyItems[0].ActionType != "" || len(legacyItems[0].Actions) != 1 || legacyItems[0].Actions[0].Label != "Claim" {
		t.Fatalf("legacy VIP rebate notice must return English copy: items=%+v err=%v", legacyItems, err)
	}
}

func vipRebateWalletMessage(t *testing.T, eventType string, userID int64, payload string) []byte {
	t.Helper()
	body, err := walletmq.EncodeWalletOutboxMessage(walletmq.WalletOutboxMessage{
		AppCode:       "fami",
		EventID:       "wev-vip-rebate",
		EventType:     eventType,
		TransactionID: "viprebate_fami_2027-01-15_42",
		CommandID:     "vip-rebate-generate:fami:2027-01-15:42",
		UserID:        userID,
		AssetType:     "COIN",
		PayloadJSON:   payload,
		OccurredAtMS:  1800000000100,
	})
	if err != nil {
		t.Fatalf("encode wallet outbox message: %v", err)
	}
	return body
}
