package util

import (
	"fmt"
	"github.com/cron"
	"go.mongodb.org/mongo-driver/bson/primitive"
	. "jy/mongodbutil"
	qu "qfw/util"
	"regexp"
	"strconv"
	"strings"

	. "gopkg.in/mgo.v2/bson"
)

// 敏感词
type DFA struct {
	Link map[string]interface{}
}

// 定义字典树
type Trie struct {
	y bool
	c map[rune]*Trie
}

var syncint chan bool //获取下标锁
var Config map[string]interface{}
var RegionsConfig map[string]interface{}

var Se = qu.SimpleEncrypt{Key: "topnet@extract"}

var BrandRules map[string]map[string]string
var GoodsConfig []string
var BrandConfig []string

var IsPriceNumber bool //是否开启价格和个数抽取
var PriceNumberConfig map[string]string
var PriceNumberReg map[string]*regexp.Regexp

var GoodsGet *DFA     //商品
var BrandGet *DFA     //品牌
var IsBrandGoods bool //是否开启品牌抽取

var SaveResult, FieldsFind, IsSaveTag, SaveBlock, QualityAudit, Ffield, Inscribe bool
var Site_Mgo, Qyxy_Mgo *MongodbSim

var IsUpdateRule bool
var DefaultRegions, AdjustmentRegions = []string{}, []string{}

func init() {
	syncint = make(chan bool, 1)
}

func UtilInit() {
	initCap := qu.IntAll(Config["dbsize"])
	addr := qu.ObjToString(Config["mgodb"])
	dbname := qu.ObjToString(Config["dbname"])
	Mgo = MgoFactory(initCap, initCap*3, 120, addr, dbname)

	//站点爬虫库~
	Site_Mgo = &MongodbSim{
		MongodbAddr: qu.ObjToString(Config["site_addr"]),
		DbName:      qu.ObjToString(Config["site_dbname"]),
		Size:        3,
		UserName:    "",
		Password:    "",
	}
	Site_Mgo.InitPool()

	Qyxy_Mgo = &MongodbSim{
		MongodbAddr: qu.ObjToString(Config["qyxy_addr"]),
		DbName:      qu.ObjToString(Config["qyxy_dbname"]),
		Size:        5,
		UserName:    qu.ObjToString(Config["qyxy_username"]),
		Password:    qu.ObjToString(Config["qyxy_password"]),
	}
	Qyxy_Mgo.InitPool()

	SaveResult, _ = Config["saveresult"].(bool)
	FieldsFind, _ = Config["fieldsfind"].(bool)
	IsSaveTag, _ = Config["iscltlog"].(bool)
	SaveBlock, _ = Config["saveblock"].(bool)
	QualityAudit, _ = Config["qualityaudit"].(bool)
	Ffield, _ = Config["ffield"].(bool)
	Inscribe, _ = Config["inscribe"].(bool)
	PriceNumberReg = make(map[string]*regexp.Regexp)
	for k, v := range PriceNumberConfig {
		PriceNumberReg[k] = regexp.MustCompile(v)
	}

	DefaultRegions = ConvertInterface(RegionsConfig["default_regions"])
	AdjustmentRegions = ConvertInterface(RegionsConfig["adjustment_regions"])

	//定时更新站点信息
	IsUpdateRule = false
	c := cron.New()
	c.AddFunc("0 0 9 * * ?", func() {
		IsUpdateRule = true
	})
	c.Start()

}

func GetSyncIndex(code string) string {
	tmp := ""
	syncint <- true
	Mgo.Update("rule_code", `{"code":"`+code+`"}`, M{"$inc": M{"index": 1}}, true, false)
	data, _ := Mgo.FindOne("rule_code", `{"code":"`+code+`"}`)
	<-syncint
	if len(*data) > 0 {
		tmp = code + "_" + fmt.Sprint((*data)["index"])
	}
	return tmp
}

