package service

import (
	"context"
	"encoding/json"
	"errors"
	"strings"

	roomv1 "hyapp.local/api/proto/room/v1"
	"hyapp/pkg/appcode"
	"hyapp/pkg/usermq"
	"hyapp/services/room-service/internal/room/command"
	"hyapp/services/room-service/internal/room/state"
)

type userRegionChangedPayload struct {
	UserID      int64  `json:"user_id"`
	OldCountry  string `json:"old_country"`
	NewCountry  string `json:"new_country"`
	OldRegionID int64  `json:"old_region_id"`
	NewRegionID int64  `json:"new_region_id"`
	Source      string `json:"source"`
	RequestID   string `json:"request_id"`
	ChangedAtMS int64  `json:"changed_at_ms"`
}

// HandleUserOutboxMessage 只消费 user-service 的当前区域迁移事实；历史注册、邀请或麦位事实不是 room-service 的状态输入。
func (s *Service) HandleUserOutboxMessage(ctx context.Context, message usermq.UserOutboxMessage) error {
	if strings.TrimSpace(message.EventType) != "UserRegionChanged" {
		return nil
	}
	var payload userRegionChangedPayload
	if err := json.Unmarshal([]byte(message.PayloadJSON), &payload); err != nil {
		return err
	}
	if payload.UserID <= 0 || payload.NewRegionID < 0 {
		// user_outbox 已经是 owner service 提交后的事实；结构错误交给 MQ 重试和告警，不在本地猜测修复。
		return errors.New("user region changed payload is invalid")
	}
	if payload.UserID != message.AggregateID {
		// aggregate_id 是 outbox 幂等和审计键，必须和 payload 指向同一个用户，避免错误事件迁移别人的房间。
		return errors.New("user region changed aggregate_id mismatch")
	}

	ctx = appcode.WithContext(ctx, message.AppCode)
	meta, exists, err := s.repository.GetRoomMetaByOwner(ctx, payload.UserID)
	if err != nil {
		return err
	}
	if !exists || meta.Status == state.RoomStatusDeleted {
		return nil
	}

	newCountry := normalizeRoomCountryCode(payload.NewCountry)
	if meta.VisibleRegionID == payload.NewRegionID && newCountry == "" {
		return nil
	}
	requestID := strings.TrimSpace(payload.RequestID)
	if requestID == "" {
		requestID = message.EventID
	}
	sentAtMS := payload.ChangedAtMS
	if sentAtMS <= 0 {
		sentAtMS = message.OccurredAtMS
	}
	updateMeta := &roomv1.RequestMeta{
		AppCode:     message.AppCode,
		RequestId:   requestID,
		CommandId:   message.EventID,
		ActorUserId: payload.UserID,
		RoomId:      meta.RoomID,
		SentAtMs:    sentAtMS,
	}
	cmd := command.AdminUpdateRoom{
		Base:      baseFromMeta(updateMeta),
		AdminName: "user-region-sync",
	}
	if meta.VisibleRegionID != payload.NewRegionID {
		cmd.VisibleRegionID = &payload.NewRegionID
	}
	if newCountry != "" {
		// UserRegionChanged 同时承载国家事实；即使区域未变，也要把房主国家投影写回房间列表。
		cmd.OwnerCountryCode = &newCountry
	}
	_, err = s.applyAdminRoomMutation(ctx, cmd, cmd)
	return err
}
