package admin

import (
    "net/http"
    "strconv"
    "time"

    "bindbox-game/internal/code"
    "bindbox-game/internal/pkg/core"
    "bindbox-game/internal/pkg/validation"
    "bindbox-game/internal/repository/mysql/model"
)

type listSystemTitlesRequest struct {
    Page     int    `form:"page"`
    PageSize int    `form:"page_size"`
    Name     string `form:"name"`
    Status   *int32 `form:"status"`
}
type listSystemTitlesResponse struct {
    Page     int                      `json:"page"`
    PageSize int                      `json:"page_size"`
    Total    int64                    `json:"total"`
    List     []*model.SystemTitles    `json:"list"`
}

// ListSystemTitles 系统称号列表
func (h *handler) ListSystemTitles() core.HandlerFunc {
    return func(ctx core.Context) {
        req := new(listSystemTitlesRequest)
        rsp := new(listSystemTitlesResponse)
        if err := ctx.ShouldBindForm(req); err != nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
            return
        }
        if req.Page <= 0 { req.Page = 1 }
        if req.PageSize <= 0 { req.PageSize = 20 }
        if req.PageSize > 100 { req.PageSize = 100 }
        q := h.readDB.SystemTitles.WithContext(ctx.RequestContext()).ReadDB()
        if req.Name != "" { q = q.Where(h.readDB.SystemTitles.Name.Like("%" + req.Name + "%")) }
        if req.Status != nil { q = q.Where(h.readDB.SystemTitles.Status.Eq(*req.Status)) }
        total, err := q.Count()
        if err != nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, 30101, err.Error()))
            return
        }
        rows, err := q.Order(h.readDB.SystemTitles.ID.Desc()).
            Offset((req.Page-1)*req.PageSize).Limit(req.PageSize).Find()
        if err != nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, 30102, err.Error()))
            return
        }
        rsp.Page = req.Page
        rsp.PageSize = req.PageSize
        rsp.Total = total
        rsp.List = rows
        ctx.Payload(rsp)
    }
}

type createSystemTitleRequest struct {
    Name            string `json:"name" binding:"required,min=1"`
    Description     string `json:"description"`
    Status          int32  `json:"status"`
    ObtainRulesJSON string `json:"obtain_rules_json"`
    ScopesJSON      string `json:"scopes_json"`
}

type modifySystemTitleRequest struct {
    Name            string `json:"name"`
    Description     string `json:"description"`
    Status          *int32 `json:"status"`
    ObtainRulesJSON string `json:"obtain_rules_json"`
    ScopesJSON      string `json:"scopes_json"`
}

type simpleMessageResponseTitle struct {
    Message string `json:"message"`
}

func (h *handler) CreateSystemTitle() core.HandlerFunc {
    return func(ctx core.Context) {
        var req createSystemTitleRequest
        if err := ctx.ShouldBindJSON(&req); err != nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
            return
        }
        if req.ObtainRulesJSON == "" { req.ObtainRulesJSON = "{}" }
        if req.ScopesJSON == "" { req.ScopesJSON = "{}" }
        it := &model.SystemTitles{
            Name:            req.Name,
            Description:     req.Description,
            Status:          req.Status,
            ObtainRulesJSON: req.ObtainRulesJSON,
            ScopesJSON:      req.ScopesJSON,
        }
        if err := h.writeDB.SystemTitles.WithContext(ctx.RequestContext()).Create(it); err != nil {
            ctx.AbortWithError(core.Error(http.StatusInternalServerError, 30106, "创建称号失败"))
            return
        }
        ctx.Payload(&simpleMessageResponseTitle{Message: "创建成功"})
    }
}

func (h *handler) ModifySystemTitle() core.HandlerFunc {
    return func(ctx core.Context) {
        titleID, err := strconv.ParseInt(ctx.Param("title_id"), 10, 64)
        if err != nil || titleID <= 0 {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递称号ID"))
            return
        }
        var req modifySystemTitleRequest
        if err := ctx.ShouldBindJSON(&req); err != nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
            return
        }
        row, err := h.readDB.SystemTitles.WithContext(ctx.RequestContext()).Where(h.readDB.SystemTitles.ID.Eq(titleID)).First()
        if err != nil || row == nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, 30107, "称号不存在"))
            return
        }
        if req.Name != "" { row.Name = req.Name }
        row.Description = req.Description
        if req.Status != nil { row.Status = *req.Status }
        if req.ObtainRulesJSON != "" { row.ObtainRulesJSON = req.ObtainRulesJSON }
        if req.ScopesJSON != "" { row.ScopesJSON = req.ScopesJSON }
        if err := h.writeDB.SystemTitles.Save(row); err != nil {
            ctx.AbortWithError(core.Error(http.StatusInternalServerError, 30108, "修改称号失败"))
            return
        }
        ctx.Payload(&simpleMessageResponseTitle{Message: "修改成功"})
    }
}