// nfields非复制字段集
func DeepCopy(value interface{}) interface{} {
	if valueMap, ok := value.(map[string]interface{}); ok {
		newMap := make(map[string]interface{})
		for k, v := range valueMap {
			newMap[k] = DeepCopy(v)
		}
		return newMap
	} else if valueSlice, ok := value.([]interface{}); ok {
		newSlice := make([]interface{}, len(valueSlice))
		for k, v := range valueSlice {
			newSlice[k] = DeepCopy(v)
		}
		return newSlice
	}
	return value
}
func (d *DFA) AddWord(keys ...string) {
	d.AddWordAll(true, keys...)
}

func (d *DFA) AddWordAll(haskey bool, keys ...string) {
	if d.Link == nil {
		d.Link = make(map[string]interface{})
	}
	for _, key := range keys {
		nowMap := &d.Link
		for i := 0; i < len(key); i++ {
			kc := key[i : i+1]
			if v, ok := (*nowMap)[kc]; ok {
				nowMap, _ = v.(*map[string]interface{})
			} else {
				newMap := map[string]interface{}{}
				newMap["YN"] = "0"
				(*nowMap)[kc] = &newMap
				nowMap = &newMap
			}
			if i == len(key)-1 {
				(*nowMap)["YN"] = "1"
				if haskey {
					(*nowMap)["K"] = key
				}
			}
		}
	}
}

func (d *DFA) CheckSensitiveWord(src string) string {
	pos := 0
	nowMap := &d.Link
	res := ""
	for i := 0; i < len(src); i++ {
		word := src[i : i+1]
		nowMap, _ = (*nowMap)[word].(*map[string]interface{})
		if nowMap != nil { // 存在，则判断是否为最后一个
			if pos == 0 {
				pos = i
			}
			if "1" == qu.ObjToString((*nowMap)["YN"]) { // 如果为最后一个匹配规则,结束循环，返回匹配标识数
				res = qu.ObjToString((*nowMap)["K"])
				//pos = 0
				//break
			}
		} else {
			if res != "" {
				break
			} else {
				nowMap = &d.Link
				if pos > 0 {
					i = pos
					pos = 0
				}
			}
		}
	}
	return res
}

func (t *Trie) AddWords(words ...string) {
	cur := t
	for _, v := range words {
		for _, one := range v {
			if cur.c == nil {
				cur.c = map[rune]*Trie{}
			}
			n := cur.c[one]
			if n == nil {
				n = &Trie{}
				cur.c[one] = n
			}
			cur = n
		}
		cur.y = true
		cur = t
	}
}

func (t *Trie) Get(word string) bool {
	cur := t
	for _, one := range word {
		n := cur.c[one]
		if n == nil {
			return false
		}
		cur = n
	}
	return cur.y
}

// 初始化商品
func InitGoods() {
	GoodsGet = &DFA{}
	GoodsGet.AddWord(GoodsConfig...)
}

// 初始化品牌
func InitBrand() {
	BrandGet = &DFA{}
	BrandGet.AddWord(BrandConfig...)
}

func FloatFormat(val float64, length int) float64 {
	tmp, err := strconv.ParseFloat(strconv.FormatFloat(val, 'f', length, 64), 64)
	if err != nil {
		return 0
	} else {
		return tmp
	}
}

func ConvertInterface(t interface{}) []string {
	p_list := []string{}
	if yl_list_0, ok_0 := t.([]string); ok_0 {
		p_list = yl_list_0
	} else {
		if yl_list_1, ok_1 := t.(primitive.A); ok_1 {
			p_list = qu.ObjArrToStringArr(yl_list_1)
		} else {
			if yl_list_2, ok_2 := t.([]interface{}); ok_2 {
				p_list = qu.ObjArrToStringArr(yl_list_2)
			}
		}
	}
	return p_list
}

func IsMarkInterfaceMap(t interface{}) []map[string]interface{} {
	p_list := []map[string]interface{}{}
	if yl_list_0, ok_0 := t.([]map[string]interface{}); ok_0 {
		return yl_list_0
	} else {
		if yl_list_1, ok_1 := t.(primitive.A); ok_1 {
			p_list = qu.ObjArrToMapArr(yl_list_1)
		} else {
			if yl_list_2, ok_2 := t.([]interface{}); ok_2 {
				p_list = qu.ObjArrToMapArr(yl_list_2)
			}
		}
	}
	return p_list
}

