package api

import (
	"copter-train/db/model"
	"copter-train/db/repo"
	"copter-train/log"
	"errors"
	"fmt"
	"net/url"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

// 用户唯一
// db.collection.createIndex({ loginName: 1 }, { unique: true })

// 新增试题
// /admin/test/create/:scope
func CreateTest(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	// 验证是否为管理员
	isAdmin, err := IsAdmin(c, apictx)
	if err != nil {
		return nil, err
	}
	if !isAdmin {
		return nil, errors.New("没有权限")
	}
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	test := &model.Test{}
	err = c.ShouldBindJSON(test)
	if err != nil {
		log.Error(err)
		return nil, err
	}
	if test.Socre == nil {
		zero := 0
		test.Socre = &zero
	}
	test.Uid = apictx.User.ID
	test.CreateTime = time.Now()
	test.UpdateTime = time.Now()
	return repo.RepoAddDbDoc(apictx.CreateRepoCtx(), db, repo.CollectionTest, test)
}

// 删除试题
// /admin/test/delete/:id/:scope
func DeleteTest(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	// 验证是否为管理员
	isAdmin, err := IsAdmin(c, apictx)
	if err != nil {
		return nil, err
	}
	if !isAdmin {
		return nil, errors.New("没有权限")
	}
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	_id := c.Param("id")
	id, _ := primitive.ObjectIDFromHex(_id)
	if id.IsZero() {
		return nil, errors.New("id错误")
	}
	return repo.RepoDeleteDbDoc(apictx.CreateRepoCtx(), db, repo.CollectionTest, _id)
}

type BatchDeleteTestReq struct {
	Ids []string `json:"ids"`
}

func BatchDeleteTest(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	// 验证是否为管理员
	isAdmin, err := IsAdmin(c, apictx)
	if err != nil {
		return nil, err
	}
	if !isAdmin {
		return nil, errors.New("没有权限")
	}
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	var form BatchDeleteTestReq
	err = c.ShouldBindJSON(&form)
	if err != nil {
		return nil, errors.New("参数错误")
	}
	if len(form.Ids) > 0 {
		for _, id := range form.Ids {
			repo.RepoDeleteDbDoc(apictx.CreateRepoCtx(), db, repo.CollectionTest, id)
		}
	}
	return true, nil
}

// 试题列表
// /admin/test/list/:scope?content=xxx&type=判断&page=1&size=10
func TestList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	page, size, query := UtilQueryPageSize(c)
	content := c.Query("content")
	_type := c.Query("type")
	if len(content) > 0 {
		query["content"] = bson.M{"$regex": content, "$options": "$i"}
	}
	if len(_type) > 0 {
		query["type"] = bson.M{"$regex": _type, "$options": "$i"}
	}

	return repo.RepoDbPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
		Db:          db,
		CollectName: repo.CollectionTest,
		Page:        page,
		Size:        size,
		Query:       query,
		Sort:        bson.D{bson.E{Key: "createTime", Value: -1}, bson.E{Key: "_id", Value: -1}},
	})
}

// 试题详情
// /admin/test/detail/:id/:scope
func TestDetail(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	_id := c.Param("id")
	id, _ := primitive.ObjectIDFromHex(_id)
	if id.IsZero() {
		return nil, errors.New("id错误")
	}
	test := &model.Test{}
	found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
		Db:          db,
		CollectName: repo.CollectionTest,
		Query:       repo.Map{"_id": id},
	}, test)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	if !found {
		return nil, errors.New("未找到该数据")
	}
	return test, nil
}

// 更新试题
// /admin/test/update/:scope
func UpdateTest(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	// 验证是否为管理员
	isAdmin, err := IsAdmin(c, apictx)
	if err != nil {
		return nil, err
	}
	if !isAdmin {
		return nil, errors.New("没有权限")
	}
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	test := &model.Test{}
	err = c.ShouldBindJSON(test)
	if err != nil {
		log.Error(err)
		return nil, err
	}
	if test.Id.IsZero() {
		return nil, errors.New("id错误")
	}
	return repo.RepoUpdateDbSetDoc(apictx.CreateRepoCtx(), db, repo.CollectionTest, test.Id.Hex(), test)
}