func (h *handler) DeleteSystemTitle() core.HandlerFunc {
    return func(ctx core.Context) {
        titleID, err := strconv.ParseInt(ctx.Param("title_id"), 10, 64)
        if err != nil || titleID <= 0 {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递称号ID"))
            return
        }
        del := &model.SystemTitles{ID: titleID}
        if _, err := h.writeDB.SystemTitles.Delete(del); err != nil {
            ctx.AbortWithError(core.Error(http.StatusInternalServerError, 30109, "删除称号失败"))
            return
        }
        ctx.Payload(&simpleMessageResponseTitle{Message: "删除成功"})
    }
}

type listEffectsResponse struct {
    List []*model.SystemTitleEffects `json:"list"`
    Total int64 `json:"total"`
}

func (h *handler) ListSystemTitleEffects() core.HandlerFunc {
    return func(ctx core.Context) {
        titleID, err := strconv.ParseInt(ctx.Param("title_id"), 10, 64)
        if err != nil || titleID <= 0 {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递称号ID"))
            return
        }
        rows, err := h.readDB.SystemTitleEffects.WithContext(ctx.RequestContext()).Where(h.readDB.SystemTitleEffects.TitleID.Eq(titleID)).Order(h.readDB.SystemTitleEffects.Sort).Find()
        if err != nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, 30110, err.Error()))
            return
        }
        total := int64(len(rows))
        ctx.Payload(&listEffectsResponse{List: rows, Total: total})
    }
}

type createEffectRequest struct {
    EffectType       int32  `json:"effect_type" binding:"required"`
    ParamsJSON       string `json:"params_json" binding:"required"`
    StackingStrategy int32  `json:"stacking_strategy"`
    CapValueX1000    int32  `json:"cap_value_x1000"`
    ScopesJSON       string `json:"scopes_json"`
    Sort             int32  `json:"sort"`
    Status           int32  `json:"status"`
}

func (h *handler) CreateSystemTitleEffect() core.HandlerFunc {
    return func(ctx core.Context) {
        titleID, err := strconv.ParseInt(ctx.Param("title_id"), 10, 64)
        if err != nil || titleID <= 0 {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递称号ID"))
            return
        }
        var req createEffectRequest
        if err := ctx.ShouldBindJSON(&req); err != nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
            return
        }
        if req.ParamsJSON == "" { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "params_json不能为空")); return }
        if req.ScopesJSON == "" { req.ScopesJSON = "{}" }
        existed, _ := h.readDB.SystemTitleEffects.WithContext(ctx.RequestContext()).
            Where(h.readDB.SystemTitleEffects.TitleID.Eq(titleID)).
            Where(h.readDB.SystemTitleEffects.EffectType.Eq(req.EffectType)).First()
        if existed != nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, 30115, "同类型效果已存在"))
            return
        }
        sanitized, verr := h.title.ValidateEffectParams(req.EffectType, req.ParamsJSON)
        if verr != nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, verr.Error()))
            return
        }
        ef := &model.SystemTitleEffects{
            TitleID:          titleID,
            EffectType:       req.EffectType,
            ParamsJSON:       sanitized,
            StackingStrategy: req.StackingStrategy,
            CapValueX1000:    req.CapValueX1000,
            ScopesJSON:       req.ScopesJSON,
            Sort:             req.Sort,
            Status:           req.Status,
        }
        if err := h.writeDB.SystemTitleEffects.WithContext(ctx.RequestContext()).Create(ef); err != nil {
            ctx.AbortWithError(core.Error(http.StatusInternalServerError, 30111, "创建效果失败"))
            return
        }
        ctx.Payload(&simpleMessageResponseTitle{Message: "创建成功"})
    }
}

type modifyEffectRequest struct {
    EffectType       *int32 `json:"effect_type"`
    ParamsJSON       string `json:"params_json"`
    StackingStrategy *int32 `json:"stacking_strategy"`
    CapValueX1000    *int32 `json:"cap_value_x1000"`
    ScopesJSON       string `json:"scopes_json"`
    Sort             *int32 `json:"sort"`
    Status           *int32 `json:"status"`
}

