package shared

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"strconv"
	"strings"
)

var ErrInvalidUserIdentityFilter = errors.New("invalid user identity filter")

// ResolveExactUserID 把后台输入框里的用户身份解析成 owner service 使用的内部 user_id。
// 查询条件复用统一身份 SQL：精确长 ID、当前展示号、默认短号、active 靓号优先，昵称只做最后的模糊兜底。
func ResolveExactUserID(ctx context.Context, db *sql.DB, appCode string, keyword string, nowMs int64) (int64, bool, error) {
	keyword = strings.TrimSpace(keyword)
	if keyword == "" || db == nil {
		return 0, false, nil
	}
	matchSQL, matchArgs := UserIdentityExactSQL("u", "u.user_id", keyword, nowMs)
	orderSQL, orderArgs := UserIdentityExactOrderSQL("u", "u.user_id", keyword, nowMs)
	args := append([]any{appCode}, matchArgs...)
	args = append(args, orderArgs...)
	row := db.QueryRowContext(ctx, `
		SELECT u.user_id
		FROM users u
		WHERE u.app_code = ? AND `+matchSQL+`
		ORDER BY
		  `+orderSQL+`,
		  u.user_id DESC
		LIMIT 1`,
		args...,
	)
	var userID int64
	if err := row.Scan(&userID); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return 0, false, nil
		}
		return 0, false, err
	}
	return userID, true, nil
}

func ResolveUserIdentityFilter(ctx context.Context, db *sql.DB, appCode string, filter UserIdentityFilter, nowMs int64) (int64, bool, error) {
	if filter.IsEmpty() || db == nil {
		return 0, false, nil
	}
	matchSQL, matchArgs := UserIdentityFieldsSQL("u", "u.user_id", filter, nowMs)
	args := append([]any{appCode}, matchArgs...)
	row := db.QueryRowContext(ctx, `
		SELECT u.user_id
		FROM users u
		WHERE u.app_code = ? AND `+matchSQL+`
		ORDER BY u.updated_at_ms DESC, u.user_id DESC
		LIMIT 1`,
		args...,
	)
	var userID int64
	if err := row.Scan(&userID); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return 0, false, nil
		}
		return 0, false, err
	}
	return userID, true, nil
}

// ResolveExactUserIDOrNumericFallback 用于列表 owner 在 wallet/activity 等下游服务的场景。
// 下游只认内部 user_id，后台先按短号/靓号解析；解析不到时只接受正整数长 ID，兼容用户资料缺失的历史事实记录。
func ResolveExactUserIDOrNumericFallback(ctx context.Context, db *sql.DB, appCode string, keyword string, nowMs int64) (int64, bool, error) {
	keyword = strings.TrimSpace(keyword)
	if keyword == "" {
		return 0, false, nil
	}
	if db != nil {
		userID, matched, err := ResolveExactUserID(ctx, db, appCode, keyword, nowMs)
		if err != nil || matched {
			return userID, matched, err
		}
	}
	userID, err := strconv.ParseInt(keyword, 10, 64)
	if err != nil || userID <= 0 {
		return 0, true, fmt.Errorf("%w: %s", ErrInvalidUserIdentityFilter, keyword)
	}
	return userID, true, nil
}
