package app

import (
	"net/http"
	"strconv"

	"git.echol.cn/loser/st/server/global"
	"git.echol.cn/loser/st/server/model/app/request"
	"git.echol.cn/loser/st/server/model/common"
	commonResponse "git.echol.cn/loser/st/server/model/common/response"
	"git.echol.cn/loser/st/server/service"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

type WorldbookApi struct{}

// CreateWorldbook
// @Tags     AppWorldbook
// @Summary  创建世界书
// @Router   /app/worldbook [post]
// @Security ApiKeyAuth
func (a *WorldbookApi) CreateWorldbook(c *gin.Context) {
	userID := common.GetAppUserID(c)
	var req request.CreateWorldbookRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	resp, err := service.ServiceGroupApp.AppServiceGroup.WorldbookService.CreateWorldbook(userID, &req)
	if err != nil {
		global.GVA_LOG.Error("创建世界书失败", zap.Error(err))
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	commonResponse.OkWithData(resp, c)
}

// GetWorldbookList
// @Tags     AppWorldbook
// @Summary  获取世界书列表
// @Router   /app/worldbook [get]
// @Security ApiKeyAuth
func (a *WorldbookApi) GetWorldbookList(c *gin.Context) {
	userID := common.GetAppUserID(c)
	var req request.GetWorldbookListRequest
	req.Page, _ = strconv.Atoi(c.DefaultQuery("page", "1"))
	req.PageSize, _ = strconv.Atoi(c.DefaultQuery("pageSize", "20"))
	req.Keyword = c.Query("keyword")
	if req.Page < 1 {
		req.Page = 1
	}
	if req.PageSize < 1 || req.PageSize > 100 {
		req.PageSize = 20
	}
	list, total, err := service.ServiceGroupApp.AppServiceGroup.WorldbookService.GetWorldbookList(userID, &req)
	if err != nil {
		global.GVA_LOG.Error("获取世界书列表失败", zap.Error(err))
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	commonResponse.OkWithDetailed(commonResponse.PageResult{
		List:     list,
		Total:    total,
		Page:     req.Page,
		PageSize: req.PageSize,
	}, "获取成功", c)
}

// GetWorldbookByID
// @Tags     AppWorldbook
// @Summary  获取世界书详情
// @Router   /app/worldbook/:id [get]
// @Security ApiKeyAuth
func (a *WorldbookApi) GetWorldbookByID(c *gin.Context) {
	userID := common.GetAppUserID(c)
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		commonResponse.FailWithMessage("无效的世界书ID", c)
		return
	}
	resp, err := service.ServiceGroupApp.AppServiceGroup.WorldbookService.GetWorldbookByID(userID, uint(id))
	if err != nil {
		global.GVA_LOG.Error("获取世界书失败", zap.Error(err))
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	commonResponse.OkWithData(resp, c)
}

// UpdateWorldbook
// @Tags     AppWorldbook
// @Summary  更新世界书
// @Router   /app/worldbook/:id [put]
// @Security ApiKeyAuth
func (a *WorldbookApi) UpdateWorldbook(c *gin.Context) {
	userID := common.GetAppUserID(c)
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		commonResponse.FailWithMessage("无效的世界书ID", c)
		return
	}
	var req request.UpdateWorldbookRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	if err := service.ServiceGroupApp.AppServiceGroup.WorldbookService.UpdateWorldbook(userID, uint(id), &req); err != nil {
		global.GVA_LOG.Error("更新世界书失败", zap.Error(err))
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	commonResponse.OkWithMessage("更新成功", c)
}

// DeleteWorldbook
// @Tags     AppWorldbook
// @Summary  删除世界书
// @Router   /app/worldbook/:id [delete]
// @Security ApiKeyAuth
func (a *WorldbookApi) DeleteWorldbook(c *gin.Context) {
	userID := common.GetAppUserID(c)
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		commonResponse.FailWithMessage("无效的世界书ID", c)
		return
	}
	if err := service.ServiceGroupApp.AppServiceGroup.WorldbookService.DeleteWorldbook(userID, uint(id)); err != nil {
		global.GVA_LOG.Error("删除世界书失败", zap.Error(err))
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	commonResponse.OkWithMessage("删除成功", c)
}

// ImportWorldbook
// @Tags     AppWorldbook
// @Summary  导入世界书（JSON）
// @Router   /app/worldbook/import [post]
// @Security ApiKeyAuth
func (a *WorldbookApi) ImportWorldbook(c *gin.Context) {
	userID := common.GetAppUserID(c)
	file, header, err := c.Request.FormFile("file")
	if err != nil {
		commonResponse.FailWithMessage("请上传文件", c)
		return
	}
	defer file.Close()

	if header.Size > 5*1024*1024 {
		commonResponse.FailWithMessage("文件大小不能超过 5MB", c)
		return
	}

	buf := make([]byte, header.Size)
	if _, err := file.Read(buf); err != nil {
		commonResponse.FailWithMessage("读取文件失败", c)
		return
	}

	// 去掉扩展名作为名称
	filename := header.Filename
	for i := len(filename) - 1; i >= 0; i-- {
		if filename[i] == '.' {
			filename = filename[:i]
			break
		}
	}

	resp, err := service.ServiceGroupApp.AppServiceGroup.WorldbookService.ImportFromJSON(userID, buf, filename)
	if err != nil {
		global.GVA_LOG.Error("导入世界书失败", zap.Error(err))
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	commonResponse.OkWithData(resp, c)
}

// ExportWorldbook
// @Tags     AppWorldbook
// @Summary  导出世界书为 JSON
// @Router   /app/worldbook/:id/export [get]
// @Security ApiKeyAuth
func (a *WorldbookApi) ExportWorldbook(c *gin.Context) {
	userID := common.GetAppUserID(c)
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		commonResponse.FailWithMessage("无效的世界书ID", c)
		return
	}
	data, filename, err := service.ServiceGroupApp.AppServiceGroup.WorldbookService.ExportToJSON(userID, uint(id))
	if err != nil {
		global.GVA_LOG.Error("导出世界书失败", zap.Error(err))
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	c.Header("Content-Disposition", "attachment; filename="+filename)
	c.Data(http.StatusOK, "application/json", data)
}

// CreateEntry
// @Tags     AppWorldbook
// @Summary  创建世界书条目
// @Router   /app/worldbook/:id/entry [post]
// @Security ApiKeyAuth
func (a *WorldbookApi) CreateEntry(c *gin.Context) {
	userID := common.GetAppUserID(c)
	worldbookID, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		commonResponse.FailWithMessage("无效的世界书ID", c)
		return
	}
	var req request.CreateEntryRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	resp, err := service.ServiceGroupApp.AppServiceGroup.WorldbookService.CreateEntry(userID, uint(worldbookID), &req)
	if err != nil {
		global.GVA_LOG.Error("创建世界书条目失败", zap.Error(err))
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	commonResponse.OkWithData(resp, c)
}

// GetEntryList
// @Tags     AppWorldbook
// @Summary  获取世界书条目列表
// @Router   /app/worldbook/:id/entries [get]
// @Security ApiKeyAuth
func (a *WorldbookApi) GetEntryList(c *gin.Context) {
	userID := common.GetAppUserID(c)
	worldbookID, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		commonResponse.FailWithMessage("无效的世界书ID", c)
		return
	}
	list, total, err := service.ServiceGroupApp.AppServiceGroup.WorldbookService.GetEntryList(userID, uint(worldbookID))
	if err != nil {
		global.GVA_LOG.Error("获取条目列表失败", zap.Error(err))
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	commonResponse.OkWithDetailed(commonResponse.PageResult{
		List:     list,
		Total:    total,
		Page:     0,
		PageSize: 0,
	}, "获取成功", c)
}

// UpdateEntry
// @Tags     AppWorldbook
// @Summary  更新世界书条目
// @Router   /app/worldbook/:id/entry/:entryId [put]
// @Security ApiKeyAuth
func (a *WorldbookApi) UpdateEntry(c *gin.Context) {
	userID := common.GetAppUserID(c)
	entryID, err := strconv.ParseUint(c.Param("entryId"), 10, 32)
	if err != nil {
		commonResponse.FailWithMessage("无效的条目ID", c)
		return
	}
	var req request.UpdateEntryRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	if err := service.ServiceGroupApp.AppServiceGroup.WorldbookService.UpdateEntry(userID, uint(entryID), &req); err != nil {
		global.GVA_LOG.Error("更新条目失败", zap.Error(err))
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	commonResponse.OkWithMessage("更新成功", c)
}

// DeleteEntry
// @Tags     AppWorldbook
// @Summary  删除世界书条目
// @Router   /app/worldbook/:id/entry/:entryId [delete]
// @Security ApiKeyAuth
func (a *WorldbookApi) DeleteEntry(c *gin.Context) {
	userID := common.GetAppUserID(c)
	entryID, err := strconv.ParseUint(c.Param("entryId"), 10, 32)
	if err != nil {
		commonResponse.FailWithMessage("无效的条目ID", c)
		return
	}
	if err := service.ServiceGroupApp.AppServiceGroup.WorldbookService.DeleteEntry(userID, uint(entryID)); err != nil {
		global.GVA_LOG.Error("删除条目失败", zap.Error(err))
		commonResponse.FailWithMessage(err.Error(), c)
		return
	}
	commonResponse.OkWithMessage("删除成功", c)
}
