package audit

import (
	"fmt"
	"html/template"
	. "jy/admin"
	. "jy/mongodbutil"
	ju "jy/util"
	qu "qfw/util"
	"regexp"
	"strings"
	"time"

	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
)

func init() {
	//列表、编辑
	//识别字段
	Admin.GET("/audit/recogfield", func(c *gin.Context) {
		c.HTML(200, "audit_recogfield.html", nil)
	})
	Admin.POST("/rulemanager/getrecogfield", GetRecogField)   //获取识别字段
	Admin.POST("/rulemanager/saverecogfield", SaveRecogField) //保存
	Admin.POST("/rulemanager/delrecogfield", DelRecogField)   //删除
	//class
	Admin.GET("/rulemanager/getclasslist", func(c *gin.Context) {
		fname := c.Query("fname")
		fid := c.Query("id")
		c.HTML(200, "audit_classlist.html", gin.H{"fname": fname, "fid": fid})
	})
	Admin.POST("/rulemanager/getclass", GetClass)           //获取分类
	Admin.POST("/rulemanager/saveclass", SaveClass)         //保存
	Admin.POST("/rulemanager/getauditfield", GetAuditField) //获取要审核的字段
	Admin.POST("/rulemanager/delclass", DelClass)           //删除
	//Admin.POST("/rulemanager/getclist", GetCList)           //获取父分类
	//rule
	Admin.GET("/rulemanager/getrulelist", func(c *gin.Context) {
		cid := c.Query("id")
		cname := c.Query("cname")
		fid := c.Query("fid")
		//		class, _ := Mgo.FindById("rc_class", cid, `{"_id":1,"s_name":1,"s_pid":1}`)
		//		//级联查询,往上查
		//		if class != nil && *class != nil {
		//			pid := qu.ObjToString((*class)["s_pid"])
		//			if pid != "" {
		//				GetParent(pid, "rc_class", class)
		//			}
		//		}
		rule, _ := Mgo.Find("rc_rule", `{"s_classid":"`+cid+`","delete":false}`, `{"i_order":1}`, nil, false, 0, 200)
		//Finds := map[string]interface{}{}
		data := map[string]interface{}{}
		//		for _, r := range *rule {
		//			rpid := qu.ObjToString(r["s_pid"])
		//			if rpid != "" {
		//				if Finds[rpid] != nil {
		//					r["p"] = Finds[rpid]
		//				} else {
		//					GetParent(rpid, "rc_rule", &r)
		//					Finds[rpid] = r["p"]
		//				}
		//			}
		//		}
		data["rule"] = rule
		//data["class"] = class
		c.HTML(200, "audit_rulelist.html", gin.H{"cid": cid, "cname": cname, "data": data, "fid": fid})
	})
	Admin.POST("/rulemanager/getrule", GetRule)   //获取规则
	Admin.POST("/rulemanager/saverule", SaveRule) //保存规则
	//	Admin.POST("/rulemanager/getrlist", GetRList)       //获取父分类中的所有规则
	Admin.POST("/rulemanager/delrule", DelRule)         //删除
	Admin.POST("/rulemanager/shift", Shift)             //移动
	Admin.POST("/rulemanager/runruletest", RunRuleTest) //规则测试

}
func GetRecogField(c *gin.Context) {
	data, _ := Mgo.Find("rc_field", `{"delete":false}`, `{"i_order":1}`, nil, false, -1, -1)
	for _, d := range *data {
		timeStr := time.Unix(d["l_createtime"].(int64), 0).Format(Date_Short_Layout)
		d["l_createtime"] = timeStr
	}
	c.JSON(200, gin.H{"data": data})
}

func SaveRecogField(c *gin.Context) {
	data := GetPostForm(c)
	_id, _ := c.GetPostForm("_id")
	session := sessions.Default(c)
	if _id != "" {
		Mgo.UpdateById("rc_field", _id, map[string]interface{}{"$set": data})
		c.JSON(200, gin.H{"rep": true})
	} else {
		//s_class, _ := c.GetPostForm("s_class")
		s_recogfield, _ := c.GetPostForm("s_recogfield")
		d, _ := Mgo.FindOne("rc_field", `{"s_recogfield":"`+s_recogfield+`","delete":false}`)
		if len(*d) > 0 {
			c.JSON(200, gin.H{"msg": "已存在！"})
		} else {
			data["l_createtime"] = time.Now().Unix()
			//data["l_date"] = time.Now().Unix()
			data["s_user"] = session.Get("username")
			data["delete"] = false
			Mgo.Save("rc_field", data)
			c.JSON(200, gin.H{"rep": true})
		}
	}
}

