package larkalarm

import (
	"io/ioutil"
	"net/http"
	"regexp"
	"strings"
	"time"

	"github.com/axgle/mahonia"
)

const (
	FS_App_ID      = `test`
	FS_App_Secrets = `test`

	Test_Group_Chat_ID     = `oc_test` // 测试群的 chat_id
	Security_Group_Chat_ID = `oc_test` // Security Group ID

	//消息模板，替换 user_open_id 、send_message、notice_title(用户的openid 消息内容 消息标题)
	Template_Notice = `
{
    "receive_id": "user_open_id",
    "content": "{\"config\":{\"wide_screen_mode\":true},\"elements\":[{\"tag\":\"div\",\"text\":{\"content\":\"send_message\",\"tag\":\"lark_md\"}}],\"header\":{\"template\":\"turquoise\",\"title\":{\"content\":\"notice_title\",\"tag\":\"plain_text\"}}}",
    "msg_type": "interactive"
}
`

	ShieldAdvanced_Alarm_Title  = `AWS Security Bulletin`
	ShieldAdvanced_Alarm_messag = `Monitoring the last info of AWS security bulletin`
)

func Send_alarm_to_lark(larkid, vulstr string) error {
	if vulstr == "" {
		return nil
	}
	err := Send_Group_Notice(larkid, ShieldAdvanced_Alarm_Title, ShieldAdvanced_Alarm_messag+"\n"+vulstr)
	if err != nil {
		return err
	}
	return nil
}

func Get_Tenant_AccessToken() (string, error) {
	var postdata string
	postdata = `{"app_id": "` + FS_App_ID + `","app_secret": "` + FS_App_Secrets + `"}`
	//fmt.Println(postdata)
	respdata, err := HTTP_Req_POST("https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal", postdata)
	if err != nil {
		return "", err
	}
	resp1, err1 := RegxStr(respdata, `"app_access_token":"t-[0-9a-zA-Z]+"`)
	if err1 != nil {
		return "", err
	}
	resp2, err2 := RegxStr(resp1, `t-[0-9a-zA-Z]+`)
	if err2 != nil {
		return "", err
	}
	return resp2, err
}

/*
发送飞书群消息函数
receive_id 为飞书群 ID，在发送消息的选择群组中可获取
*/
func Send_Group_Notice(receive_id string, title string, sendmessage string) error {
	receive_id = strings.TrimSpace(receive_id)
	title = strings.TrimSpace(title)
	sendmessage = strings.TrimSpace(sendmessage)
	//获取 header token
	APP_Token, aterr := Get_Tenant_AccessToken()
	if aterr != nil {
		return aterr
	}

	//send message to user
	APP_Token, aterr = Get_Tenant_AccessToken()
	if aterr != nil {
		return aterr
	}
	send_msg_url := "https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id"
	send_message_data := strings.ReplaceAll(Template_Notice, "user_open_id", receive_id) //user open id
	sendmessage = strings.ReplaceAll(sendmessage, "\n", `\\n`)
	send_message_data = strings.ReplaceAll(send_message_data, "send_message", sendmessage)
	send_message_data = strings.ReplaceAll(send_message_data, "notice_title", title)

	_, serr := HTTP_POST(send_msg_url, APP_Token, send_message_data)
	if serr != nil {
		return serr
	}

	return nil
}

func HTTP_POST(Hurl string, ha string, postdata string) (string, error) {
	req, err := http.NewRequest("POST", Hurl, strings.NewReader(postdata))
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0")
	req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2")
	//req.Header.Set("Accept-Encoding","gzip, deflate")
	req.Header.Set("Upgrade-Insecure-Requests", "1")
	req.Header.Set("Sec-Fetch-Dest", "document")
	req.Header.Set("Sec-Fetch-Mode", "navigate")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+ha)
	//req.Header.Set("Content-Type","application/x-www-form-urlencoded")
	//req.Header.Set("Cookie","lianan")
	client := &http.Client{
		Timeout: time.Millisecond * 10000,
	}
	resp2, err := client.Do(req)
	if err != nil {
		return "", err
	}
	body, err := ioutil.ReadAll(resp2.Body)
	if err != nil {
		return "", err
	}
	resp2.Body.Close()
	Retexecstr := mahonia.NewDecoder("gbk").ConvertString(string(body))
	return Retexecstr, nil
}

/*
Hurl --> http url
postdata   --> The data that needs to be submitted by post
string --> Return the requested data
*/
func HTTP_Req_POST(Hurl string, postdata string) (string, error) {
	req, err := http.NewRequest("POST", Hurl, strings.NewReader(postdata))
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:96.0) Gecko/20100101 Firefox/96.0")
	req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2")
	//req.Header.Set("Accept-Encoding","gzip, deflate")
	req.Header.Set("Upgrade-Insecure-Requests", "1")
	req.Header.Set("Sec-Fetch-Dest", "document")
	req.Header.Set("Sec-Fetch-Mode", "navigate")
	req.Header.Set("Content-Type", "application/json")
	//req.Header.Set("Content-Type","application/x-www-form-urlencoded")
	//req.Header.Set("Cookie","lianan")
	client := &http.Client{
		Timeout: time.Millisecond * 10000,
	}
	resp2, err := client.Do(req)
	if err != nil {
		return "", err
	}
	body, err := ioutil.ReadAll(resp2.Body)
	if err != nil {
		return "", err
	}
	resp2.Body.Close()
	Retexecstr := mahonia.NewDecoder("gbk").ConvertString(string(body))
	return Retexecstr, nil
}

func RegxStr(datastr string, regx string) (string, error) {
	//Regular test, the MatchString function can only judge whether it can be matched, and return true if it can match, otherwise return false
	_, errs := regexp.MatchString(regx, datastr)
	if errs != nil {
		return "", errs
	}

	//Traverse the matching content
	comstr := regexp.MustCompile(regx)
	matchstr := comstr.FindAllString(datastr, -1)
	var regxres string = ""
	for x := range matchstr { //通过range函数遍历，打印全部输出
		regxres = regxres + matchstr[x] + "\n"
	}
	regxres = strings.TrimRight(regxres, "\n")
	return regxres, nil
}
