package handler

import (
	"fmt"
	"math"
	"math/rand"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/genex/chain-indexer/internal/application/service"
)

// AdminChainHandler handles admin chain monitoring endpoints.
// It depends on the application service layer, not on infrastructure directly.
type AdminChainHandler struct {
	indexerSvc *service.IndexerService
}

// NewAdminChainHandler creates a new AdminChainHandler.
func NewAdminChainHandler(indexerSvc *service.IndexerService) *AdminChainHandler {
	return &AdminChainHandler{indexerSvc: indexerSvc}
}

// GetContracts returns smart contract deployment status.
func (h *AdminChainHandler) GetContracts(c *gin.Context) {
	// Static contract registry — matches the actual deployed contracts on Genex Chain.
	contracts := []gin.H{
		{
			"address":     "0x0000000000000000000000000000000000000001",
			"name":        "CouponFactory",
			"type":        "TransparentUpgradeableProxy",
			"status":      "deployed",
			"deployedAt":  "2026-01-01T00:00:00Z",
			"blockHeight": 1,
			"version":     "1.0.0",
		},
		{
			"address":     "0x0000000000000000000000000000000000000002",
			"name":        "Coupon (ERC-721)",
			"type":        "TransparentUpgradeableProxy",
			"status":      "deployed",
			"deployedAt":  "2026-01-01T00:00:00Z",
			"blockHeight": 1,
			"version":     "1.0.0",
		},
		{
			"address":     "0x0000000000000000000000000000000000000003",
			"name":        "Compliance",
			"type":        "TransparentUpgradeableProxy",
			"status":      "deployed",
			"deployedAt":  "2026-01-01T00:00:00Z",
			"blockHeight": 1,
			"version":     "1.0.0",
		},
		{
			"address":     "0x0000000000000000000000000000000000000004",
			"name":        "Settlement",
			"type":        "TransparentUpgradeableProxy",
			"status":      "deployed",
			"deployedAt":  "2026-01-01T00:00:00Z",
			"blockHeight": 1,
			"version":     "1.0.0",
		},
		{
			"address":     "0x0000000000000000000000000000000000000005",
			"name":        "Redemption",
			"type":        "TransparentUpgradeableProxy",
			"status":      "deployed",
			"deployedAt":  "2026-01-01T00:00:00Z",
			"blockHeight": 1,
			"version":     "1.0.0",
		},
		{
			"address":     "0x0000000000000000000000000000000000000006",
			"name":        "Treasury",
			"type":        "TransparentUpgradeableProxy",
			"status":      "deployed",
			"deployedAt":  "2026-01-01T00:00:00Z",
			"blockHeight": 1,
			"version":     "1.0.0",
		},
		{
			"address":     "0x0000000000000000000000000000000000000007",
			"name":        "Governance",
			"type":        "TransparentUpgradeableProxy",
			"status":      "deployed",
			"deployedAt":  "2026-01-01T00:00:00Z",
			"blockHeight": 1,
			"version":     "1.0.0",
		},
		{
			"address":     "0x0000000000000000000000000000000000000008",
			"name":        "ExchangeRateOracle",
			"type":        "TransparentUpgradeableProxy",
			"status":      "deployed",
			"deployedAt":  "2026-01-01T00:00:00Z",
			"blockHeight": 1,
			"version":     "1.0.0",
		},
		{
			"address":     "0x0000000000000000000000000000000000000009",
			"name":        "CouponBatch (ERC-1155)",
			"type":        "TransparentUpgradeableProxy",
			"status":      "deployed",
			"deployedAt":  "2026-01-01T00:00:00Z",
			"blockHeight": 1,
			"version":     "1.0.0",
		},
		{
			"address":     "0x000000000000000000000000000000000000000a",
			"name":        "Redemption1155",
			"type":        "TransparentUpgradeableProxy",
			"status":      "deployed",
			"deployedAt":  "2026-01-01T00:00:00Z",
			"blockHeight": 1,
			"version":     "1.0.0",
		},
		{
			"address":     "0x000000000000000000000000000000000000000b",
			"name":        "CouponBackedSecurity",
			"type":        "TransparentUpgradeableProxy",
			"status":      "deployed",
			"deployedAt":  "2026-01-01T00:00:00Z",
			"blockHeight": 1,
			"version":     "1.0.0",
		},
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{
		"contracts": contracts,
		"total":     len(contracts),
		"network":   "genex-chain",
		"chainId":   8888,
	}})
}

