package admin

import (
	"fmt"
	"net/http"
	"strings"
	"sync"

	c "ciyon/zciyon"
)

var Gtokentype string  //cookie(更安全，只支持https) 、 localstorage(兼容性好)
var Gtokenfield string //header api field
var Gtokensalt string  //登录盐值
var Gtokenswapsec int  //更换JWT时间
var Gtokenexpsec int   //过期退出时间
var Gdefpass string    //默认密码
var Gusermap sync.Map  //用户全局缓存

func init() {
	Gtokentype = "localstorage"
	Gtokenfield = "ciyadm"
	Gtokensalt = "bka02$59gG"
	Gtokenswapsec = 3600
	Gtokenexpsec = 86400 * 7
	Gdefpass = "1q2w"
}
func Verifyfast(r *http.Request, db *c.CiyMysql, post *c.CiyPost) (map[string]any, int) {
	rsuser, err := Verifyuser(r, c.CiyDB, post)
	if err != nil {
		c.ErrJSON(post.W, "请重新登录", 2)
		return nil, 0
	}
	return rsuser, c.Toint(rsuser["id"])
}

func Verifyuser(r *http.Request, db *c.CiyMysql, post *c.CiyPost) (map[string]any, error) {
	ciyauth := post.R.Header.Get("ciyauth")
	if ciyauth == "" {
		ciyauth = c.GetQuery("_ciyauth", post.R)
	}
	if ciyauth == "" {
		return nil, fmt.Errorf("verify nofind ciyauth header or query")
	}
	auth := c.Str_JSON(c.Encrypt(ciyauth, "D", Gtokensalt))
	if auth == nil {
		return nil, fmt.Errorf("verify ciyauth error")
	}
	csql := c.NewCiySQL("zc_online")
	csql.Where("id", auth["_o"])
	onlinerow, err := db.Getone(csql)
	if err != nil {
		return nil, fmt.Errorf("verify read online err:%v", err)
	}
	if c.Toint(onlinerow["user"]) != c.Toint(auth["id"]) {
		return nil, fmt.Errorf("verify userid not match oid=%v", onlinerow["id"])
	}
	if c.Tostr(onlinerow["sid"]) != c.Tostr(auth["_s"]) {
		return nil, fmt.Errorf("verify sid not match oid=%v", onlinerow["id"])
	}
	if c.Toint(onlinerow["exptimes"]) < c.Tostamp()-Gtokenexpsec {
		return nil, fmt.Errorf("verify exptimes timeout oid=%v", onlinerow["id"])
	}
	if c.Toint(onlinerow["usrchg"]) == 9 {
		csql := c.NewCiySQL("zc_admin")
		csql.Where("id", auth["_o"])
		userrow, _ := db.Getone(csql)
		if userrow == nil {
			return nil, fmt.Errorf("verify user nofind")
		}
		if c.Toint(userrow["stpstatus"]) != 10 {
			return nil, fmt.Errorf("verify user disabled")
		}
	}
	if c.Toint(onlinerow["usrchg"]) == 2 {
		post.W.Header().Set("_re", "true")
	}
	if c.Toint(onlinerow["exptimes"]) > c.Tostamp() {
		return auth, nil
	}
	exptimes := c.Tostamp() + Gtokenswapsec
	sid := c.Randstr(10)
	auth["_s"] = sid
	authstr := c.JSON_Str(auth)
	newauth := c.Encrypt(authstr, "E", Gtokensalt)
	ctx := r.Context().Value(c.GhttpKey)
	if ctx != nil {
		reqCtx := ctx.(*c.RequestContext)
		if reqCtx != nil {
			reqCtx.CiyAuth = newauth
		}
	}
	//post.W.Header().Set(Gtokenfield, newauth)
	userid := c.Toint(auth["id"])
	db.UserID = userid
	updata := map[string]any{}
	updata["exptimes"] = exptimes
	updata["sid"] = sid
	updata["ip"] = post.GetIP()
	csql = c.NewCiySQL("zc_online")
	csql.Where("id", auth["_o"])
	_, err = db.Update(csql, updata)
	if err != nil {
		return nil, fmt.Errorf("verify sid online update err:%v", err)
	}
	return auth, nil
}