// 导入试题
func ImportTest(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	isAdmin, err := IsAdmin(c, apictx)
	if err != nil {
		return nil, err
	}
	if !isAdmin {
		return nil, errors.New("没有权限")
	}
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	file, _, err := c.Request.FormFile("file")
	if err != nil {
		return nil, errors.New("文件错误")
	}
	excel, err := excelize.OpenReader(file)
	if err != nil {
		return nil, err
	}
	excelIndex := excel.GetActiveSheetIndex()
	sheetName := excel.GetSheetName(excelIndex)
	tests, err := excel.GetRows(sheetName)
	if err != nil {
		return nil, err
	}
	errors := []string{}

	if len(tests) > 0 {
		for index, ts := range tests {
			rowNum := index + 1
			// 标题行
			if index == 0 {
				continue
			}
			// 表头
			if index == 1 {
				continue
			}
			// 去除可能的空行
			if len(ts) == 0 {
				continue
			}
			// 去除可能的空行
			if len(ts[0]) == 0 {
				continue
			}
			// 问题(content) 试题类型(type)  (options)选项A 选项B 选项C 选项D 分值(score) (answer)答案
			test := &model.Test{}
			test.Content = ts[0]
			test.Uid = apictx.User.ID
			test.Type = ts[1]
			socre, _ := strconv.Atoi(ts[6])
			test.Socre = &socre
			test.Answer = ts[7]

			if ts[1] == "选择" {
				test.Options = map[string]string{
					"A": ts[2],
					"B": ts[3],
					"C": ts[4],
					"D": ts[5],
				}
			}
			if ts[1] == "判断" {
				test.Options = map[string]string{
					"T": "正确",
					"F": "错误",
				}
			}
			test.CreateTime = time.Now()
			test.UpdateTime = time.Now()

			_, err = repo.RepoAddDbDoc(apictx.CreateRepoCtx(), db, repo.CollectionTest, test)
			if err != nil {
				errors = append(errors, fmt.Sprintf("第%d行错误: %s", rowNum, "保存数据失败, 请检查数据格式是否正确"))
				log.Error(err)
			}

		}
	}

	return errors, nil
}

// 导出试题
func ExportTest(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	isAdmin, err := IsAdmin(c, apictx)
	if err != nil {
		return nil, err
	}
	if !isAdmin {
		return nil, errors.New("没有权限")
	}
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	f := excelize.NewFile()
	index, _ := f.NewSheet("Sheet1")
	f.SetActiveSheet(index)
	f.SetDefaultFont("宋体")

	testExcel := NewTestExcel(f)
	testExcel.Title = fmt.Sprintf("%s-考核试题", db)

	_, _, query := UtilQueryPageSize(c)
	// 获取试题列表
	tests := make([]*model.Test, 0)
	err = repo.RepoSeachDocs(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
		Db:          db,
		CollectName: repo.CollectionTest,
		Query:       query,
		Sort:        bson.M{"createTime": 1},
	}, &tests)
	if err != nil {
		return nil, err
	}
	testExcel.Content = tests
	fmt.Println(len(tests))
	testExcel.Draws()
	fileName := url.PathEscape(fmt.Sprintf("%s-考核试题.xlsx", db))
	c.Header("Content-Type", "application/octet-stream")
	c.Header("Content-Disposition", "attachment; filename="+fileName)
	c.Header("Content-Transfer-Encoding", "binary")

	err = f.Write(c.Writer)
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// 下载试题模板
func TestTmplate(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	db := c.Param("scope")
	fmt.Println(db)
	filename := "考核试题模板.xlsx"
	// url.PathEscape将字符串中的特殊字符进行编码，使其符合URL规范
	filename = url.PathEscape(filename)

	// 设置下载的文件名
	c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))

	// 设置文件类型
	c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")

	c.File(TESTS_TMPLATE_FILE)
	return nil, nil
}
