package admin

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

	"bindbox-game/internal/code"
	"bindbox-game/internal/pkg/core"
	"bindbox-game/internal/pkg/validation"
	activitysvc "bindbox-game/internal/service/activity"
)

type createActivityRequest struct {
	Name                  string  `json:"name" binding:"required"`
	Banner                string  `json:"banner"`
	Image                 string  `json:"image"`
	GameplayIntro         string  `json:"gameplay_intro"`
	ActivityCategoryID    int64   `json:"activity_category_id" binding:"required"`
	Status                int32   `json:"status"`
	PriceDraw             int64   `json:"price_draw"`
	IsBoss                int32   `json:"is_boss"`
	StartTime             string  `json:"start_time"`
	EndTime               string  `json:"end_time"`
	DrawMode              string  `json:"draw_mode"`
	MinParticipants       int64   `json:"min_participants"`
	ScheduledTime         string  `json:"scheduled_time"`
	ScheduledDelayMinutes int64   `json:"scheduled_delay_minutes"`
	IntervalMinutes       int64   `json:"interval_minutes"`
	RefundCouponType      string  `json:"refund_coupon_type"`
	RefundCouponAmount    float64 `json:"refund_coupon_amount"`
	RefundCouponID        int64   `json:"refund_coupon_id"`
	PlayType              string  `json:"play_type"`
	AllowItemCards        int32   `json:"allow_item_cards"`
	AllowCoupons          int32   `json:"allow_coupons"`
}

type createActivityResponse struct {
	ID      int64  `json:"id"`
	Message string `json:"message"`
}

type activityDetailResponse struct {
	ID                 int64     `json:"id"`
	CreatedAt          time.Time `json:"created_at"`
	UpdatedAt          time.Time `json:"updated_at"`
	Name               string    `json:"name"`
	Banner             string    `json:"banner"`
	ActivityCategoryID int64     `json:"activity_category_id"`
	Status             int32     `json:"status"`
	PriceDraw          int64     `json:"price_draw"`
	IsBoss             int32     `json:"is_boss"`
	StartTime          time.Time `json:"start_time"`
	EndTime            time.Time `json:"end_time"`
	DrawMode           string    `json:"draw_mode"`
	PlayType           string    `json:"play_type"`
	MinParticipants    int64     `json:"min_participants"`
	IntervalMinutes    int64     `json:"interval_minutes"`
	ScheduledTime      time.Time `json:"scheduled_time"`
	LastSettledAt      time.Time `json:"last_settled_at"`
	RefundCouponID     int64     `json:"refund_coupon_id"`
	Image              string    `json:"image"`
	GameplayIntro      string    `json:"gameplay_intro"`
	AllowItemCards     bool      `json:"allow_item_cards"`
	AllowCoupons       bool      `json:"allow_coupons"`
}

