package controller

import (
	"net/http"
	"strconv"

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

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

// EnergyController 域能 API 控制器
type EnergyController struct {
	energySvc energyUseCase
}

// NewEnergyController 构造函数
func NewEnergyController(energySvc energyUseCase) *EnergyController {
	return &EnergyController{energySvc: energySvc}
}

// Energize 赋能文章
func (ec *EnergyController) Energize(c *gin.Context) {
	uid, _, ok := common.GetGinUser(c)
	if !ok {
		common.Error(c, http.StatusUnauthorized, "请先登录")
		return
	}

	var req struct {
		PostID uint `json:"post_id" binding:"required"`
		Amount int  `json:"amount" binding:"required"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		common.Error(c, http.StatusBadRequest, "参数错误")
		return
	}

	expGained, err := ec.energySvc.Energize(uid, req.PostID, req.Amount)
	if err != nil {
		switch err {
		case common.ErrPostNotFound:
			common.Error(c, http.StatusNotFound, "文章不存在")
		case common.ErrCannotEnergizeSelf:
			common.Error(c, http.StatusBadRequest, "不能给自己的文章赋能")
		case common.ErrInsufficientEnergy:
			common.Error(c, http.StatusBadRequest, "域能不足，可通过每日签到或创作被赋能获取")
		case common.ErrEnergizeLimitReached:
			common.Error(c, http.StatusBadRequest, "对该文章赋能已达上限")
		case common.ErrInvalidEnergyAmount:
			common.Error(c, http.StatusBadRequest, "无效的赋能数量")
		default:
			common.Error(c, http.StatusInternalServerError, "赋能失败")
		}
		return
	}

	common.Ok(c, gin.H{
		"exp_gained": expGained,
		"message":    buildEnergizeMessage(expGained),
	})
}

// buildEnergizeMessage 根据获得的经验生成提示消息
func buildEnergizeMessage(expGained int) string {
	if expGained > 0 {
		return "赋能成功！" + strconv.Itoa(expGained) + "经验已加入你的旅程。"
	}
	return "赋能成功！今日赋能经验奖励已达上限，对方仍会获得激励。"
}

// GetEnergyInfo 获取域能余额和经验上限状态
func (ec *EnergyController) GetEnergyInfo(c *gin.Context) {
	uid, _, ok := common.GetGinUser(c)
	if !ok {
		common.Error(c, http.StatusUnauthorized, "请先登录")
		return
	}

	info, err := ec.energySvc.GetEnergyInfo(uid)
	if err != nil {
		common.Error(c, http.StatusInternalServerError, "获取域能信息失败")
		return
	}

	energyDisplay := float64(info.Energy) / 10
	common.Ok(c, gin.H{
		"energy":                info.Energy,
		"energy_display":        energyDisplay,
		"daily_energize_exp":    info.DailyEnergizeExp,
		"daily_exp_cap":         info.DailyExpCap,
		"daily_exp_cap_reached": info.DailyExpCapReached,
	})
}

// GetEnergyLogs 获取我的域能流水
func (ec *EnergyController) GetEnergyLogs(c *gin.Context) {
	uid, _, ok := common.GetGinUser(c)
	if !ok {
		common.Error(c, http.StatusUnauthorized, "请先登录")
		return
	}

	days, _ := strconv.Atoi(c.DefaultQuery("days", "7"))
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))

	logs, total, err := ec.energySvc.GetEnergyLogs(uid, days, page, pageSize)
	if err != nil {
		common.Error(c, http.StatusInternalServerError, "获取流水失败")
		return
	}

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

// EnergyLogView 前端展示用的域能流水视图
type EnergyLogView struct {
	ID          uint    `json:"id"`
	Amount      int     `json:"amount"`
	AmountDisplay float64 `json:"amount_display"`
	Type        string  `json:"type"`
	TypeName    string  `json:"type_name"`
	Description string  `json:"description"`
	CreatedAt   string  `json:"created_at"`
}

func toEnergyLogViews(logs []model.EnergyLog) []EnergyLogView {
	views := make([]EnergyLogView, len(logs))
	for i, l := range logs {
		views[i] = EnergyLogView{
			ID:            l.ID,
			Amount:        l.Amount,
			AmountDisplay: float64(l.Amount) / 10,
			Type:          l.Type,
			TypeName:      model.EnergyLogDisplayNames[l.Type],
			Description:   l.Description,
			CreatedAt:     l.CreatedAt.Format(common.TimeFormat),
		}
	}
	return views
}
