package admin

import (
	"net/http"
	"strconv"

	"metazone.cc/metalab/internal/common"
	"metazone.cc/metalab/internal/model"

	"github.com/gin-gonic/gin"
)

// adminEnergyUseCase AdminEnergyController 对 EnergyService 的最小依赖（ISP：4 个方法）
type adminEnergyUseCase interface {
	AdminAdjust(operatorUID uint, userIDs []uint, amount int, description string, mode string) error
	GetAdminEnergyLogs(energyType string, page, pageSize int) ([]model.EnergyLog, int64, error)
	GetFundBalance() (int, error)
	GetFundLogs(logType string, page, pageSize int) ([]model.FundLog, int64, error)
}

// AdminEnergyController 后台域能管理控制器
type AdminEnergyController struct {
	energySvc adminEnergyUseCase
}

// NewAdminEnergyController 构造函数
func NewAdminEnergyController(energySvc adminEnergyUseCase) *AdminEnergyController {
	return &AdminEnergyController{energySvc: energySvc}
}

// EnergyPage 域能管理页面（公户余额 + 用户域能调整）
func (ac *AdminEnergyController) EnergyPage(c *gin.Context) {
	balance := 0
	if b, err := ac.energySvc.GetFundBalance(); err == nil {
		balance = b
	}
	c.HTML(http.StatusOK, "admin/energy/index.html", common.BuildAdminPageData(c, gin.H{
		"Title":              "域能管理",
		"ExtraCSS":           "/admin/static/css/energy.css",
		"ExtraJS":            "/admin/static/js/energy.js",
		"FundBalance":        balance,
		"FundBalanceDisplay": float64(balance) / 10,
	}))
}

// EnergyLogPage 域能日志页面
func (ac *AdminEnergyController) EnergyLogPage(c *gin.Context) {
	c.HTML(http.StatusOK, "admin/energy/logs.html", common.BuildAdminPageData(c, gin.H{
		"Title":    "域能日志",
		"ExtraCSS": "/admin/static/css/energy.css",
		"ExtraJS":  "/admin/static/js/energy.js",
		"LogTypes": model.EnergyLogDisplayNames,
	}))
}

// FundLogPage 公户流水页面
func (ac *AdminEnergyController) FundLogPage(c *gin.Context) {
	c.HTML(http.StatusOK, "admin/energy/fund_logs.html", common.BuildAdminPageData(c, gin.H{
		"Title":    "公户流水",
		"ExtraCSS": "/admin/static/css/energy.css",
		"ExtraJS":  "/admin/static/js/energy.js",
		"LogTypes": model.FundLogDisplayNames,
	}))
}

// AdjustEnergy 调整用户域能
func (ac *AdminEnergyController) AdjustEnergy(c *gin.Context) {
	operatorUID, ok := c.Get("uid")
	if !ok {
		common.Error(c, http.StatusUnauthorized, "请先登录")
		return
	}

	var req struct {
		UserIDs     []uint `json:"user_ids" binding:"required,min=1"`
		Amount      int    `json:"amount" binding:"required"`
		Description string `json:"description" binding:"required,min=1,max=500"`
		Mode        string `json:"mode"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		common.Error(c, http.StatusBadRequest, "参数错误：需要 user_ids、amount 和 description")
		return
	}

	// 默认模式为 admin_transfer
	if req.Mode == "" {
		req.Mode = model.FundTypeAdminTransfer
	}

	// system_operation 仅 owner 可用
	if req.Mode == model.FundTypeSystemOperation {
		role, _ := c.Get("role")
		if !model.HasMinRole(role.(string), model.RoleOwner) {
			common.Error(c, http.StatusForbidden, "仅站长可使用系统操作模式")
			return
		}
	}

	if err := ac.energySvc.AdminAdjust(operatorUID.(uint), req.UserIDs, req.Amount, req.Description, req.Mode); err != nil {
		if err == common.ErrInsufficientFund {
			common.Error(c, http.StatusBadRequest, "公户余额不足，无法执行操作")
			return
		}
		common.Error(c, http.StatusInternalServerError, "调整失败")
		return
	}

	common.OkMessage(c, "域能调整成功")
}

// ListEnergyLogs 查询域能日志
func (ac *AdminEnergyController) ListEnergyLogs(c *gin.Context) {
	energyType := c.Query("type")
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))

	logs, total, err := ac.energySvc.GetAdminEnergyLogs(energyType, page, pageSize)
	if err != nil {
		common.Error(c, http.StatusInternalServerError, "查询失败")
		return
	}

	// 转换为展示友好的视图
	type logView struct {
		model.EnergyLog
		EnergyDisplay float64 `json:"energy_display"`
		TypeName      string  `json:"type_name"`
	}
	views := make([]logView, len(logs))
	for i, l := range logs {
		views[i] = logView{
			EnergyLog:     l,
			EnergyDisplay: float64(l.Amount) / 10,
			TypeName:      model.EnergyLogDisplayNames[l.Type],
		}
	}

	common.Ok(c, gin.H{
		"items":       views,
		"total":       total,
		"page":        page,
		"page_size":   pageSize,
		"total_pages": common.PageCount(total, pageSize),
	})
}

// GetFundBalance 获取公户余额
func (ac *AdminEnergyController) GetFundBalance(c *gin.Context) {
	balance, err := ac.energySvc.GetFundBalance()
	if err != nil {
		common.Error(c, http.StatusInternalServerError, "查询失败")
		return
	}
	common.Ok(c, gin.H{
		"balance":        balance,
		"balance_display": float64(balance) / 10,
	})
}

// ListFundLogs 查询公户流水
func (ac *AdminEnergyController) ListFundLogs(c *gin.Context) {
	logType := c.Query("type")
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))

	logs, total, err := ac.energySvc.GetFundLogs(logType, page, pageSize)
	if err != nil {
		common.Error(c, http.StatusInternalServerError, "查询失败")
		return
	}

	type logView struct {
		model.FundLog
		AmountDisplay float64 `json:"amount_display"`
		TypeName      string  `json:"type_name"`
	}
	views := make([]logView, len(logs))
	for i, l := range logs {
		views[i] = logView{
			FundLog:       l,
			AmountDisplay: float64(l.Amount) / 10,
			TypeName:      model.FundLogDisplayNames[l.Type],
		}
	}

	common.Ok(c, gin.H{
		"items":       views,
		"total":       total,
		"page":        page,
		"page_size":   pageSize,
		"total_pages": common.PageCount(total, pageSize),
	})
}
