package controllers

import (
	"annual-lottery/models"
	"annual-lottery/models/model"
	"annual-lottery/utils"
	"encoding/json"
	"errors"
	"net/http"
	"strconv"

	"github.com/astaxie/beego"
)

// LotteryController 基础controller
type LotteryController struct {
	dao *models.LotteryModel
	BaseController
}

// Constructor 初始化
func (c *LotteryController) Constructor() {
	c.dao = new(models.LotteryModel)
}

// UserList 获取人员名单
// @router /user [get]
func (c *LotteryController) UserList() {
	users, err := c.dao.UserList()
	if err != nil {
		beego.Error("获取人员名单失败,", err)
		c.ResponseJson(errors.New("获取人员名单失败"))
		return
	}

	c.ResponseJson(map[string]interface{}{
		"users": users,
	})
}

// PrizeSettingList 获取抽奖设置列表
// @router /setting/prize [get]
func (c *LotteryController) PrizeSettingList() {
	ps, err := c.dao.PrizeSettingList()
	if err != nil {
		beego.Error("获取抽奖设置列表失败,", err)
		c.ResponseJson(errors.New("获取抽奖设置列表失败"))
		return
	}

	c.ResponseJson(map[string]interface{}{
		"settings": ps,
	})
}

// PrizeSetting 抽奖设置
// @router /setting/prize/?:id [post,put,delete]
func (c *LotteryController) PrizeSetting() {
	id := c.GetString(":id")
	bt := []byte(c.GetString("data"))

	ps := model.TaPrizeSetting{}
	mp := make(map[string]interface{})
	if err := json.Unmarshal(bt, &mp); err != nil {
		beego.Error("转换抽奖设置数据失败,", err)
		c.ResponseJson(errors.New("接收抽奖配置失败"))
		return
	}

	utils.Map2Struct(mp, &ps)

	switch c.Ctx.Input.Method() {
	case http.MethodPost:
		ps.SettingId = 0
		if err := c.dao.PrizeSetting(&ps, models.DATA_ADD); err != nil {
			beego.Error("新增抽奖设置失败,", err)
			c.ResponseJson(errors.New("新增抽奖设置失败"))
			return
		}
	case http.MethodPut:
		if id == "" {
			c.ResponseJson(errors.New("抽奖设置ID不能为空"), http.StatusBadRequest)
			return
		}

		ps.SettingId, _ = strconv.Atoi(id)
		if err := c.dao.PrizeSetting(&ps, models.DATA_UPDATE); err != nil {
			beego.Error("更新抽奖设置失败,", err)
			c.ResponseJson(errors.New("更新抽奖设置失败"))
			return
		}
	case http.MethodDelete:
		if id == "" {
			c.ResponseJson(errors.New("抽奖设置ID不能为空"), http.StatusBadRequest)
			return
		}

		ps.PrizeId, _ = strconv.Atoi(id)
		if err := c.dao.PrizeSetting(&ps, models.DATA_DELETE); err != nil {
			beego.Error("删除抽奖设置失败,", err)
			c.ResponseJson(errors.New("删除抽奖设置失败"))
			return
		}
	default:
		c.ResponseJson(errors.New("404"), http.StatusNotFound)
		return
	}

	// 返回最新结果
	c.PrizeSettingList()
}

// Draw 抽奖
// @router /draw [post]
func (c *LotteryController) Draw() {
	pw, err := c.dao.Draw()
	if err != nil {
		beego.Error("抽奖失败,", err)
		c.ResponseJson(errors.New("抽奖失败, 请重试"))
		return
	}

	c.ResponseJson(map[string]interface{}{
		"winner": pw,
	})
}

// PrizeList 奖品列表
// @router /prize [get]
func (c *LotteryController) PrizeList() {
	pl, err := c.dao.PrizeList()
	if err != nil {
		beego.Error("获取奖品列表失败,", err)
		c.ResponseJson(errors.New("获取奖品列表失败"))
		return
	}

	c.ResponseJson(map[string]interface{}{
		"prizes": pl,
	})
}

