package service_test

import (
	"context"
	"os"
	"strconv"
	"strings"
	"testing"
	"time"

	roomv1 "hyapp.local/api/proto/room/v1"
	"hyapp/pkg/tencentim"
	"hyapp/services/room-service/internal/integration"
	roomservice "hyapp/services/room-service/internal/room/service"
	"hyapp/services/room-service/internal/router"
	"hyapp/services/room-service/internal/testutil/mysqltest"
)

func TestRealCreateRoomEnsuresTencentIMGroup(t *testing.T) {
	if os.Getenv("ROOM_CREATE_REAL_IM_TEST") != "1" {
		t.Skip("set ROOM_CREATE_REAL_IM_TEST=1, ROOM_SERVICE_MYSQL_TEST_DSN, and Tencent IM env vars to run the real create-room smoke test")
	}

	imClient, err := tencentim.NewRESTClient(realRoomCreateIMConfig(t))
	if err != nil {
		t.Fatalf("new real Tencent IM client failed: %v", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	repository := mysqltest.NewRepository(t)
	roomID := "room-real-im-" + strconv.FormatInt(time.Now().UTC().UnixMilli(), 10)
	ownerID := time.Now().UTC().UnixMilli() % 9_000_000_000
	t.Cleanup(func() {
		cleanupCtx, cleanupCancel := context.WithTimeout(context.Background(), 20*time.Second)
		defer cleanupCancel()
		if err := imClient.DestroyGroup(cleanupCtx, roomID); err != nil {
			t.Errorf("destroy real Tencent IM room group failed: %v", err)
		}
	})

	svc := roomservice.New(roomservice.Config{
		NodeID:         "node-real-create-room-im",
		LeaseTTL:       10 * time.Second,
		RankLimit:      20,
		SnapshotEveryN: 1,
	}, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewTencentIMPublisher(imClient), integration.NewNoopOutboxPublisher())

	resp, err := svc.CreateRoom(ctx, &roomv1.CreateRoomRequest{
		Meta:            roomservice.NewRequestMeta(roomID, ownerID),
		SeatCount:       10,
		Mode:            "voice",
		VisibleRegionId: 1001,
		RoomName:        "Real Tencent IM Room",
		RoomAvatar:      testRoomCoverURL,
		RoomShortId:     strconv.FormatInt(ownerID, 10),
	})
	if err != nil {
		t.Fatalf("CreateRoom with real Tencent IM failed: %v", err)
	}
	if resp.GetRoom().GetRoomId() != roomID || !resp.GetResult().GetApplied() {
		t.Fatalf("unexpected CreateRoom response: %+v", resp)
	}
	if _, exists, err := repository.GetRoomMeta(ctx, roomID); err != nil || !exists {
		t.Fatalf("room meta must be persisted after real IM group succeeds: exists=%t err=%v", exists, err)
	}

	t.Logf("real create room IM smoke passed: room_id=%s owner_user_id=%d", roomID, ownerID)
}

func realRoomCreateIMConfig(t *testing.T) tencentim.RESTConfig {
	t.Helper()

	sdkAppID, err := strconv.ParseInt(requiredRoomCreateEnv(t, "TENCENT_IM_SDK_APP_ID"), 10, 64)
	if err != nil || sdkAppID <= 0 {
		t.Fatalf("TENCENT_IM_SDK_APP_ID is invalid")
	}
	endpoint := strings.TrimSpace(os.Getenv("TENCENT_IM_ENDPOINT"))
	if endpoint == "" {
		endpoint = tencentim.DefaultEndpoint
	}
	ttl := time.Hour
	if rawTTL := strings.TrimSpace(os.Getenv("TENCENT_IM_ADMIN_USERSIG_TTL")); rawTTL != "" {
		parsed, err := time.ParseDuration(rawTTL)
		if err != nil || parsed <= 0 {
			t.Fatalf("TENCENT_IM_ADMIN_USERSIG_TTL is invalid")
		}
		ttl = parsed
	}

	return tencentim.RESTConfig{
		SDKAppID:        sdkAppID,
		SecretKey:       requiredRoomCreateEnv(t, "TENCENT_IM_SECRET_KEY"),
		AdminIdentifier: requiredRoomCreateEnv(t, "TENCENT_IM_ADMIN_IDENTIFIER"),
		AdminUserSigTTL: ttl,
		Endpoint:        endpoint,
		GroupType:       tencentim.DefaultGroupType,
	}
}

func requiredRoomCreateEnv(t *testing.T, key string) string {
	t.Helper()

	value := strings.TrimSpace(os.Getenv(key))
	if value == "" {
		t.Fatalf("%s is required for real create-room smoke test", key)
	}
	return value
}