// CreateActivity 创建活动
// @Summary 创建活动
// @Description 创建活动，配置基本信息与分类、Boss标签
// @Tags 管理端.活动
// @Accept json
// @Produce json
// @Param RequestBody body createActivityRequest true "请求参数"
// @Success 200 {object} simpleMessageResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/activities [post]
// @Security LoginVerifyToken
func (h *handler) CreateActivity() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(createActivityRequest)
		res := new(createActivityResponse)

		if err := ctx.ShouldBindJSON(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}

		if req.ActivityCategoryID == 0 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "活动分类ID不能为空"))
			return
		}

		if req.PriceDraw <= 0 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "抽奖价格必须大于0（单位：积分）"))
			return
		}

		if ctx.SessionUserInfo().IsSuper != 1 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateActivityError, "禁止操作"))
			return
		}

		var st, et *time.Time
		if req.StartTime != "" {
			if t, err := time.Parse(time.RFC3339, req.StartTime); err == nil {
				st = &t
			} else if t2, err2 := time.ParseInLocation("2006-01-02 15:04:05", req.StartTime, time.Local); err2 == nil {
				st = &t2
			}
		}
		if req.EndTime != "" {
			if t, err := time.Parse(time.RFC3339, req.EndTime); err == nil {
				et = &t
			} else if t2, err2 := time.ParseInLocation("2006-01-02 15:04:05", req.EndTime, time.Local); err2 == nil {
				et = &t2
			}
		}

		aic := req.AllowItemCards
		if aic == 0 {
			aic = 1
		}
		acp := req.AllowCoupons
		if acp == 0 {
			acp = 1
		}
		item, err := h.activity.CreateActivity(ctx.RequestContext(), activitysvc.CreateActivityInput{
			Name:               req.Name,
			Banner:             req.Banner,
			Image:              req.Image,
			GameplayIntro:      req.GameplayIntro,
			ActivityCategoryID: req.ActivityCategoryID,
			Status:             req.Status,
			PriceDraw:          req.PriceDraw,
			IsBoss:             req.IsBoss,
			StartTime:          st,
			EndTime:            et,
			AllowItemCards:     aic,
			AllowCoupons:       acp,
		})
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateActivityError, err.Error()))
			return
		}

		if req.DrawMode != "" {
			var stPtr *time.Time
			if req.ScheduledDelayMinutes > 0 {
				t := time.Now().Add(time.Duration(req.ScheduledDelayMinutes) * time.Minute)
				stPtr = &t
			} else if req.IntervalMinutes > 0 && req.ScheduledTime == "" {
				t := time.Now().Add(time.Duration(req.IntervalMinutes) * time.Minute)
				stPtr = &t
			} else if req.ScheduledTime != "" {
				if t, err := time.Parse(time.RFC3339, req.ScheduledTime); err == nil {
					stPtr = &t
				} else if t2, err2 := time.ParseInLocation("2006-01-02 15:04:05", req.ScheduledTime, time.Local); err2 == nil {
					stPtr = &t2
				}
			}
			if err := h.activity.SaveActivityDrawConfig(ctx.RequestContext(), item.ID, activitysvc.DrawConfig{PlayType: req.PlayType, DrawMode: req.DrawMode, MinParticipants: req.MinParticipants, IntervalMinutes: req.IntervalMinutes, ScheduledTime: stPtr, RefundCouponID: req.RefundCouponID}); err != nil {
				ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.CreateActivityError, err.Error()))
				return
			}
		}

		res.ID = item.ID
		res.Message = "操作成功"
		ctx.Payload(res)
	}
}

type modifyActivityRequest struct {
	Name                  string  `json:"name"`
	Banner                string  `json:"banner"`
	Image                 string  `json:"image"`
	GameplayIntro         string  `json:"gameplay_intro"`
	ActivityCategoryID    int64   `json:"activity_category_id"`
	Status                int32   `json:"status"`
	PriceDraw             int64   `json:"price_draw"`
	IsBoss                int32   `json:"is_boss"`
	StartTime             string  `json:"start_time"`
	EndTime               string  `json:"end_time"`
	DrawMode              string  `json:"draw_mode"`
	MinParticipants       int64   `json:"min_participants"`
	ScheduledTime         string  `json:"scheduled_time"`
	ScheduledDelayMinutes int64   `json:"scheduled_delay_minutes"`
	IntervalMinutes       int64   `json:"interval_minutes"`
	RefundCouponType      string  `json:"refund_coupon_type"`
	RefundCouponAmount    float64 `json:"refund_coupon_amount"`
	RefundCouponID        int64   `json:"refund_coupon_id"`
	PlayType              string  `json:"play_type"`
	AllowItemCards        *int32  `json:"allow_item_cards"`
	AllowCoupons          *int32  `json:"allow_coupons"`
	Force                 bool    `json:"force"`
}

