package roomadmin

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"slices"
	"strconv"
	"strings"

	"gorm.io/gorm"
	"hyapp-admin-server/internal/appctx"
	"hyapp-admin-server/internal/model"
)

const roomRegionWhitelistGroup = "room-region-whitelist"

type RoomWhitelistConfig struct {
	UserIDs     []string `json:"userIds"`
	UpdatedAtMS int64    `json:"updatedAtMs"`
}

type roomRegionWhitelistValue struct {
	UserIDs []string `json:"user_ids"`
}

// GetRoomWhitelistConfig 读取当前 app 的房间区域白名单；缺行时返回空集合，表示所有用户仍受区域限制。
func (s *Service) GetRoomWhitelistConfig(ctx context.Context) (RoomWhitelistConfig, error) {
	if s.store == nil {
		return RoomWhitelistConfig{}, fmt.Errorf("admin store is not configured")
	}
	item, err := s.store.GetAppConfig(roomRegionWhitelistGroup, appctx.FromContext(ctx))
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return RoomWhitelistConfig{UserIDs: []string{}}, nil
	}
	if err != nil {
		return RoomWhitelistConfig{}, err
	}
	userIDs, err := roomWhitelistIDsFromValue(item.Value)
	if err != nil {
		return RoomWhitelistConfig{}, err
	}
	return RoomWhitelistConfig{UserIDs: userIDs, UpdatedAtMS: item.UpdatedAtMS}, nil
}

// UpdateRoomWhitelistConfig 覆盖当前 app 的房间区域白名单；gateway 会在最多五分钟内通过 Redis 缓存刷新结果。
func (s *Service) UpdateRoomWhitelistConfig(ctx context.Context, req updateRoomWhitelistRequest) (RoomWhitelistConfig, error) {
	if s.store == nil {
		return RoomWhitelistConfig{}, fmt.Errorf("admin store is not configured")
	}
	userIDs, err := normalizeRoomWhitelistUserIDs(req.UserIDs)
	if err != nil {
		return RoomWhitelistConfig{}, err
	}
	payload, err := json.Marshal(roomRegionWhitelistValue{UserIDs: userIDs})
	if err != nil {
		return RoomWhitelistConfig{}, err
	}
	item := model.AppConfig{
		Group:       roomRegionWhitelistGroup,
		Key:         appctx.FromContext(ctx),
		Value:       string(payload),
		Description: "房间区域白名单用户，命中后 App 房间列表不按用户 region_id 过滤",
	}
	if err := s.store.UpsertAppConfigs([]model.AppConfig{item}); err != nil {
		return RoomWhitelistConfig{}, err
	}
	return s.GetRoomWhitelistConfig(ctx)
}

func roomWhitelistIDsFromValue(raw string) ([]string, error) {
	raw = strings.TrimSpace(raw)
	if raw == "" {
		return []string{}, nil
	}
	var payload roomRegionWhitelistValue
	if strings.HasPrefix(raw, "[") {
		if err := json.Unmarshal([]byte(raw), &payload.UserIDs); err != nil {
			return nil, err
		}
	} else if err := json.Unmarshal([]byte(raw), &payload); err != nil {
		return nil, err
	}
	return normalizeRoomWhitelistUserIDs(payload.UserIDs)
}

func normalizeRoomWhitelistUserIDs(values []string) ([]string, error) {
	seen := make(map[int64]struct{}, len(values))
	out := make([]int64, 0, len(values))
	for _, value := range values {
		value = strings.TrimSpace(value)
		if value == "" {
			continue
		}
		id, err := strconv.ParseInt(value, 10, 64)
		if err != nil || id <= 0 {
			return nil, fmt.Errorf("%w: 用户 ID 不正确", ErrInvalidArgument)
		}
		if _, ok := seen[id]; ok {
			continue
		}
		seen[id] = struct{}{}
		out = append(out, id)
	}
	slices.Sort(out)
	result := make([]string, 0, len(out))
	for _, id := range out {
		result = append(result, strconv.FormatInt(id, 10))
	}
	return result, nil
}