// GetQualifications 从正文中获取气质要求
func GetQualifications(text string) (qualifications string) {
	re1 := regexp.MustCompile(`(\n(\s)*(\d)[、.．](\s*)[\p{Han}]+[:：]?)`)
	re2 := regexp.MustCompile(`(?m)^(★)?(一|二|三|四|五|六|七|八|九|十|十一)[、.](.+?)[\p{Han}]?[:：]?$`)
	match := regexp.MustCompile(`(投标人|参选单位|投标商|供应商|申请人|参选人|应答人|承包人|应答方|报名人|报价人|投标单位|服务商|竞价方).*(资质|资格|要求|准入条件|条件).*`)
	matchWords := []string{"合格的投标人", "资格要求", "入围审核条价", "报名要求"}

	var sections = make([]map[string]interface{}, 0)
	sections = ExtractSections(text, re2)
	if len(sections) > 0 {

	} else {
		sections = ExtractSections(text, re1)
	}

	for _, section := range sections {
		matches := match.FindStringSubmatch(section["title"].(string))
		if len(matches) > 1 {
			return section["content"].(string)
		} else {
			for _, mword := range matchWords {
				if strings.Contains(section["title"].(string), mword) {
					return section["content"].(string)
				}
			}
		}
	}
	return
}

// ExtractSections 函数提取文本中的标题和内容，并返回一个包含map的切片
func ExtractSections(text string, re *regexp.Regexp) []map[string]interface{} {
	// 使用正则表达式在文本中找到所有章节标题的起始索引位置
	sectionIndexes := re.FindAllStringIndex(text, -1)
	// 将文本的结束索引位置也添加为一个哨兵，方便处理最后一个章节
	sectionIndexes = append(sectionIndexes, []int{len(text), len(text)})
	// 初始化一个map切片，用于保存提取的各个章节内容
	sections := make([]map[string]interface{}, len(sectionIndexes)-1)
	// 遍历各个章节标题的索引位置，将文本切分为不同的章节
	for i := range sections {
		// 当前章节的起始和结束索引位置
		start := sectionIndexes[i][1]
		end := sectionIndexes[i+1][0]
		// 提取当前章节的标题和文本内容，并去除前后的空白字符
		title := strings.TrimSpace(text[sectionIndexes[i][0]:start])
		content := strings.TrimSpace(text[start:end])
		// 将标题和内容添加到map中
		sections[i] = map[string]interface{}{
			"title":   title,
			"content": content,
		}
	}
	// 返回提取的各个章节内容组成的map切片
	return sections
}

// ContainSpecialWord 判断一个字符串是否包含特殊关键词
func ContainSpecialWord(key string, words []string) bool {
	//含有排除关键词，直接跳过
	for _, word := range words {
		if strings.Contains(key, word) {
			return true
		}
	}

	return false
}

// RemoveDuplicates 移除重复字符串
func RemoveDuplicates(input []string) []string {
	seen := make(map[string]bool)
	output := []string{}

	for _, str := range input {
		if !seen[str] {
			seen[str] = true
			output = append(output, str)
		}
	}

	return output
}

//RemoveDuplicatesAndKeepLonger 去除字符串数组中的重复数据，同时只保留更全的字符串
func RemoveDuplicatesAndKeepLonger(arr []string) []string {
	result := make([]string, 0)
	uniqueStrings := make(map[string]struct{})

	for _, s := range arr {
		// 检查是否已经存在更全的字符串
		isDuplicate := false
		for existing := range uniqueStrings {
			if strings.Contains(existing, s) {
				isDuplicate = true
				break
			}
			if strings.Contains(s, existing) {
				delete(uniqueStrings, existing)
			}
		}
		// 如果不是重复的，将其添加到结果中
		if !isDuplicate {
			uniqueStrings[s] = struct{}{}
		}
	}

	for unique := range uniqueStrings {
		result = append(result, unique)
	}

	return result
}
