package rigger

import (
	"ciyon/web/admin"
	c "ciyon/zciyon"
	"ciyon/zciyon/xlsx"
	"fmt"
	"math/rand"
	"net/http"
	"strings"
)

func admin_setwhere(post *c.CiyPost) (map[string]any, *c.CiySQL) {
	query := post.Getobj("query")
	csql := c.NewCiySQL("zc_admin")
	csql.Where("departid", post.Get("departid"))
	liid := c.Getint(query, "liid")
	if liid > 0 {
		csql.Where("stpstatus", liid)
	}
	csql.Where("name like", c.Getstr(query, "name"))
	csql.Where("mobile like", c.Getstr(query, "mobile"))
	csql.Where("sex", c.Getstr(query, "sex"))
	csql.Where_daterange("logintimes", c.Getstr(query, "logintimes"))
	csql.Where_daterange("addtimes", c.Getstr(query, "addtimes"))
	order := post.Get("order", "id desc")
	csql.Order(order)
	query["order"] = order
	return query, csql
}
func Admin_init(w http.ResponseWriter, r *http.Request) bool {
	post := c.NewCiyPost(w, r)
	_, userid := admin.Verifyfast(r, c.CiyDB, post)
	if userid == 0 {
		return false
	}
	where, csql := admin_setwhere(post)
	pageno := post.Getint("pageno", 1)
	pagecount := post.Getint("pagecount", 10)
	csql.Limit(pageno, pagecount)
	rows, mainrowcount, err := c.CiyDB.Get(csql, post.Getint("count"))
	if err != nil {
		return c.ErrJSON(w, "读取错误", err)
	}
	ret := map[string]any{}
	ret["where"] = where
	ret["pageno"] = pageno
	ret["pagecount"] = pagecount
	ret["count"] = mainrowcount
	ret["list"] = rows
	if post.Getbool("field") {
		field, fshow := c.CiyDB.GetField(csql)
		c.FieldAdd(&field, &fshow, 0, "_btn", "操作")
		ret["fshow"] = fshow
		ret["field"] = field
	}
	if post.Getbool("once") {
		once := map[string]any{}
		input := make([]map[string]any, 0)
		input = append(input, map[string]any{
			"form": "name",
			"type": "input",
			"name": "姓名",
			"prop": ` style="width:8em;"`,
		})
		input = append(input, map[string]any{
			"form": "mobile",
			"type": "input",
			"name": "手机号",
			"prop": ` style="width:8em;"`,
		})
		input = append(input, map[string]any{
			"form":   "sex",
			"type":   "select",
			"name":   "性别",
			"select": "sex",
			"all":    "全部",
		})
		input = append(input, map[string]any{
			"form": "logintimes",
			"type": "daterange",
			"name": "登录时间",
		})
		input = append(input, map[string]any{
			"form": "addtimes",
			"type": "daterange",
			"name": "注册时间",
		})
		once["input"] = input

		csql = c.NewCiySQL("zc_depart")
		csql.Column("id,upid,name,isuse")
		ret["zc_depart"], _, _ = c.CiyDB.Get(csql)
		csql = c.NewCiySQL("zc_role")
		csql.Column("id,name")
		ret["zc_role"], _, _ = c.CiyDB.Get(csql)
		ret["once"] = once
	}
	return c.SuccJSON(w, r, ret)
}