func Nopower(db *c.CiyMysql, userid int, chkpower string) bool {
	csql := c.NewCiySQL("zc_admin")
	csql.Where("id", userid)
	csql.Column("power")
	mepower := c.Tostr(c.CiyDB.Get1(csql))
	if mepower == "" {
		return true
	}
	if len(chkpower) < 3 {
		return true
	}
	if userid == 10 { //超级管理员
		return false
	}
	pows := strings.Split(mepower, ".")
	for _, p := range pows {
		if p == "" {
			continue
		}
		if !strings.HasPrefix(chkpower, p) {
			continue
		}
		return false
	}
	return true
}
func SaveLog(db *c.CiyMysql, types, msg string) {
	updata := map[string]any{}
	updata["types"] = types
	updata["loguser"] = db.UserID
	updata["logs"] = msg
	updata["readuser"] = 0
	updata["addtimes"] = c.Tostamp()
	csql := c.NewCiySQL("zc_log")
	_, err := db.Insert(csql, updata)
	if err != nil {
		c.Log.Warn("LOG", fmt.Sprintf("SaveLog Error:%v[%v]", err, types+":"+msg))
		return
	}
}
func SaveLogDB(db *c.CiyMysql, types string, oldrow map[string]any, newrow map[string]any) {
	SaveLog(db, types, c.LogDBStr(oldrow, newrow))
}

func Getconfig(db *c.CiyMysql, types, defvalue any) any {
	csql := c.NewCiySQL("zc_config")
	csql.Where("types", types)
	row, _ := db.Getone(csql)
	if row != nil {
		return row["params"]
	}
	return defvalue
}
func Setconfig(db *c.CiyMysql, types, value any) bool {
	updata := map[string]any{}
	updata["types"] = types
	updata["params"] = value
	csql := c.NewCiySQL("zc_config")
	csql.Where("types", types)
	_, err := db.Update(csql, updata)
	return err == nil
}

func Getcatas(db *c.CiyMysql, cbstr any) []map[string]any {
	cbid := 0
	if c.Is_int(cbstr) {
		cbid = c.Toint(cbstr)
	} else {
		csql := c.NewCiySQL("zc_cata")
		csql.Where("codeid", cbstr)
		csql.Where("cbid=0")
		csql.Column("id")
		cbid = c.Toint(db.Get1(csql))
	}
	if cbid == 0 {
		return []map[string]any{}
	}
	csql := c.NewCiySQL("zc_cata")
	csql.Where("cbid", cbid)
	csql.Order("csort,id")
	csql.Column("codeid as id,name,upid,name,extdata")
	catarows, _, err := db.Get(csql)
	if err != nil {
		return []map[string]any{}
	}
	return catarows
}

// func Getsaascatas(db *c.CiyMysql, cbstr any, saasid int) []map[string]any {
// 	cbid := 0
// 	if c.Is_int(cbstr) {
// 		cbid = c.Toint(cbstr)
// 	} else {
// 		csql := c.NewCiySQL("zc_catsaas")
// 		csql.Where("codeid", cbstr)
// 		csql.Where("cbid=0")
// 		csql.Column("id")
// 		cbid = c.Toint(db.Get1(csql))
// 	}
// 	if cbid == 0 {
// 		return []map[string]any{}
// 	}
// 	csql := c.NewCiySQL("zc_catsaas")
// 	csql.Where("saasid", saasid)
// 	csql.Where("cbid", cbid)
// 	csql.Order("csort,id")
// 	csql.Column("codeid as id,name,upid,name,extdata")
// 	catarows, _, err := db.Get(csql)
// 	if err != nil {
// 		return []map[string]any{}
// 	}
// 	if len(catarows) == 0 {
// 		csql = c.NewCiySQL("zc_cata")
// 		csql.Where("cbid", cbid)
// 		csql.Order("csort,id")
// 		csql.Column("codeid as id,name,upid,name,extdata")
// 		catarows, _, err = db.Get(csql)
// 		if err != nil {
// 			return []map[string]any{}
// 		}
// 	}
// 	return catarows
// }