func DelRecogField(c *gin.Context) {
	//删除识别字段，对应的删除识别字段下的分类和规则
	_id, _ := c.GetPostForm("_id")
	b := Mgo.Update("rc_field", `{"_id":"`+_id+`"}`, map[string]interface{}{
		"$set": map[string]interface{}{"delete": true},
	}, false, false)
	go DelClassAndRule(_id)
	if b {
		c.JSON(200, gin.H{"rep": true})
	} else {
		c.JSON(200, gin.H{"rep": false})
	}
}

func GetClass(c *gin.Context) {
	s_fid, _ := c.GetPostForm("fid")
	data, _ := Mgo.Find("rc_class", `{"s_fid":"`+s_fid+`","delete":false}`, `{"i_order":1}`, nil, false, -1, -1)
	for _, d := range *data {
		timeStr := time.Unix(d["l_createtime"].(int64), 0).Format(Date_Short_Layout)
		d["l_createtime"] = timeStr
	}
	c.JSON(200, gin.H{"data": data})
}

func SaveClass(c *gin.Context) {
	data := GetPostForm(c)
	_id, _ := c.GetPostForm("_id")
	session := sessions.Default(c)
	if _id != "" {
		Mgo.UpdateById("rc_class", _id, map[string]interface{}{"$set": data})
		c.JSON(200, gin.H{"rep": true})
	} else {
		s_name, _ := c.GetPostForm("s_name")
		s_recogfield, _ := c.GetPostForm("s_recogfield")
		s_fid, _ := c.GetPostForm("s_fid")
		class, _ := Mgo.FindOne("rc_class", `{"s_name":"`+s_name+`","s_fid":"`+s_fid+`","s_recogfield":"`+s_recogfield+`","delete":false}`)
		if len(*class) > 0 {
			c.JSON(200, gin.H{"rep": false})
		} else {
			data["l_createtime"] = time.Now().Unix()
			//data["l_date"] = time.Now().Unix()
			data["s_user"] = session.Get("username")
			data["i_order"] = GetOrder("class")
			data["delete"] = false
			Mgo.Save("rc_class", data)
			c.JSON(200, gin.H{"rep": true})
		}
	}
}

func GetAuditField(c *gin.Context) {
	v, _ := Mgo.FindOne("version", `{"isuse":true,"delete":false}`)
	if len(*v) > 0 {
		vid := qu.BsonIdToSId((*v)["_id"])
		query := map[string]interface{}{
			"isaudit": true,
			"delete":  false,
			"vid":     vid,
		}
		data, _ := Mgo.Find("versioninfo", query, `{"_id":-1}`, nil, false, -1, -1)
		for _, d := range *data {
			d["_id"] = qu.BsonIdToSId(d["s_field"])
			d["s_name"] = d["s_field"]
		}
		c.JSON(200, gin.H{"data": data})
	} else {
		c.JSON(200, gin.H{"data": map[string]interface{}{}})
	}
}

func DelClass(c *gin.Context) {
	_id, _ := c.GetPostForm("_id")
	b := Mgo.Update("rc_class", `{"_id":"`+_id+`"}`, map[string]interface{}{
		"$set": map[string]interface{}{"delete": true},
	}, false, false)
	go DelRuleByClass(_id)
	if b {
		c.JSON(200, gin.H{"rep": true})
	} else {
		c.JSON(200, gin.H{"rep": false})
	}
}

func GetOrder(sel string) int {
	q := `{"s_name":"` + sel + `"}`
	res, _ := Mgo.FindOneByField("rc_order", q, `{"i_order":1}`)
	v := qu.IntAllDef((*res)["i_order"], 1)
	Mgo.Update("rc_order", q, &map[string]interface{}{
		"s_name":  sel,
		"i_order": (v + 1),
	}, true, false)
	return v
}