func Admin_update(w http.ResponseWriter, r *http.Request) bool {
	post := c.NewCiyPost(w, r)
	_, userid := admin.Verifyfast(r, c.CiyDB, post)
	if userid == 0 {
		return false
	}
	id := post.Getint("id")
	name := post.Get("name")
	if name == "" {
		return c.ErrJSON(w, "请填写姓名")
	}
	stpstatus := post.Getint("stpstatus")
	if stpstatus <= 0 {
		return c.ErrJSON(w, "请填写状态")
	}
	mobile := post.Get("mobile")
	if mobile == "" {
		return c.ErrJSON(w, "请填写手机号")
	}
	sex := post.Getint("sex")
	if sex <= 0 {
		return c.ErrJSON(w, "请填写性别")
	}
	departid := post.Getint("departid")
	icon := post.Get("icon")
	roleid := post.Getint("roleid")
	var err error
	var datarow map[string]any
	if id > 0 {
		if admin.Nopower(c.CiyDB, userid, "p500u") {
			return c.ErrJSON(w, "您未被授权操作修改")
		}
		csql := c.NewCiySQL("zc_admin")
		csql.Where("id", id)
		datarow, err = c.CiyDB.Getone(csql)
		if datarow == nil {
			return c.ErrJSON(w, "数据不存在", err)
		}
		if c.Toint(datarow["roleid"]) != roleid {
			if admin.Nopower(c.CiyDB, userid, "p500r") {
				return c.ErrJSON(w, "您没有赋予角色的权限")
			}
		} else {
			roleid = 0
		}
	} else {
		if admin.Nopower(c.CiyDB, userid, "p500a") {
			return c.ErrJSON(w, "您未被授权操作新增")
		}
		if admin.Nopower(c.CiyDB, userid, "p500r") {
			roleid = 0
		}
	}
	rolerow := map[string]any{}
	if roleid > 0 {
		csql := c.NewCiySQL("zc_role")
		csql.Where("id", roleid)
		rolerow, err := c.CiyDB.Getone(csql)
		if rolerow == nil {
			return c.ErrJSON(w, "角色不存在", err)
		}
	}
	updata := map[string]any{}
	err = c.CiyDB.Tran(func() error {
		var csql *c.CiySQL
		csql = c.NewCiySQL("zc_admin")
		csql.Where("mobile", mobile)
		csql.Column("id")
		chkid := c.Toint(c.CiyDB.Get1(csql))
		if chkid > 0 && ((id > 0 && chkid != id) || id == 0) {
			return fmt.Errorf("数据已存在")
		}
		updata["icon"] = icon
		updata["name"] = name
		updata["stpstatus"] = stpstatus
		updata["mobile"] = mobile
		updata["sex"] = sex
		updata["departid"] = departid
		updata["roleid"] = roleid
		if roleid > 0 {
			updata["power"] = rolerow["power"]
		}
		csql = c.NewCiySQL("zc_admin")
		if id > 0 {
			csql.Where("id", id)
			_, err = c.CiyDB.Update(csql, updata)
			if stpstatus == 10 {
				if roleid > 0 || datarow["name"] != name || datarow["icon"] != icon {
					c.CiyDB.Execute("update zc_online set usrchg=2 where user=?", id)
				}
			} else {
				c.CiyDB.Execute("delete from zc_online where user=?", id)
			}
			if datarow["name"] != name {
				c.CiyDB.Execute("update zc_online set usrchg=2")
			}
		} else {
			updata["addtimes"] = c.Tostamp()
			id, err = c.CiyDB.Insert(csql, updata)
			c.CiyDB.Execute("update zc_online set usrchg=2")
		}
		updata["id"] = id
		if err != nil {
			return fmt.Errorf("更新失败:%v", err)
		}
		admin.SaveLogDB(c.CiyDB, "zc_admin", datarow, updata)
		return nil
	})
	if err != nil {
		return c.ErrJSON(w, "事务"+err.Error())
	}
	ret := map[string]any{}
	ret["data"] = updata
	return c.SuccJSON(w, r, ret)
}