// ModifyActivity 修改活动
// @Summary 修改活动
// @Description 修改活动基本信息、分类、Boss标签等
// @Tags 管理端.活动
// @Accept json
// @Produce json
// @Param activity_id path integer true "活动ID"
// @Param RequestBody body modifyActivityRequest true "请求参数"
// @Success 200 {object} simpleMessageResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/activities/{activity_id} [put]
// @Security LoginVerifyToken
func (h *handler) ModifyActivity() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(modifyActivityRequest)
		res := new(simpleMessageResponse)

		if err := ctx.ShouldBindJSON(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}

		if ctx.SessionUserInfo().IsSuper != 1 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ModifyActivityError, "禁止操作"))
			return
		}

		id, err := strconv.ParseInt(ctx.Param("activity_id"), 10, 64)
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID"))
			return
		}

		var st, et *time.Time
		if req.StartTime != "" {
			if t, err := time.Parse(time.RFC3339, req.StartTime); err == nil {
				st = &t
			} else if t2, err2 := time.ParseInLocation("2006-01-02 15:04:05", req.StartTime, time.Local); err2 == nil {
				st = &t2
			}
		}
		if req.EndTime != "" {
			if t, err := time.Parse(time.RFC3339, req.EndTime); err == nil {
				et = &t
			} else if t2, err2 := time.ParseInLocation("2006-01-02 15:04:05", req.EndTime, time.Local); err2 == nil {
				et = &t2
			}
		}

		// 检查下线时的未消费次数卡
		if req.Status == 2 && !req.Force {
			ugp := h.readDB.UserGamePasses
			count, err := ugp.WithContext(ctx.RequestContext()).Where(ugp.ActivityID.Eq(id), ugp.Remaining.Gt(0)).Count()
			if err != nil {
				ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ModifyActivityError, err.Error()))
				return
			}
			if count > 0 {
				ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ModifyActivityError, "该活动还有 "+strconv.FormatInt(count, 10)+" 张未使用的次数卡，确认强制下架吗？请勾选强制执行。"))
				return
			}
		}

		if err := h.activity.ModifyActivity(ctx.RequestContext(), id, activitysvc.ModifyActivityInput{
			Name:               req.Name,
			Banner:             req.Banner,
			Image:              req.Image,
			GameplayIntro:      req.GameplayIntro,
			ActivityCategoryID: req.ActivityCategoryID,
			Status:             req.Status,
			PriceDraw:          req.PriceDraw,
			IsBoss:             req.IsBoss,
			StartTime:          st,
			EndTime:            et,
			AllowItemCards:     req.AllowItemCards,
			AllowCoupons:       req.AllowCoupons,
		}); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ModifyActivityError, err.Error()))
			return
		}

		if req.DrawMode != "" {
			var stPtr *time.Time
			if req.ScheduledDelayMinutes > 0 {
				t := time.Now().Add(time.Duration(req.ScheduledDelayMinutes) * time.Minute)
				stPtr = &t
			} else if req.IntervalMinutes > 0 && req.ScheduledTime == "" {
				t := time.Now().Add(time.Duration(req.IntervalMinutes) * time.Minute)
				stPtr = &t
			} else if req.ScheduledTime != "" {
				if t, err := time.Parse(time.RFC3339, req.ScheduledTime); err == nil {
					stPtr = &t
				} else if t2, err2 := time.ParseInLocation("2006-01-02 15:04:05", req.ScheduledTime, time.Local); err2 == nil {
					stPtr = &t2
				}
			}
			if err := h.activity.SaveActivityDrawConfig(ctx.RequestContext(), id, activitysvc.DrawConfig{PlayType: req.PlayType, DrawMode: req.DrawMode, MinParticipants: req.MinParticipants, IntervalMinutes: req.IntervalMinutes, ScheduledTime: stPtr, RefundCouponID: req.RefundCouponID}); err != nil {
				ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ModifyActivityError, err.Error()))
				return
			}
		}

		res.Message = "操作成功"
		ctx.Payload(res)
	}
}

