package dashboard

import (
	"context"
	"fmt"
	"strings"
	"time"
)

// CoinSellerRechargeBillQuery 是 finance legacy 列表需要的币商进货明细筛选。
// 它只服务只读展示；金额口径必须与 StatisticsOverview 的 coin_seller_recharge_usd_minor 保持一致。
type CoinSellerRechargeBillQuery struct {
	Keyword  string
	RegionID int64
	StatTZ   string
	StartMS  int64
	EndMS    int64
	Page     int
	PageSize int
}

type CoinSellerRechargeBill struct {
	TransactionID  string
	Source         string
	UserID         int64
	CountryCode    string
	USDMinorAmount int64
	CreatedAtMS    int64
}

type CoinSellerRechargeBillSource interface {
	ListCoinSellerRechargeBills(ctx context.Context, query CoinSellerRechargeBillQuery) ([]CoinSellerRechargeBill, int64, error)
}

func (s *AslanMongoDashboardSource) ListCoinSellerRechargeBills(ctx context.Context, query CoinSellerRechargeBillQuery) ([]CoinSellerRechargeBill, int64, error) {
	if s == nil || s.legacyDB == nil {
		return nil, 0, fmt.Errorf("aslan legacy mysql is not configured")
	}
	countryFilter, err := s.countryFilter(ctx, StatisticsQuery{RegionID: query.RegionID})
	if err != nil {
		return nil, 0, err
	}
	if countryFilter.Applied && len(countryFilter.Codes) == 0 {
		return []CoinSellerRechargeBill{}, 0, nil
	}
	page := query.Page
	if page < 1 {
		page = 1
	}
	pageSize := query.PageSize
	if pageSize < 1 {
		pageSize = 10
	}
	unionSQL, args := s.coinSellerRechargeBillUnionSQL(query, countryFilter)

	queryCtx, cancel := context.WithTimeout(ctx, s.requestTimeout)
	defer cancel()

	var total int64
	if err := s.legacyDB.QueryRowContext(queryCtx, `SELECT COUNT(*) FROM (`+unionSQL+`) bills`, args...).Scan(&total); err != nil {
		return nil, 0, fmt.Errorf("count aslan coin seller recharge bills: %w", err)
	}
	if total == 0 {
		return []CoinSellerRechargeBill{}, 0, nil
	}

	rows, err := s.legacyDB.QueryContext(queryCtx, `
SELECT transaction_id, source, user_id, country_code, amount, created_at
FROM (`+unionSQL+`) bills
ORDER BY created_at DESC, transaction_id DESC
LIMIT ? OFFSET ?`, append(args, pageSize, (page-1)*pageSize)...)
	if err != nil {
		return nil, 0, fmt.Errorf("query aslan coin seller recharge bills: %w", err)
	}
	defer rows.Close()

	items := make([]CoinSellerRechargeBill, 0, pageSize)
	for rows.Next() {
		var item CoinSellerRechargeBill
		var amountText string
		var createdAt time.Time
		if err := rows.Scan(&item.TransactionID, &item.Source, &item.UserID, &item.CountryCode, &amountText, &createdAt); err != nil {
			return nil, 0, fmt.Errorf("scan aslan coin seller recharge bill: %w", err)
		}
		amount, err := decimalTextToMinor(amountText)
		if err != nil {
			return nil, 0, fmt.Errorf("parse aslan coin seller recharge bill %s amount: %w", item.TransactionID, err)
		}
		item.CountryCode = aslanMongoCountryCode(item.CountryCode)
		item.USDMinorAmount = amount
		item.CreatedAtMS = createdAt.UnixMilli()
		items = append(items, item)
	}
	if err := rows.Err(); err != nil {
		return nil, 0, fmt.Errorf("iterate aslan coin seller recharge bills: %w", err)
	}
	return items, total, nil
}

