// Package ante — 验证节点级合规交易拦截
//
// ComplianceAnteHandler 在验证节点打包交易前执行合规检查：
// 1. OFAC 地址拦截 — 制裁名单地址的交易直接拒绝
// 2. Structuring 检测 — 拆分交易规避 $3,000 Travel Rule 阈值
// 3. Travel Rule 预检查 — ≥$3,000 转移必须携带身份哈希
//
// 参考: FinCEN Travel Rule, OFAC SDN List, FATF Recommendation 16
package ante

import (
	"fmt"
	"math/big"
	"sync"
	"time"
)

// ComplianceAnteHandler 验证节点级合规检查处理器
type ComplianceAnteHandler struct {
	mu sync.RWMutex

	// OFAC 制裁名单（地址 → 是否制裁）
	ofacList map[string]bool

	// Travel Rule 记录（sender+receiver hash → 是否已记录）
	travelRuleRecords map[string]bool

	// Structuring 检测：地址 → 24h 内累计转移金额
	recentTransfers map[string]*TransferWindow

	// 配置
	travelRuleThreshold *big.Int // $3,000 USDC (3000 * 1e6)
	structuringWindow   time.Duration
}

// TransferWindow 滑动窗口内的转移记录
type TransferWindow struct {
	TotalAmount *big.Int
	Transfers   []TransferRecord
}

// TransferRecord 单笔转移记录
type TransferRecord struct {
	Amount    *big.Int
	Timestamp time.Time
}

// ComplianceResult 合规检查结果
type ComplianceResult struct {
	Allowed    bool
	Reason     string
	Suspicious bool   // 标记为可疑但不拒绝
	SuspReason string // 可疑原因
}

// NewComplianceAnteHandler 创建合规检查处理器
func NewComplianceAnteHandler() *ComplianceAnteHandler {
	threshold := new(big.Int).Mul(big.NewInt(3000), big.NewInt(1e6)) // $3,000 USDC

	return &ComplianceAnteHandler{
		ofacList:            make(map[string]bool),
		travelRuleRecords:   make(map[string]bool),
		recentTransfers:     make(map[string]*TransferWindow),
		travelRuleThreshold: threshold,
		structuringWindow:   24 * time.Hour,
	}
}

// AnteHandle 执行合规检查（在交易打包前调用）
//
// 返回:
//   - ComplianceResult.Allowed = false: 交易被拒绝，不会被打包
//   - ComplianceResult.Suspicious = true: 标记为可疑，仍可打包但上报
func (h *ComplianceAnteHandler) AnteHandle(from, to string, value *big.Int) ComplianceResult {
	h.mu.RLock()
	defer h.mu.RUnlock()

	// 1. OFAC 地址拦截（链级强制）
	if h.ofacList[from] {
		return ComplianceResult{
			Allowed: false,
			Reason:  fmt.Sprintf("OFAC sanctioned address (sender: %s), transaction rejected at validator level", from),
		}
	}
	if h.ofacList[to] {
		return ComplianceResult{
			Allowed: false,
			Reason:  fmt.Sprintf("OFAC sanctioned address (receiver: %s), transaction rejected at validator level", to),
		}
	}

	result := ComplianceResult{Allowed: true}

	// 2. Structuring 检测（拆分交易规避 $3,000 阈值）
	if h.isStructuringPattern(from, value) {
		result.Suspicious = true
		result.SuspReason = fmt.Sprintf(
			"Potential structuring detected for %s: cumulative transfers approaching Travel Rule threshold",
			from,
		)
	}

	// 3. Travel Rule 预打包检查（≥$3,000）
	if value.Cmp(h.travelRuleThreshold) >= 0 {
		recordKey := fmt.Sprintf("%s:%s", from, to)
		if !h.travelRuleRecords[recordKey] {
			return ComplianceResult{
				Allowed: false,
				Reason:  fmt.Sprintf("Travel Rule: identity data required for transfers >= $3,000 (from: %s, to: %s)", from, to),
			}
		}
	}

	return result
}

