package router

import (
	"encoding/json"
	"exam_system/config"
	"exam_system/dao"
	"exam_system/entity"
	"exam_system/result"
	"exam_system/utils"
	"exam_system/vo"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/nats-io/nats.go"
	"github.com/xuri/excelize/v2"
)

func ExamRecord(router *RouterPlus) {

	// 添加考试记录管理(开始考试)
	router.POST("/examRecord", AddExamRecord)
	// 提交答案
	router.PUT("/examRecord", UpdateExamRecord)
	// 获取考试记录列表
	router.GET("/examRecord/list", ExamRecordList)
	// 获取考试记录
	router.GET("/examRecord/:id", GetExamRecord)
	// 导出考试记录
	//router.router.GET("/examRecord/download",)

	r := router.Group("/admin")
	{
		// 获取考试记录管理
		r.GET("/examRecord/:id", AdminGetExamRecord)

		// 获取考试记录管理列表
		r.GET("/examRecord/list", AdminExamRecordList)

		// 删除考试记录管理
		// r.DELETE("/examRecord/:ids", AdminDeleteExamRecord)

		// 导出考试记录
		r.routerGroup.GET("/examRecord/download/:id", AdminDownloadExamRecord)

	}

	go UpdateExamRecordTask()

}
func UpdateExamRecordTask() {
	config.JS.AddConsumer("EXAMS", &nats.ConsumerConfig{
		Durable: "MONITOR",
	})
	sub, err := config.JS.PullSubscribe("EXAMS.info", "MONITOR")
	if err != nil {
		fmt.Println(err)
	}

	for {
		time.Sleep(time.Second)
		// 分批从stream拉取消息一次10个
		msgs, err := sub.Fetch(100)
		if err != nil && err != nats.ErrTimeout {
			fmt.Println(err)
		}
		for _, msg := range msgs {

			var e entity.Exam
			err = json.Unmarshal(msg.Data, &e)
			if err != nil && err != nats.ErrTimeout {
				fmt.Println(err)
			}

			if e.EndAt.Before(time.Now()) {
				// 更新为
				res := dao.UpdateExamRecordTask(e.Id)
				if res.Code == result.SUCCESS.Code {
					err = msg.Ack()
					if err != nil {
						fmt.Println(err)
					}
				}
			}

		}
	}
}

func AddExamRecord(c *gin.Context) *result.Result {
	var examRecord entity.ExamRecord
	err := c.ShouldBindJSON(&examRecord)
	id, exists := c.Get("id")
	if !exists {
		return result.UNAUTHORIZED
	}
	examRecord.UserId = id.(int)
	if err != nil || examRecord.Id == 0 {
		return result.PARAM_ERROR
	}
	examRecord.Ip = strings.Split(c.Request.RemoteAddr, ":")[0]

	return dao.AddExamRecord(&examRecord)
}

func ExamRecordList(c *gin.Context) *result.Result {
	page, size, _, query, err := utils.Page(c)
	if err != nil {
		return result.PARAM_ERROR
	}
	uid, exists := c.Get("id")
	if !exists {
		return result.UNAUTHORIZED
	}
	return dao.ExamRecordList(page, size, query, uid.(int))
}

func GetExamRecord(c *gin.Context) *result.Result {
	idStr := c.Param("id")
	if idStr == "" {
		return result.UNKNOW_ERROR
	}
	id, err := strconv.Atoi(idStr)
	if err != nil {
		return result.UNKNOW_ERROR
	}

	uid, exists := c.Get("id")
	if !exists {
		return result.UNAUTHORIZED
	}
	return dao.ExamRecordDetail(id, uid.(int))
}

func UpdateExamRecord(c *gin.Context) *result.Result {
	var examRecord vo.ExamRecordVo
	err := c.ShouldBindJSON(&examRecord)
	if err != nil || examRecord.Id == 0 || examRecord.AnswerVo == nil || examRecord.Token == "" {
		return result.PARAM_ERROR
	}
	return dao.UpdateExamRecord(&examRecord)
}

func AdminGetExamRecord(c *gin.Context) *result.Result {
	idStr := c.Param("id")
	if idStr == "" {
		return result.UNKNOW_ERROR
	}
	id, err := strconv.Atoi(idStr)
	if err != nil {
		return result.UNKNOW_ERROR
	}

	return dao.AdminExamRecordDetail(id)
}

func AdminExamRecordList(c *gin.Context) *result.Result {
	page, size, _, query, err := utils.Page(c)
	examIdStr := c.Query("exam_id")
	if err != nil {
		return result.PARAM_ERROR
	}

	examId, _ := strconv.Atoi(examIdStr)
	return dao.AdminExamRecordList(page, size, query, examId)
}

func AdminDeleteExamRecord(c *gin.Context) *result.Result {
	idStr := c.Param("ids")
	if idStr == "" {
		return result.PARAM_ERROR
	}

	ids := strings.Split(idStr, ",")

	return dao.DeleteExamRecords(ids)
}

func AdminDownloadExamRecord(c *gin.Context) {

	idStr := c.Param("id")

	file, err := excelize.OpenFile(utils.ScorePath)
	if err != nil {
		c.JSON(http.StatusOK, result.UNKNOW_ERROR.SetMsg(err.Error()))
	}

	res := dao.AdminDownloadExamRecord(file, idStr)
	if res.Code != result.SUCCESS.Code {
		c.JSON(http.StatusOK, res)
	}

	c.Header("Content-Type", "application/octet-stream")
	c.Header("Content-Disposition", "attachment; filename=考生信息导出.xlsx")
	c.Header("Content-Transfer-Encoding", "binary")

	_ = file.Write(c.Writer)
}