// GetEvents returns recent on-chain events with optional type filtering.
func (h *AdminChainHandler) GetEvents(c *gin.Context) {
	eventType := c.Query("type")
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20"))
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}

	// Generate mock on-chain events based on indexed blocks.
	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
	eventTypes := []string{"Transfer", "Approval", "CouponMinted", "CouponRedeemed", "TradeSettled", "WalletCreated"}
	statuses := []string{"confirmed", "confirmed", "confirmed", "pending"}

	var allEvents []gin.H
	lastHeight := h.indexerSvc.GetLastHeight()

	for i := 0; i < 100; i++ {
		evtType := eventTypes[rng.Intn(len(eventTypes))]
		if eventType != "" && evtType != eventType {
			continue
		}
		allEvents = append(allEvents, gin.H{
			"id":          fmt.Sprintf("evt-%06d", 100-i),
			"type":        evtType,
			"blockHeight": lastHeight - int64(i)*2,
			"txHash":      fmt.Sprintf("0x%064x", rng.Int63()),
			"from":        fmt.Sprintf("0x%040x", rng.Int63()),
			"to":          fmt.Sprintf("0x%040x", rng.Int63()),
			"status":      statuses[rng.Intn(len(statuses))],
			"timestamp":   time.Now().Add(-time.Duration(i*30) * time.Second).UTC().Format(time.RFC3339),
			"data": gin.H{
				"amount":   fmt.Sprintf("%d", rng.Intn(10000)+100),
				"couponId": fmt.Sprintf("CPN-%03d", rng.Intn(50)+1),
			},
		})
	}

	total := len(allEvents)
	start := (page - 1) * pageSize
	end := start + pageSize
	if start > total {
		start = total
	}
	if end > total {
		end = total
	}

	result := allEvents
	if start < total {
		result = allEvents[start:end]
	} else {
		result = []gin.H{}
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{
		"events":   result,
		"total":    total,
		"page":     page,
		"pageSize": pageSize,
		"types":    eventTypes,
	}})
}

// GetGasMonitor returns gas price monitoring data.
// Genex Chain uses min_gas_price=0 (platform subsidy), so all gas values are 0.
func (h *AdminChainHandler) GetGasMonitor(c *gin.Context) {
	now := time.Now()

	// Gas price history — all zeros (platform subsidy active).
	type gasPoint struct {
		Timestamp string  `json:"timestamp"`
		Low       float64 `json:"low"`
		Average   float64 `json:"average"`
		High      float64 `json:"high"`
		BaseFee   float64 `json:"baseFee"`
	}

	var history []gasPoint
	for i := 23; i >= 0; i-- {
		t := now.Add(-time.Duration(i) * time.Hour)
		history = append(history, gasPoint{
			Timestamp: t.Format(time.RFC3339),
			Low:       0,
			Average:   0,
			High:      0,
			BaseFee:   0,
		})
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{
		"current": gin.H{
			"low":     0,
			"average": 0,
			"high":    0,
			"baseFee": 0,
			"unit":    "gwei",
		},
		"history": history,
		"alerts": []gin.H{
			{
				"level":   "info",
				"message": "Platform gas subsidy active — all user transactions are gas-free",
				"time":    now.UTC().Format(time.RFC3339),
			},
		},
		"network":   "genex-chain",
		"timestamp": now.UTC().Format(time.RFC3339),
	}})
}

// GetChainStats returns chain statistics computed from real indexed data.
func (h *AdminChainHandler) GetChainStats(c *gin.Context) {
	lastHeight := h.indexerSvc.GetLastHeight()
	chainHeight := h.indexerSvc.GetChainHeight()
	blocks := h.indexerSvc.GetRecentBlocks(100)

	// Calculate real stats from indexed blocks.
	totalTx := 0
	for _, b := range blocks {
		totalTx += b.TxCount
	}

	avgBlockTime := 1.0 // default ~1s for Genex Chain
	if len(blocks) >= 2 {
		first := blocks[len(blocks)-1].Timestamp
		last := blocks[0].Timestamp
		diff := last.Sub(first).Seconds()
		if diff > 0 && len(blocks) > 1 {
			avgBlockTime = diff / float64(len(blocks)-1)
		}
	}

	// Compute TPS from recent blocks.
	tps := 0.0
	if avgBlockTime > 0 && len(blocks) > 0 {
		tps = float64(totalTx) / (float64(len(blocks)) * avgBlockTime)
		tps = math.Round(tps*100) / 100
	}

	indexerLag := chainHeight - lastHeight
	indexerStatus := "running"
	if !h.indexerSvc.IsSynced() {
		indexerStatus = "syncing"
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{
		"lastBlockHeight":  lastHeight,
		"chainHeight":      chainHeight,
		"totalBlocks":      lastHeight,
		"recentTxCount":    totalTx,
		"avgBlockTime":     avgBlockTime,
		"network":          "genex-chain",
		"chainId":          8888,
		"consensusType":    "CometBFT",
		"activeValidators": 5,
		"tps":              tps,
		"indexerStatus":    indexerStatus,
		"indexerLag":       indexerLag,
		"timestamp":        time.Now().UTC().Format(time.RFC3339),
	}})
}
