package controllers

import (
	"ai_developer_admin/libs/odysseus"
	"ai_developer_admin/libs/postgres"
	"ai_developer_admin/models"
	"encoding/json"
	"fmt"
	"github.com/beego/beego/orm"
	"github.com/beego/beego/v2/core/logs"
	"net/http"
	"strconv"
	"time"
)

type ClientController struct {
	MainController
}

func (server *ClientController) Statistics() {
	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.WorkerAcc == "" {
		server.respond(models.MissingParameter, "Missing worker_acc parameter")
		return
	}

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("count(*)").
		From("bills").Where(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc))
	sql := countQB.String()
	count, err := postgres.QueryTotal(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}

	sumQB, _ := orm.NewQueryBuilder("mysql")
	sumQB.Select("sum(workload)").
		From("bills").Where(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc))
	sql = sumQB.String()
	workload, err := postgres.QueryTotal(sql)

	currentTime := time.Now()
	endTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, time.UTC)
	temp := fmt.Sprintf("-%dh", 24*7)
	m, _ := time.ParseDuration(temp)
	tempTime := currentTime.Add(m)
	startTime := time.Date(tempTime.Year(), tempTime.Month(), tempTime.Day(), 0, 0, 0, 0, time.UTC)

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

	YCountQB, _ := orm.NewQueryBuilder("mysql")
	YCountQB.Select("count(*)").
		From("bills").Where(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc)).
		And(fmt.Sprintf("time >= '%s'", start)).And(fmt.Sprintf("time <= '%s'", end))
	sql = YCountQB.String()
	YCount, err := postgres.QueryTotal(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}

	YSumQB, _ := orm.NewQueryBuilder("mysql")
	YSumQB.Select("sum(workload)").
		From("bills").Where(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc)).
		And(fmt.Sprintf("time >= '%s'", start)).And(fmt.Sprintf("time <= '%s'", end))
	sql = YSumQB.String()
	YWorkload, err := postgres.QueryTotal(sql)

	responseData := struct {
		TotalWorkload     int64 `json:"total_workload"`
		TotalTask         int64 `json:"total_task"`
		YesterdayWorkload int64 `json:"yesterday_workload"`
		YesterdayTask     int64 `json:"yesterday_task"`
	}{
		TotalWorkload:     workload,
		TotalTask:         count,
		YesterdayWorkload: YWorkload,
		YesterdayTask:     YCount,
	}
	server.respond(http.StatusOK, "", responseData)
}

func (server *ClientController) TasksPerDay() {

	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

	if appRequest.WorkerAcc == "" && appRequest.ProfitAcc == "" {
		server.respond(models.MissingParameter, "At least one of worker_acc or profit_acc needs to be passed.")
		return
	}

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

	queryQB, _ := orm.NewQueryBuilder("mysql")
	queryQB.Select("count(*),sum(workload) AS workload", "sum(exec_duration) AS exec_duration", "time").
		From("bills")

	if appRequest.WorkerAcc != "" {
		countQB.Where(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc))
		queryQB.Where(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc))
	}
	if appRequest.ProfitAcc != "" {
		countQB.Where(fmt.Sprintf("profit_acc = '%s'", appRequest.ProfitAcc))
		queryQB.Where(fmt.Sprintf("profit_acc = '%s'", appRequest.ProfitAcc))
	}

	sql := fmt.Sprintf("%s SAMPLE BY 1M ALIGN TO CALENDAR", countQB.String())
	sql = fmt.Sprintf("SELECT count(*) FROM (%s);", sql)

	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 ORDER BY time DESC LIMIT %d,%d;", queryQB.String(), offset, size)
	counts, err := postgres.QueryBills(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 *ClientController) Tasks() {
	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.WorkerAcc == "" {
		server.respond(models.MissingParameter, "Missing worker_acc parameter")
		return
	}

	countQB, _ := orm.NewQueryBuilder("mysql")
	countQB.Select("count(*)").
		From("bills").Where(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc))

	queryQB, _ := orm.NewQueryBuilder("mysql")
	queryQB.Select("id", "fee", "type", "time", "exec_duration", "workload", "profit_acc", "worker_acc", "result").
		From("bills").Where(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 *ClientController) RevenuePerDay() {

	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

	if appRequest.WorkerAcc == "" && appRequest.ProfitAcc == "" {
		server.respond(models.MissingParameter, "At least one of worker_acc or profit_acc needs to be passed.")
		return
	}

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

	queryQB, _ := orm.NewQueryBuilder("mysql")
	queryQB.Select("count(*),sum(workload) AS workload", "sum(exec_duration) AS exec_duration", "time").
		From("bills")

	if appRequest.WorkerAcc != "" {
		countQB.Where(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc))
		queryQB.Where(fmt.Sprintf("worker_acc = '%s'", appRequest.WorkerAcc))
	}
	if appRequest.ProfitAcc != "" {
		countQB.Where(fmt.Sprintf("profit_acc = '%s'", appRequest.ProfitAcc))
		queryQB.Where(fmt.Sprintf("profit_acc = '%s'", appRequest.ProfitAcc))
	}

	sql := fmt.Sprintf("%s SAMPLE BY 1M ALIGN TO CALENDAR", countQB.String())
	sql = fmt.Sprintf("SELECT count(*) FROM (%s);", sql)

	total, err := postgres.QueryTotal(sql)
	if err != nil {
		server.respond(models.BusinessFailed, err.Error())
		return
	}
	logs.Debug("total = %d", total)
	var responseTasks []models.TaskCount
	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)
}
