package mysql

import (
	"context"
	"runtime"
	"testing"
	"time"

	"hyapp/internal/testutil/mysqlschema"
	"hyapp/pkg/appcode"
)

func TestConsumeUserRoomDailyStatsUpdatedProjectsRoomOnline(t *testing.T) {
	ctx := context.Background()
	_, file, _, _ := runtime.Caller(0)
	statsSchema := mysqlschema.New(t, mysqlschema.Config{
		InitDBPath:     mysqlschema.InitDBPath(t, file, "..", "..", "..", "deploy", "mysql", "initdb", "001_statistics_service.sql"),
		DatabasePrefix: "hy_stats_room_online_test",
	})
	repository, err := Open(ctx, statsSchema.DSN)
	if err != nil {
		t.Fatalf("open repository: %v", err)
	}
	t.Cleanup(func() { _ = repository.Close() })

	appCtx := appcode.WithContext(ctx, "lalu")
	occurredAt := time.Date(2026, 7, 1, 10, 0, 0, 0, time.UTC).UnixMilli()

	// 客户端 room_stay 埋点先落 60s；服务端事实到达前它是 room_stay_ms 的唯一来源。
	if _, err := repository.ConsumeAppTrackingEvents(appCtx, []AppTrackingEvent{{
		AppCode:      "lalu",
		EventID:      "evt-room-stay-client",
		EventName:    "room_stay",
		UserID:       42,
		DeviceID:     "dev-42",
		DurationMS:   60_000,
		Success:      true,
		OccurredAtMS: occurredAt,
	}}); err != nil {
		t.Fatalf("consume client room_stay: %v", err)
	}

	event := UserRoomDailyStatsUpdatedEvent{
		AppCode:           "lalu",
		EventID:           "UserRoomDailyStatsUpdated:sess-1:2026-07-01",
		UserID:            42,
		StatDate:          "2026-07-01",
		RoomOnlineDeltaMS: 600_000,
		OccurredAtMS:      occurredAt,
	}
	if err := repository.ConsumeUserRoomDailyStatsUpdated(appCtx, event); err != nil {
		t.Fatalf("consume server room online fact: %v", err)
	}
	// 事件级幂等：同一 event_id 重放不能双计。
	if err := repository.ConsumeUserRoomDailyStatsUpdated(appCtx, event); err != nil {
		t.Fatalf("replay server room online fact: %v", err)
	}
	if err := repository.ConsumeUserRoomDailyStatsUpdated(appCtx, UserRoomDailyStatsUpdatedEvent{
		AppCode:           "lalu",
		EventID:           "UserRoomDailyStatsUpdated:sess-2:2026-07-01",
		UserID:            42,
		StatDate:          "2026-07-01",
		RoomOnlineDeltaMS: 300_000,
		OccurredAtMS:      occurredAt,
	}); err != nil {
		t.Fatalf("consume second server room online fact: %v", err)
	}

	var roomStayMS, roomOnlineMS, roomJoinOK int64
	if err := repository.db.QueryRowContext(ctx, `
		SELECT room_stay_ms, room_online_ms, room_join_success
		FROM stat_social_user_day
		WHERE app_code = 'lalu' AND stat_tz = 'UTC' AND stat_day = '2026-07-01' AND subject_key = 'u:42'
	`).Scan(&roomStayMS, &roomOnlineMS, &roomJoinOK); err != nil {
		t.Fatalf("query stat_social_user_day: %v", err)
	}
	// 双轨分列：客户端埋点只进 room_stay_ms，服务端事实只进 room_online_ms，互不双计。
	if roomStayMS != 60_000 || roomOnlineMS != 900_000 || roomJoinOK != 1 {
		t.Fatalf("social user day mismatch: room_stay=%d room_online=%d join_ok=%d", roomStayMS, roomOnlineMS, roomJoinOK)
	}

	rows, err := repository.querySocialUserDays(ctx, "lalu", "UTC", "2026-07-01", "2026-07-01", 0, 0, nil)
	if err != nil {
		t.Fatalf("query social user days: %v", err)
	}
	var found bool
	for _, row := range rows {
		if row.Subject != "u:42" {
			continue
		}
		found = true
		// 查询口径取 GREATEST(room_stay_ms, room_online_ms)：切换期两条来源并存也不会低估在房时长。
		if row.RoomStayMS != 900_000 || row.RoomOnlineMS != 900_000 {
			t.Fatalf("query clamp mismatch: %+v", row)
		}
	}
	if !found {
		t.Fatalf("subject u:42 not returned by querySocialUserDays: %+v", rows)
	}
}
