package lotterymanage

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	model "go-admin/app/admin/models"
	orm "go-admin/common/global"
	"go-admin/logger"
	"go-admin/tools/app"
	"gorm.io/gorm"
	"net/http"
	"time"
)

// GetPublicLotteryConfigHandler 查询抽奖配置（公开接口）
// @Summary 查询抽奖模块配置（公开）
// @Tags 积分抽奖，V1.5.0
// @Produce json
// @Success 200 {object} models.LotteryConfig
// @Router /api/v1/lottery/config/public [post]
func GetPublicLotteryConfigHandler(c *gin.Context) {
	cfg, err := model.GetLotteryConfig()
	if err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "获取抽奖配置失败")
		return
	}

	app.OK(c, cfg, "配置更新成功")
}

// UpdateLotteryConfig 更新抽奖参数配置
// @Summary 更新积分抽奖参数配置
// @Tags 积分抽奖，V1.5.0
// @Accept json
// @Produce json
// @Param data body models.UpdateLotteryConfigRequest true "抽奖配置"
// @Success 200 {object} app.Response
// @Router /api/v1/lottery/config/update [post]
func UpdateLotteryConfig(c *gin.Context) {
	var req model.UpdateLotteryConfigRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
		return
	}

	// 转为 JSON 字符串
	valueBytes, err := json.Marshal(req)
	if err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "配置序列化失败")
		return
	}

	// 尝试读取是否已有记录
	var config model.Config
	tx := orm.Eloquent
	err = tx.Where("name = ?", model.ConfigNameLotteryLimit).First(&config).Error

	if errors.Is(err, gorm.ErrRecordNotFound) {
		// 不存在则创建
		newCfg := model.Config{
			Name:  model.ConfigNameLotteryLimit,
			Value: string(valueBytes),
		}
		if err := tx.Create(&newCfg).Error; err != nil {
			app.Error(c, http.StatusInternalServerError, nil, "创建配置失败: "+err.Error())
			return
		}
	} else if err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "查询配置失败: "+err.Error())
		return
	} else {
		// 存在则更新
		if err := tx.Model(&config).
			Update("value", string(valueBytes)).Error; err != nil {
			app.Error(c, http.StatusInternalServerError, nil, "更新配置失败: "+err.Error())
			return
		}
	}

	app.OK(c, nil, "配置更新成功")
}

// CreateLotteryPrize 创建奖品
// @Summary 创建奖品
// @Tags 积分抽奖，V1.5.0
// @Accept json
// @Produce json
// @Param data body models.CreatePrizeRequest true "奖品信息"
// @Success 200 {object} models.CreatePrizeResp
// @Router /api/v1/lottery/prize/create [post]
func CreateLotteryPrize(c *gin.Context) {
	var req model.CreatePrizeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
		return
	}

	prize := model.LotteryPrize{
		Name:             req.Name,
		PrizeType:        req.PrizeType,
		PrizeValue:       req.PrizeValue,
		Level:            req.Level,
		Weight:           req.Weight,
		Stock:            req.Stock,
		Status:           req.Status,
		UnlockUserCount:  req.UnlockUserCount,
		UnlockTotalCount: req.UnlockTotalCount,
		DailyAmountLimit: req.DailyAmountLimit,
		Images:           req.Images,
	}

	if err := orm.Eloquent.Create(&prize).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "创建失败: "+err.Error())
		return
	}

	app.OK(c, model.CreatePrizeResp{ID: prize.ID}, "创建成功")
}

