package handler

import (
	"fmt"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	appservice "github.com/genex/trading-service/internal/application/service"
)

// AdminMMHandler handles admin market maker endpoints.
type AdminMMHandler struct {
	tradeService *appservice.TradeService
}

// NewAdminMMHandler creates a new AdminMMHandler.
func NewAdminMMHandler(tradeService *appservice.TradeService) *AdminMMHandler {
	return &AdminMMHandler{tradeService: tradeService}
}

// ListMarketMakers returns market maker list with statistics.
func (h *AdminMMHandler) ListMarketMakers(c *gin.Context) {
	makers := []gin.H{
		{
			"id":             "mm-001",
			"name":           "Alpha Capital",
			"status":         "active",
			"totalVolume":    1250000.00,
			"activeOrders":   42,
			"spreadAvg":      0.015,
			"uptimePercent":  99.2,
			"couponsManaged": 8,
			"lastActiveAt":   time.Now().Add(-2 * time.Minute).UTC().Format(time.RFC3339),
		},
		{
			"id":             "mm-002",
			"name":           "Beta Trading",
			"status":         "active",
			"totalVolume":    980000.00,
			"activeOrders":   35,
			"spreadAvg":      0.018,
			"uptimePercent":  97.8,
			"couponsManaged": 6,
			"lastActiveAt":   time.Now().Add(-5 * time.Minute).UTC().Format(time.RFC3339),
		},
		{
			"id":             "mm-003",
			"name":           "Gamma Securities",
			"status":         "suspended",
			"totalVolume":    450000.00,
			"activeOrders":   0,
			"spreadAvg":      0.022,
			"uptimePercent":  85.5,
			"couponsManaged": 3,
			"lastActiveAt":   time.Now().Add(-48 * time.Hour).UTC().Format(time.RFC3339),
		},
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{
		"marketMakers": makers,
		"total":        len(makers),
	}})
}

// GetMarketMakerDetails returns detailed information for a specific market maker.
func (h *AdminMMHandler) GetMarketMakerDetails(c *gin.Context) {
	mmID := c.Param("id")

	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{
		"id":            mmID,
		"name":          fmt.Sprintf("Market Maker %s", mmID),
		"status":        "active",
		"registeredAt":  time.Now().AddDate(0, -3, 0).UTC().Format(time.RFC3339),
		"totalVolume":   1250000.00,
		"totalTrades":   8420,
		"activeOrders":  42,
		"spreadAvg":     0.015,
		"uptimePercent": 99.2,
		"config": gin.H{
			"maxSpread":     0.03,
			"minDepth":      100,
			"maxOrderSize":  5000,
			"refreshRateMs": 500,
		},
		"coupons": []gin.H{
			{"couponId": "CPN-001", "bidDepth": 15, "askDepth": 12, "spread": 0.012},
			{"couponId": "CPN-002", "bidDepth": 10, "askDepth": 8, "spread": 0.018},
			{"couponId": "CPN-003", "bidDepth": 8, "askDepth": 6, "spread": 0.020},
		},
		"performance": gin.H{
			"pnl7d":       12580.50,
			"pnl30d":      45200.00,
			"fillRate":    0.87,
			"cancelRate":  0.05,
			"avgFillTime": "120ms",
		},
	}})
}