// DeleteActivity 删除活动
// @Summary 删除活动
// @Description 删除指定活动
// @Tags 管理端.活动
// @Accept json
// @Produce json
// @Param activity_id path integer true "活动ID"
// @Success 200 {object} simpleMessageResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/activities/{activity_id} [delete]
// @Security LoginVerifyToken
func (h *handler) DeleteActivity() core.HandlerFunc {
	return func(ctx core.Context) {
		res := new(simpleMessageResponse)

		if ctx.SessionUserInfo().IsSuper != 1 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.DeleteActivityError, "禁止操作"))
			return
		}

		id, err := strconv.ParseInt(ctx.Param("activity_id"), 10, 64)
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID"))
			return
		}

		// 检查是否有未使用的次数卡
		ugp := h.readDB.UserGamePasses
		count, err := ugp.WithContext(ctx.RequestContext()).Where(ugp.ActivityID.Eq(id), ugp.Remaining.Gt(0)).Count()
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.DeleteActivityError, err.Error()))
			return
		}
		if count > 0 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.DeleteActivityError, "该活动还有 "+strconv.FormatInt(count, 10)+" 张未使用的次数卡，禁止删除。请先处理或等待过期。"))
			return
		}

		if err := h.activity.DeleteActivity(ctx.RequestContext(), id); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.DeleteActivityError, err.Error()))
			return
		}

		res.Message = "操作成功"
		ctx.Payload(res)
	}
}

// GetActivityDetail 查看活动详情
// @Summary 查看活动详情
// @Description 查看指定活动的详细信息
// @Tags 管理端.活动
// @Accept json
// @Produce json
// @Param activity_id path integer true "活动ID"
// @Success 200 {object} activityDetailResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/activities/{activity_id} [get]
// @Security LoginVerifyToken
func (h *handler) GetActivityDetail() core.HandlerFunc {
	return func(ctx core.Context) {
		id, err := strconv.ParseInt(ctx.Param("activity_id"), 10, 64)
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID"))
			return
		}
		item, err := h.activity.GetActivity(ctx.RequestContext(), id)
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.GetActivityError, err.Error()))
			return
		}
		rsp := &activityDetailResponse{
			ID:                 item.ID,
			CreatedAt:          item.CreatedAt,
			UpdatedAt:          item.UpdatedAt,
			Name:               item.Name,
			Banner:             item.Banner,
			ActivityCategoryID: item.ActivityCategoryID,
			Status:             item.Status,
			PriceDraw:          item.PriceDraw,
			IsBoss:             item.IsBoss,
			StartTime:          item.StartTime,
			EndTime:            item.EndTime,
			DrawMode:           item.DrawMode,
			PlayType:           item.PlayType,
			MinParticipants:    item.MinParticipants,
			IntervalMinutes:    item.IntervalMinutes,
			ScheduledTime:      item.ScheduledTime,
			LastSettledAt:      item.LastSettledAt,
			RefundCouponID:     item.RefundCouponID,
			Image:              item.Image,
			GameplayIntro:      item.GameplayIntro,
			AllowItemCards:     item.AllowItemCards,
			AllowCoupons:       item.AllowCoupons,
		}
		ctx.Payload(rsp)
	}
}

type copyActivityResponse struct {
	NewActivityID int64  `json:"new_activity_id"`
	Status        string `json:"status"`
}

// CopyActivity 复制活动
// @Summary 复制活动
// @Description 根据活动ID深度复制期次与奖品，生成新的活动
// @Tags 管理端.活动
// @Accept json
// @Produce json
// @Param activity_id path integer true "活动ID"
// @Success 200 {object} copyActivityResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/activities/{activity_id}/copy [post]
// @Security LoginVerifyToken
func (h *handler) CopyActivity() core.HandlerFunc {
	return func(ctx core.Context) {
		res := new(copyActivityResponse)

		if ctx.SessionUserInfo().IsSuper != 1 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateActivityError, "禁止操作"))
			return
		}

		id, err := strconv.ParseInt(ctx.Param("activity_id"), 10, 64)
		if err != nil || id <= 0 {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID"))
			return
		}

		newID, err := h.activity.CopyActivity(ctx.RequestContext(), id)
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateActivityError, err.Error()))
			return
		}

		res.NewActivityID = newID
		res.Status = "success"
		ctx.Payload(res)
	}
}