func (h *handler) ModifySystemTitleEffect() core.HandlerFunc {
    return func(ctx core.Context) {
        titleID, err := strconv.ParseInt(ctx.Param("title_id"), 10, 64)
        if err != nil || titleID <= 0 {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递称号ID"))
            return
        }
        effectID, err := strconv.ParseInt(ctx.Param("effect_id"), 10, 64)
        if err != nil || effectID <= 0 {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递效果ID"))
            return
        }
        var req modifyEffectRequest
        if err := ctx.ShouldBindJSON(&req); err != nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
            return
        }
        row, err := h.readDB.SystemTitleEffects.WithContext(ctx.RequestContext()).Where(h.readDB.SystemTitleEffects.ID.Eq(effectID)).Where(h.readDB.SystemTitleEffects.TitleID.Eq(titleID)).First()
        if err != nil || row == nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, 30112, "效果不存在"))
            return
        }
        if req.EffectType != nil {
            existed, _ := h.readDB.SystemTitleEffects.WithContext(ctx.RequestContext()).
                Where(h.readDB.SystemTitleEffects.TitleID.Eq(titleID)).
                Where(h.readDB.SystemTitleEffects.EffectType.Eq(*req.EffectType)).
                Where(h.readDB.SystemTitleEffects.ID.Neq(effectID)).First()
            if existed != nil {
                ctx.AbortWithError(core.Error(http.StatusBadRequest, 30116, "同类型效果已存在"))
                return
            }
            row.EffectType = *req.EffectType
        }
        if req.ParamsJSON != "" {
            et := row.EffectType
            if req.EffectType != nil { et = *req.EffectType }
            sanitized, verr := h.title.ValidateEffectParams(et, req.ParamsJSON)
            if verr != nil {
                ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, verr.Error()))
                return
            }
            row.ParamsJSON = sanitized
        }
        if req.StackingStrategy != nil { row.StackingStrategy = *req.StackingStrategy }
        if req.CapValueX1000 != nil { row.CapValueX1000 = *req.CapValueX1000 }
        if req.ScopesJSON != "" { row.ScopesJSON = req.ScopesJSON }
        if req.Sort != nil { row.Sort = *req.Sort }
        if req.Status != nil { row.Status = *req.Status }
        if err := h.writeDB.SystemTitleEffects.Save(row); err != nil {
            ctx.AbortWithError(core.Error(http.StatusInternalServerError, 30113, "修改效果失败"))
            return
        }
        ctx.Payload(&simpleMessageResponseTitle{Message: "修改成功"})
    }
}


func (h *handler) DeleteSystemTitleEffect() core.HandlerFunc {
    return func(ctx core.Context) {
        titleID, err := strconv.ParseInt(ctx.Param("title_id"), 10, 64)
        if err != nil || titleID <= 0 {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递称号ID"))
            return
        }
        effectID, err := strconv.ParseInt(ctx.Param("effect_id"), 10, 64)
        if err != nil || effectID <= 0 {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递效果ID"))
            return
        }
        del := &model.SystemTitleEffects{ID: effectID, TitleID: titleID}
        if _, err := h.writeDB.SystemTitleEffects.Delete(del); err != nil {
            ctx.AbortWithError(core.Error(http.StatusInternalServerError, 30114, "删除效果失败"))
            return
        }
        ctx.Payload(&simpleMessageResponseTitle{Message: "删除成功"})
    }
}
type assignUserTitleRequest struct {
    TitleID   int64   `json:"title_id" binding:"required,min=1"`
    ExpiresAt *string `json:"expires_at"` // RFC3339 字符串，可空
    Remark    string  `json:"remark"`
}
type assignUserTitleResponse struct {
    Message string `json:"message"`
}

// AssignUserTitle 给用户分配称号（存在则更新有效期与备注，并激活）
func (h *handler) AssignUserTitle() core.HandlerFunc {
    return func(ctx core.Context) {
        userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64)
        if err != nil || userID <= 0 {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID"))
            return
        }
        var req assignUserTitleRequest
        if err := ctx.ShouldBindJSON(&req); err != nil {
            ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
            return
        }
        var expPtr *time.Time
        if req.ExpiresAt != nil && *req.ExpiresAt != "" {
            t, perr := time.Parse(time.RFC3339, *req.ExpiresAt)
            if perr != nil {
                ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "expires_at格式错误"))
                return
            }
            expPtr = &t
        }
        if err := h.title.AssignUserTitle(ctx.RequestContext(), userID, req.TitleID, expPtr, req.Remark); err != nil {
            if err.Error() == "already_owned" {
                ctx.AbortWithError(core.Error(http.StatusBadRequest, 30117, "该用户已拥有该称号"))
                return
            }
            ctx.AbortWithError(core.Error(http.StatusInternalServerError, 30105, "分配称号失败"))
            return
        }
        ctx.Payload(&assignUserTitleResponse{Message: "分配称号成功"})
    }
}