// UpdateLotteryPrize 编辑奖品
// @Summary 编辑奖品
// @Tags 积分抽奖，V1.5.0
// @Accept json
// @Produce json
// @Param data body models.UpdatePrizeRequest true "奖品信息"
// @Success 200 {object} models.CreatePrizeResp
// @Router /api/v1/lottery/prize/update [post]
func UpdateLotteryPrize(c *gin.Context) {
	var req model.UpdatePrizeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
		return
	}

	var prize model.LotteryPrize
	if err := orm.Eloquent.First(&prize, req.ID).Error; err != nil {
		app.Error(c, http.StatusNotFound, nil, "未找到该奖品")
		return
	}

	// 更新字段
	prize.Name = req.Name
	prize.PrizeType = req.PrizeType
	prize.PrizeValue = req.PrizeValue
	prize.Level = req.Level
	prize.Weight = req.Weight
	prize.Stock = req.Stock
	prize.Status = req.Status
	prize.UnlockUserCount = req.UnlockUserCount
	prize.UnlockTotalCount = req.UnlockTotalCount
	prize.DailyAmountLimit = req.DailyAmountLimit
	prize.Images = req.Images

	if err := orm.Eloquent.Save(&prize).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "更新失败: "+err.Error())
		return
	}

	app.OK(c, model.CreatePrizeResp{ID: prize.ID}, "编辑成功")
}

// DeleteLotteryPrize 删除奖品
// @Summary 删除奖品
// @Tags 积分抽奖，V1.5.0
// @Accept json
// @Produce json
// @Param data body models.DeletePrizeRequest true "奖品ID"
// @Success 200 {object} app.Response
// @Router /api/v1/lottery/prize/delete [post]
func DeleteLotteryPrize(c *gin.Context) {
	var req model.DeletePrizeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
		return
	}

	if err := orm.Eloquent.Delete(&model.LotteryPrize{}, req.ID).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "删除失败: "+err.Error())
		return
	}

	app.OK(c, nil, "删除成功")
}

// LotteryPrizeList 查询奖品列表（分页）
// @Summary 查询奖品列表
// @Tags 积分抽奖，V1.5.0
// @Accept json
// @Produce json
// @Param data body models.PrizeListRequest true "查询参数"
// @Success 200 {object} models.PrizeListResponse
// @Router /api/v1/lottery/prize/list [post]
func LotteryPrizeList(c *gin.Context) {
	var req model.PrizeListRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误")
		return
	}

	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}

	// 查询启用状态奖品的总权重（或根据筛选条件的权重）
	weightDB := orm.Eloquent.Model(&model.LotteryPrize{})
	if req.Status != 0 {
		weightDB = weightDB.Where("status = ?", req.Status)
	}
	if req.Level > 0 {
		weightDB = weightDB.Where("level = ?", req.Level)
	}
	if req.Name != "" {
		weightDB = weightDB.Where("name LIKE ?", "%"+req.Name+"%")
	}

	var totalWeight int64
	row := weightDB.Select("SUM(weight)").Row()
	if err := row.Scan(&totalWeight); err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "计算总权重失败")
		return
	}

	// 查询分页数据
	db := orm.Eloquent.Model(&model.LotteryPrize{})
	if req.Name != "" {
		db = db.Where("name LIKE ?", "%"+req.Name+"%")
	}
	if req.Status != 0 {
		db = db.Where("status = ?", req.Status)
	}
	if req.Level > 0 {
		db = db.Where("level = ?", req.Level)
	}

	var total int64
	if err := db.Count(&total).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "查询总数失败")
		return
	}

	var list []model.LotteryPrize
	if err := db.Order("id ASC").
		Offset((req.Page - 1) * req.PageSize).
		Limit(req.PageSize).
		Find(&list).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "查询失败")
		return
	}

	// 动态计算中奖概率，避免小概率显示为 0.00%
	if totalWeight > 0 {
		for i := range list {
			rate := float64(list[i].Weight) / float64(totalWeight) * 100
			switch {
			case rate >= 1:
				list[i].Probability = fmt.Sprintf("%.2f%%", rate)
			case rate >= 0.01:
				list[i].Probability = fmt.Sprintf("%.4f%%", rate)
			default:
				list[i].Probability = fmt.Sprintf("%.6f%%", rate)
			}
			list[i].Probability = model.TrimTrailingZerosFromPercent(list[i].Probability)
		}
	} else {
		for i := range list {
			list[i].Probability = "0.000000%"
		}
	}

	resp := model.PrizeListResponse{
		List:     list,
		Total:    total,
		Page:     req.Page,
		PageSize: req.PageSize,
	}
	app.OK(c, resp, "查询成功")
}