// PrizeEdit 奖品维护
// @router /prize/?:id [post,put,delete]
func (c *LotteryController) PrizeEdit() {
	id := c.GetString(":id")
	bt := []byte(c.GetString("data"))

	ps := model.TaPrize{}
	mp := make(map[string]interface{})
	if err := json.Unmarshal(bt, &mp); err != nil {
		beego.Error("转换奖品数据失败,", err)
		c.ResponseJson(errors.New("接收奖品数据失败"))
		return
	}

	utils.Map2Struct(mp, &ps)

	switch c.Ctx.Input.Method() {
	case http.MethodPost:
		ps.PrizeId = 0
		if err := c.dao.PrizeEdit(&ps, models.DATA_ADD); err != nil {
			beego.Error("新增奖品数据失败,", err)
			c.ResponseJson(errors.New("新增奖品数据失败"))
			return
		}
	case http.MethodPut:
		if id == "" {
			c.ResponseJson(errors.New("奖品数据ID不能为空"), http.StatusBadRequest)
			return
		}

		ps.PrizeId, _ = strconv.Atoi(id)
		if err := c.dao.PrizeEdit(&ps, models.DATA_UPDATE); err != nil {
			beego.Error("更新奖品数据失败,", err)
			c.ResponseJson(errors.New("更新奖品数据失败"))
			return
		}
	case http.MethodDelete:
		if id == "" {
			c.ResponseJson(errors.New("奖品数据ID不能为空"), http.StatusBadRequest)
			return
		}

		ps.PrizeId, _ = strconv.Atoi(id)
		if err := c.dao.PrizeEdit(&ps, models.DATA_DELETE); err != nil {
			beego.Error("删除奖品数据失败,", err)
			c.ResponseJson(errors.New("删除奖品数据失败"))
			return
		}
	default:
		c.ResponseJson(errors.New("404"), http.StatusNotFound)
		return
	}

	// 返回最新结果
	c.PrizeList()
}

// WinnerList 中奖人员名单
// @router /winner [get]
func (c *LotteryController) WinnerList() {
	typ := c.GetString("type")
	name := c.GetString("name")
	delStr := c.GetString("del")
	del, _ := strconv.Atoi(delStr)

	var wl []model.TaPrizeWinner
	var err error

	if delStr == "" {
		wl, err = c.dao.WinnerList(typ, name)
		if err != nil {
			beego.Error("获取中奖人员名单失败,", err)
			c.ResponseJson(errors.New("获取中奖人员名单失败"))
			return
		}
	} else {
		wl, err = c.dao.WinnerList(typ, name, del)
		if err != nil {
			beego.Error("获取中奖人员名单失败,", err)
			c.ResponseJson(errors.New("获取中奖人员名单失败"))
			return
		}
	}

	c.ResponseJson(map[string]interface{}{
		"winners": wl,
	})
}

// CancelWinner 作废中奖人员
// @router /winner/:uid [delete]
func (c *LotteryController) CancelWinner() {
	pid, _ := c.GetInt("pid")
	uid, _ := c.GetInt(":uid")

	if err := c.dao.CancelWinner(pid, uid); err != nil {
		beego.Error("作废中奖人员失败,", err)
		c.ResponseJson(errors.New("作废中奖人员失败"))
		return
	}

	c.ResponseJson(map[string]interface{}{
		"result": "success",
	})
}

// ExportWinners 导出中奖名单
// @router /excel/winner [get]
func (c *LotteryController) ExportWinners() {
	typ := c.GetString("type")
	del := models.STATUS_NORMAL

	wl, err := c.dao.WinnerList(typ, "", del)
	if err != nil {
		beego.Error("获取中奖人员名单失败,", err)
		c.ResponseJson(errors.New("获取中奖人员名单失败"))
		return
	}

	excel, err := utils.NewTinyXLSXEngine()
	if err != nil {
		beego.Error("导出中奖人员名单失败,", err)
		c.ResponseJson(errors.New("导出中奖人员名单失败"))
		return
	}

	excel.SetCell(
		excel.InsertRow(),
		[]string{
			"序号",
			"中奖人",
			"公司",
			"部门",
			"分类",
			"奖品",
		},
	)

	for k, w := range wl {
		row := excel.InsertRow()

		excel.SetCell(row, []string{
			strconv.Itoa(k + 1),
			w.UserName,
			w.UserOrg,
			w.UserDept,
			w.PrizeType,
			w.PrizeName,
		})
	}

	c.SaveToExcel("中奖名单.xlsx", excel)
}