// isStructuringPattern 检测是否存在拆分交易模式
// 规则：24h 内同一地址的累计小额转移接近或超过 $3,000
func (h *ComplianceAnteHandler) isStructuringPattern(from string, currentValue *big.Int) bool {
	window, exists := h.recentTransfers[from]
	if !exists {
		return false
	}

	// 清理过期记录
	now := time.Now()
	var validTransfers []TransferRecord
	totalAmount := new(big.Int)
	for _, t := range window.Transfers {
		if now.Sub(t.Timestamp) <= h.structuringWindow {
			validTransfers = append(validTransfers, t)
			totalAmount.Add(totalAmount, t.Amount)
		}
	}

	// 加上当前交易
	totalAmount.Add(totalAmount, currentValue)

	// 如果每笔都低于阈值，但累计超过阈值 → 可疑
	allBelowThreshold := true
	for _, t := range validTransfers {
		if t.Amount.Cmp(h.travelRuleThreshold) >= 0 {
			allBelowThreshold = false
			break
		}
	}
	if currentValue.Cmp(h.travelRuleThreshold) >= 0 {
		allBelowThreshold = false
	}

	return allBelowThreshold && totalAmount.Cmp(h.travelRuleThreshold) >= 0
}

// ========================
// OFAC 名单管理
// ========================

// UpdateOFACList 更新 OFAC 制裁名单（由链下服务定期调用）
func (h *ComplianceAnteHandler) UpdateOFACList(addresses []string) {
	h.mu.Lock()
	defer h.mu.Unlock()

	h.ofacList = make(map[string]bool, len(addresses))
	for _, addr := range addresses {
		h.ofacList[addr] = true
	}
}

// AddToOFACList 添加地址到 OFAC 名单
func (h *ComplianceAnteHandler) AddToOFACList(address string) {
	h.mu.Lock()
	defer h.mu.Unlock()
	h.ofacList[address] = true
}

// RemoveFromOFACList 从 OFAC 名单移除
func (h *ComplianceAnteHandler) RemoveFromOFACList(address string) {
	h.mu.Lock()
	defer h.mu.Unlock()
	delete(h.ofacList, address)
}

// IsOFACSanctioned 查询地址是否在 OFAC 名单中
func (h *ComplianceAnteHandler) IsOFACSanctioned(address string) bool {
	h.mu.RLock()
	defer h.mu.RUnlock()
	return h.ofacList[address]
}

// ========================
// Travel Rule 管理
// ========================

// RecordTravelRule 记录 Travel Rule 数据
func (h *ComplianceAnteHandler) RecordTravelRule(from, to string) {
	h.mu.Lock()
	defer h.mu.Unlock()
	key := fmt.Sprintf("%s:%s", from, to)
	h.travelRuleRecords[key] = true
}

// HasTravelRuleRecord 查询是否已记录 Travel Rule
func (h *ComplianceAnteHandler) HasTravelRuleRecord(from, to string) bool {
	h.mu.RLock()
	defer h.mu.RUnlock()
	key := fmt.Sprintf("%s:%s", from, to)
	return h.travelRuleRecords[key]
}

// ========================
// 转移记录（Structuring 检测用）
// ========================

// RecordTransfer 记录一笔转移（用于 Structuring 检测）
func (h *ComplianceAnteHandler) RecordTransfer(from string, amount *big.Int) {
	h.mu.Lock()
	defer h.mu.Unlock()

	window, exists := h.recentTransfers[from]
	if !exists {
		window = &TransferWindow{
			TotalAmount: new(big.Int),
			Transfers:   make([]TransferRecord, 0),
		}
		h.recentTransfers[from] = window
	}

	window.Transfers = append(window.Transfers, TransferRecord{
		Amount:    new(big.Int).Set(amount),
		Timestamp: time.Now(),
	})
	window.TotalAmount.Add(window.TotalAmount, amount)
}

// GetOFACListSize 获取当前 OFAC 名单大小
func (h *ComplianceAnteHandler) GetOFACListSize() int {
	h.mu.RLock()
	defer h.mu.RUnlock()
	return len(h.ofacList)
}