// LotteryRecordList 查询抽奖记录列表
// @Summary 查询抽奖记录列表
// @Tags 积分抽奖，V1.5.0
// @Accept json
// @Produce json
// @Param data body models.LotteryRecordListRequest true "查询参数"
// @Success 200 {object} models.LotteryRecordListResponse
// @Router /api/v1/lottery/record/list [post]
func LotteryRecordList(c *gin.Context) {
	var req model.LotteryRecordListRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误")
		return
	}

	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}

	db := orm.Eloquent.Model(&model.LotteryRecord{}).
		Select(`lottery_record.id,
			lottery_record.created_at,
			lottery_record.updated_at,
			lottery_record.deleted_at,
			lottery_record.uid,
			lottery_record.prize_id,
			lottery_record.prize_name,
			lottery_record.prize_type,
			lottery_record.prize_level,
			lottery_record.prize_value,
			lottery_record.status,
			lottery_record.is_win,
			user.tel,
			user.store_id as store_id,
			user.member_level,
			store.name as store_name`).
		Joins("LEFT JOIN user ON user.uid = lottery_record.uid").
		Joins("LEFT JOIN store ON store.id = user.store_id")

	// 构建基础查询
	query := orm.Eloquent.Model(&model.LotteryRecord{}).
		Select(`lottery_record.id,
			lottery_record.created_at,
			lottery_record.updated_at,
			lottery_record.deleted_at,
			lottery_record.uid,
			lottery_record.prize_id,
			lottery_record.prize_name,
			lottery_record.prize_type,
			lottery_record.prize_level,
			lottery_record.prize_value,
			lottery_record.status,
			lottery_record.is_win,
			user.tel,
			user.store_id as store_id,
			user.member_level,
			store.name as store_name`).
		Joins("LEFT JOIN user ON user.uid = lottery_record.uid").
		Joins("LEFT JOIN store ON store.id = user.store_id")

	// 条件过滤
	if req.Uid > 0 {
		db = db.Where("lottery_record.uid = ?", req.Uid)
		query = query.Where("lottery_record.uid = ?", req.Uid)
	}
	if req.Tel != "" {
		db = db.Where("user.tel = ?", req.Tel)
		query = query.Where("user.tel = ?", req.Tel)
	}
	if req.StoreId > 0 {
		db = db.Where("user.store_id = ?", req.StoreId)
		query = query.Where("user.store_id = ?", req.StoreId)
	}
	if req.MemberLevel > 0 {
		db = db.Where("user.member_level = ?", req.MemberLevel)
		query = query.Where("user.member_level = ?", req.MemberLevel)
	}
	if req.PrizeLevel > 0 {
		db = db.Where("lottery_record.prize_level = ?", req.PrizeLevel)
		query = query.Where("lottery_record.prize_level = ?", req.PrizeLevel)
	}
	if req.StartTime != "" {
		t, err := time.Parse(model.QueryTimeFormat, req.StartTime)
		if err == nil {
			db = db.Where("lottery_record.created_at >= ?", t)
			query = query.Where("lottery_record.created_at >= ?", t)
		}
	}
	// 根据 win_status 筛选记录：0=全部，1=已中奖，2=未中奖
	switch req.WinStatus {
	case 1:
		db = db.Where("lottery_record.is_win = ?", true)
	case 2:
		db = db.Where("lottery_record.is_win = ?", false)
	}
	if req.EndTime != "" {
		t, err := time.Parse(model.QueryTimeFormat, req.EndTime)
		if err == nil {
			db = db.Where("lottery_record.created_at <= ?", t.Add(24*time.Hour))
			query = query.Where("lottery_record.created_at <= ?", t.Add(24*time.Hour))
		}
	}

	var total int64
	if err := query.Count(&total).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "统计失败")
		return
	}

	var list []model.LotteryRecordWithUserInfo
	if err := db.Order("lottery_record.id DESC").
		Offset((req.Page - 1) * req.PageSize).
		Limit(req.PageSize).
		Scan(&list).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "查询失败")
		return
	}

	app.OK(c, model.LotteryRecordListResponse{
		List:     list,
		Total:    total,
		Page:     req.Page,
		PageSize: req.PageSize,
	}, "查询成功")
}