func Admin_del(w http.ResponseWriter, r *http.Request) bool {
	post := c.NewCiyPost(w, r)
	_, userid := admin.Verifyfast(r, c.CiyDB, post)
	if userid == 0 {
		return false
	}
	if admin.Nopower(c.CiyDB, userid, "p500d") {
		return c.ErrJSON(w, "您未被授权操作")
	}
	ids := post.Get("ids")
	if ids == "" {
		return c.ErrJSON(w, "请选择至少一条")
	}
	csql := c.NewCiySQL("zc_admin")
	csql.Where("id in", ids)
	rows, _, err := c.CiyDB.Get(csql)
	if err != nil {
		return c.ErrJSON(w, "读取数据错误", err)
	}
	vids := make([]int, 0)
	err = c.CiyDB.Tran(func() error {
		for _, row := range rows {
			delid := c.Toint(row["id"])
			if userid == delid {
				return fmt.Errorf("不能删除本人")
			}
			if delid == 10 {
				return fmt.Errorf("不能删除超级管理员")
			}
			c.Delme(c.CiyDB, delid, "zc_admin")
			c.CiyDB.Execute("delete from zc_online where user=?", delid)
			admin.SaveLogDB(c.CiyDB, "zc_admin", row, nil)
			vids = append(vids, delid)
		}
		return nil
	})
	if err != nil {
		return c.ErrJSON(w, "事务"+err.Error())
	}
	c.CiyDB.Execute("update zc_online set usrchg=2")
	ret := map[string]any{}
	ret["ids"] = vids
	return c.SuccJSON(w, r, ret)
}

