package autotask

import (
	c "ciyon/zciyon"
	"fmt"
	"net/http"
	"time"
)

func _runtaskfunc(systemrow map[string]any, runfunc string) string {
	symbol := funcindex()
	defer func() {
		if err := recover(); err != nil {
			c.Log.Error("AUTO", fmt.Sprintf("函数执行出错：%v", err))
		}
	}()
	if _, ok := symbol[runfunc]; !ok {
		return "缺少函数:" + runfunc
	}
	return symbol[runfunc](systemrow)
}
func Main() bool {
	for {
		csql := c.NewCiySQL("zc_autotask")
		csql.Where("autotaskstatus<", 90)
		csql.Where("nexttimes<=", c.Tostamp())
		systemrow, err := c.CiyDB.Getone(csql)
		if err != nil {
			return _returnerr(err)
		}
		if systemrow == nil {
			break
		}
		_run(systemrow, "zc_auto")
	}
	return true
}
func Task_main(w http.ResponseWriter, r *http.Request) bool {
	post := c.NewCiyPost(w, r)
	// rsuser, err := admin.Verifyuser(r, c.CiyDB, post)
	// if err != nil {
	// 	w.Write([]byte("您未登录"))
	// 	return false
	// }
	// if admin.Nopower(c.CiyDB, c.Toint(rsuser["id"]), "p602r") {
	// 	w.Write([]byte("您未被授权操作"))
	// 	return false
	// }
	runid := post.Getint("runid")
	csql := c.NewCiySQL("zc_autotask")
	csql.Where("id", runid)
	taskrow, err := c.CiyDB.Getone(csql)
	if taskrow == nil {
		w.Write([]byte("任务ID不存在:" + c.Tostr(runid)))
		return false
	}
	autotaskstatus := c.Toint(taskrow["autotaskstatus"])
	if autotaskstatus == 30 {
		return c.ErrJSON(w, "任务正在执行中", err)
	}
	runtaskid, err2 := _run(taskrow, "zc_auto")
	if err2 != nil {
		return c.ErrJSON(w, "任务执行失败:"+c.Tostr(runid), err2)
	}
	csql = c.NewCiySQL("zc_autotsk_run")
	csql.Where("id", runtaskid)
	tskrunrow, _ := c.CiyDB.Getone(csql)
	csql = c.NewCiySQL("zc_autotsk_log")
	csql.Where("runtaskid", runtaskid)
	tsklogrows, _, _ := c.CiyDB.Get(csql)

	html := ""
	html += "<!DOCTYPE html> <html><head>"
	html += "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>"
	html += "<title>AutoTask Running</title>"
	html += "</head><body>"
	html += "<table border='1' style='border-collapse:collapse;font-size:0.8em;' cellpadding='5px'>"
	html += "<tr><td>任务名称</td><td>" + c.Tostr(taskrow["name"]) + "</td></tr>"
	html += "<tr><td>入口函数</td><td>" + c.Tostr(taskrow["runfunc"]) + "</td></tr>"
	html += "<tr><td>执行参数</td><td>" + c.Tostr(taskrow["runparam"]) + "</td></tr>"
	html += "<tr><td>执行时长</td><td>" + c.Tostr(tskrunrow["runsec"]) + "s</td></tr>"
	html += "<tr><td>任务简报</td><td>" + c.Tostr(tskrunrow["msg"]) + "</td></tr>"
	html += "</table>"
	if len(tsklogrows) > 0 {
		html += "<br/><table border='1' style='border-collapse:collapse;font-size:0.8em;' cellpadding='5px'>"
		html += "<tr><td>时间</td><td>数据</td></tr>"
		for _, row := range tsklogrows {
			html += "<tr><td>" + c.Todate(c.Toint(row["addtimes"])) + "</td><td>" + c.Tostr(row["msg"]) + "</td></tr>"
		}
		html += "</table>"
	} else {
		html += "无日志记录"
	}
	html += "</body></html>"
	w.Write([]byte(html))
	return true
}
func _run(systemrow map[string]any, table string) (int, error) {

	runfunc := c.Tostr(systemrow["runfunc"])
	if runfunc == "" || runfunc[0] == '_' {
		return 0, fmt.Errorf("入口函数设置错误:%s", runfunc)
	}
	sysid := c.Toint(systemrow["id"])
	nexttimes := c.Toint(systemrow["nexttimes"])
	runtimes := c.Toint(systemrow["runtimes"])
	runcycle := c.Toint(systemrow["runcycle"])
	autotaskstatus := c.Toint(systemrow["autotaskstatus"])
	for {
		if nexttimes > c.Tostamp() {
			break
		}
		if runcycle < 0 {
			t := time.Unix(int64(nexttimes), 0)
			t = t.AddDate(0, -runcycle, 0)
			nexttimes = int(t.Unix())
		} else {
			nexttimes += runcycle
		}
	}
	updata := make(map[string]any)
	runningmsg := "任务执行中，本次跳过"
	if autotaskstatus == 30 {
		if runtimes < c.Tostamp()-3600 {
			updata["autotaskstatus"] = 20
			runningmsg = "任务执行中，超过1小时，强制复位"
		}
	} else {
		updata["autotaskstatus"] = 30
		updata["runtimes"] = c.Tostamp()
	}
	updata["nexttimes"] = nexttimes
	csql := c.NewCiySQL(table + "task")
	csql.Where("id", sysid)
	_, err := c.CiyDB.Update(csql, updata)
	if err != nil {
		return 0, err
	}
	if autotaskstatus == 30 {
		updata = make(map[string]any)
		updata["autotaskid"] = sysid
		updata["addtimes"] = c.Tostamp()
		updata["runsec"] = -1
		updata["logcnt"] = 0
		updata["msg"] = runningmsg
		csql = c.NewCiySQL(table + "tsk_run")
		_, err = c.CiyDB.Insert(csql, updata)
		if err != nil {
			return 0, err
		}
		return 0, nil
	}
	runlogstart := c.Tostamp()
	updata = make(map[string]any)
	updata["autotaskid"] = sysid
	updata["addtimes"] = runlogstart
	csql = c.NewCiySQL(table + "tsk_run")
	runtaskid, err2 := c.CiyDB.Insert(csql, updata)
	if err2 != nil {
		return 0, err2
	}
	systemrow["runtaskid"] = runtaskid
	systemrow["table"] = table

	errmsg := _runtaskfunc(systemrow, runfunc)

	updata = make(map[string]any)
	updata["autotaskstatus"] = 20
	updata["runtimes"] = 0
	csql = c.NewCiySQL(table + "task")
	csql.Where("id", sysid)
	_, err2 = c.CiyDB.Update(csql, updata)
	if err2 != nil {
		return 0, err2
	}
	csql = c.NewCiySQL(table + "tsk_log")
	csql.Where("runtaskid", runtaskid)
	logcnt := c.Toint(c.CiyDB.Get1(csql))

	updata = make(map[string]any)
	updata["runsec"] = c.Tostamp() - runlogstart
	updata["msg"] = errmsg
	updata["logcnt"] = logcnt
	csql = c.NewCiySQL(table + "tsk_run")
	csql.Where("id", runtaskid)
	_, err2 = c.CiyDB.Update(csql, updata)
	if err2 != nil {
		return 0, err2
	}
	return runtaskid, nil
}
func _returnerr(err error) bool {
	c.Log.Error("AUTO", fmt.Sprintf("运行出错：%v", err))
	return false
}
func _tasklog(systemrow map[string]any, msg string) {
	updata := make(map[string]any)
	updata["autotaskid"] = systemrow["id"]
	updata["runtaskid"] = systemrow["runtaskid"]
	updata["addtimes"] = c.Tostamp()
	updata["msg"] = msg
	csql := c.NewCiySQL(c.Tostr(systemrow["table"]) + "tsk_log")
	_, err := c.CiyDB.Insert(csql, updata)
	if err != nil {
		_returnerr(err)
	}
}