// LotteryPrizeOrderList 查询抽奖订单列表
// @Summary 查询抽奖订单列表
// @Tags 积分抽奖，V1.5.0
// @Accept json
// @Produce json
// @Param data body models.LotteryPrizeOrderListRequest true "查询参数"
// @Success 200 {object} models.LotteryPrizeOrderListResponse
// @Router /api/v1/lottery/prize_order/list [post]
func LotteryPrizeOrderList(c *gin.Context) {
	var req model.LotteryPrizeOrderListRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误")
		return
	}

	if req.Page <= 0 {
		req.Page = 1
	}
	if req.PageSize <= 0 {
		req.PageSize = 10
	}

	db := orm.Eloquent.Model(&model.LotteryPrizeOrder{}).
		Select(`lottery_prize_order.*,
			user.tel,
			user.store_id as store_id,
			user.member_level,
			store.name as store_name`).
		Joins("LEFT JOIN user ON user.uid = lottery_prize_order.uid").
		Joins("LEFT JOIN store ON store.id = user.store_id")

	// 筛选条件
	if req.Uid > 0 {
		db = db.Where("lottery_prize_order.uid = ?", req.Uid)
	}
	if req.Tel != "" {
		db = db.Where("lottery_prize_order.tel = ?", req.Tel)
	}
	if req.StoreId > 0 {
		db = db.Where("user.store_id = ?", req.StoreId)
	}
	if req.MemberLevel > 0 {
		db = db.Where("user.member_level = ?", req.MemberLevel)
	}
	if req.PrizeName != "" {
		db = db.Where("lottery_prize_order.prize_name LIKE ?", "%"+req.PrizeName+"%")
	}
	if req.Status != model.LotteryPrizeOrderStatusAll {
		db = db.Where("lottery_prize_order.status = ?", req.Status)
	}
	if req.StartTime != "" {
		t, err := time.Parse(model.QueryTimeFormat, req.StartTime)
		if err == nil {
			db = db.Where("lottery_prize_order.created_at >= ?", t)
		}
	}
	if req.EndTime != "" {
		t, err := time.Parse(model.QueryTimeFormat, req.EndTime)
		if err == nil {
			db = db.Where("lottery_prize_order.created_at <= ?", t.Add(24*time.Hour))
		}
	}

	// 分页统计
	var total int64
	if err := db.Count(&total).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "统计失败")
		return
	}

	var list []model.LotteryPrizeOrderItem
	if err := db.Order("lottery_prize_order.id DESC").
		Offset((req.Page - 1) * req.PageSize).
		Limit(req.PageSize).
		Scan(&list).Error; err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "查询失败")
		return
	}

	app.OK(c, model.LotteryPrizeOrderListResponse{
		List:     list,
		Total:    total,
		Page:     req.Page,
		PageSize: req.PageSize,
	}, "查询成功")
}

// GetLotteryPrizeOrderDetail 查询抽奖订单详情
// @Summary 查询抽奖订单详情
// @Tags 积分抽奖，V1.5.0
// @Accept json
// @Produce json
// @Param data body models.GetLotteryPrizeOrderDetailRequest true "查询参数"
// @Success 200 {object} models.LotteryPrizeOrderDetailResponse
// @Router /api/v1/lottery/prize_order/detail [post]
func GetLotteryPrizeOrderDetail(c *gin.Context) {
	var req model.GetLotteryPrizeOrderDetailRequest
	if err := c.ShouldBindJSON(&req); err != nil || req.OrderID == 0 {
		app.Error(c, http.StatusBadRequest, nil, "参数错误：order_id 必传")
		return
	}

	var detail model.LotteryPrizeOrderDetailResponse
	db := orm.Eloquent.Table("lottery_prize_order").
		Select(`lottery_prize_order.*,
			user.wx_name as nickname,
			user.tel,
			user.member_level,
			store.name as store_name,
			lottery_prize.prize_type,
			lottery_prize.level as prize_level,
			lottery_prize.prize_value`).
		Joins("LEFT JOIN user ON user.uid = lottery_prize_order.uid").
		Joins("LEFT JOIN store ON store.id = user.store_id").
		Joins("LEFT JOIN lottery_prize ON lottery_prize.id = lottery_prize_order.prize_id").
		Where("lottery_prize_order.id = ?", req.OrderID)

	if err := db.First(&detail).Error; err != nil {
		app.Error(c, http.StatusNotFound, nil, "未找到对应的订单记录")
		return
	}

	app.OK(c, detail, "查询成功")
}

