package gamemanagement

import (
	"context"
	"crypto/rand"
	"database/sql"
	"fmt"
	"math/big"
	"net/url"
	"strings"
	"unicode/utf8"

	"hyapp-admin-server/internal/integration/activityclient"
	"hyapp-admin-server/internal/integration/walletclient"
)

type RobotProfile struct {
	Nickname string
	Avatar   string
	Gender   string
}

type RobotProfileSource interface {
	RandomRobotProfiles(ctx context.Context, count int) ([]RobotProfile, error)
}

type likeiRobotProfileSource struct {
	db *sql.DB
}

func NewLikeiRobotProfileSource(db *sql.DB) RobotProfileSource {
	if db == nil {
		return nil
	}
	return &likeiRobotProfileSource{db: db}
}

// WithRobotProfileSource 注入机器人资料池；创建机器人优先消费线上 likei 用户昵称和头像，未配置时再走本地随机资料兜底。
func WithRobotProfileSource(source RobotProfileSource) Option {
	return func(h *Handler) {
		h.robotProfiles = source
	}
}

// WithRobotAppearanceServices 注入机器人装扮和等级初始化依赖；robot-service 只登记机器人事实，
// 因此创建账号后的资源发放和成长等级必须由 admin-server 编排到对应 owner service。
func WithRobotAppearanceServices(wallet walletclient.Client, activity activityclient.Client) Option {
	return func(h *Handler) {
		h.wallet = wallet
		h.activity = activity
	}
}

func (s *likeiRobotProfileSource) RandomRobotProfiles(ctx context.Context, count int) ([]RobotProfile, error) {
	if s == nil || s.db == nil {
		return nil, fmt.Errorf("likei robot profile source is not configured")
	}
	if count <= 0 {
		return nil, nil
	}
	rows, err := s.db.QueryContext(ctx, `
		SELECT TRIM(user_nickname), TRIM(user_avatar)
		FROM user_base_info
		WHERE account_status = 'NORMAL'
		  AND is_del = 0
		  AND origin_sys = 'LIKEI'
		  AND user_avatar IS NOT NULL AND TRIM(user_avatar) <> ''
		  AND user_nickname IS NOT NULL AND TRIM(user_nickname) <> ''
		  AND CHAR_LENGTH(TRIM(user_nickname)) <= 64
		  AND CHAR_LENGTH(TRIM(user_avatar)) <= 512
		  AND (TRIM(user_avatar) LIKE 'http://%' OR TRIM(user_avatar) LIKE 'https://%')
		ORDER BY RAND()
		LIMIT ?
	`, count)
	if err != nil {
		return nil, fmt.Errorf("query likei robot profiles: %w", err)
	}
	defer rows.Close()

	profiles := make([]RobotProfile, 0, count)
	for rows.Next() {
		var profile RobotProfile
		if err := rows.Scan(&profile.Nickname, &profile.Avatar); err != nil {
			return nil, fmt.Errorf("scan likei robot profile: %w", err)
		}
		if normalized, ok := normalizeRobotProfile(profile); ok {
			profiles = append(profiles, normalized)
		}
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate likei robot profiles: %w", err)
	}
	if len(profiles) < count {
		return nil, fmt.Errorf("likei robot profile pool returned %d profiles, need %d", len(profiles), count)
	}
	return profiles, nil
}

func robotProfilesForGenerate(ctx context.Context, source RobotProfileSource, count int) ([]RobotProfile, error) {
	if source != nil {
		// 已配置 likei 时继续使用真实资料池；查询失败不能静默降级，否则线上数据源故障会被批量造号掩盖。
		return source.RandomRobotProfiles(ctx, count)
	}
	profiles := make([]RobotProfile, 0, count)
	for index := 0; index < count; index++ {
		profiles = append(profiles, randomRobotProfile())
	}
	return profiles, nil
}

func randomRobotProfile() RobotProfile {
	seed := randomRobotHex(8)
	nameSeed := randomRobotHex(3)
	if seed == "fallback" {
		seed = fmt.Sprintf("fallback-%d", randomRobotInt(1000000))
	}
	// 本地随机头像只保存绝对 URL，不在 admin-server 里下载或转存图片；user-service 仍负责资料字段校验。
	return RobotProfile{
		Nickname: fmt.Sprintf("Robot %s", strings.ToUpper(nameSeed)),
		Avatar:   "https://api.dicebear.com/9.x/adventurer/png?seed=hyapp-robot-" + url.QueryEscape(seed),
		Gender:   randomRobotGender(),
	}
}

func randomRobotGender() string {
	if randomRobotInt(2) == 0 {
		return "male"
	}
	return "female"
}

func randomRobotInt(max int64) int64 {
	if max <= 0 {
		return 0
	}
	value, err := rand.Int(rand.Reader, big.NewInt(max))
	if err != nil {
		return 0
	}
	return value.Int64()
}

func normalizeRobotProfile(profile RobotProfile) (RobotProfile, bool) {
	profile.Nickname = strings.TrimSpace(profile.Nickname)
	profile.Avatar = strings.TrimSpace(profile.Avatar)
	if profile.Nickname == "" || profile.Avatar == "" {
		return RobotProfile{}, false
	}
	if utf8.RuneCountInString(profile.Nickname) > 64 || utf8.RuneCountInString(profile.Avatar) > 512 {
		return RobotProfile{}, false
	}
	parsed, err := url.Parse(profile.Avatar)
	if err != nil || parsed.Host == "" || (parsed.Scheme != "http" && parsed.Scheme != "https") {
		return RobotProfile{}, false
	}
	if strings.ContainsAny(profile.Avatar, " \t\r\n") {
		return RobotProfile{}, false
	}
	return profile, true
}
