package service

import (
	"context"
	"log/slog"
	"time"

	"hyapp/pkg/appcode"
	"hyapp/pkg/logx"
	"hyapp/services/room-service/internal/room/outbox"
)

const (
	// robotDisplayPublishTimeout 是机器人展示直发 IM 的单条上限；超时或失败只记日志，不影响已提交房间状态。
	robotDisplayPublishTimeout = 3 * time.Second
)

func (s *Service) publishRobotDisplayRecordsBestEffort(ctx context.Context, records []outbox.Record) {
	if s == nil || len(records) == 0 {
		return
	}
	if s.robotDisplayPublisher == nil {
		// 缺少腾讯 IM publisher 时不能阻断房间命令，只把整批展示事件视为 best-effort 投递失败。
		logx.Warn(ctx, "robot_display_im_publish_skipped",
			slog.String("node_id", s.nodeID),
			slog.Int("record_count", len(records)),
			slog.String("reason", "publisher_not_configured"),
		)
		return
	}
	scopedApp := appcode.FromContext(ctx)
	copied := append([]outbox.Record(nil), records...)
	for index := range copied {
		copied[index].AppCode = appcode.Normalize(firstNonEmpty(copied[index].AppCode, scopedApp))
		if copied[index].Envelope != nil {
			copied[index].Envelope.AppCode = copied[index].AppCode
		}
	}
	sortOutboxRecords(copied)

	go func(records []outbox.Record) {
		for _, record := range records {
			if record.Envelope == nil {
				logx.Warn(ctx, "robot_display_im_publish_skipped",
					slog.String("node_id", s.nodeID),
					slog.String("event_id", record.EventID),
					slog.String("event_type", record.EventType),
					slog.String("room_id", record.RoomID),
					slog.String("reason", "nil_envelope"),
				)
				continue
			}
			publishCtx, cancel := context.WithTimeout(appcode.WithContext(context.Background(), record.AppCode), robotDisplayPublishTimeout)
			err := s.robotDisplayPublisher.PublishOutboxEvent(publishCtx, record.Envelope)
			cancel()
			if err != nil {
				// 机器人展示事件允许极小概率丢失；这里只暴露日志，客户端靠房间快照恢复最终状态。
				logx.Warn(ctx, "robot_display_im_publish_failed",
					slog.String("node_id", s.nodeID),
					slog.String("event_id", record.EventID),
					slog.String("event_type", record.EventType),
					slog.String("room_id", record.RoomID),
					slog.String("error", trimOutboxError(err.Error())),
				)
			}
		}
	}(copied)
}