// SuspendMarketMaker suspends a market maker.
func (h *AdminMMHandler) SuspendMarketMaker(c *gin.Context) {
	mmID := c.Param("id")

	var req struct {
		Reason string `json:"reason" binding:"required"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": -1, "message": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{
		"id":          mmID,
		"status":      "suspended",
		"reason":      req.Reason,
		"suspendedAt": time.Now().UTC().Format(time.RFC3339),
		"suspendedBy": c.GetString("userId"),
	}})
}

// ResumeMarketMaker resumes a suspended market maker.
func (h *AdminMMHandler) ResumeMarketMaker(c *gin.Context) {
	mmID := c.Param("id")

	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{
		"id":        mmID,
		"status":    "active",
		"resumedAt": time.Now().UTC().Format(time.RFC3339),
		"resumedBy": c.GetString("userId"),
	}})
}

// GetLiquidityPools returns liquidity pool distribution across coupons.
func (h *AdminMMHandler) GetLiquidityPools(c *gin.Context) {
	orderbooks := h.tradeService.GetAllOrderBooks()

	type poolInfo struct {
		CouponID  string  `json:"couponId"`
		BidDepth  int     `json:"bidDepth"`
		AskDepth  int     `json:"askDepth"`
		BidVolume float64 `json:"bidVolume"`
		AskVolume float64 `json:"askVolume"`
		Spread    float64 `json:"spread"`
		MidPrice  float64 `json:"midPrice"`
	}

	var pools []poolInfo
	for couponID, ob := range orderbooks {
		bids, asks := ob.Snapshot(100)

		bidDepth := 0
		bidVolume := 0.0
		bestBidPrice := 0.0
		for _, level := range bids {
			bidDepth += level.OrderCount()
			for _, o := range level.Orders {
				bidVolume += o.Price.Float64() * float64(o.RemainingQty.Int())
			}
			if bestBidPrice == 0 {
				bestBidPrice = level.Price.Float64()
			}
		}

		askDepth := 0
		askVolume := 0.0
		bestAskPrice := 0.0
		for _, level := range asks {
			askDepth += level.OrderCount()
			for _, o := range level.Orders {
				askVolume += o.Price.Float64() * float64(o.RemainingQty.Int())
			}
			if bestAskPrice == 0 {
				bestAskPrice = level.Price.Float64()
			}
		}

		spread := 0.0
		midPrice := 0.0
		if bestBidPrice > 0 && bestAskPrice > 0 {
			spread = (bestAskPrice - bestBidPrice) / bestBidPrice
			midPrice = (bestBidPrice + bestAskPrice) / 2
		}

		pools = append(pools, poolInfo{
			CouponID:  couponID,
			BidDepth:  bidDepth,
			AskDepth:  askDepth,
			BidVolume: roundFloat(bidVolume, 2),
			AskVolume: roundFloat(askVolume, 2),
			Spread:    roundFloat(spread, 6),
			MidPrice:  roundFloat(midPrice, 2),
		})
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{
		"pools": pools,
		"total": len(pools),
	}})
}

// GetOrderBookDepth returns aggregated order book depth data for admin monitoring.
func (h *AdminMMHandler) GetOrderBookDepth(c *gin.Context) {
	couponID := c.Query("couponId")
	depth := 50

	orderbooks := h.tradeService.GetAllOrderBooks()

	type depthLevel struct {
		Price    float64 `json:"price"`
		Quantity int     `json:"quantity"`
		Orders   int     `json:"orders"`
		Total    float64 `json:"total"`
	}

	type bookDepth struct {
		CouponID string       `json:"couponId"`
		Bids     []depthLevel `json:"bids"`
		Asks     []depthLevel `json:"asks"`
	}

	var results []bookDepth

	for cID, ob := range orderbooks {
		if couponID != "" && cID != couponID {
			continue
		}
		bids, asks := ob.Snapshot(depth)

		var bidLevels []depthLevel
		cumTotal := 0.0
		for _, level := range bids {
			qty := 0
			for _, o := range level.Orders {
				qty += o.RemainingQty.Int()
			}
			cumTotal += level.Price.Float64() * float64(qty)
			bidLevels = append(bidLevels, depthLevel{
				Price:    level.Price.Float64(),
				Quantity: qty,
				Orders:   level.OrderCount(),
				Total:    roundFloat(cumTotal, 2),
			})
		}

		var askLevels []depthLevel
		cumTotal = 0.0
		for _, level := range asks {
			qty := 0
			for _, o := range level.Orders {
				qty += o.RemainingQty.Int()
			}
			cumTotal += level.Price.Float64() * float64(qty)
			askLevels = append(askLevels, depthLevel{
				Price:    level.Price.Float64(),
				Quantity: qty,
				Orders:   level.OrderCount(),
				Total:    roundFloat(cumTotal, 2),
			})
		}

		results = append(results, bookDepth{
			CouponID: cID,
			Bids:     bidLevels,
			Asks:     askLevels,
		})
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{
		"orderbooks": results,
		"total":      len(results),
	}})
}

// GetHealthIndicators returns market health metrics.
func (h *AdminMMHandler) GetHealthIndicators(c *gin.Context) {
	orderbooks := h.tradeService.GetAllOrderBooks()
	tradeCount := h.tradeService.GetTradeCount()

	activePairs := 0
	totalBidDepth := 0
	totalAskDepth := 0
	narrowSpreadCount := 0

	for _, ob := range orderbooks {
		bids, asks := ob.Snapshot(100)
		bidCount := 0
		askCount := 0
		bestBid := 0.0
		bestAsk := 0.0

		for _, level := range bids {
			bidCount += level.OrderCount()
			if bestBid == 0 {
				bestBid = level.Price.Float64()
			}
		}
		for _, level := range asks {
			askCount += level.OrderCount()
			if bestAsk == 0 {
				bestAsk = level.Price.Float64()
			}
		}

		totalBidDepth += bidCount
		totalAskDepth += askCount

		if bidCount > 0 || askCount > 0 {
			activePairs++
		}
		if bestBid > 0 && bestAsk > 0 {
			spread := (bestAsk - bestBid) / bestBid
			if spread < 0.02 {
				narrowSpreadCount++
			}
		}
	}

	healthScore := 85.0 // base score
	if activePairs > 0 {
		healthScore += float64(narrowSpreadCount) / float64(activePairs) * 10
	}
	if totalBidDepth+totalAskDepth > 50 {
		healthScore += 5
	}
	if healthScore > 100 {
		healthScore = 100
	}

	c.JSON(http.StatusOK, gin.H{"code": 0, "data": gin.H{
		"healthScore":       roundFloat(healthScore, 1),
		"activePairs":       activePairs,
		"totalBidDepth":     totalBidDepth,
		"totalAskDepth":     totalAskDepth,
		"narrowSpreadPairs": narrowSpreadCount,
		"totalTrades":       tradeCount,
		"marketMakers": gin.H{
			"total":     3,
			"active":    2,
			"suspended": 1,
		},
		"alerts":    []gin.H{},
		"timestamp": time.Now().UTC().Format(time.RFC3339),
	}})
}
