package handler

import (
	"context"
	"log"
	"time"
)

// 掉单补偿（P5.3，设计见 PAYMENT_DESIGN.md §5）：
// 前端轮询只在「用户开着账单页」时才查单确认——用户扫完码就关页面的话，钱付了、
// 订单却永远挂 pending、积分永远不到账。这个后台定时器把「用户在不在场」从入账链路
// 里摘掉：周期扫 pending 微信单，逐单 reconcileOrder（与前端轮询同一份幂等落态逻辑）。

const reconcileInterval = 1 * time.Minute

// StartReconcile 启动掉单补偿定时器（微信渠道未配置时空转，几乎零成本）。随进程生命周期运行，
// ctx 取消即退出。返回给调用方保存以便优雅停机时取消。
func (h *Handler) StartReconcile(ctx context.Context) {
	go func() {
		t := time.NewTicker(reconcileInterval)
		defer t.Stop()
		for {
			select {
			case <-ctx.Done():
				return
			case <-t.C:
				h.reconcilePending(ctx)
			}
		}
	}()
	log.Printf("[payment] 掉单补偿定时器已启动（每 %s 扫一次 pending 微信单）", reconcileInterval)
}

// reconcilePending 扫一轮待补偿的 pending 微信单。渠道未配置时直接返回（不打扰）。
func (h *Handler) reconcilePending(ctx context.Context) {
	if h.pay.Current() == nil {
		return
	}
	orders, err := h.db.PendingWechatOrders(ctx, 200)
	if err != nil {
		log.Printf("[payment] 补偿扫描取 pending 单失败: %v", err)
		return
	}
	var paid, expired, mismatch int
	for i := range orders {
		o := &orders[i]
		updated, mm := h.reconcileOrder(ctx, o)
		switch {
		case mm:
			mismatch++
			log.Printf("[payment] ⚠️ 订单 %s 支付金额与订单不符，已挂起待人工对账", o.ID)
		case updated.Status == "paid":
			paid++
		case updated.Status == "expired":
			expired++
		}
	}
	// 只在有变化时记一行，避免空转刷屏。
	if paid+expired+mismatch > 0 {
		log.Printf("[payment] 补偿扫描：入账 %d、过期 %d、金额不符 %d（本轮 %d 单）", paid, expired, mismatch, len(orders))
	}
}