// ShipLotteryPrizeOrder 抽奖订单发货
// @Summary 抽奖订单发货
// @Tags 积分抽奖，V1.5.0
// @Accept json
// @Produce json
// @Param data body models.ShipLotteryPrizeOrderRequest true "查询参数"
// @Success 200 {object} app.Response
// @Router /api/v1/lottery/prize_order/ship [post]
func ShipLotteryPrizeOrder(c *gin.Context) {
	var req model.ShipLotteryPrizeOrderRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误："+err.Error())
		return
	}

	sysUser, err := model.GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}

	var order model.LotteryPrizeOrder
	if err := orm.Eloquent.First(&order, req.OrderID).Error; err != nil {
		app.Error(c, http.StatusNotFound, nil, "订单不存在")
		return
	}

	if order.Status != 0 {
		app.Error(c, http.StatusBadRequest, nil, "订单状态不为待发货，无法发货")
		return
	}

	err = orm.Eloquent.Model(&order).Updates(map[string]interface{}{
		"deliver_shopper_code": sysUser.UserId,
		"deliver_shopper_name": sysUser.NickName,
		"logistics_company":    req.LogisticsCompany,
		"logistics_number":     req.LogisticsNumber,
		"shipped_at":           time.Now(),
		"status":               1, // 已发货
	}).Error

	if err != nil {
		app.Error(c, http.StatusInternalServerError, nil, "发货失败："+err.Error())
		return
	}

	app.OK(c, nil, "发货成功")
}

// PickupLotteryPrizeOrder 抽奖订单门店自提
// @Summary 抽奖订单门店自提
// @Tags 积分抽奖，V1.5.0
// @Accept json
// @Produce json
// @Param data body models.PickupLotteryPrizeOrderRequest true "查询参数"
// @Success 200 {object} app.Response
// @Router /api/v1/lottery/prize_order/pickup [post]
func PickupLotteryPrizeOrder(c *gin.Context) {
	var req model.PickupLotteryPrizeOrderRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, http.StatusBadRequest, nil, "参数错误："+err.Error())
		return
	}

	var order model.LotteryPrizeOrder
	if err := orm.Eloquent.First(&order, req.OrderID).Error; err != nil {
		app.Error(c, http.StatusNotFound, nil, "订单不存在")
		return
	}

	if order.Status != 0 {
		app.Error(c, http.StatusBadRequest, nil, "订单状态不为待提货，无法确认自提")
		return
	}

	sysUser, err := model.GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		app.Error(c, http.StatusInternalServerError, err, "操作失败")
		return
	}

	// 开启事务，保证订单和记录一起更新
	tx := orm.Eloquent.Begin()

	// 更新订单状态为已收货
	if err = tx.Model(&order).Updates(map[string]interface{}{
		"deliver_shopper_code": sysUser.UserId,
		"deliver_shopper_name": sysUser.NickName,
		"status":               2, // 已收货
		"received_at":          time.Now(),
		"shipped_at":           time.Now(),
		"logistics_company":    "门店自提",
	}).Error; err != nil {
		tx.Rollback()
		app.Error(c, http.StatusInternalServerError, nil, "更新订单状态失败："+err.Error())
		return
	}

	// 更新对应的 LotteryRecord 状态为已发放
	if err = tx.Model(&model.LotteryRecord{}).
		Where("id = ?", order.RecordId).
		Update("status", 1).Error; err != nil {
		tx.Rollback()
		app.Error(c, http.StatusInternalServerError, nil, "更新抽奖记录状态失败："+err.Error())
		return
	}

	err = tx.Commit().Error
	if err != nil {
		tx.Rollback()
		app.Error(c, http.StatusInternalServerError, nil, "更新状态失败："+err.Error())
		return
	}

	app.OK(c, nil, "门店自提成功")
}