func (s *AslanMongoDashboardSource) coinSellerRechargeBillUnionSQL(query CoinSellerRechargeBillQuery, countryFilter externalDashboardCountryFilter) (string, []any) {
	goldWhere := []string{
		"ugcr.sys_origin = ?",
		"ugcr.gold_coin_source = 2",
		"ugcr.recharge_amount > 0",
		"ubi.country_code IS NOT NULL",
		"ubi.country_code != ''",
	}
	goldArgs := []any{s.sysOrigin}
	freightWhere := []string{
		"fbrw.sys_origin = ?",
		"((fbrw.origin = 'PURCHASE' AND fbrw.type = 0) OR (fbrw.origin = 'DEDUCTION' AND fbrw.type = 1))",
		"(COALESCE(fbrw.amount, 0) <> 0 OR COALESCE(fbrw.usd_quantity, 0) <> 0)",
		"ubi.country_code IS NOT NULL",
		"ubi.country_code != ''",
	}
	freightArgs := []any{s.sysOrigin}
	if query.StartMS > 0 {
		start := time.UnixMilli(query.StartMS)
		goldWhere = append(goldWhere, "ugcr.create_time >= ?")
		goldArgs = append(goldArgs, start)
		freightWhere = append(freightWhere, "fbrw.create_time >= ?")
		freightArgs = append(freightArgs, start)
	}
	if query.EndMS > 0 {
		end := time.UnixMilli(query.EndMS)
		goldWhere = append(goldWhere, "ugcr.create_time < ?")
		goldArgs = append(goldArgs, end)
		freightWhere = append(freightWhere, "fbrw.create_time < ?")
		freightArgs = append(freightArgs, end)
	}
	if keyword := strings.TrimSpace(query.Keyword); keyword != "" {
		goldWhere = append(goldWhere, "(CAST(ugcr.id AS CHAR) = ? OR CONCAT('aslan-gold-coin-', ugcr.id) = ? OR CAST(ugcr.user_id AS CHAR) = ?)")
		goldArgs = append(goldArgs, keyword, keyword, keyword)
		freightWhere = append(freightWhere, "(CAST(fbrw.id AS CHAR) = ? OR CONCAT('aslan-freight-', LOWER(fbrw.origin), '-', fbrw.id) = ? OR CAST(fbrw.user_id AS CHAR) = ?)")
		freightArgs = append(freightArgs, keyword, keyword, keyword)
	}
	if countryFilter.Applied {
		placeholders := make([]string, 0, len(countryFilter.Codes))
		for _, code := range countryFilter.Codes {
			normalized := aslanMongoCountryCode(code)
			if normalized == "" {
				continue
			}
			placeholders = append(placeholders, "?")
			goldArgs = append(goldArgs, normalized)
			freightArgs = append(freightArgs, normalized)
		}
		if len(placeholders) == 0 {
			placeholders = append(placeholders, "?")
			goldArgs = append(goldArgs, "__NO_COUNTRY__")
			freightArgs = append(freightArgs, "__NO_COUNTRY__")
		}
		condition := "UPPER(ubi.country_code) IN (" + strings.Join(placeholders, ",") + ")"
		goldWhere = append(goldWhere, condition)
		freightWhere = append(freightWhere, condition)
	}
	walletDatabase := strings.TrimSpace(s.legacyWalletDatabase)
	if walletDatabase == "" {
		walletDatabase = "atyou_wallet"
	}
	unionSQL := `
SELECT CONCAT('aslan-gold-coin-', ugcr.id) AS transaction_id,
       'gold_coin_recharge' AS source,
       ugcr.user_id,
       UPPER(ubi.country_code) AS country_code,
       CAST(ugcr.recharge_amount AS CHAR) AS amount,
       ugcr.create_time AS created_at
FROM user_gold_coin_recharge ugcr
     INNER JOIN user_base_info ubi ON ubi.id = ugcr.user_id
WHERE ` + strings.Join(goldWhere, " AND ") + `
UNION ALL
SELECT CONCAT('aslan-freight-', LOWER(fbrw.origin), '-', fbrw.id) AS transaction_id,
       CONCAT('freight_', LOWER(fbrw.origin)) AS source,
       fbrw.user_id,
       UPPER(ubi.country_code) AS country_code,
       CAST(CASE
         WHEN fbrw.origin = 'DEDUCTION' OR fbrw.type = 1 THEN -ABS(CASE
           WHEN fbrw.amount IS NOT NULL AND fbrw.amount <> 0 THEN fbrw.amount
           ELSE COALESCE(fbrw.usd_quantity, 0)
         END)
         WHEN fbrw.amount IS NOT NULL AND fbrw.amount <> 0 THEN fbrw.amount
         ELSE COALESCE(fbrw.usd_quantity, 0)
       END AS CHAR) AS amount,
       fbrw.create_time AS created_at
FROM ` + quoteMySQLIdentifier(walletDatabase) + `.user_freight_balance_running_water fbrw
     INNER JOIN user_base_info ubi ON ubi.id = fbrw.user_id
WHERE ` + strings.Join(freightWhere, " AND ")
	return unionSQL, append(goldArgs, freightArgs...)
}
