package controllers

import (
	"ai_developer_admin/libs/cronjob"
	"ai_developer_admin/libs/mysql"
	"ai_developer_admin/libs/odysseus"
	"ai_developer_admin/libs/postgres"
	"ai_developer_admin/libs/redis"
	"ai_developer_admin/libs/utils"
	"ai_developer_admin/models"
	"encoding/json"
	"fmt"
	"github.com/beego/beego/orm"
	"github.com/beego/beego/v2/core/logs"
	"github.com/odysseus/cache/model"
	"net/http"
	"sort"
	"strconv"
	"strings"
	"time"
)

var format = "2006-01-02T15:04:05.000000Z"
var layout = "2006-01-02T15:04:05"

type TaskController struct {
	MainController
}

func (server *TaskController) Bills() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}

	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)

	currentTime := time.Now()
	if appRequest.EndTime == "" {
		endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, time.UTC)
		appRequest.EndTime = fmt.Sprintf(endTime.Format(format))
	}
	if appRequest.StartTime == "" {
		temp := fmt.Sprintf("-%dh", 24*7)
		m, _ := time.ParseDuration(temp)
		tempTime := currentTime.Add(m)
		tempTime = time.Date(tempTime.Year(), tempTime.Month(), tempTime.Day(), 0, 0, 0, 0, time.UTC)
		appRequest.StartTime = fmt.Sprintf(tempTime.Format(format))
	}
	startTimeIn, _ := time.Parse(layout, appRequest.StartTime)
	endTimeIn, _ := time.Parse(layout, appRequest.EndTime)
	if appRequest.Page == 0 {
		appRequest.Page = 1
	}
	if appRequest.Size == 0 {
		appRequest.Size = 10
	}
	offset := (appRequest.Page - 1) * appRequest.Size
	size := appRequest.Page * appRequest.Size

	if endTimeIn.Before(startTimeIn) {
		server.respond(models.BusinessFailed, "Start time cannot be greater than end time")
		return
	}
	startTime := fmt.Sprintf(startTimeIn.Format(format))
	endTime := fmt.Sprintf(endTimeIn.Format(format))

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("count(*)").
		From("bills").Where("worker_acc != ''")

	queryQB, _ := orm.NewQueryBuilder("mysql")
	queryQB.Select("sum(fee) AS fee", "time").
		From("bills").Where("worker_acc != ''")

	//Where("worker_acc != ''")
	if info.Role != 1 && info.Role != 2 {
		countQB.And(fmt.Sprintf("uid = '%d'", info.UserID))
		queryQB.And(fmt.Sprintf("uid = '%d'", info.UserID))
	}
	countQB.And(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	queryQB.And(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	sql := fmt.Sprintf("%s SAMPLE BY 1M ALIGN TO CALENDAR;", countQB.String())

	total, err := postgres.QueryTotal(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	logs.Debug("total = %d", total)
	var responseTasks []models.Bills
	if total == 0 {
		responseData := struct {
			Total int64       `json:"total"`
			Data  interface{} `json:"data,omitempty"`
		}{
			Total: total,
			Data:  responseTasks,
		}
		server.respond(http.StatusOK, "", responseData)
		return
	}

	queryQB.OrderBy("time").Desc()
	sql = fmt.Sprintf("%s SAMPLE BY 1M ALIGN TO CALENDAR LIMIT %d,%d;", queryQB.String(), offset, size)
	counts, err := postgres.CountTasks(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	responseData := struct {
		Total int64       `json:"total"`
		Data  interface{} `json:"data,omitempty"`
	}{
		Total: total,
		Data:  counts,
	}
	server.respond(http.StatusOK, "", responseData)
}

func (server *TaskController) BillDetails() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)

	if appRequest.Page == 0 {
		appRequest.Page = 1
	}
	if appRequest.Size == 0 {
		appRequest.Size = 10
	}
	offset := (appRequest.Page - 1) * appRequest.Size
	size := appRequest.Page * appRequest.Size

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("count(*)").
		From("bills").Where("worker_acc != ''").
		And("uid != '0'")

	queryQB, _ := orm.NewQueryBuilder("mysql")
	queryQB.Select("id", "fee", "type", "time", "result").
		From("bills").Where("worker_acc != ''").
		And("uid != '0'")

	if info.Role != 1 && info.Role != 2 {
		countQB.And(fmt.Sprintf("uid = '%d'", info.UserID))
		queryQB.And(fmt.Sprintf("uid = '%d'", info.UserID))
	}

	if appRequest.StartTime != "" && appRequest.EndTime != "" {
		temp, _ := time.Parse(layout, appRequest.StartTime)
		startTime := fmt.Sprintf(temp.Format(format))
		temp, _ = time.Parse(layout, appRequest.EndTime)
		endTime := fmt.Sprintf(temp.Format(format))
		countQB.And(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
		queryQB.And(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	}
	if appRequest.FeeCondition != 0 {
		if appRequest.FeeCondition == int(models.FeeFree) {
			countQB.And("fee <= 0")
			queryQB.And("fee <= 0")
		}
		if appRequest.FeeCondition == int(models.FeeBased) {
			countQB.And("fee > 0")
			queryQB.And("fee > 0")
		}
	}

	sql := countQB.String()
	total, err := postgres.QueryTotal(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	logs.Debug("total = %d", total)
	var responseTasks []models.Bills
	if total == 0 {
		responseData := struct {
			Total int64       `json:"total"`
			Data  interface{} `json:"data,omitempty"`
		}{
			Total: total,
			Data:  responseTasks,
		}
		server.respond(http.StatusOK, "", responseData)
		return
	}

	//qb.OrderBy("time").Desc().Offset(int(offset)).Limit(int(size))
	queryQB.OrderBy("time").Desc()
	sql = fmt.Sprintf("%s LIMIT %d,%d;", queryQB.String(), offset, size)
	data, err := postgres.QueryBills(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	for _, task := range data {
		apiPath := ""
		desc := ""
		taskId, err := strconv.Atoi(task.Type)
		if err == nil {
			taskType, err1 := odysseus.GetTaskType(int64(taskId))
			if err1 == nil {
				apiPath = taskType.ApiPath
				//desc = taskType.Desc
			}
		}

		balance, _ := odysseus.GetUserBalance(int64(info.UserID))

		reTask := models.Bills{
			Id:      task.Id,
			Type:    "txt2Img",
			Fee:     task.Fee,
			Time:    task.Time,
			Result:  task.Result,
			ApiPath: apiPath,
			Desc:    desc,
			Balance: balance,
		}
		responseTasks = append(responseTasks, reTask)
	}
	responseData := struct {
		Total int64       `json:"total"`
		Data  interface{} `json:"data,omitempty"`
	}{
		Total: total,
		Data:  responseTasks,
	}
	server.respond(http.StatusOK, "", responseData)
}

func (server *TaskController) Tasks() {
	//info, err := server.Check()
	//if err != nil {
	//	server.respond(http.StatusUnauthorized, err.Error())
	//	return
	//}

	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err := json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest, string(body))

	if appRequest.Page == 0 {
		appRequest.Page = 1
	}
	if appRequest.Size == 0 {
		appRequest.Size = 10
	}
	offset := (appRequest.Page - 1) * appRequest.Size
	size := appRequest.Page * appRequest.Size
	if appRequest.StartTime == "" && appRequest.EndTime != "" {
		server.respond(models.MissingParameter, "Missing start time")
		return
	}
	if appRequest.StartTime != "" && appRequest.EndTime == "" {
		server.respond(models.MissingParameter, "Missing end time")
		return
	}

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("count(*)").
		From("bills").Where("worker_acc != ''")

	queryQB, _ := orm.NewQueryBuilder("mysql")
	queryQB.Select("id", "fee", "type", "time", "exec_duration", "workload", "profit_acc", "worker_acc", "result").
		From("bills").Where("worker_acc != ''")

	if appRequest.StartTime != "" && appRequest.EndTime != "" {
		start, _ := time.Parse(layout, appRequest.StartTime)
		startTime := fmt.Sprintf(start.Format(format))
		end, _ := time.Parse(layout, appRequest.EndTime)
		endTime := fmt.Sprintf(end.Format(format))
		if end.Before(start) {
			server.respond(models.BusinessFailed, "Start time cannot be greater than end time")
			return
		}
		countQB.And(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
		queryQB.And(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	}
	if appRequest.ProfitAcc != "" {
		countQB.And(fmt.Sprintf("profit_acc = '%s'", appRequest.ProfitAcc))
		queryQB.And(fmt.Sprintf("profit_acc = '%s'", appRequest.ProfitAcc))
	}
	if appRequest.WorkerAcc != "" {
		countQB.And(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc))
		queryQB.And(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc))
	}

	sql := countQB.String()
	total, err := postgres.QueryTotal(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	logs.Debug("total = %d", total)
	var responseTasks []models.Bills
	if total == 0 {
		responseData := struct {
			Total int64       `json:"total"`
			Data  interface{} `json:"data,omitempty"`
		}{
			Total: total,
			Data:  responseTasks,
		}
		server.respond(http.StatusOK, "", responseData)
		return
	}

	queryQB.OrderBy("time").Desc()
	sql = fmt.Sprintf("%s LIMIT %d,%d;", queryQB.String(), offset, size)
	data, err := postgres.QueryBills(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}

	for _, task := range data {
		apiPath := ""
		model := ""
		baseModel := ""
		kind := 1
		typeDe := 1
		taskId, err := strconv.Atoi(task.Type)
		if err == nil {
			taskType, _ := odysseus.GetTaskType(int64(taskId))
			if taskType != nil {
				apiPath = taskType.ApiPath
				model = taskType.Model
				baseModel = taskType.BaseModel
				kind = taskType.Kind
				typeDe = taskType.Type
			}
		}

		reTask := models.Bills{
			Id:        task.Id,
			Type:      models.ModelType(typeDe).String(),
			Time:      task.Time,
			Result:    task.Result,
			ApiPath:   apiPath,
			Model:     model,
			BaseModel: baseModel,
			Kind:      models.TaskKind(kind).EnString(),
			//Desc:      desc,
			Workload:  task.Workload,
			ProfitAcc: task.ProfitAcc,
			WorkerAcc: task.WorkerAcc,
		}
		responseTasks = append(responseTasks, reTask)
	}
	responseData := struct {
		Total int64       `json:"total"`
		Data  interface{} `json:"data,omitempty"`
	}{
		Total: total,
		Data:  responseTasks,
	}
	server.respond(http.StatusOK, "", responseData)
}

func (server *TaskController) TasksPerDay() {
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err := json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	//if err != nil {
	//	server.respond(models.NoRequestBody, err.Error())
	//	return
	//}
	if appRequest.StartTime == "" && appRequest.EndTime != "" {
		server.respond(models.MissingParameter, "Missing start time")
		return
	}
	if appRequest.StartTime != "" && appRequest.EndTime == "" {
		server.respond(models.MissingParameter, "Missing end time")
		return
	}
	tempLayout := layout
	if appRequest.EndTime == "" && appRequest.StartTime == "" {
		tempLayout = format
	}
	currentTime := time.Now()
	if appRequest.EndTime == "" {
		endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, time.UTC)
		appRequest.EndTime = fmt.Sprintf(endTime.Format(format))
	}
	if appRequest.StartTime == "" {
		temp := fmt.Sprintf("-%dh", 24*7)
		m, _ := time.ParseDuration(temp)
		tempTime := currentTime.Add(m)
		tempTime = time.Date(tempTime.Year(), tempTime.Month(), tempTime.Day(), 0, 0, 0, 0, time.UTC)
		appRequest.StartTime = fmt.Sprintf(tempTime.Format(format))
	}
	startTimeIn, _ := time.Parse(tempLayout, appRequest.StartTime)
	endTimeIn, _ := time.Parse(tempLayout, appRequest.EndTime)

	if endTimeIn.Before(startTimeIn) {
		server.respond(models.BusinessFailed, "Start time cannot be greater than end time")
		return
	}

	startTime := fmt.Sprintf(startTimeIn.Format(format))
	endTime := fmt.Sprintf(endTimeIn.Format(format))

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("count(*)", "time").
		From("bills").Where("worker_acc != ''")

	//queryQB, _ := orm.NewQueryBuilder("mysql")
	//queryQB.Select("sum(fee) AS fee", "time").
	//	From("bills").Where("worker_acc != ''")
	countQB.And(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	//queryQB.And(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	if appRequest.ProfitAcc != "" {
		countQB.And(fmt.Sprintf("profit_acc = '%s'", appRequest.ProfitAcc))
		//queryQB.And(fmt.Sprintf("profit_acc = '%s'", appRequest.ProfitAcc))
	}
	if appRequest.WorkerAcc != "" {
		countQB.And(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc))
		//queryQB.And(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc))
	}
	sql := fmt.Sprintf("%s SAMPLE BY 1d ALIGN TO CALENDAR;", countQB.String())

	endDateIn := time.Date(endTimeIn.Year(), endTimeIn.Month(), endTimeIn.Day(), 0, 0, 0, 0, time.UTC)
	endDate := fmt.Sprintf(endDateIn.Format(format))
	dates := utils.SplitDate(startTime, endDate, format)

	//sql := fmt.Sprintf("SELECT time,count(*) FROM bills WHERE worker_acc != '' and time >= '%s' and time <= '%s' %s SAMPLE BY 1d ALIGN TO CALENDAR;", startTime, endTime, timeCondition)
	counts, err := postgres.CountTasks(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	for _, value := range dates {
		tempDate := findTime(counts, value)
		if tempDate != nil {
			reTask := models.TaskCount{
				Type:    "0",
				Time:    *tempDate,
				Count:   "0",
				ApiPath: "",
			}
			counts = append(counts, reTask)
		}
	}
	sort.Slice(counts, func(i, j int) bool {
		return counts[i].Time.Before(counts[j].Time)
	})
	server.respond(http.StatusOK, "", counts)
}

func (server *TaskController) UserTasks() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)

	if appRequest.Page == 0 {
		appRequest.Page = 1
	}
	if appRequest.Size == 0 {
		appRequest.Size = 10
	}
	offset := (appRequest.Page - 1) * appRequest.Size
	size := appRequest.Page * appRequest.Size

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("count(*)").
		From("tasks")

	queryQB, _ := orm.NewQueryBuilder("mysql")
	queryQB.Select("id", "type", "time", "fee", "in_len").
		From("tasks")
	if info.Role != 1 && info.Role != 2 {
		countQB.Where(fmt.Sprintf("uid = '%d'", info.UserID))
		queryQB.Where(fmt.Sprintf("uid = '%d'", info.UserID))
	}
	if appRequest.StartTime != "" && appRequest.EndTime != "" {
		temp, _ := time.Parse(layout, appRequest.StartTime)
		startTime := fmt.Sprintf(temp.Format(format))
		temp, _ = time.Parse(layout, appRequest.EndTime)
		endTime := fmt.Sprintf(temp.Format(format))
		if info.Role == 1 || info.Role == 2 {
			countQB.Where(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
			queryQB.Where(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
		} else {
			countQB.And(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
			queryQB.And(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
		}
	}

	sql := countQB.String()

	//sql := fmt.Sprintf("%s SAMPLE BY 1d ALIGN TO CALENDAR;", countQB.String())
	//sql := fmt.Sprintf("SELECT count(*) FROM tasks WHERE uid='%d'%s%s;", info.UserID, cond, timeCondition)
	//if info.Role == 1 || info.Role == 2 {
	//	sql = fmt.Sprintf("SELECT count(*) FROM tasks WHERE %s;", timeCondition)
	//}
	total, err := postgres.QueryTotal(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	var responseTasks []models.Bills
	if total == 0 {
		responseData := struct {
			Total int64       `json:"total"`
			Data  interface{} `json:"data,omitempty"`
		}{
			Total: total,
			Data:  responseTasks,
		}
		server.respond(http.StatusOK, "", responseData)
		return
	}

	queryQB.OrderBy("time").Desc()
	sql = fmt.Sprintf("%s  LIMIT %d,%d;", queryQB.String(), offset, size)
	//qb.Select("id", "type", "time", "fee", "in_len").From("tasks").Where("uid=?").And("time>='?'").And("time<='?").OrderBy("time").Desc().Offset(int(offset)).Limit(int(appRequest.Size))
	//sql = fmt.Sprintf("SELECT id,type,time,fee,in_len FROM tasks WHERE uid='%d'%s%s ORDER BY time DESC LIMIT %d,%d;", info.UserID, cond, timeCondition, offset, size)
	//if info.Role == 1 || info.Role == 2 {
	//	sql = fmt.Sprintf("SELECT id,type,time,fee,in_len FROM tasks WHERE %s ORDER BY time DESC LIMIT %d,%d;", timeCondition, offset, size)
	//}
	tasks, err := postgres.QueryBills(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	if len(tasks) <= 0 {
		server.respond(models.BusinessFailed, "no data")
		return
	}
	ids := ""
	for _, value := range tasks {
		ids = ids + "'" + value.Id + "'" + ","
	}
	ids = ids[:len(ids)-1]
	queryBillQB, _ := orm.NewQueryBuilder("mysql")
	queryBillQB.Select("id", "result", "time", "fee", "out_len", "task_duration").
		From("bills").Where(fmt.Sprintf("id IN(%s)", ids)).OrderBy("time").Desc()
	sql = fmt.Sprintf("%s LIMIT %d,%d;", queryBillQB.String(), offset, size)

	//first := tasks[0]
	//logs.Debug("first = ", first.Time)
	//fmt.Printf("time = %s\n", first.Time)
	//fmt.Printf("format = %s\n", first.Time.Format(format))
	//startTime = fmt.Sprintf(first.Time.Format(format))
	//last := tasks[len(tasks)-1]
	//endTime = fmt.Sprintf(last.Time.Format(format))
	//timeCondition = fmt.Sprintf(" and  time >= '%s' and time <= '%s'", endTime, startTime)

	//qb.Select("id", "out_len", "time", "fee", "result", "duration").From("bills").Where("uid=?").And("time>='?'").And("time<='?").OrderBy("time").Desc().Offset(int(offset)).Limit(int(appRequest.Size))

	//sql = fmt.Sprintf("SELECT id,time,fee,out_len,result,task_duration  FROM bills %s ORDER BY time DESC LIMIT %d,%d;", timeCondition, offset, size)
	bills, err := postgres.QueryBills(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}

	for _, task := range tasks {
		apiPath := ""
		desc := ""
		taskId, err := strconv.Atoi(task.Type)
		if err == nil {
			taskType, err1 := odysseus.GetTaskType(int64(taskId))
			if err1 == nil {
				apiPath = taskType.ApiPath
				//desc = taskType.Desc
			}
		}

		bill := findBills(bills, task.Id)

		reTask := models.Bills{
			Id:           task.Id,
			Type:         task.Type,
			Time:         task.Time,
			InLen:        task.InLen,
			OutLen:       bill.OutLen,
			TaskDuration: bill.TaskDuration,
			Result:       bill.Result,
			Fee:          bill.Fee,
			ApiPath:      apiPath,
			Desc:         desc,
		}
		responseTasks = append(responseTasks, reTask)
	}

	responseData := struct {
		Total int64       `json:"total"`
		Data  interface{} `json:"data,omitempty"`
	}{
		Total: total,
		Data:  responseTasks,
	}
	server.respond(http.StatusOK, "", responseData)
}

func findBills(bills []models.Bills, id string) models.Bills {
	for _, value := range bills {
		if strings.Compare(value.Id, id) == 0 {
			return value
		}
	}
	return models.Bills{}
}

func (server *TaskController) UserTasksPerDay() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	//if err != nil {
	//	server.respond(models.NoRequestBody, err.Error())
	//	return
	//}
	if appRequest.StartTime == "" && appRequest.EndTime != "" {
		server.respond(models.MissingParameter, "Missing start time")
		return
	}
	if appRequest.StartTime != "" && appRequest.EndTime == "" {
		server.respond(models.MissingParameter, "Missing end time")
		return
	}
	tempLayout := layout
	if appRequest.EndTime == "" && appRequest.StartTime == "" {
		tempLayout = format
	}
	currentTime := time.Now()
	if appRequest.EndTime == "" {
		endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, time.UTC)
		appRequest.EndTime = fmt.Sprintf(endTime.Format(format))
	}
	if appRequest.StartTime == "" {
		temp := fmt.Sprintf("-%dh", 24*7)
		m, _ := time.ParseDuration(temp)
		tempTime := currentTime.Add(m)
		tempTime = time.Date(tempTime.Year(), tempTime.Month(), tempTime.Day(), 0, 0, 0, 0, time.UTC)
		appRequest.StartTime = fmt.Sprintf(tempTime.Format(format))
	}
	startTimeIn, _ := time.Parse(tempLayout, appRequest.StartTime)
	endTimeIn, _ := time.Parse(tempLayout, appRequest.EndTime)

	if endTimeIn.Before(startTimeIn) {
		server.respond(models.BusinessFailed, "Start time cannot be greater than end time")
		return
	}

	startTime := fmt.Sprintf(startTimeIn.Format(format))
	endTime := fmt.Sprintf(endTimeIn.Format(format))

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("count(*)", "time").
		From("tasks").Where(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	if info.Role != 1 && info.Role != 2 {
		countQB.And(fmt.Sprintf("uid = %d", info.UserID))
	}
	sql := fmt.Sprintf("%s SAMPLE BY 1d ALIGN TO CALENDAR;", countQB.String())

	endDateIn := time.Date(endTimeIn.Year(), endTimeIn.Month(), endTimeIn.Day(), 0, 0, 0, 0, time.UTC)
	endDate := fmt.Sprintf(endDateIn.Format(format))
	dates := utils.SplitDate(startTime, endDate, format)
	//sql := fmt.Sprintf("SELECT time,count(*) FROM tasks WHERE uid='%d' and time >= '%s' and time <= '%s' SAMPLE BY 1d ALIGN TO CALENDAR;", info.UserID, startTime, endTime)
	//if info.Role == 1 || info.Role == 2 {
	//	sql = fmt.Sprintf("SELECT time,count(*) FROM tasks WHERE time >= '%s' and time <= '%s' SAMPLE BY 1d ALIGN TO CALENDAR;", startTime, endTime)
	//}
	counts, err := postgres.CountTasks(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	for _, value := range dates {
		tempDate := findTime(counts, value)
		if tempDate != nil {
			reTask := models.TaskCount{
				Type:    "0",
				Time:    *tempDate,
				Count:   "0",
				ApiPath: "",
			}
			counts = append(counts, reTask)
		}
	}
	sort.Slice(counts, func(i, j int) bool {
		return counts[i].Time.Before(counts[j].Time)
	})
	server.respond(http.StatusOK, "", counts)
}

func (server *TaskController) UserTasksPerPeriod() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	//if err != nil {
	//	server.respond(models.NoRequestBody, err.Error())
	//	return
	//}
	period := 7
	if appRequest.Period != 0 {
		period = appRequest.Period
	}
	if period != 365 {
		period = period - 1
	}
	currentTime := time.Now()
	end := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, time.UTC)
	temp := fmt.Sprintf("-%dh", 24*period)
	m, _ := time.ParseDuration(temp)
	tempTime := currentTime.Add(m)
	tempTime = time.Date(tempTime.Year(), tempTime.Month(), tempTime.Day(), 0, 0, 0, 0, time.UTC)

	startTime := fmt.Sprintf(tempTime.Format(format))
	endTime := fmt.Sprintf(end.Format(format))

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("count(*)", "time").
		From("tasks").Where(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	if info.Role != 1 && info.Role != 2 {
		countQB.And(fmt.Sprintf("uid = %d", info.UserID))
	}
	sql := fmt.Sprintf("%s SAMPLE BY 1d ALIGN TO CALENDAR;", countQB.String())

	endDateIn := time.Date(end.Year(), end.Month(), end.Day(), 0, 0, 0, 0, time.UTC)
	endDate := fmt.Sprintf(endDateIn.Format(format))
	dates := utils.SplitDate(startTime, endDate, format)

	if period == 365 {
		sql = fmt.Sprintf("%s SAMPLE BY 1M ALIGN TO CALENDAR;", countQB.String())
		if tempTime.Day() != 1 {
			tempTime = tempTime.AddDate(0, 1, 0)
		}
		dates = utils.YearMonthRange(tempTime, endDateIn, format)
	}

	counts, err := postgres.CountTasks(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	for _, value := range dates {
		tempDate := findTime(counts, value)
		if tempDate != nil {
			reTask := models.TaskCount{
				Type:    "0",
				Time:    *tempDate,
				Count:   "0",
				ApiPath: "",
			}
			counts = append(counts, reTask)
		}
	}
	sort.Slice(counts, func(i, j int) bool {
		return counts[i].Time.Before(counts[j].Time)
	})
	server.respond(http.StatusOK, "", counts)
}

func (server *TaskController) UserTaskTypePerDay() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	//if err != nil {
	//	server.respond(models.NoRequestBody, err.Error())
	//	return
	//}
	if appRequest.StartTime == "" && appRequest.EndTime != "" {
		server.respond(models.MissingParameter, "Missing start time")
		return
	}
	if appRequest.StartTime != "" && appRequest.EndTime == "" {
		server.respond(models.MissingParameter, "Missing end time")
		return
	}
	tempLayout := layout
	if appRequest.EndTime == "" && appRequest.StartTime == "" {
		tempLayout = format
	}
	currentTime := time.Now()
	if appRequest.EndTime == "" {
		endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, time.UTC)
		appRequest.EndTime = fmt.Sprintf(endTime.Format(format))
	}
	if appRequest.StartTime == "" {
		temp := fmt.Sprintf("-%dh", 24*7)
		m, _ := time.ParseDuration(temp)
		tempTime := currentTime.Add(m)
		tempTime = time.Date(tempTime.Year(), tempTime.Month(), tempTime.Day(), 0, 0, 0, 0, time.UTC)
		appRequest.StartTime = fmt.Sprintf(tempTime.Format(format))
	}
	startTimeIn, _ := time.Parse(tempLayout, appRequest.StartTime)
	endTimeIn, _ := time.Parse(tempLayout, appRequest.EndTime)
	if endTimeIn.Before(startTimeIn) {
		server.respond(models.BusinessFailed, "Start time cannot be greater than end time")
		return
	}

	startTime := fmt.Sprintf(startTimeIn.Format(format))
	endTime := fmt.Sprintf(endTimeIn.Format(format))

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("count(*)", "time", "type").
		From("tasks").Where(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	if info.Role != 1 && info.Role != 2 {
		countQB.And(fmt.Sprintf("uid = %d", info.UserID))
	}
	sql := fmt.Sprintf("%s SAMPLE BY 1d ALIGN TO CALENDAR;", countQB.String())

	endDateIn := time.Date(endTimeIn.Year(), endTimeIn.Month(), endTimeIn.Day(), 0, 0, 0, 0, time.UTC)
	endDate := fmt.Sprintf(endDateIn.Format(format))
	dates := utils.SplitDate(startTime, endDate, format)
	//sql := fmt.Sprintf("SELECT type, time,count(*) FROM tasks WHERE uid='%d' and time >= '%s' and time <= '%s' SAMPLE BY 1d ALIGN TO CALENDAR;", info.UserID, startTime, endTime)
	//if info.Role == 1 || info.Role == 2 {
	//	sql = fmt.Sprintf("SELECT type, time,count(*) FROM tasks WHERE time >= '%s' and time <= '%s' SAMPLE BY 1d ALIGN TO CALENDAR;", startTime, endTime)
	//}
	counts, err := postgres.CountTasks(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	var responseTasks []models.TaskCount
	for _, task := range counts {
		apiPath := ""
		taskId, err := strconv.Atoi(task.Type)
		if err == nil {
			taskType, err1 := odysseus.GetTaskType(int64(taskId))
			if err1 == nil {
				apiPath = taskType.ApiPath
			}
		}

		reTask := models.TaskCount{
			Type:    task.Type,
			Time:    task.Time,
			Count:   task.Count,
			ApiPath: apiPath,
		}
		responseTasks = append(responseTasks, reTask)
	}
	for _, value := range dates {
		tempDate := findTime(responseTasks, value)
		if tempDate != nil {
			reTask := models.TaskCount{
				Type:    "0",
				Time:    *tempDate,
				Count:   "0",
				ApiPath: "",
			}
			responseTasks = append(responseTasks, reTask)
		}
	}
	sort.Slice(responseTasks, func(i, j int) bool {
		return responseTasks[i].Time.Before(responseTasks[j].Time)
	})

	server.respond(http.StatusOK, "", responseTasks)
}

func findTime(tasks []models.TaskCount, date string) *time.Time {
	t, _ := time.Parse(format, date)
	for _, value := range tasks {
		if utils.InSameDay(t, value.Time) {
			return nil
		}
	}
	return &t
}

func (server *TaskController) UserTaskTypePercentage() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	//if err != nil {
	//	server.respond(models.NoRequestBody, err.Error())
	//	return
	//}
	if appRequest.StartTime == "" && appRequest.EndTime != "" {
		server.respond(models.MissingParameter, "Missing start time")
		return
	}
	if appRequest.StartTime != "" && appRequest.EndTime == "" {
		server.respond(models.MissingParameter, "Missing end time")
		return
	}
	tempLayout := layout
	if appRequest.EndTime == "" && appRequest.StartTime == "" {
		tempLayout = format
	}
	period := 7
	if appRequest.Period != 0 {
		period = appRequest.Period
	}
	if period != 365 {
		period = period - 1
	}
	currentTime := time.Now()
	if appRequest.EndTime == "" {
		endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, time.UTC)
		appRequest.EndTime = fmt.Sprintf(endTime.Format(format))
	}
	if appRequest.StartTime == "" {
		temp := fmt.Sprintf("-%dh", 24*period)
		m, _ := time.ParseDuration(temp)
		tempTime := currentTime.Add(m)
		tempTime = time.Date(tempTime.Year(), tempTime.Month(), tempTime.Day(), 0, 0, 0, 0, time.UTC)
		appRequest.StartTime = fmt.Sprintf(tempTime.Format(format))
	}
	startTimeIn, _ := time.Parse(tempLayout, appRequest.StartTime)
	endTimeIn, _ := time.Parse(tempLayout, appRequest.EndTime)

	if endTimeIn.Before(startTimeIn) {
		server.respond(models.BusinessFailed, "Start time cannot be greater than end time")
		return
	}

	startTime := fmt.Sprintf(startTimeIn.Format(format))
	endTime := fmt.Sprintf(endTimeIn.Format(format))
	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("count(type)", "type").
		From("tasks").Where(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	if info.Role != 1 && info.Role != 2 {
		countQB.And(fmt.Sprintf("uid = %d", info.UserID))
	}
	countQB.GroupBy("type")
	sql := countQB.String()

	//sql := fmt.Sprintf("SELECT type, count(type) FROM tasks WHERE uid='%d' and time >= '%s' and time <= '%s' GROUP BY type;", info.UserID, startTime, endTime)
	//if info.Role == 1 || info.Role == 2 {
	//	sql = fmt.Sprintf("SELECT type, count(type) FROM tasks WHERE time >= '%s' and time <= '%s' GROUP BY type;", startTime, endTime)
	//}
	counts, err := postgres.CountTasks(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	var responseTasks []models.TaskCount
	for _, task := range counts {
		apiPath := ""
		taskId, err := strconv.Atoi(task.Type)
		if err == nil {
			taskType, err1 := odysseus.GetTaskType(int64(taskId))
			if err1 == nil {
				apiPath = taskType.ApiPath
			}
		}

		reTask := models.TaskCount{
			Type:    task.Type,
			Time:    task.Time,
			Count:   task.Count,
			ApiPath: apiPath,
		}
		responseTasks = append(responseTasks, reTask)
	}
	server.respond(http.StatusOK, "", responseTasks)
}

func (server *TaskController) UserFeePerDay() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	//if err != nil {
	//	server.respond(models.NoRequestBody, err.Error())
	//	return
	//}
	if appRequest.StartTime == "" && appRequest.EndTime != "" {
		server.respond(models.MissingParameter, "Missing start time")
		return
	}
	if appRequest.StartTime != "" && appRequest.EndTime == "" {
		server.respond(models.MissingParameter, "Missing end time")
		return
	}
	tempLayout := layout
	if appRequest.EndTime == "" && appRequest.StartTime == "" {
		tempLayout = format
	}
	currentTime := time.Now()
	if appRequest.EndTime == "" {
		endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, time.UTC)
		appRequest.EndTime = fmt.Sprintf(endTime.Format(format))
	}
	if appRequest.StartTime == "" {
		temp := fmt.Sprintf("-%dh", 24*7)
		m, _ := time.ParseDuration(temp)
		tempTime := currentTime.Add(m)
		tempTime = time.Date(tempTime.Year(), tempTime.Month(), tempTime.Day(), 0, 0, 0, 0, time.UTC)
		appRequest.StartTime = fmt.Sprintf(tempTime.Format(format))
	}
	startTimeIn, _ := time.Parse(tempLayout, appRequest.StartTime)
	endTimeIn, _ := time.Parse(tempLayout, appRequest.EndTime)

	if endTimeIn.Before(startTimeIn) {
		server.respond(models.BusinessFailed, "Start time cannot be greater than end time")
		return
	}

	startTime := fmt.Sprintf(startTimeIn.Format(format))
	endTime := fmt.Sprintf(endTimeIn.Format(format))

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("time", "sum(fee) AS fee").
		From("bills").Where(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	if info.Role != 1 && info.Role != 2 {
		countQB.And(fmt.Sprintf("uid = %d", info.UserID))
	}
	sql := fmt.Sprintf("%s SAMPLE BY 1d ALIGN TO CALENDAR;", countQB.String())

	endDateIn := time.Date(endTimeIn.Year(), endTimeIn.Month(), endTimeIn.Day(), 0, 0, 0, 0, time.UTC)
	endDate := fmt.Sprintf(endDateIn.Format(format))
	dates := utils.SplitDate(startTime, endDate, format)

	//sql := fmt.Sprintf("SELECT time,sum(fee) AS fee FROM bills WHERE uid='%d' and time >= '%s' and time <= '%s' SAMPLE BY 1d ALIGN TO CALENDAR;", info.UserID, startTime, endTime)
	//if info.Role == 1 || info.Role == 2 {
	//	sql = fmt.Sprintf("SELECT time,sum(fee) AS fee FROM bills WHERE time >= '%s' and time <= '%s' SAMPLE BY 1d ALIGN TO CALENDAR;", startTime, endTime)
	//}
	counts, err := postgres.CountTasks(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	for _, value := range dates {
		tempDate := findTime(counts, value)
		if tempDate != nil {
			reTask := models.TaskCount{
				Type:    "0",
				Time:    *tempDate,
				Count:   "0",
				ApiPath: "",
			}
			counts = append(counts, reTask)
		}
	}
	sort.Slice(counts, func(i, j int) bool {
		return counts[i].Time.Before(counts[j].Time)
	})
	server.respond(http.StatusOK, "", counts)
}

func (server *TaskController) UserFee() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	//if err != nil {
	//	server.respond(models.NoRequestBody, err.Error())
	//	return
	//}
	//if appRequest.StartTime == "" && appRequest.EndTime != "" {
	//	server.respond(models.MissingParameter, "缺少开始时间")
	//	return
	//}
	//if appRequest.StartTime != "" && appRequest.EndTime == "" {
	//	server.respond(models.MissingParameter, "缺少结束时间")
	//	return
	//}
	//tempLayout := layout
	//if appRequest.EndTime == "" && appRequest.StartTime == "" {
	//	tempLayout = format
	//}
	//currentTime := time.Now()
	//if appRequest.EndTime == "" {
	//	endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, time.UTC)
	//	appRequest.EndTime = fmt.Sprintf(endTime.Format(format))
	//}
	//if appRequest.StartTime == "" {
	//	temp := fmt.Sprintf("-%dh", 24*7)
	//	m, _ := time.ParseDuration(temp)
	//	tempTime := currentTime.Add(m)
	//	tempTime = time.Date(tempTime.Year(), tempTime.Month(), tempTime.Day(), 0, 0, 0, 0, time.UTC)
	//	appRequest.StartTime = fmt.Sprintf(tempTime.Format(format))
	//}
	//startTimeIn, _ := time.Parse(tempLayout, appRequest.StartTime)
	//endTimeIn, _ := time.Parse(tempLayout, appRequest.EndTime)
	//
	//if endTimeIn.Before(startTimeIn) {
	//	server.respond(models.BusinessFailed, "起始时间不能大于结束时间")
	//	return
	//}
	//
	//startTime := fmt.Sprintf(startTimeIn.Format(format))
	//endTime := fmt.Sprintf(endTimeIn.Format(format))

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("sum(fee) AS fee").
		From("bills")
	if info.Role != 1 && info.Role != 2 {
		countQB.Where(fmt.Sprintf("uid = %d", info.UserID))
	}
	//sql := fmt.Sprintf("%s SAMPLE BY 1d ALIGN TO CALENDAR;", countQB.String())
	sql := countQB.String()

	//endDateIn := time.Date(endTimeIn.Year(), endTimeIn.Month(), endTimeIn.Day(), 0, 0, 0, 0, time.UTC)
	//endDate := fmt.Sprintf(endDateIn.Format(format))
	//dates := utils.SplitDate(startTime, endDate, format)

	//sql := fmt.Sprintf("SELECT time,sum(fee) AS fee FROM bills WHERE uid='%d' and time >= '%s' and time <= '%s' SAMPLE BY 1d ALIGN TO CALENDAR;", info.UserID, startTime, endTime)
	//if info.Role == 1 || info.Role == 2 {
	//	sql = fmt.Sprintf("SELECT time,sum(fee) AS fee FROM bills WHERE time >= '%s' and time <= '%s' SAMPLE BY 1d ALIGN TO CALENDAR;", startTime, endTime)
	//}
	counts, err := postgres.CountTasks(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	fee := int64(0)
	for _, value := range counts {
		fee, _ = strconv.ParseInt(value.Fee, 10, 64)
	}
	fee = fee / 1000000
	data := struct {
		Fee int64 `json:"fee"`
	}{
		Fee: fee,
	}
	//sort.Slice(counts, func(i, j int) bool {
	//	return counts[i].Time.Before(counts[j].Time)
	//})
	server.respond(http.StatusOK, "", data)
}

func (server *TaskController) UserTaskTypeFeePerDay() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	//if err != nil {
	//	server.respond(models.NoRequestBody, err.Error())
	//	return
	//}
	if appRequest.StartTime == "" && appRequest.EndTime != "" {
		server.respond(models.MissingParameter, "Missing start time")
		return
	}
	if appRequest.StartTime != "" && appRequest.EndTime == "" {
		server.respond(models.MissingParameter, "Missing end time")
		return
	}
	tempLayout := layout
	if appRequest.EndTime == "" && appRequest.StartTime == "" {
		tempLayout = format
	}
	currentTime := time.Now()
	if appRequest.EndTime == "" {
		endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, time.UTC)
		appRequest.EndTime = fmt.Sprintf(endTime.Format(format))
	}
	if appRequest.StartTime == "" {
		temp := fmt.Sprintf("-%dh", 24*7)
		m, _ := time.ParseDuration(temp)
		tempTime := currentTime.Add(m)
		tempTime = time.Date(tempTime.Year(), tempTime.Month(), tempTime.Day(), 0, 0, 0, 0, time.UTC)
		appRequest.StartTime = fmt.Sprintf(tempTime.Format(format))
	}
	startTimeIn, _ := time.Parse(tempLayout, appRequest.StartTime)
	endTimeIn, _ := time.Parse(tempLayout, appRequest.EndTime)

	if endTimeIn.Before(startTimeIn) {
		server.respond(models.BusinessFailed, "Start time cannot be greater than end time")
		return
	}

	startTime := fmt.Sprintf(startTimeIn.Format(format))
	endTime := fmt.Sprintf(endTimeIn.Format(format))

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("time", "sum(fee) AS fee", "type").
		From("bills").Where(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	if info.Role != 1 && info.Role != 2 {
		countQB.And(fmt.Sprintf("uid = %d", info.UserID))
	}
	sql := fmt.Sprintf("%s SAMPLE BY 1d ALIGN TO CALENDAR;", countQB.String())

	endDateIn := time.Date(endTimeIn.Year(), endTimeIn.Month(), endTimeIn.Day(), 0, 0, 0, 0, time.UTC)
	endDate := fmt.Sprintf(endDateIn.Format(format))
	dates := utils.SplitDate(startTime, endDate, format)

	//sql := fmt.Sprintf("SELECT type, time,sum(fee) AS fee FROM bills WHERE uid='%d' and time >= '%s' and time <= '%s' SAMPLE BY 1d ALIGN TO CALENDAR;", info.UserID, startTime, endTime)
	//if info.Role == 1 || info.Role == 2 {
	//	sql = fmt.Sprintf("SELECT type, time,sum(fee) AS fee FROM bills WHERE time >= '%s' and time <= '%s' SAMPLE BY 1d ALIGN TO CALENDAR;", startTime, endTime)
	//}
	counts, err := postgres.CountTasks(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	var responseTasks []models.TaskCount
	for _, task := range counts {
		apiPath := ""
		taskId, err := strconv.Atoi(task.Type)
		if err == nil {
			taskType, err1 := odysseus.GetTaskType(int64(taskId))
			if err1 == nil {
				apiPath = taskType.ApiPath
			}
		}

		reTask := models.TaskCount{
			Type:    task.Type,
			Time:    task.Time,
			Fee:     task.Fee,
			ApiPath: apiPath,
		}
		responseTasks = append(responseTasks, reTask)
	}
	for _, value := range dates {
		tempDate := findTime(responseTasks, value)
		if tempDate != nil {
			reTask := models.TaskCount{
				Type:    "0",
				Time:    *tempDate,
				Fee:     "0",
				ApiPath: "",
			}
			responseTasks = append(responseTasks, reTask)
		}
	}
	sort.Slice(responseTasks, func(i, j int) bool {
		return responseTasks[i].Time.Before(responseTasks[j].Time)
	})
	server.respond(http.StatusOK, "", responseTasks)
}

func (server *TaskController) UserTaskTypeFeePercentage() {
	info, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	//if err != nil {
	//	server.respond(models.NoRequestBody, err.Error())
	//	return
	//}
	if appRequest.StartTime == "" && appRequest.EndTime != "" {
		server.respond(models.MissingParameter, "Missing start time")
		return
	}
	if appRequest.StartTime != "" && appRequest.EndTime == "" {
		server.respond(models.MissingParameter, "Missing end time")
		return
	}
	tempLayout := layout
	if appRequest.EndTime == "" && appRequest.StartTime == "" {
		tempLayout = format
	}
	currentTime := time.Now()
	if appRequest.EndTime == "" {
		endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, time.UTC)
		appRequest.EndTime = fmt.Sprintf(endTime.Format(format))
	}
	if appRequest.StartTime == "" {
		temp := fmt.Sprintf("-%dh", 24*7)
		m, _ := time.ParseDuration(temp)
		tempTime := currentTime.Add(m)
		tempTime = time.Date(tempTime.Year(), tempTime.Month(), tempTime.Day(), 0, 0, 0, 0, time.UTC)
		appRequest.StartTime = fmt.Sprintf(tempTime.Format(format))
	}
	startTimeIn, _ := time.Parse(tempLayout, appRequest.StartTime)
	endTimeIn, _ := time.Parse(tempLayout, appRequest.EndTime)

	if endTimeIn.Before(startTimeIn) {
		server.respond(models.BusinessFailed, "Start time cannot be greater than end time")
		return
	}

	startTime := fmt.Sprintf(startTimeIn.Format(format))
	endTime := fmt.Sprintf(endTimeIn.Format(format))

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("sum(fee) AS fee", "type").
		From("bills").Where(fmt.Sprintf("time >= '%s'", startTime)).And(fmt.Sprintf("time <= '%s'", endTime))
	if info.Role != 1 && info.Role != 2 {
		countQB.And(fmt.Sprintf("uid = %d", info.UserID))
	}
	countQB.GroupBy("type")
	sql := countQB.String()

	//sql := fmt.Sprintf("SELECT type, sum(fee) AS fee FROM bills WHERE uid='%d' and time >= '%s' and time <= '%s' GROUP BY type;", info.UserID, startTime, endTime)
	//if info.Role == 1 || info.Role == 2 {
	//	sql = fmt.Sprintf("SELECT type, sum(fee) AS fee FROM bills WHERE time >= '%s' and time <= '%s' GROUP BY type;", startTime, endTime)
	//}
	counts, err := postgres.CountTasks(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	var responseTasks []models.TaskCount
	for _, task := range counts {
		apiPath := ""
		taskId, err := strconv.Atoi(task.Type)
		if err == nil {
			taskType, err1 := odysseus.GetTaskType(int64(taskId))
			if err1 == nil {
				apiPath = taskType.ApiPath
			}
		}

		reTask := models.TaskCount{
			Type:    task.Type,
			Time:    task.Time,
			Count:   task.Count,
			ApiPath: apiPath,
		}
		responseTasks = append(responseTasks, reTask)
	}
	server.respond(http.StatusOK, "", responseTasks)
}

func (server *TaskController) Computility() {
	_, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest, string(body))

	if appRequest.Page == 0 {
		appRequest.Page = 1
	}
	if appRequest.Size == 0 {
		appRequest.Size = 10
	}
	offset := (appRequest.Page - 1) * appRequest.Size

	qs := mysql.GetMysqlInstace().Ormer.QueryTable("computility").Filter("deleted", 0)
	if appRequest.Type != 0 {
		qs.Filter("type", appRequest.Type)
	}
	if appRequest.Keyword != "" {
		cond := orm.NewCondition()
		cond1 := cond.Or("model__contains", appRequest.Keyword).Or("series__contains", appRequest.Keyword).Or("brand__contains", appRequest.Keyword)
		cond2 := cond.AndNotCond(cond1)
		qs = qs.SetCond(cond2)
	}
	infoQs := qs.Offset(offset).Limit(appRequest.Size)
	count, err := infoQs.Count()
	logs.Debug("lists = ", count)
	var lists []*models.Computility
	if count > 0 {
		infoQs.All(&lists)
	}
	total, err := qs.Count()
	responseData := struct {
		Total int64       `json:"total"`
		Data  interface{} `json:"data,omitempty"`
	}{
		Total: total,
		Data:  lists,
	}
	server.respond(http.StatusOK, "", responseData)
}

func (server *TaskController) AddTasktype() {
	_, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AddTaskType{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest, string(body))
	if err != nil {
		server.respond(models.NoRequestBody, err.Error())
		return
	}

	if &appRequest.TaskTypeIn == nil {
		server.respond(models.MissingParameter, "Missing type parameter")
		return
	}
	if &appRequest.TaskTypeIn.Name == nil {
		server.respond(models.MissingParameter, "Missing name parameter")
		return
	}
	if &appRequest.TaskTypeIn.Type == nil {
		server.respond(models.MissingParameter, "Missing type.type parameter")
		return
	}

	//if &appRequest.Type.Version == nil {
	//	server.respond(models.MissingParameter, "版本 不能为空")
	//	return
	//}
	if &appRequest.TaskTypeIn.BaseModel == nil {
		server.respond(models.MissingParameter, "Missing base_model parameter")
		return
	}
	//if &appRequest.Type.Version == nil {
	//	server.respond(models.MissingParameter, "基础模型 不能为空")
	//	return
	//}

	if &appRequest.Levels == nil {
		server.respond(models.MissingParameter, "Missing levels parameter")
		return
	}
	if len(appRequest.Levels) <= 0 {
		server.respond(models.MissingParameter, "levels.length is 0")
		return
	}

	//ormer := orm.NewOrm()
	if appRequest.TaskTypeIn.ResultFileExpires == 0 {
		appRequest.TaskTypeIn.ResultFileExpires = 1800
	}

	ormer := mysql.GetMysqlInstace().Ormer
	//err = ormer.Begin()
	//if err != nil {
	//	server.respond(models.BusinessFailed, "填加 task type 失败")
	//	return
	//}

	timestamp := time.Now()

	hardwareRequire, err := json.Marshal(appRequest.TaskTypeIn.HardwareRequire)
	cmd, err := json.Marshal(appRequest.TaskTypeIn.Cmd)
	//examples, err := json.Marshal(appRequest.Type.Examples)
	//apiPath := fmt.Sprintf("/%s/%s/%s", appRequest.TaskTypeIn.Type.String(), appRequest.TaskTypeIn.BaseModel, appRequest.TaskTypeIn.Model)
	//if appRequest.Type.BaseModel != "" {
	//	apiPath = fmt.Sprintf("/%s/%s", apiPath, appRequest.Type.BaseModel)
	//}
	//if appRequest.Type.Version != "" {
	//	apiPath = fmt.Sprintf("/%s/%s", apiPath, appRequest.Type.Version)
	//}
	price := int64(appRequest.TaskTypeIn.Price * 1000000)
	dbType := models.TaskType{
		Name:              appRequest.TaskTypeIn.Name,
		BaseModel:         appRequest.TaskTypeIn.BaseModel,
		Model:             appRequest.TaskTypeIn.Model,
		Version:           appRequest.TaskTypeIn.Version,
		Desc:              appRequest.TaskTypeIn.Desc,
		Price:             price,
		PublicKey:         appRequest.TaskTypeIn.PublicKey,
		Complexity:        appRequest.TaskTypeIn.Complexity,
		Type:              int(appRequest.TaskTypeIn.Type),
		Kind:              appRequest.TaskTypeIn.Kind,
		HardwareRequire:   string(hardwareRequire),
		ImageId:           appRequest.TaskTypeIn.ImageId,
		ImageUrl:          appRequest.TaskTypeIn.ImageUrl,
		Cmd:               string(cmd),
		ResultFileExpires: appRequest.TaskTypeIn.ResultFileExpires,
		Workload:          appRequest.TaskTypeIn.Workload,
		ApiPath:           appRequest.TaskTypeIn.ApiPath,
		ImageName:         appRequest.TaskTypeIn.ImageName,
		SignUrl:           appRequest.TaskTypeIn.SignUrl,
		Username:          appRequest.TaskTypeIn.Username,
		Password:          appRequest.TaskTypeIn.Password,
		Category:          appRequest.TaskTypeIn.Category,
		PublishStatus:     appRequest.TaskTypeIn.PublishStatus,
		AccessStatus:      appRequest.TaskTypeIn.AccessStatus,
		CreatedTime:       timestamp,
		UpdatedTime:       timestamp,
	}

	id, err := ormer.Insert(&dbType)
	if err != nil {
		//ormer.Rollback()
		server.respond(models.BusinessFailed, "failed")
		return
	}

	dataString, err := redis.GetDataToString(cronjob.HeatKey)
	var response []models.TaskHeat
	if err != nil {
		logs.Debug("GetDataToString err")
	}
	err = json.Unmarshal([]byte(dataString), &response)
	if err != nil {
		logs.Debug("GetDataToString Unmarshal err")
	}
	retask := models.TaskHeat{
		TaskId:          int(id),
		User:            dbType.Username,
		Pwd:             dbType.Password,
		Repository:      dbType.ImageUrl,
		SignUrl:         dbType.SignUrl,
		ImageName:       dbType.ImageName,
		ImageId:         dbType.ImageId,
		HardwareRequire: appRequest.TaskTypeIn.HardwareRequire,
		Count:           int64(0),
		Kind:            dbType.Kind,
		FileExpiresTime: strconv.Itoa(dbType.ResultFileExpires),
		AccessStatus:    dbType.AccessStatus,
		PublishStatus:   dbType.PublishStatus,
	}
	response = append(response, retask)
	data, err := json.Marshal(response)
	if err == nil {
		redis.SetKeyAndData(cronjob.HeatKey, string(data), 0)
	}

	//todo:插入model表，并且关联task_type_id
	var levels []models.UserLevelTaskType
	for _, value := range appRequest.Levels {
		temp := value
		temp.TaskTypeId = int(id)
		temp.CreatedTime = timestamp
		temp.UpdatedTime = timestamp
		levels = append(levels, temp)
	}
	_, err = ormer.InsertMulti(len(appRequest.Levels), &levels)
	if err != nil {
		//ormer.Rollback()
		server.respond(models.BusinessFailed, "failed")
		return
	}
	//err = ormer.Commit()
	//if err != nil {
	//	server.respond(models.BusinessFailed, "填加 task type 失败")
	//	return
	//}
	server.respond(http.StatusOK, "success")
}

func (server *TaskController) UpdateTaskType() {
	//todo:需要调用学前的setTaskType，然后再调用PublichTaskUpdate
	_, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AddTaskType{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	if err != nil {
		server.respond(models.NoRequestBody, err.Error())
		return
	}

	if &appRequest.TaskTypeIn == nil {
		server.respond(models.MissingParameter, "Missing type parameter")
		return
	}
	if &appRequest.TaskTypeIn.Id == nil {
		server.respond(models.MissingParameter, "Missing type.id parameter")
		return
	}
	if &appRequest.TaskTypeIn.Name == nil {
		server.respond(models.MissingParameter, "Missing name parameter")
		return
	}
	if &appRequest.TaskTypeIn.Type == nil {
		server.respond(models.MissingParameter, "Missing type.type parameter")
		return
	}
	if &appRequest.TaskTypeIn.BaseModel == nil {
		server.respond(models.MissingParameter, "Missing type.base_model parameter")
		return
	}

	if len(appRequest.Levels) > 0 {
		flag := false
		for _, value := range appRequest.Levels {
			if value.Id == 0 {
				flag = true
				break
			}
		}
		if flag {
			server.respond(models.MissingParameter, "Missing levels.id parameter")
			return
		}
	}
	if appRequest.TaskTypeIn.ResultFileExpires == 0 {
		appRequest.TaskTypeIn.ResultFileExpires = 1800
	}

	//ormer := orm.NewOrm()

	ormer := mysql.GetMysqlInstace().Ormer
	//err = ormer.Begin()
	//if err != nil {
	//	server.respond(models.BusinessFailed, "填加 task type 失败")
	//	return
	//}

	checkType := &models.TaskType{Id: appRequest.TaskTypeIn.Id}
	err = mysql.GetMysqlInstace().Ormer.Read(checkType)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}

	timestamp := time.Now()

	hardwareRequire, err := json.Marshal(appRequest.TaskTypeIn.HardwareRequire)
	cmd, err := json.Marshal(appRequest.TaskTypeIn.Cmd)
	//apiPath := fmt.Sprintf("/%s/%s/%s", appRequest.TaskTypeIn.Type.String(), appRequest.TaskTypeIn.BaseModel, appRequest.TaskTypeIn.Model)
	//apiPath := fmt.Sprintf("/%s/%s", appRequest.Type.Type.String(), appRequest.Type.Name)
	//if appRequest.Type.BaseModel != "" {
	//	apiPath = fmt.Sprintf("/%s/%s", apiPath, appRequest.Type.BaseModel)
	//}
	//if appRequest.Type.Version != "" {
	//	apiPath = fmt.Sprintf("/%s/%s", apiPath, appRequest.Type.Version)
	//}
	price := int64(appRequest.TaskTypeIn.Price * 1000000)
	dbType := models.TaskType{
		Id:                appRequest.TaskTypeIn.Id,
		Name:              appRequest.TaskTypeIn.Name,
		BaseModel:         appRequest.TaskTypeIn.BaseModel,
		Model:             appRequest.TaskTypeIn.Model,
		Version:           appRequest.TaskTypeIn.Version,
		Desc:              appRequest.TaskTypeIn.Desc,
		Price:             price,
		PublicKey:         appRequest.TaskTypeIn.PublicKey,
		Complexity:        appRequest.TaskTypeIn.Complexity,
		HardwareRequire:   string(hardwareRequire),
		ImageId:           appRequest.TaskTypeIn.ImageId,
		ImageUrl:          appRequest.TaskTypeIn.ImageUrl,
		Type:              int(appRequest.TaskTypeIn.Type),
		Kind:              appRequest.TaskTypeIn.Kind,
		Cmd:               string(cmd),
		Workload:          appRequest.TaskTypeIn.Workload,
		ApiPath:           appRequest.TaskTypeIn.ApiPath,
		ImageName:         appRequest.TaskTypeIn.ImageName,
		SignUrl:           appRequest.TaskTypeIn.SignUrl,
		Username:          appRequest.TaskTypeIn.Username,
		Password:          appRequest.TaskTypeIn.Password,
		Category:          appRequest.TaskTypeIn.Category,
		ResultFileExpires: appRequest.TaskTypeIn.ResultFileExpires,
		PublishStatus:     appRequest.TaskTypeIn.PublishStatus,
		AccessStatus:      appRequest.TaskTypeIn.AccessStatus,
		UpdatedTime:       timestamp,
	}

	_, err = ormer.Update(&dbType, "name",
		"base_model",
		"model",
		"version",
		"desc",
		"price",
		"public_key",
		"complexity",
		"hardware_require",
		"image_id",
		"image_url",
		"type",
		"kind",
		"cmd",
		"workload",
		"api_path",
		"image_name",
		"sign_url",
		"username",
		"password",
		"category",
		"result_file_expires",
		"updated_time",
		"publish_status",
		"access_status")
	if err != nil {
		//ormer.Rollback()
		server.respond(models.BusinessFailed, "failed")
		return
	}
	dataString, err := redis.GetDataToString(cronjob.HeatKey)
	var response []*models.TaskHeat
	if err != nil {
		logs.Debug("GetDataToString err")
	}
	err = json.Unmarshal([]byte(dataString), &response)
	if err != nil {
		logs.Debug("GetDataToString Unmarshal err")
	}

	var output interface{}
	if checkType.Form != "" {
		//var form interface{}
		err = json.Unmarshal([]byte(checkType.Form), &output)
		if err != nil {
			logs.Debug("Form Unmarshal err")
		}
	}
	for _, task := range response {
		if task.TaskId == dbType.Id {
			task.User = dbType.Username
			task.Pwd = dbType.Password
			task.Repository = dbType.ImageUrl
			task.SignUrl = dbType.SignUrl
			task.ImageName = dbType.ImageName
			task.ImageId = dbType.ImageId
			task.HardwareRequire = appRequest.TaskTypeIn.HardwareRequire
			task.Kind = dbType.Kind
			task.FileExpiresTime = strconv.Itoa(dbType.ResultFileExpires)
			task.OutPutJson = output
			task.AccessStatus = dbType.AccessStatus
			task.PublishStatus = dbType.PublishStatus
		}
	}
	data, err := json.Marshal(response)
	if err == nil {
		redis.SetKeyAndData(cronjob.HeatKey, string(data), 0)
	}

	//todo:插入model表，并且关联task_type_id
	//var levels []models.UserLevelTaskType
	for _, value := range appRequest.Levels {
		value.UpdatedTime = timestamp
		_, err = ormer.Update(&value)
		//if err != nil {
		//	//ormer.Rollback()
		//	//server.respond(models.BusinessFailed, "填加 task type 失败")
		//	return
		//}
	}

	//err = ormer.Commit()
	//if err != nil {
	//	server.respond(models.BusinessFailed, "填加 task type 失败")
	//	return
	//}

	task := model.TaskType{
		ID:              int64(dbType.Id),
		BaseModel:       dbType.BaseModel,
		Model:           dbType.Model,
		Desc:            dbType.Desc,
		Price:           price,
		PublicKey:       dbType.PublicKey,
		Complexity:      int64(dbType.Complexity),
		HardwareRequire: string(hardwareRequire),
		ImageId:         dbType.ImageId,
		ImageUrl:        dbType.ImageUrl,
		Type:            int(dbType.Type),
		Kind:            dbType.Kind,
		Cmd:             string(cmd),
		Workload:        int64(dbType.Workload),
		ApiPath:         dbType.ApiPath,
		ImageName:       dbType.ImageName,
		SignUrl:         dbType.SignUrl,
		Username:        dbType.Username,
		Password:        dbType.Password,
		CreatedTime:     appRequest.TaskTypeIn.CreatedTime,
		UpdatedTime:     dbType.UpdatedTime,
	}

	odysseus.SetTaskDataToRedis(&task)
	odysseus.PublichTaskUpdate(dbType.ApiPath)
	server.respond(http.StatusOK, "success")
}

func (server *TaskController) GetTaskTypes() {
	_, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}

	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest, string(body))
	//if err != nil {
	//	server.respond(models.NoRequestBody, err.Error())
	//	return
	//}

	if appRequest.Page == 0 {
		appRequest.Page = 1
	}

	if appRequest.Size == 0 {
		appRequest.Size = 10
	}
	offset := (appRequest.Page - 1) * appRequest.Size
	//size := appRequest.Page * appRequest.Size

	qs := mysql.GetMysqlInstace().Ormer.QueryTable("task_type").Filter("deleted", 0)
	infoQs := qs.Offset(offset).Limit(appRequest.Size)
	count, err := infoQs.Count()
	logs.Debug("Levels = ", count)
	var types []*models.TaskType
	if count > 0 {
		infoQs.All(&types)
	}
	var remodels []*models.NewTaskType
	for _, data := range types {
		var hardwareRequire interface{}
		eer := json.Unmarshal([]byte(data.HardwareRequire), &hardwareRequire)
		if eer != nil {

		}
		var cmd interface{}
		eer = json.Unmarshal([]byte(data.Cmd), &cmd)
		if eer != nil {

		}
		var examples interface{}
		eer = json.Unmarshal([]byte(data.Examples), &examples)
		if eer != nil {

		}
		var codes interface{}
		eer = json.Unmarshal([]byte(data.Codes), &codes)
		if eer != nil {

		}
		var tags []string
		eer = json.Unmarshal([]byte(data.Tags), &tags)
		if eer != nil {

		}
		remodel := models.NewTaskType{
			Id:                data.Id,
			Name:              data.Name,
			BaseModel:         data.BaseModel,
			Model:             data.Model,
			Version:           data.Version,
			Desc:              data.Desc,
			Price:             float64(data.Price / 1000000),
			PublicKey:         data.PublicKey,
			Complexity:        data.Complexity,
			Type:              models.ModelType(data.Type),
			TypeDesc:          models.ModelType(data.Type).String(),
			Kind:              data.Kind,
			KindDesc:          models.TaskKind(data.Kind).String(),
			KindDescEn:        models.TaskKind(data.Kind).EnString(),
			Category:          data.Category,
			HardwareRequire:   hardwareRequire,
			ImageId:           data.ImageId,
			ImageUrl:          data.ImageUrl,
			Cmd:               cmd,
			Workload:          data.Workload,
			ApiPath:           data.ApiPath,
			ImageName:         data.ImageName,
			SignUrl:           data.SignUrl,
			Username:          data.Username,
			Password:          data.Password,
			Examples:          examples,
			Codes:             codes,
			Tags:              tags,
			PublishStatus:     data.PublishStatus,
			AccessStatus:      data.AccessStatus,
			ResultFileExpires: data.ResultFileExpires,
		}
		remodels = append(remodels, &remodel)
	}
	total, err := qs.Count()
	responseData := struct {
		Total int64       `json:"total"`
		Data  interface{} `json:"data,omitempty"`
	}{
		Total: total,
		Data:  remodels,
	}

	//sql := "SELECT count(*) FROM task_type WHERE deleted = 0;"
	//var total int64
	//mysql.GetMysqlInstace().Ormer.Raw(sql).QueryRow(&total)
	//logs.Debug("total = %d", total)
	//if total == 0 {
	//	responseData := struct {
	//		Total int64       `json:"total"`
	//		Data  interface{} `json:"data,omitempty"`
	//	}{
	//		Total: total,
	//		Data:  types,
	//	}
	//	server.respond(http.StatusOK, "", responseData)
	//	return
	//}
	//sql = fmt.Sprintf("SELECT * FROM task_type WHERE deleted = 0 LIMIT %d,%d;", offset, size)
	//mysql.GetMysqlInstace().Ormer.Raw(sql).QueryRows(&types)
	//var remodels []*models.NewTaskType
	//for _, data := range types {
	//	var hardwareRequire interface{}
	//	eer := json.Unmarshal([]byte(data.HardwareRequire), &hardwareRequire)
	//	if eer != nil {
	//
	//	}
	//	var cmd interface{}
	//	eer = json.Unmarshal([]byte(data.Cmd), &cmd)
	//	if eer != nil {
	//
	//	}
	//	remodel := models.NewTaskType{
	//		Id:              data.Id,
	//		Name:            data.Name,
	//		BaseModel:       data.BaseModel,
	//		Model:           data.Model,
	//		Version:         data.Version,
	//		Desc:            data.Desc,
	//		Price:           float64(data.Price / 1000000),
	//		PublicKey:       data.PublicKey,
	//		Complexity:      data.Complexity,
	//		Type:            models.ModelType(data.Type),
	//		TypeDesc:        models.ModelType(data.Type).String(),
	//		Kind:            data.Kind,
	//		KindDesc:        models.TaskKind(data.Kind).String(),
	//		Category:        data.Category,
	//		HardwareRequire: hardwareRequire,
	//		ImageId:         data.ImageId,
	//		ImageUrl:        data.ImageUrl,
	//		Cmd:             cmd,
	//		Workload:        data.Workload,
	//		ApiPath:         data.ApiPath,
	//		ImageName:       data.ImageName,
	//		SignUrl:         data.SignUrl,
	//		Username:        data.Username,
	//		Password:        data.Password,
	//	}
	//	remodels = append(remodels, &remodel)
	//}
	//responseData := struct {
	//	Total int64       `json:"total"`
	//	Data  interface{} `json:"data,omitempty"`
	//}{
	//	Total: total,
	//	Data:  remodels,
	//}
	server.respond(http.StatusOK, "", responseData)

	//qb, _ := orm.NewQueryBuilder("mysql")
	//
	//// 构建查询对象
	//qb.Select("name", "type", "").
	//	From("user").
	//	InnerJoin("profile").On("user.id_user = profile.fk_user").
	//	Where("age > ?").
	//	OrderBy("name").Desc().
	//	Limit(10).Offset(0)
	//
	//// 导出 SQL 语句
	////sql := qb.String()
	//sql := "SELECT `name` AS tit,type,`desc` AS content, tags ,examples,codes,base_model,api_path,version FROM task_type WHERE deleted = 0;"
	//
	//// 执行 SQL 语句
	//o := orm.NewOrm()
	//o.Raw(sql, 20).QueryRows(&types)

	//qs := mysql.GetMysqlInstace().Ormer.QueryTable("task_type")
	//mysql.GetMysqlInstace().Ormer.LoadRelated(types, "UserLevelTaskType")
	//count, err := qs.Count()
	//logs.Debug("types = ", count)
	//var types []*models.TaskType
	//if count > 0 {
	//	qs.All(&types)
	//	//mysql.GetMysqlInstace().Ormer.LoadRelated(types, "UserLevelTaskType")
	//	//for _, dbType := range types {
	//	//	var levels []*models.UserLevelTaskType
	//	//	qs := mysql.GetMysqlInstace().Ormer.QueryTable(" user_level_task_type ")
	//	//}
	//}
	//server.respond(http.StatusOK, "", types)
}

func (server *TaskController) DelTaskType() {
	_, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	logs.Debug("AddLevel body", string(body))
	request := models.TaskType{}
	err = json.Unmarshal(body, &request) //解析body中数据
	logs.Debug("request", request)
	if err != nil {
		server.respond(models.NoRequestBody, err.Error())
		return
	}

	if request.Id == 0 {
		server.respond(models.MissingParameter, "Missing id parameter")
		return
	}
	checkType := &models.TaskType{Id: request.Id}
	err = mysql.GetMysqlInstace().Ormer.Read(checkType)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	checkType.Deleted = 1

	mysql.GetMysqlInstace().Ormer.Update(checkType)
	server.respond(http.StatusOK, "success")
}

func (server *TaskController) AddOrUpdateExamples() {
	_, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.NewTaskType{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	if err != nil {
		server.respond(models.NoRequestBody, err.Error())
		return
	}
	if appRequest.Id == 0 {
		server.respond(models.MissingParameter, "Missing id parameter")
		return
	}

	checkType := &models.TaskType{Id: appRequest.Id}
	err = mysql.GetMysqlInstace().Ormer.Read(checkType)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	if appRequest.Examples != nil {
		examples, _ := json.Marshal(appRequest.Examples)
		checkType.Examples = string(examples)
	}

	if appRequest.Codes != nil {
		codes, _ := json.Marshal(appRequest.Codes)
		checkType.Codes = string(codes)
	}

	if appRequest.Tags != nil {
		tags, _ := json.Marshal(appRequest.Tags)
		checkType.Tags = string(tags)
	}

	checkType.ApiDocUrl = appRequest.ApiDocUrl
	checkType.ApiDocContent = appRequest.ApiDocContent

	_, err = mysql.GetMysqlInstace().Ormer.Update(checkType)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}

	server.respond(http.StatusOK, "success")
}

func (server *TaskController) Examples() {
	body := server.Ctx.Input.RequestBody

	appRequest := models.AppRequest{}
	//if len(body) <= 0 {
	//	appRequest.Page == 1
	//}
	_ = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest, string(body))
	//if err != nil {
	//	server.respond(models.NoRequestBody, err.Error())
	//	return
	//}

	if appRequest.Page == 0 {
		appRequest.Page = 1
	}

	if appRequest.Size == 0 {
		appRequest.Size = 10
	}
	offset := (appRequest.Page - 1) * appRequest.Size
	size := appRequest.Page * appRequest.Size

	where := ""
	if appRequest.Id != 0 {
		where = fmt.Sprintf("and id = %d", appRequest.Id)
	} else {
		if appRequest.Keyword != "" {
			keyword := "%" + appRequest.Keyword + "%"
			where = fmt.Sprintf("and (`name` LIKE '%s' OR `desc` LIKE '%s' OR tags LIKE '%s')", keyword, keyword, keyword)
		}
		if appRequest.Category != 0 {
			where = fmt.Sprintf("%s and category = %d", where, appRequest.Category)
		}
	}

	var types []*models.Model

	sql := fmt.Sprintf("SELECT count(*) FROM task_type WHERE deleted = 0 and access_status = 1 %s;", where)
	var total int64
	mysql.GetMysqlInstace().Ormer.Raw(sql).QueryRow(&total)
	logs.Debug("total = %d", total)
	if total == 0 {
		responseData := struct {
			Total int64       `json:"total"`
			Data  interface{} `json:"data,omitempty"`
		}{
			Total: total,
			Data:  types,
		}
		server.respond(http.StatusOK, "", responseData)
		return
	}

	sql = fmt.Sprintf("SELECT id, `name` AS tit,type,`desc` AS content, tags ,examples,codes,base_model,model,api_path,version,category,form,access_status,publish_status FROM task_type WHERE deleted = 0 and access_status = 1 %s order by codes desc LIMIT %d,%d;", where, offset, size)
	mysql.GetMysqlInstace().Ormer.Raw(sql).QueryRows(&types)
	var remodels []*models.ResonseModel
	for _, data := range types {
		//if data.Id == 19 {
		//	logs.Debug("")
		//}
		var examples interface{}
		eer := json.Unmarshal([]byte(data.Examples), &examples)
		if eer != nil {

		}
		var codes interface{}
		eer = json.Unmarshal([]byte(data.Codes), &codes)
		if eer != nil {

		}
		var tags interface{}
		eer = json.Unmarshal([]byte(data.Tags), &tags)
		if eer != nil {

		}
		var form interface{}
		eer = json.Unmarshal([]byte(data.Form), &form)
		if eer != nil {

		}
		remodel := models.ResonseModel{
			Id:                data.Id,
			Tit:               data.Tit,
			Version:           data.Version,
			Content:           data.Content,
			Type:              data.Type,
			ApiPath:           data.ApiPath,
			BaseModel:         data.BaseModel,
			Model:             data.Model,
			Examples:          examples,
			ApiDocUrl:         data.ApiDocUrl,
			ApiDocContent:     data.ApiDocContent,
			Codes:             codes,
			Tags:              tags,
			Category:          data.Category,
			Form:              form,
			ResultFileExpires: data.ResultFileExpires,
			AccessStatus:      data.AccessStatus,
			PublishStatus:     data.PublishStatus,
		}
		remodels = append(remodels, &remodel)
	}
	responseData := struct {
		Total int64       `json:"total"`
		Data  interface{} `json:"data,omitempty"`
	}{
		Total: total,
		Data:  remodels,
	}
	server.respond(http.StatusOK, "", responseData)
}

func (server *TaskController) GetLevelsByTypeId() {
	_, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	body := server.Ctx.Input.RequestBody
	appRequest := models.AppRequest{}
	err = json.Unmarshal(body, &appRequest) //解析body中数据
	logs.Debug("appRequest", appRequest)
	if err != nil {
		server.respond(models.NoRequestBody, err.Error())
		return
	}
	if appRequest.Id == 0 {
		server.respond(models.MissingParameter, "Missing id parameter")
		return
	}
	var types []*models.UserLevelTaskType
	qs := mysql.GetMysqlInstace().Ormer.QueryTable("user_level_task_type").Filter("task_type_id", appRequest.Id)
	//mysql.GetMysqlInstace().Ormer.LoadRelated(types, "UserLevelTaskType")
	count, err := qs.Count()
	logs.Debug("types = ", count)
	//var types []*models.TaskType
	if count > 0 {
		qs.All(&types)
		//mysql.GetMysqlInstace().Ormer.LoadRelated(types, "UserLevelTaskType")
		//for _, dbType := range types {
		//	var levels []*models.UserLevelTaskType
		//	qs := mysql.GetMysqlInstace().Ormer.QueryTable(" user_level_task_type ")
		//}
	}
	server.respond(http.StatusOK, "", types)
}

func (server *TaskController) AllCategorys() {
	var category []*models.Category
	qs := mysql.GetMysqlInstace().Ormer.QueryTable("category").
		Filter("deleted", 0).
		OrderBy("sort")
	count, _ := qs.Count()
	logs.Debug("types = ", count)
	if count > 0 {
		qs.All(&category)
	}
	server.respond(http.StatusOK, "", category)
}

func (server *TaskController) Enumeration() {
	_, err := server.Check()
	if err != nil {
		server.respond(http.StatusUnauthorized, err.Error())
		return
	}
	var categorys []*models.Category
	qs := mysql.GetMysqlInstace().Ormer.QueryTable("category").Filter("deleted", 0)
	//mysql.GetMysqlInstace().Ormer.LoadRelated(types, "UserLevelTaskType")
	count, err := qs.Count()
	logs.Debug("types = ", count)
	//var types []*models.TaskType
	if count > 0 {
		qs.All(&categorys)
		//mysql.GetMysqlInstace().Ormer.LoadRelated(types, "UserLevelTaskType")
		//for _, dbType := range types {
		//	var levels []*models.UserLevelTaskType
		//	qs := mysql.GetMysqlInstace().Ormer.QueryTable(" user_level_task_type ")
		//}
	}

	var types []*models.EnumType
	for _, value := range [...]models.ModelType{models.TXTTOIMG, models.TXTTOTXT, models.TXTTOVIDEO, models.IMGTOTXT, models.IMGTOVIDEO, models.IMGTOIMG, models.IMGTXTTOTXT, models.IMGTXTTOIMG, models.IMGTXTTOVIDEO, models.TXTTOSPEECH, models.SPEECHTOTXT} {
		typeData := models.EnumType{
			Id:     int(value),
			Desc:   value.String(),
			EnDesc: "",
		}
		types = append(types, &typeData)
	}

	var publishStatusEnumS []*models.EnumType
	for _, value := range [...]models.PublishStatusEnum{models.Publish, models.UnPublish} {
		typeData := models.EnumType{
			Id:     int(value),
			Desc:   value.String(),
			EnDesc: "",
		}
		publishStatusEnumS = append(publishStatusEnumS, &typeData)
	}

	var accessStatusEnums []*models.EnumType
	for _, value := range [...]models.AccessStatusEnum{models.Public, models.Private} {
		typeData := models.EnumType{
			Id:     int(value),
			Desc:   value.String(),
			EnDesc: "",
		}
		accessStatusEnums = append(accessStatusEnums, &typeData)
	}

	var kinds []*models.EnumType
	for _, value := range [...]models.TaskKind{models.SystemTask, models.ComputeTask, models.CustomTask, models.StandardTask} {
		typeData := models.EnumType{
			Id:     int(value),
			Desc:   value.String(),
			EnDesc: value.EnString(),
		}
		kinds = append(kinds, &typeData)
	}

	var feeConditionEnums []*models.EnumType
	for _, value := range [...]models.FeeConditionEnum{models.FeeAll, models.FeeFree, models.FeeBased} {
		typeData := models.EnumType{
			Id:     int(value),
			Desc:   value.String(),
			EnDesc: value.EnString(),
		}
		feeConditionEnums = append(feeConditionEnums, &typeData)
	}
	responseData := struct {
		Categorys     []*models.Category `json:"categorys,omitempty"`
		Types         []*models.EnumType `json:"types,omitempty"`
		Kinds         []*models.EnumType `json:"kinds,omitempty"`
		FeeConditions []*models.EnumType `json:"fee_conditions,omitempty"`
		AccessStatus  []*models.EnumType `json:"access_status,omitempty"`
		PublishStatus []*models.EnumType `json:"publish_status,omitempty"`
	}{
		Categorys:     categorys,
		Types:         types,
		Kinds:         kinds,
		FeeConditions: feeConditionEnums,
		AccessStatus:  accessStatusEnums,
		PublishStatus: publishStatusEnumS,
	}
	server.respond(http.StatusOK, "", responseData)
}

func taskTypeCount() int64 {
	qs := mysql.GetMysqlInstace().Ormer.QueryTable("task_type")
	count, err := qs.Count()
	if err != nil {
		return 0
	}
	return count
}

func initTypeInRedis() []models.TaskHeat {
	qs := mysql.GetMysqlInstace().Ormer.QueryTable("task_type")
	count, _ := qs.Count()
	logs.Debug("types = ", count)
	var types []*models.TaskType
	if count > 0 {
		qs.All(&types)
	}
	var response []models.TaskHeat
	for _, dbType := range types {
		var hardwareRequire interface{}
		eer := json.Unmarshal([]byte(dbType.HardwareRequire), &hardwareRequire)
		if eer != nil {

		}
		var output interface{}
		if dbType.Form != "" {
			err := json.Unmarshal([]byte(dbType.Form), &output)
			if err != nil {
				logs.Debug("Form Unmarshal err")
			}
		}
		retask := models.TaskHeat{
			TaskId:          dbType.Id,
			User:            dbType.Username,
			Pwd:             dbType.Password,
			Repository:      dbType.ImageUrl,
			SignUrl:         dbType.SignUrl,
			ImageName:       dbType.ImageName,
			ImageId:         dbType.ImageId,
			HardwareRequire: hardwareRequire,
			Count:           int64(0),
			Kind:            dbType.Kind,
			FileExpiresTime: strconv.Itoa(dbType.ResultFileExpires),
			OutPutJson:      output,
			AccessStatus:    dbType.AccessStatus,
			PublishStatus:   dbType.PublishStatus,
		}
		response = append(response, retask)
	}
	dataRedis, err := json.Marshal(response)
	if err == nil {
		redis.SetKeyAndData(cronjob.HeatKey, string(dataRedis), 0)
	}

	return response
}

func (server *TaskController) TaskHeat() {
	data, err := redis.GetDataToString(cronjob.HeatKey)
	if data == "" || err != nil {
		response := initTypeInRedis()
		server.respond(http.StatusOK, "", response)
		return
	}

	var response []models.TaskHeat
	err = json.Unmarshal([]byte(data), &response)
	if err != nil {
		response = initTypeInRedis()
		server.respond(http.StatusOK, "", response)
		return
	}
	count := taskTypeCount()
	if len(response) < int(count) {
		response = initTypeInRedis()
		server.respond(http.StatusOK, "", response)
		return
	}
	server.respond(http.StatusOK, "", response)
}