func GetRule(c *gin.Context) {
	cid, _ := c.GetPostForm("cid")
	data, _ := Mgo.Find("rc_rule", `{"s_classid":"`+cid+`","delete":false}`, `{"i_order":1}`, nil, false, -1, -1)
	for _, d := range *data {
		timeStr := time.Unix(d["l_createtime"].(int64), 0).Format(Date_Short_Layout)
		d["l_createtime"] = timeStr
	}
	c.JSON(200, gin.H{"data": data})
}

func SaveRule(c *gin.Context) {
	data := GetPostForm(c)
	_id, _ := c.GetPostForm("_id")
	session := sessions.Default(c)
	var s_ruleArr []string
	rule, _ := c.GetPostForm("s_rule")
	rule = regexp.MustCompile("\\n|\\s+").ReplaceAllString(rule, "")
	s_rule := strings.Split(rule, "'")
	for k, r := range s_rule {
		if k%2 == 1 { //奇数为正则
			r = "'" + r + "'" //为正则加上''
			if r != "" {
				s_ruleArr = append(s_ruleArr, r)
			}
		} else {
			fr := strings.Split(r, ",")
			for _, frs := range fr {
				if frs != "" {
					s_ruleArr = append(s_ruleArr, frs)
				}
			}
		}
	}
	data["s_rule"] = s_ruleArr
	if _id != "" {
		Mgo.UpdateById("rc_rule", _id, map[string]interface{}{"$set": data})
		c.JSON(200, gin.H{"rep": true})
	} else {
		s_name, _ := c.GetPostForm("s_name")
		s_classid, _ := c.GetPostForm("s_classid")
		d, _ := Mgo.FindOne("rc_rule", `{"s_name":"`+s_name+`","s_classid":"`+s_classid+`","delete":false}`)
		if len(*d) > 0 {
			c.JSON(200, gin.H{"msg": "已存在！"})
		} else {
			data["l_createtime"] = time.Now().Unix()
			//data["l_date"] = time.Now().Unix()
			data["s_user"] = session.Get("username")
			data["i_order"] = GetOrder("rule")
			data["delete"] = false
			Mgo.Save("rc_rule", data)
			c.JSON(200, gin.H{"rep": true})
		}
	}
}

func DelRule(c *gin.Context) {
	_id, _ := c.GetPostForm("_id")
	b := Mgo.Update("rc_rule", `{"_id":"`+_id+`"}`, map[string]interface{}{
		"$set": map[string]interface{}{"delete": true},
	}, false, false)
	if b {
		c.JSON(200, gin.H{"rep": true})
	} else {
		c.JSON(200, gin.H{"rep": false})
	}
}

func Shift(c *gin.Context) {
	str, _ := c.GetPostForm("str")
	strs := strings.Split(str, ",")
	if str == "" {
		c.JSON(200, gin.H{"rep": false})
	} else {
		b := Mgo.Update("rc_rule", `{"_id":"`+strs[0]+`"}`, &map[string]interface{}{
			"$set": map[string]interface{}{
				"i_order": qu.IntAll(strs[3]),
			},
		}, false, false)
		if b {
			Mgo.Update("rc_rule", `{"_id":"`+strs[2]+`"}`, &map[string]interface{}{
				"$set": map[string]interface{}{
					"i_order": qu.IntAll(strs[1]),
				},
			}, false, false)
			c.JSON(200, gin.H{"rep": true})
		} else {
			c.JSON(200, gin.H{"rep": false})
		}
	}
}

func RunRuleTest(c *gin.Context) {
	_id, _ := c.GetPostForm("_id")
	s_con, _ := c.GetPostForm("s_con")
	data := map[string]interface{}{
		"b":     false,
		"rules": "",
		"text":  "",
		"pos":   0,
	}
	if _id == "" || s_con == "" {
		c.JSON(200, gin.H{"rep": false})
	} else {
		rule, _ := Mgo.FindById("rc_rule", _id, `{"s_rule":1,"s_rule_prerule":1}`)
		s_rule := qu.ObjArrToStringArr((*rule)["s_rule"].([]interface{}))
		s_con = ju.PreFilter(s_con, qu.ObjToString((*rule)["s_rule_prerule"])) //对文本先进行前置过滤
		text, rules, pos, b := ju.ClassificationText(s_con, ju.AnalyRules(s_rule))
		data["b"] = b
		data["pos"] = pos + 1
		data["rules"] = func() template.HTML {
			ts := []string{}
			for ppos, s := range rules {
				ts = append(ts, fmt.Sprintf("<p>%d.%s</p>", ppos+1, strings.Join(s, "")))
			}
			return template.HTML(strings.Join(ts, ""))
		}()
		data["text"] = template.HTML(text)
		c.HTML(200, "checkres.html", gin.H{"data": data})
	}
}