func Admin_repass(w http.ResponseWriter, r *http.Request) bool {
	post := c.NewCiyPost(w, r)
	_, userid := admin.Verifyfast(r, c.CiyDB, post)
	if userid == 0 {
		return false
	}
	if admin.Nopower(c.CiyDB, userid, "p500p") {
		return c.ErrJSON(w, "您未被授权操作")
	}
	id := post.Getint("id")
	err := c.CiyDB.Tran(func() error {
		updata := map[string]any{}
		updata["trytime"] = 0
		updata["password"] = c.Sha256(admin.Gdefpass + admin.Gtokensalt)
		csql := c.NewCiySQL("zc_admin")
		csql.Where("id", id)
		_, err := c.CiyDB.Update(csql, updata)
		if err != nil {
			return fmt.Errorf("更新失败:%v", err)
		}
		return nil
	})
	if err != nil {
		return c.ErrJSON(w, "事务"+err.Error())
	}
	c.CiyDB.Execute("delete from zc_online where user=?", id)
	ret := map[string]any{}
	ret["msg"] = "默认密码: " + admin.Gdefpass
	return c.SuccJSON(w, r, ret)
}
func Admin_exportxls(w http.ResponseWriter, r *http.Request) bool {
	post := c.NewCiyPost(w, r)
	_, userid := admin.Verifyfast(r, c.CiyDB, post)
	if userid == 0 {
		return false
	}
	if admin.Nopower(c.CiyDB, userid, "p500e") {
		return c.ErrJSON(w, "您未被授权操作")
	}
	_, csql := admin_setwhere(post)
	rows, _, err := c.CiyDB.Get(csql)
	if err != nil {
		return c.ErrJSON(w, "读取错误", err)
	}
	if len(rows) > 10000 {
		return c.ErrJSON(w, "将导出"+c.Tostr(len(rows))+"条，不建议超过1万条，请筛选缩小范围", err)
	}
	fields := []map[string]string{}
	fields = append(fields, map[string]string{"style": "c", "width": "60", "field": "id", "name": "行码"})
	fields = append(fields, map[string]string{"style": "l", "width": "100", "field": "name", "name": "姓名"})
	fields = append(fields, map[string]string{"style": "c", "width": "60", "field": "stpstatus", "name": "状态"})
	fields = append(fields, map[string]string{"style": "l", "width": "100", "field": "mobile", "name": "手机号"})
	fields = append(fields, map[string]string{"style": "c", "width": "60", "field": "sex", "name": "性别"})
	fields = append(fields, map[string]string{"style": "l", "width": "100", "field": "departid", "name": "所属组织"})
	fields = append(fields, map[string]string{"style": "l", "width": "100", "field": "logintimes", "name": "登录时间"})
	fields = append(fields, map[string]string{"style": "l", "width": "100", "field": "addtimes", "name": "注册时间"})

	code_stpstatus := admin.Getcatas(c.CiyDB, "stpstatus")
	code_sex := admin.Getcatas(c.CiyDB, "sex")
	csql = c.NewCiySQL("zc_depart")
	csql.Column("id,upid,name")
	code_departid, _, err2 := c.CiyDB.Get(csql)
	if err2 != nil {
		return c.ErrJSON(w, "读取zc_depart错误", err2)
	}

	datas := [][]string{}
	for _, row := range rows {
		dat := make([]string, 0)
		for _, f := range fields {
			field := f["field"]
			if val, ok := row[field]; ok {
				var str string
				if field == "id" {
					str = c.EnID(c.Toint(val))
				} else if field == "stpstatus" {
					str = c.Ccode(code_stpstatus, c.Toint(val))
				} else if field == "sex" {
					str = c.Ccode(code_sex, c.Toint(val))
				} else if field == "departid" {
					str = strings.Join(c.Mcode(code_departid, c.Toint(val)), "-")
				} else if field == "logintimes" {
					t := c.Toint(val)
					if t <= 0 {
						str = "--"
					} else {
						str = c.Todate(t, "Y-m-d H:i")
					}
				} else if field == "addtimes" {
					t := c.Toint(val)
					if t <= 0 {
						str = "--"
					} else {
						str = c.Todate(t, "Y-m-d H:i")
					}
				} else {
					str = c.Tostr(val)
				}
				dat = append(dat, str)
			} else {
				dat = append(dat, "")
			}
		}
		datas = append(datas, dat)
	}
	param := map[string]any{}
	param["sheetname"] = "数据报表"
	param["titleheight"] = "25" //列头高度
	param["landscape"] = true   //横向打印
	param["fixtopage"] = true   //打印整个工作表
	param["toptitle"] = "管理员数据报表"
	total := []map[string]any{} //单行统计数据
	// total = append(total, map[string]any{"style": "l", "name": "合计", "merge": 5})
	// total = append(total, map[string]any{"style": "r", "name": "=SUM(R[-" + c.Tostr(len(datas)) + "]C:R[-1]C)"})
	// total = append(total, map[string]any{"style": "r", "name": "=MAX(R[-" + c.Tostr(len(datas)) + "]C:R[-1]C)"})
	// param["rowstop"] = `<Row ss:Height="45"><Cell ss:MergeAcross="7" ss:StyleID="cap"><Data ss:Type="String">众产Ciyon</Data></Cell></Row>`
	// param["rowsfooter"] = `<Row><Cell ss:MergeAcross="2"><Data ss:Type="String" ss:StyleID="r">总计</Data></Cell><Cell ss:Formula="=SUM(R[-2]C:R[-1]C)"><Data ss:Type="Number"></Data></Cell></Row>`
	str := c.General_excel_xml(fields, datas, param, total)
	filename := "/ud/tmp/" + c.Todate(-1, "Ymd_His") + c.Tostr(rand.Intn(8999)+1000) + ".xls"
	err = c.FileSave(c.CiyWebDir+filename, str)
	if err != nil {
		return c.ErrJSON(w, "导出保存文件错误:%v[%v]", err, filename)
	}
	ret := map[string]any{}
	ret["url"] = filename
	return c.SuccJSON(w, r, ret)
}
func Admin_importxls_in(w http.ResponseWriter, r *http.Request) bool {
	post := c.NewCiyPost(w, r)
	_, userid := admin.Verifyfast(r, c.CiyDB, post)
	if userid == 0 {
		return false
	}
	if admin.Nopower(c.CiyDB, userid, "p500u") {
		return c.ErrJSON(w, "您未被授权操作")
	}
	file := post.Get("file")
	if c.FileExist(c.CiyWebDir+"/ud/"+file) != nil {
		return c.ErrJSON(w, "文件不存在")
	}
	xlFile, err := xlsx.OpenFile(c.CiyWebDir + "/ud/" + file)
	if err != nil {
		return c.ErrJSON(w, "文件打开错误:%v", err)
	}
	datas, err := xlFile.ToSlice()
	if err != nil {
		return c.ErrJSON(w, "文件解析错误:%v", err)
	}
	datacnt := len(datas[0])
	if datacnt < 2 {
		return c.ErrJSON(w, "数据为空")
	}
	html := ""
	headsn := []string{}
	headsn = append(headsn, "行码.id")
	headsn = append(headsn, "姓名.name")
	headsn = append(headsn, "状态.stpstatus")
	headsn = append(headsn, "手机号.mobile")
	headsn = append(headsn, "性别.sex")
	headsn = append(headsn, "所属组织.departid")

	xlsidx := 1
	if datas[0][0][len(headsn)-1] == "" {
		xlsidx = 2
	}
	heads := make([]map[string]string, 0)
	for _, head := range headsn {
		hd := strings.Split(head, ".")
		if len(hd) < 2 {
			continue
		}
		heads = append(heads, map[string]string{
			"idx":  c.Tostr(c.In_array(datas[0][xlsidx-1], hd[0])),
			"fld":  hd[1],
			"name": hd[0],
		})
	}

	code_sex := admin.Getcatas(c.CiyDB, "sex")
	code_departid, _, _ := c.CiyDB.Get(c.NewCiySQL("zc_depart").Where("isuse", 1).Column("id,upid,name"))
	code_stpstatus := admin.Getcatas(c.CiyDB, "stpstatus")

	html += "<div class=\"table\">\n"
	html += "<table><thead><tr>\n"
	html += "<th>#</th>\n"
	for _, arr := range heads {
		html += "<th>" + arr["name"] + "</th>\n"
	}
	html += "</tr>\n"
	cnt := 0
	un_name := []string{}
	un_mobile := []string{}
	id := 0
	for rowidx := xlsidx; rowidx < datacnt; rowidx++ {
		lineidx := c.Tostr(rowidx - xlsidx + 1)
		hrhtml := ""
		firsthtml := "<td><div>" + lineidx + "</div></td>"
		bempty := true
		for _, arr := range heads {
			name := arr["name"]
			errmsg := ""  //数据有误，显示红色说明
			showdat := "" //显示在表格中的数据
			if c.Toint(arr["idx"]) > -1 {
				showdat = strings.TrimSpace(datas[0][rowidx][c.Toint(arr["idx"])])
			}
			if showdat == "--" {
				showdat = ""
			}
			var value any
			value = showdat //在表单中的数据(转换后)
			ext := ""       //扩展表单
			if name == "行码" {
				if showdat == "" {
					value = 0
					showdat = "<kbd>新增</kbd>"
				} else {
					id = c.DeID(showdat)
					if id == 0 {
						errmsg = name + "解析错误"
					} else {
						csqlchk := c.NewCiySQL("zc_admin")
						csqlchk.Where("id", id).Column("id")
						chkid := c.Toint(c.CiyDB.Get1(csqlchk))
						if chkid != id {
							errmsg = name + "在数据库中不存在"
						}
						value = id
					}
				}
			} else if name == "状态" {
				if showdat == "" {
					value = 0
				} else {
					value = c.Dcode(code_stpstatus, c.Tostr(showdat))
					if value == -1 {
						errmsg = name + "文字与系统数据不匹配"
					}
				}
			} else if name == "性别" {
				if showdat == "" {
					value = 0
				} else {
					value = c.Dcode(code_sex, c.Tostr(showdat))
					if value == -1 {
						errmsg = name + "文字与系统数据不匹配"
					}
				}
			} else if name == "姓名" {
				if showdat == "" {
					errmsg = name + "为必填项"
				} else {
					csqlchk := c.NewCiySQL("zc_admin")
					csqlchk.Where("name", id).Column("id")
					chkid := c.Toint(c.CiyDB.Get1(csqlchk))
					if chkid > 0 && ((id > 0 && chkid != id) || id == 0) {
						errmsg = name + "在数据库中出现重复"
					}
					if c.In_array(un_name, showdat) > -1 {
						errmsg = name + "发现重复"
					} else {
						un_name = append(un_name, showdat)
					}
				}
			} else if name == "手机号" {
				if showdat == "" {
					errmsg = name + "为必填项"
				} else {
					csqlchk := c.NewCiySQL("zc_admin")
					csqlchk.Where("mobile", id).Column("id")
					chkid := c.Toint(c.CiyDB.Get1(csqlchk))
					if chkid > 0 && ((id > 0 && chkid != id) || id == 0) {
						errmsg = name + "在数据库中出现重复"
					}
					if c.In_array(un_mobile, showdat) > -1 {
						errmsg = name + "发现重复"
					} else {
						un_mobile = append(un_mobile, showdat)
					}
				}
			} else if name == "所属组织" {
				if showdat == "" {
					value = 0
				} else {
					dats := strings.Split(showdat, "-")
					value = c.Dcode(code_departid, dats[len(dats)-1])
					if value == -1 {
						errmsg = name + "文字与系统数据不匹配"
					}
				}
			}
			if showdat != "" {
				bempty = false
			}
			if errmsg == "" {
				hrhtml += "<td><div>" + showdat + "<input type=\"hidden\" name=\"" + c.Tostr(arr["fld"]) + "_" + lineidx + "\" value=\"" + c.Tostr(value) + "\"/>" + ext + "</div></td>"
			} else {
				hrhtml += "<td><div style=\"background:#ffe8c5;\" title=\"#" + lineidx + ":" + errmsg + "\">" + showdat + "</div></td>"
			}
		}
		if bempty {
			continue
		}

		html += "<tr>"
		html += firsthtml
		html += hrhtml
		html += "</tr>"
		cnt++
	}
	html += "</tbody>\n"
	html += "</table>\n"
	html += "</div>\n"
	html += "<input type=\"hidden\" name=\"total\" value=\"" + c.Tostr(cnt) + "\"/>\n"
	html += "<code>共" + c.Tostr(cnt) + "条数据</code>\n"
	return c.SuccJSON(w, r, map[string]any{
		"html":  html,
		"count": cnt,
	})
}
func Admin_importxls_data(w http.ResponseWriter, r *http.Request) bool {
	post := c.NewCiyPost(w, r)
	_, userid := admin.Verifyfast(r, c.CiyDB, post)
	if userid == 0 {
		return false
	}
	if admin.Nopower(c.CiyDB, userid, "p500a") {
		return c.ErrJSON(w, "您未被授权操作新增")
	}
	total := post.Getint("total")
	err := c.CiyDB.Tran(func() error {
		for i := 1; i <= total; i++ {
			istr := c.Tostr(i)
			id := post.Getint("id_" + istr)
			stpstatus := post.Getint("stpstatus_" + istr)
			name := post.Get("name_" + istr)
			mobile := post.Get("mobile_" + istr)
			sex := post.Getint("sex_" + istr)
			departid := post.Getint("departid_" + istr)
			csql := c.NewCiySQL("zc_admin")
			csql.Where("mobile", mobile)
			csql.Column("id")
			chkid := c.Toint(c.CiyDB.Get1(csql))
			if chkid > 0 && ((id > 0 && chkid != id) || id == 0) {
				return fmt.Errorf("发现手机号有重复")
			}
			updata := map[string]any{}
			updata["name"] = name
			updata["mobile"] = mobile
			updata["stpstatus"] = stpstatus
			updata["sex"] = sex
			updata["departid"] = departid
			csql = c.NewCiySQL("zc_admin")
			var err error
			if id == 0 {
				updata["addtimes"] = c.Tostamp()
				_, err = c.CiyDB.Insert(csql, updata)
			} else {
				csql.Where("id", id)
				_, err = c.CiyDB.Update(csql, updata)
			}
			if err != nil {
				return fmt.Errorf("导入失败:%v", err)
			}
		}
		return nil
	})
	if err != nil {
		return c.ErrJSON(w, "事务"+err.Error())
	}
	c.CiyDB.Execute("update zc_online set usrchg=2")
	return c.SuccJSON(w, r)
}
