package tencentim

import (
	"context"
	"encoding/json"
	"fmt"
	"os"
	"strconv"
	"strings"
	"testing"
	"time"
)

func TestRealTencentIMCreateSendAndDestroyGroup(t *testing.T) {
	if os.Getenv("TENCENT_IM_REAL_TEST") != "1" {
		t.Skip("set TENCENT_IM_REAL_TEST=1 and Tencent IM env vars to run the real REST smoke test")
	}

	cfg := realRESTConfigFromEnv(t)
	client, err := NewRESTClient(cfg)
	if err != nil {
		t.Fatalf("NewRESTClient failed: %v", err)
	}

	nowMS := time.Now().UTC().UnixMilli()
	groupID := fmt.Sprintf("hy_codex_bc_r_%d", nowMS)
	eventID := fmt.Sprintf("codex_real_im_%d", nowMS)
	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
	defer cancel()

	// 真实 IM 测试必须使用临时 GroupID，避免污染业务全局/区域播报群。
	if err := client.EnsureGroup(ctx, GroupSpec{
		GroupID:         groupID,
		Name:            "codex real im smoke",
		Type:            DefaultGroupType,
		ApplyJoinOption: "FreeAccess",
	}); err != nil {
		t.Fatalf("real Tencent IM create group failed: %v", err)
	}
	t.Cleanup(func() {
		cleanupCtx, cleanupCancel := context.WithTimeout(context.Background(), 20*time.Second)
		defer cleanupCancel()
		if err := client.DestroyGroup(cleanupCtx, groupID); err != nil {
			t.Errorf("real Tencent IM destroy group cleanup failed: %v", err)
		}
	})
	memberUserID := nowMS % 9_000_000_000
	if err := realImportAccount(ctx, client, memberUserID); err != nil {
		t.Fatalf("real Tencent IM account import failed: %v", err)
	}
	if err := realAddGroupMember(ctx, client, groupID, memberUserID); err != nil {
		t.Fatalf("real Tencent IM add group member failed: %v", err)
	}

	payload, err := json.Marshal(map[string]any{
		"event_id":       eventID,
		"broadcast_type": "codex_real_im_smoke",
		"scope":          "region",
		"app_code":       "codex",
		"region_id":      210,
		"sent_at_ms":     nowMS,
		"action": map[string]any{
			"type":    "enter_room",
			"room_id": "codex-room-smoke",
		},
	})
	if err != nil {
		t.Fatalf("marshal smoke payload failed: %v", err)
	}

	// 真正向腾讯云 IM REST 发送 TIMCustomElem；成功只表示腾讯服务端接受消息，不代表有客户端在线展示。
	if err := client.PublishGroupCustomMessage(ctx, CustomGroupMessage{
		GroupID:     groupID,
		EventID:     eventID,
		Desc:        "codex_real_im_smoke",
		Ext:         "im_broadcast",
		PayloadJSON: payload,
	}); err != nil {
		t.Fatalf("real Tencent IM send group custom message failed: %v", err)
	}
	if err := client.DeleteGroupMember(ctx, groupID, memberUserID); err != nil {
		t.Fatalf("real Tencent IM delete group member failed: %v", err)
	}

	t.Logf("real Tencent IM smoke passed: sdk_app_id=%d group_id=%s event_id=%s removed_user_id=%d", cfg.SDKAppID, groupID, eventID, memberUserID)
}

func realImportAccount(ctx context.Context, client *RESTClient, userID int64) error {
	var response restResponse
	if err := client.post(ctx, "v4/im_open_login_svc/account_import", map[string]any{
		"UserID": strconv.FormatInt(userID, 10),
		"Nick":   "codex-im-smoke",
	}, &response); err != nil {
		return err
	}
	return response.err()
}

func realAddGroupMember(ctx context.Context, client *RESTClient, groupID string, userID int64) error {
	var response restResponse
	if err := client.post(ctx, "v4/group_open_http_svc/add_group_member", map[string]any{
		"GroupId": groupID,
		"Silence": 1,
		"MemberList": []map[string]any{
			{"Member_Account": strconv.FormatInt(userID, 10)},
		},
	}, &response); err != nil {
		return err
	}
	return response.err()
}

func realRESTConfigFromEnv(t *testing.T) RESTConfig {
	t.Helper()

	sdkAppID, err := strconv.ParseInt(requiredEnv(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 = DefaultEndpoint
	}
	adminUserSigTTL := 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")
		}
		adminUserSigTTL = parsed
	}

	return RESTConfig{
		SDKAppID:        sdkAppID,
		SecretKey:       requiredEnv(t, "TENCENT_IM_SECRET_KEY"),
		AdminIdentifier: requiredEnv(t, "TENCENT_IM_ADMIN_IDENTIFIER"),
		AdminUserSigTTL: adminUserSigTTL,
		Endpoint:        endpoint,
		GroupType:       DefaultGroupType,
	}
}

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

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