//func GetParent(s_pid, coll string, pm *map[string]interface{}) {
//	if s_pid != "" {
//		//可能有多个父类
//		ids := strings.Split(s_pid, ",")
//		idsmap := []map[string]interface{}{}
//		for _, val := range ids {
//			idsmap = append(idsmap, map[string]interface{}{
//				"_id": qu.StringTOBsonId(val),
//			})
//		}
//		class, b := Mgo.Find(coll, &map[string]interface{}{
//			"$or": idsmap,
//		}, nil, `{"_id":1,"s_name":1,"s_pid":1}`, false, 0, 10)
//		if b && class != nil && len(*class) > 0 {
//			for _, cla := range *class {
//				pid := qu.ObjToString(cla["s_pid"])
//				GetParent(pid, coll, &cla)
//			}
//			(*pm)["p"] = class
//		}
//	}
//	return
//}

func DelClassAndRule(fid string) {
	class, _ := Mgo.Find("rc_class", `{"s_fid":"`+fid+`"}`, nil, `{"_id":1}`, false, -1, -1)
	for _, c := range *class {
		Mgo.UpdateById("rc_class", c["_id"], map[string]interface{}{ //删除class
			"$set": map[string]interface{}{"delete": true},
		})
		classid := qu.BsonIdToSId(c["_id"])
		Mgo.Update("rc_rule", `{"s_classid":"`+classid+`"}`, map[string]interface{}{ //删除class
			"$set": map[string]interface{}{"delete": true},
		}, false, true)
	}
}

func DelRuleByClass(classid string) {
	Mgo.Update("rc_rule", `{"s_classid":"`+classid+`"}`, map[string]interface{}{ //删除class
		"$set": map[string]interface{}{"delete": true},
	}, false, true)
}

//func GetCList(c *gin.Context) {
//	nid := c.Query("nid")
//	fname := c.Query("fname")
//	query := map[string]interface{}{
//		"delete": false,
//	}
//	if nid != "" {
//		query = map[string]interface{}{
//			"_id": map[string]interface{}{
//				"$ne": qu.StringTOBsonId(nid),
//			},
//		}
//	}
//	if fname != "" {
//		query = map[string]interface{}{
//			"s_recogfield": map[string]interface{}{
//				"$ne": fname,
//			},
//		}
//	}
//	class, _ := Mgo.Find("rc_class", query, nil, `{"s_name":1}`, false, 0, 200)
//	c.JSON(200, gin.H{"data": class})
//}

//func GetRList(c *gin.Context) {
//	cid := c.Query("id")
//	if cid == "" {
//		c.JSON(200, gin.H{"data": map[string]interface{}{}})
//	} else {
//		//先找类
//		ids := strings.Split(cid, ",")
//		ids2 := make([]string, len(ids))
//		idsmap := []map[string]interface{}{}
//		for n, val := range ids {
//			idsmap = append(idsmap, map[string]interface{}{
//				"_id": qu.StringTOBsonId(val),
//			})
//			ids2[n] = fmt.Sprintf(`{"s_classid":"%s"}`, val)
//		}
//		class, _ := Mgo.Find("rc_class", &map[string]interface{}{
//			"$or": idsmap,
//		}, nil, `{"s_name":1}`, false, 0, 10)
//		rule, _ := Mgo.Find("rc_rule", fmt.Sprintf(`{"$or":[%s]}`, strings.Join(ids2, ",")), `{"i_order":1}`, `{"s_name":1,"s_code":1,"s_classid":1}`, false, 0, 200)
//		for _, ru := range *rule {
//			for _, c := range *class {
//				if qu.BsonIdToSId(c["_id"]) == ru["s_classid"] {
//					ru["s_name"] = fmt.Sprintf("%s[%s]", ru["s_name"], c["s_name"])
//				}
//			}
//		}
//		c.JSON(200, gin.H{"data": rule})
//	}
//}
