package mysql

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

	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
)

const defaultPointWithdrawalMinimumPoints int64 = 1_000_000

// walletPolicyInstance 只承载现有 POINT 提现和兑换仍需使用的参数。
// 礼物结算不得调用这个解析器；主播周期钻石只由礼物类型倍率和 Host 政策系数计算。
type walletPolicyInstance struct {
	InstanceCode   string
	RegionID       int64
	PointsPerUSD   int64
	MinimumPoints  int64
	WithdrawFeeBPS int64
}

// resolveActiveWalletPolicy 延续既有 POINT 钱包已发布实例的区域优先、App 兜底语义。
// 查询由 idx_wallet_policy_active 覆盖配置筛选，不扫描账户、流水或礼物明细。
func (r *Repository) resolveActiveWalletPolicy(ctx context.Context, tx *sql.Tx, appCode string, regionID int64, nowMS int64) (walletPolicyInstance, bool, error) {
	appCode = appcode.Normalize(appCode)
	if regionID < 0 {
		return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "region_id is invalid")
	}
	row := tx.QueryRowContext(ctx, `
		SELECT instance_code, region_id, points_per_usd, withdraw_fee_bps,
		       COALESCE(JSON_UNQUOTE(JSON_EXTRACT(rule_json, '$.host.minimum_withdraw_points')), '')
		FROM wallet_policy_instances
		WHERE app_code = ?
		  AND region_id IN (?, 0)
		  AND status = 'active'
		  AND effective_from_ms <= ?
		  AND (effective_to_ms = 0 OR effective_to_ms > ?)
		ORDER BY CASE WHEN region_id = ? THEN 0 ELSE 1 END,
		         published_at_ms DESC, instance_code DESC
		LIMIT 1`,
		appCode, regionID, nowMS, nowMS, regionID,
	)
	var item walletPolicyInstance
	var minimumPointsRaw string
	if err := row.Scan(&item.InstanceCode, &item.RegionID, &item.PointsPerUSD, &item.WithdrawFeeBPS, &minimumPointsRaw); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return walletPolicyInstance{}, false, nil
		}
		return walletPolicyInstance{}, false, err
	}
	item.MinimumPoints = defaultPointWithdrawalMinimumPoints
	if strings.TrimSpace(minimumPointsRaw) != "" {
		minimumPoints, err := strconv.ParseInt(strings.TrimSpace(minimumPointsRaw), 10, 64)
		if err != nil {
			return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "wallet policy minimum withdrawal points is invalid")
		}
		item.MinimumPoints = minimumPoints
	}
	if item.InstanceCode == "" || item.PointsPerUSD <= 0 || item.MinimumPoints <= 0 || item.WithdrawFeeBPS < 0 || item.WithdrawFeeBPS > 10_000 {
		return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "wallet point policy is invalid")
	}
	return item, true, nil
}
