package controllers

import (
	"annual-lottery/utils"
	"bytes"
	"errors"
	"reflect"
	"strconv"
	"time"

	"github.com/astaxie/beego"

	"net/http"
	"net/url"
)

//Message api统一的返回消息格式
type Message struct {
	Code    int         `json:"code"`
	Message interface{} `json:"message"`
}

//BaseController 基础controller
type BaseController struct {
	beego.Controller
}

const (
	SESSION_USER = "h5.user"
	PAGENUM      = 10
	LISTPAGENUM  = 20
)

// BaseControllerInterface 项目约定的 Controller 须满足的接口
type BaseControllerInterface interface {
	Constructor()
}

//Prepare 继承beego的
func (c *BaseController) Prepare() {
	// 路由对应的实际 Controller 初始化
	c.initController()
}

// ResponseJson 自定义的JSON返回
func (c *BaseController) ResponseJson(msg interface{}, code ...int) {
	status := http.StatusOK
	if len(code) > 0 {
		status = code[0]
	}

	if reflect.ValueOf(msg).Type().String() == "*errors.errorString" {
		err := msg.(error)
		if status == http.StatusOK {
			status = http.StatusInternalServerError
		}

		c.Data["json"] = Message{status, err.Error()}
	} else {
		c.Data["json"] = Message{status, msg}
	}

	c.ServeJSON()
	// c.StopRun()
}

// initAppController 执行当前路由请求对应的 Controller 初始化
func (c *BaseController) initController() {
	if ctrl, ok := c.AppController.(BaseControllerInterface); ok {
		ctrl.Constructor()
	}
}

// UploadFile 文件上传
// @router /file [post]
func (c *BaseController) UploadFile() {
	f, h, err := c.GetFile("file")
	if err != nil {
		beego.Error("获取上传文件失败,", err)
		c.ResponseJson("获取上传文件失败")
		return
	}
	defer f.Close()

	// 出现并发问题的概率忽略
	pre := strconv.Itoa(time.Now().Nanosecond())
	fname := pre + "-" + h.Filename
	fpath := "/upload/" + pre + "-" + h.Filename
	if err := c.SaveToFile("file", "."+fpath); err != nil {
		beego.Error("转储上传文件失败,", err)
		c.ResponseJson("转储上传文件失败")
		return
	}

	c.ResponseJson(map[string]interface{}{
		"name": fname,
		"url":  fpath,
	})
}

// SaveToExcel 保存文件到 excel
// 文件不落地, 对内存开销比较大, 如果文件过大, 服务可能会崩掉
func (c *BaseController) SaveToExcel(fn string, excel *utils.TinyXLSXEngine) {
	var buf bytes.Buffer
	if err := excel.Write(&buf); err != nil {
		beego.Error("写 xlsx buffer 失败: " + err.Error())
		c.ResponseJson(errors.New("生成 excel 异常, 请重试"))
		return
	}

	c.Ctx.Output.Header("Content-Disposition", "attachment; filename="+url.QueryEscape(fn))
	c.Ctx.Output.Header("Content-Description", "File Transfer")
	c.Ctx.Output.ContentType(".xlsx")
	c.Ctx.Output.Header("Content-Transfer-Encoding", "binary")
	c.Ctx.Output.Header("Expires", "0")
	c.Ctx.Output.Header("Cache-Control", "must-revalidate")
	c.Ctx.Output.Header("Pragma", "public")

	r := bytes.NewReader(buf.Bytes())
	http.ServeContent(c.Ctx.ResponseWriter, c.Ctx.Request, fn, time.Now().Local(), r)

	// c.StopRun()
}

func (c *BaseController) Index() {
	c.TplName = "index.html"
	// c.EnableRender = true
	c.Render()
}