type listActivitiesRequest struct {
	Name       string `form:"name"`
	CategoryID int64  `form:"category_id"`
	IsBoss     int32  `form:"is_boss"`
	Status     int32  `form:"status"`
	Page       int    `form:"page"`
	PageSize   int    `form:"page_size"`
}

type activityItem struct {
	ID                 int64  `json:"id"`
	Name               string `json:"name"`
	Banner             string `json:"banner"`
	Image              string `json:"image"`
	ActivityCategoryID int64  `json:"activity_category_id"`
	CategoryName       string `json:"category_name"`
	Status             int32  `json:"status"`
	PriceDraw          int64  `json:"price_draw"`
	IsBoss             int32  `json:"is_boss"`
	PlayType           string `json:"play_type"`
}

type listActivitiesResponse struct {
	Page     int            `json:"page"`
	PageSize int            `json:"page_size"`
	Total    int64          `json:"total"`
	List     []activityItem `json:"list"`
}

// ListActivities 活动列表
// @Summary 活动列表
// @Description 获取活动列表，支持分类、Boss、状态过滤与分页
// @Tags 管理端.活动
// @Accept json
// @Produce json
// @Param name query string false "活动名称(模糊)"
// @Param category_id query int false "活动分类ID"
// @Param is_boss query int false "是否Boss(0/1)"
// @Param status query int false "状态(1进行中 2下线)"
// @Param page query int true "页码" default(1)
// @Param page_size query int true "每页数量，最多100" default(20)
// @Success 200 {object} listActivitiesResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/activities [get]
// @Security LoginVerifyToken
func (h *handler) ListActivities() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(listActivitiesRequest)
		res := new(listActivitiesResponse)
		if err := ctx.ShouldBindForm(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}
		var isBossPtr *int32
		if req.IsBoss == 0 || req.IsBoss == 1 {
			isBossPtr = &req.IsBoss
		}
		var statusPtr *int32
		if req.Status == 1 || req.Status == 2 {
			statusPtr = &req.Status
		}
		items, total, err := h.activity.ListActivities(ctx.RequestContext(), struct {
			Name       string
			CategoryID int64
			IsBoss     *int32
			Status     *int32
			Page       int
			PageSize   int
		}{Name: req.Name, CategoryID: req.CategoryID, IsBoss: isBossPtr, Status: statusPtr, Page: req.Page, PageSize: req.PageSize})
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListActivitiesError, err.Error()))
			return
		}
		res.Page = req.Page
		res.PageSize = req.PageSize
		res.Total = total
		res.List = make([]activityItem, len(items))
		// collect category ids
		var catIDs []int64
		catSet := make(map[int64]struct{})
		for _, v := range items {
			if v.ActivityCategoryID != 0 {
				if _, ok := catSet[v.ActivityCategoryID]; !ok {
					catSet[v.ActivityCategoryID] = struct{}{}
					catIDs = append(catIDs, v.ActivityCategoryID)
				}
			}
		}
		nameMap, _ := h.activity.GetCategoryNames(ctx.RequestContext(), catIDs)
		for i, v := range items {
			res.List[i] = activityItem{
				ID:                 v.ID,
				Name:               v.Name,
				Banner:             v.Banner,
				Image:              v.Image,
				ActivityCategoryID: v.ActivityCategoryID,
				CategoryName:       nameMap[v.ActivityCategoryID],
				Status:             v.Status,
				PriceDraw:          v.PriceDraw,
				IsBoss:             v.IsBoss,
				PlayType:           v.PlayType,
			}
		}
		ctx.Payload(res)
	}
}
