package monitor

import (
	"context"
	"math"
	"sync"
	"time"

	"github.com/gogenex/bridge-monitor/internal/eth"
	"github.com/gogenex/bridge-monitor/internal/genex"
	log "github.com/sirupsen/logrus"
)

// ReconciliationResult 对账结果
type ReconciliationResult struct {
	EthLocked    float64   `json:"ethLocked"`
	GenexMinted  float64   `json:"genexMinted"`
	Discrepancy  float64   `json:"discrepancy"`
	Healthy      bool      `json:"healthy"`
	Timestamp    time.Time `json:"timestamp"`
	BlockEth     int64     `json:"blockEth"`
	BlockGenex   int64     `json:"blockGenex"`
}

// BridgeMonitor 跨链桥监控器
type BridgeMonitor struct {
	ethClient   *eth.Client
	genexClient *genex.Client
	alerter     *Alerter
	metrics     *Metrics
	threshold   float64

	mu      sync.RWMutex
	latest  *ReconciliationResult
	history []ReconciliationResult
}

func NewBridgeMonitor(
	ethClient *eth.Client,
	genexClient *genex.Client,
	alerter *Alerter,
	metrics *Metrics,
	threshold float64,
) *BridgeMonitor {
	return &BridgeMonitor{
		ethClient:   ethClient,
		genexClient: genexClient,
		alerter:     alerter,
		metrics:     metrics,
		threshold:   threshold,
		history:     make([]ReconciliationResult, 0, 1000),
	}
}

// Reconcile 执行对账：两侧资产必须一致
func (bm *BridgeMonitor) Reconcile(ctx context.Context) (*ReconciliationResult, error) {
	// Ethereum 侧：查询 Axelar Gateway 合约锁定的 USDC
	ethLocked, ethBlock, err := bm.ethClient.GetLockedAmount("USDC")
	if err != nil {
		return nil, err
	}

	// Genex Chain 侧：查询桥铸造的 wrapped USDC 总量
	genexMinted, genexBlock, err := bm.genexClient.GetBridgeTokenSupply("USDC")
	if err != nil {
		return nil, err
	}

	discrepancy := math.Abs(ethLocked - genexMinted)

	result := ReconciliationResult{
		EthLocked:   ethLocked,
		GenexMinted: genexMinted,
		Discrepancy: discrepancy,
		Healthy:     true,
		Timestamp:   time.Now(),
		BlockEth:    ethBlock,
		BlockGenex:  genexBlock,
	}

	// 更新 Prometheus 指标
	bm.metrics.SetEthLocked(ethLocked)
	bm.metrics.SetGenexMinted(genexMinted)
	bm.metrics.SetDiscrepancy(discrepancy)
	bm.metrics.SetTVL(ethLocked)
	bm.metrics.IncReconciliation()

	// 偏差检查
	if ethLocked > 0 && discrepancy > ethLocked*bm.threshold {
		result.Healthy = false
		log.WithField("ethLocked", ethLocked).
			WithField("genexMinted", genexMinted).
			WithField("discrepancy", discrepancy).
			Error("Bridge asset discrepancy detected!")

		bm.alerter.Critical("Bridge asset discrepancy detected", map[string]interface{}{
			"ethLocked":   ethLocked,
			"genexMinted": genexMinted,
			"discrepancy": discrepancy,
		})

		bm.alerter.EmergencyPause()
		bm.metrics.IncEmergencyPause()
	}

	// 保存结果
	bm.mu.Lock()
	bm.latest = &result
	bm.history = append(bm.history, result)
	if len(bm.history) > 1000 {
		bm.history = bm.history[len(bm.history)-1000:]
	}
	bm.mu.Unlock()

	return &result, nil
}

// GetLatestResult 获取最新对账结果
func (bm *BridgeMonitor) GetLatestResult() *ReconciliationResult {
	bm.mu.RLock()
	defer bm.mu.RUnlock()
	return bm.latest
}

// GetHistory 获取最近 N 条对账记录
func (bm *BridgeMonitor) GetHistory(n int) []ReconciliationResult {
	bm.mu.RLock()
	defer bm.mu.RUnlock()
	if n > len(bm.history) {
		n = len(bm.history)
	}
	return bm.history[len(bm.history)-n:]
}
