package mysql

import (
	"context"
	"strings"

	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	"hyapp/services/wallet-service/internal/domain/ledger"
)

// ListRechargeBills 查询 wallet-service 的充值账单投影，后台不能直接读写业务库内部语义。
func (r *Repository) ListRechargeBills(ctx context.Context, query ledger.ListRechargeBillsQuery) ([]ledger.RechargeBill, int64, error) {
	if r == nil || r.db == nil {
		return nil, 0, xerr.New(xerr.Unavailable, "mysql repository is not configured")
	}
	ctx = contextWithCommandApp(ctx, query.AppCode)
	query = normalizeRechargeBillsQuery(query)
	query.AppCode = appcode.FromContext(ctx)

	where, args := rechargeBillsWhereSQL(query)
	total, err := r.countRechargeBillRows(ctx, where, args...)
	if err != nil {
		return nil, 0, err
	}
	rows, err := r.db.QueryContext(ctx, `
		SELECT rr.app_code, rr.transaction_id, wt.command_id, wt.biz_type, wt.status, wt.external_ref,
		       rr.user_id, rr.seller_user_id, rr.seller_region_id, rr.target_region_id,
		       rr.policy_id, rr.policy_version, rr.currency_code,
		       rr.coin_amount, rr.usd_minor_amount, rr.exchange_coin_amount, rr.exchange_usd_minor_amount,
		       rr.created_at_ms
		FROM wallet_recharge_records rr
		JOIN wallet_transactions wt ON wt.app_code = rr.app_code AND wt.transaction_id = rr.transaction_id
		`+where+`
		ORDER BY rr.created_at_ms DESC, rr.transaction_id DESC
		LIMIT ? OFFSET ?`,
		append(args, query.PageSize, resourceOffset(query.Page, query.PageSize))...,
	)
	if err != nil {
		return nil, 0, err
	}
	defer rows.Close()

	items := make([]ledger.RechargeBill, 0, query.PageSize)
	for rows.Next() {
		var item ledger.RechargeBill
		if err := rows.Scan(
			&item.AppCode,
			&item.TransactionID,
			&item.CommandID,
			&item.RechargeType,
			&item.Status,
			&item.ExternalRef,
			&item.UserID,
			&item.SellerUserID,
			&item.SellerRegionID,
			&item.TargetRegionID,
			&item.PolicyID,
			&item.PolicyVersion,
			&item.CurrencyCode,
			&item.CoinAmount,
			&item.USDMinorAmount,
			&item.ExchangeCoinAmount,
			&item.ExchangeUSDMinorAmount,
			&item.CreatedAtMS,
		); err != nil {
			return nil, 0, err
		}
		items = append(items, item)
	}
	if err := rows.Err(); err != nil {
		return nil, 0, err
	}
	return items, total, nil
}

func (r *Repository) countRechargeBillRows(ctx context.Context, where string, args ...any) (int64, error) {
	var total int64
	err := r.db.QueryRowContext(ctx, `
		SELECT COUNT(*)
		FROM wallet_recharge_records rr
		JOIN wallet_transactions wt ON wt.app_code = rr.app_code AND wt.transaction_id = rr.transaction_id
		`+where,
		args...,
	).Scan(&total)
	return total, err
}

func normalizeRechargeBillsQuery(query ledger.ListRechargeBillsQuery) ledger.ListRechargeBillsQuery {
	query.AppCode = appcode.Normalize(query.AppCode)
	query.RechargeType = strings.ToLower(strings.TrimSpace(query.RechargeType))
	query.Status = strings.ToLower(strings.TrimSpace(query.Status))
	query.Keyword = strings.TrimSpace(query.Keyword)
	query.Page, query.PageSize = normalizePage(query.Page, query.PageSize)
	if query.EndAtMS > 0 && query.StartAtMS > query.EndAtMS {
		query.StartAtMS, query.EndAtMS = query.EndAtMS, query.StartAtMS
	}
	return query
}

func rechargeBillsWhereSQL(query ledger.ListRechargeBillsQuery) (string, []any) {
	where := `WHERE rr.app_code = ?`
	args := []any{query.AppCode}
	if query.UserID > 0 {
		where += ` AND rr.user_id = ?`
		args = append(args, query.UserID)
	}
	if query.SellerUserID > 0 {
		where += ` AND rr.seller_user_id = ?`
		args = append(args, query.SellerUserID)
	}
	if query.RegionID > 0 {
		where += ` AND rr.target_region_id = ?`
		args = append(args, query.RegionID)
	}
	if query.RechargeType != "" {
		where += ` AND wt.biz_type = ?`
		args = append(args, query.RechargeType)
	}
	if query.Status != "" {
		where += ` AND wt.status = ?`
		args = append(args, query.Status)
	}
	if query.StartAtMS > 0 {
		where += ` AND rr.created_at_ms >= ?`
		args = append(args, query.StartAtMS)
	}
	if query.EndAtMS > 0 {
		where += ` AND rr.created_at_ms < ?`
		args = append(args, query.EndAtMS)
	}
	if query.Keyword != "" {
		like := "%" + query.Keyword + "%"
		where += ` AND (rr.transaction_id LIKE ? OR wt.command_id LIKE ? OR wt.external_ref LIKE ? OR rr.policy_version LIKE ?)`
		args = append(args, like, like, like, like)
	}
	return where, args
}
