package resourceChannel

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/go-redis/redis"
	"golang.org/x/net/context"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"path"
	"runtime"
	"strconv"
	"strings"
	"time"
)

func redisCli() *redis.Client {
	client := redis.NewClient(&redis.Options{
		//Addr:     coo.RedisHost, // Redis地址
		Addr:     "192.168.204.193:6379", // Redis地址
		Password: "",                     // Redis密码,默认为空
		DB:       1,                      // 使用哪个数据库,默认为0
	})
	_, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
	defer cancel()
	return client
}

type ResourceAssessment struct {
	ID           uint      `gorm:"primaryKey" json:"id"` // 留学评估表
	DataType     uint8     `json:"data_type"`            // 1.网课 2.api资源 3.专题页 4.工作台录入 5.后台录入 6 小程序
	ChatID       string    `json:"chat_id"`              // 会话id
	Channel      int       `json:"channel"`              // 渠道id
	Category     int       `json:"category"`             // 分类id
	CreatedAt    time.Time `json:"created_at"`           // 数据创建时间
	ReferPageURL string    `json:"refer_page_url"`       // 来源网址
	URL          string    `json:"url"`                  // 落地页地址
	ChatURL      string    `json:"chat_url"`             // 对话发起页
	GrUserId     string    `json:"gr_user_id"`           // 神策distinct_id
}

type SemJsChatRecord struct {
	ChatID     int64     `gorm:"column:CHAT_ID"`
	CreateTime time.Time `gorm:"column:CREATE_TIME"`
	ReferPage  string    `gorm:"type:text;column:REFER_PAGE"`
	ChatURL    string    `gorm:"type:text;column:CHAT_URL"`
	ChannleID  int       `gorm:"column:CHANNLE_ID"`
	CategoryID int       `gorm:"column:CATEGORY_ID"`
	GrUserID   string    `gorm:"column:gr_user_id"`
	SourceUrl  string    `gorm:"column:source_url"`
}

type ChannelCategory struct {
	Channel  int
	Category int
}

// GetChannel 表单渠道归因处理
func GetChannel(assessment ResourceAssessment) ChannelCategory {
	log.Printf("%v", assessment)
	// 获取神策URL(不包含utm)
	cc, _ := redisCli().Get("website:" + assessment.GrUserId).Result()
	var websiteUrl SensorsData
	json.Unmarshal([]byte(cc), &websiteUrl)

	// 到梦解析
	if !strings.Contains(assessment.URL, "utm") && !strings.Contains(assessment.ChatURL, "utm") && !strings.Contains(assessment.ReferPageURL, "utm") && (strings.Contains(assessment.ReferPageURL, "daomeng") || strings.Contains(assessment.ChatURL, "daomeng")) {
		log.Printf("解析到梦")
		assessment.Channel = 38
		assessment.Category = getCategory(201)
		return ChannelCategory{assessment.Channel, assessment.Category}
	}
	// 网课解析
	if assessment.DataType == 1 {
		log.Printf("解析网课")
		assessment.Channel = 26
		assessment.Category = getCategory(121)
		return ChannelCategory{assessment.Channel, assessment.Category}
	}
	// 小程序解析
	if strings.Contains(assessment.ChatURL, "pages") && strings.Split(strings.Split(assessment.ChatURL, "?")[1], "=")[0] == "miniapp" && (strings.Contains(assessment.ChatURL, "baidu") || strings.Contains(assessment.ChatURL, "wechat")) {
		log.Printf("解析小程序")
		appType := strings.Split(strings.Split(strings.Split(assessment.ChatURL, "?")[1], "=")[1], "_")[1]
		if appType == "baidu" {
			assessment.Channel = 1
			assessment.Category = getCategory(30)
		} else if appType == "wechat" {
			assessment.Channel = 8
			assessment.Category = getCategory(32)
		}
		return ChannelCategory{assessment.Channel, assessment.Category}
	}
	// URL解析
	if strings.Contains(assessment.URL, "link=") || strings.Contains(assessment.ReferPageURL, "link=") || strings.Contains(assessment.ChatURL, "link=") {
		log.Printf("解析URL")
		if len(strings.Split(assessment.URL, "_")) == 3 {
			var category, _ = strconv.Atoi(strings.Split(assessment.URL, "_")[1])
			if category > 10000 {
				assessment.Channel = category
				assessment.Category = category
			}
		}
		if strings.Contains(assessment.URL, "link=") {
			split := strings.Split(assessment.URL, "link")
			if strings.Contains(split[1], "form") || strings.Contains(split[1], "from") {
				assessment.Channel, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.URL, "link")[1], "form")[0], "_")[1])
				var category, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.URL, "link")[1], "form")[0], "_")[2])
				assessment.Category = getCategory(category)
			} else {
				assessment.Channel = 5
				assessment.Category = getCategory(11)
			}
		} else if strings.Contains(assessment.ReferPageURL, "link=") {
			split := strings.Split(assessment.ReferPageURL, "link")
			if strings.Contains(split[1], "form") || strings.Contains(split[1], "from") {
				assessment.Channel, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.ReferPageURL, "link")[1], "form")[0], "_")[1])
				var category, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.ReferPageURL, "link")[1], "form")[0], "_")[2])
				assessment.Category = getCategory(category)
			} else {
				assessment.Channel = 5
				assessment.Category = getCategory(11)
			}
		} else {
			split := strings.Split(assessment.ChatURL, "link")
			if strings.Contains(split[1], "form") || strings.Contains(split[1], "from") {
				assessment.Channel, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.ChatURL, "link")[1], "form")[0], "_")[1])
				var category, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.ChatURL, "link")[1], "form")[0], "_")[2])
				assessment.Category = getCategory(category)
			} else {
				assessment.Channel = 5
				assessment.Category = getCategory(11)
			}
		}
		// 百度惠生活渠道合并
		if assessment.Category == 239 {
			assessment.Category = getCategory(292)
		}
		return ChannelCategory{assessment.Channel, assessment.Category}
	}
	// 获取神策url(包含utm)
	cc1, _ := redisCli().Get("sensors:" + assessment.GrUserId).Result()
	var utmUrl SensorsData
	json.Unmarshal([]byte(cc1), &utmUrl)
	// 神策解析
	if utmUrl.Url != "" && !strings.Contains(assessment.URL, "link=") && !strings.Contains(assessment.ReferPageURL, "link=") && !strings.Contains(assessment.ChatURL, "link=") {
		log.Printf("解析神策")
		assessment.Channel = utmUrl.Channel
		assessment.Category = utmUrl.Category
		// 百度惠生活渠道合并
		if assessment.Category == 239 {
			assessment.Category = getCategory(292)
		}
		return ChannelCategory{assessment.Channel, assessment.Category}
	}
	// 搜索引擎SEO,外链解析
	if assessment.ReferPageURL != "" && !strings.Contains(assessment.ReferPageURL, "https://www.jjl.cn/") && !strings.Contains(assessment.ReferPageURL, "https://m.jjl.cn/") {
		log.Printf("解析SEO")
		assessment.Channel = 5
		assessment.Category = getCategory(11)
		return ChannelCategory{assessment.Channel, assessment.Category}
	}
	// 官网自然访问解析
	if strings.Contains(assessment.URL, "https://www.jjl.cn/") || strings.Contains(assessment.URL, "https://m.jjl.cn/") ||
		strings.Contains(assessment.ReferPageURL, "https://www.jjl.cn/") || strings.Contains(assessment.ReferPageURL, "https://m.jjl.cn/") ||
		strings.Contains(assessment.ChatURL, "https://www.jjl.cn/") || strings.Contains(assessment.ChatURL, "https://m.jjl.cn/") ||
		strings.Contains(utmUrl.Url, "https://www.jjl.cn/") || strings.Contains(utmUrl.Url, "https://m.jjl.cn/") {
		log.Printf("解析官网")
		assessment.Channel = 7
		assessment.Category = getCategory(126)
		return ChannelCategory{assessment.Channel, assessment.Category}
	}
	log.Printf("默认解析为SEO")
	assessment.Channel = 5
	assessment.Category = getCategory(11)
	return ChannelCategory{assessment.Channel, assessment.Category}
}

// GetChatChannel 会话渠道归因处理
func GetChatChannel(chat SemJsChatRecord) ChannelCategory {
	log.Printf("%v", chat)
	// 获取神策URL(不包含utm)
	cc, _ := redisCli().Get("website:" + chat.GrUserID).Result()
	var websiteUrl SensorsData
	json.Unmarshal([]byte(cc), &websiteUrl)
	// 小程序解析
	if strings.Contains(chat.ChatURL, "pages") && strings.Split(strings.Split(chat.ChatURL, "?")[1], "=")[0] == "miniapp" && (strings.Contains(chat.ChatURL, "baidu") || strings.Contains(chat.ChatURL, "wechat")) {
		log.Printf("小程序解析")
		log.Printf(chat.ChatURL)
		appType := strings.Split(strings.Split(strings.Split(chat.ChatURL, "?")[1], "=")[1], "_")[1]
		if appType == "baidu" {
			chat.ChannleID = 1
			chat.CategoryID = getCategory(30)
		} else if appType == "wechat" {
			chat.ChannleID = 8
			chat.CategoryID = getCategory(32)
		}
		return ChannelCategory{chat.ChannleID, chat.CategoryID}
	}
	// 到梦解析
	if !strings.Contains(chat.ReferPage, "utm") && !strings.Contains(chat.ChatURL, "utm") && (strings.Contains(chat.ReferPage, "daomeng") || strings.Contains(chat.ChatURL, "daomeng")) {
		log.Printf("到梦解析")
		chat.ChannleID = 38
		chat.CategoryID = getCategory(201)
		return ChannelCategory{chat.ChannleID, chat.CategoryID}
	}
	// URL解析
	if strings.Contains(chat.ChatURL, "link=") || strings.Contains(chat.ReferPage, "link=") {
		log.Printf("解析CHATURL")
		if strings.Contains(chat.ChatURL, "link=") {
			split := strings.Split(chat.ChatURL, "link=")
			if strings.Contains(split[1], "form") || strings.Contains(split[1], "from") {
				chat.ChannleID, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(chat.ChatURL, "link")[1], "form")[0], "_")[1])
				var category, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(chat.ChatURL, "link")[1], "form")[0], "_")[2])
				chat.CategoryID = getCategory(category)
			} else {
				chat.ChannleID = 5
				chat.CategoryID = getCategory(11)
			}
		} else {
			split := strings.Split(chat.ReferPage, "link=")
			if strings.Contains(split[01], "form") || strings.Contains(split[1], "from") {
				chat.ChannleID, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(chat.ReferPage, "link")[1], "form")[0], "_")[1])
				var category, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(chat.ReferPage, "link")[1], "form")[0], "_")[2])
				chat.CategoryID = getCategory(category)
			} else {
				chat.ChannleID = 5
				chat.CategoryID = getCategory(11)
			}
		}
		// 百度惠生活渠道合并
		if chat.CategoryID == 239 {
			chat.CategoryID = getCategory(292)
		}
		return ChannelCategory{chat.ChannleID, chat.CategoryID}
	}
	// 获取神策url(包含utm)
	cc1, _ := redisCli().Get("sensors:" + chat.GrUserID).Result()
	var utmUrl SensorsData
	json.Unmarshal([]byte(cc1), &utmUrl)
	// 神策解析
	if utmUrl.Url != "" && utmUrl.Channel > 0 && !strings.Contains(chat.ReferPage, "link=") && !strings.Contains(chat.ChatURL, "link=") {
		log.Printf("解析神策")
		chat.ChannleID = utmUrl.Channel
		chat.CategoryID = utmUrl.Category
		// 百度惠生活渠道合并
		if chat.CategoryID == 239 {
			chat.CategoryID = getCategory(292)
		}
		return ChannelCategory{chat.ChannleID, chat.CategoryID}
	}
	// 搜索引擎SEO,外链解析
	if chat.ReferPage != "" && !strings.Contains(chat.ReferPage, "https://www.jjl.cn/") && !strings.Contains(chat.ReferPage, "https://m.jjl.cn/") {
		log.Printf("解析SEO")
		chat.ChannleID = 5
		chat.CategoryID = getCategory(11)
		return ChannelCategory{chat.ChannleID, chat.CategoryID}
	}
	// 官网自然访问解析
	if strings.Contains(chat.ReferPage, "https://www.jjl.cn/") || strings.Contains(chat.ReferPage, "https://m.jjl.cn/") ||
		strings.Contains(chat.ChatURL, "https://www.jjl.cn/") || strings.Contains(chat.ChatURL, "https://m.jjl.cn/") ||
		strings.Contains(utmUrl.Url, "https://www.jjl.cn/") || strings.Contains(utmUrl.Url, "https://m.jjl.cn/") {
		log.Printf("解析官网")
		chat.ChannleID = 7
		chat.CategoryID = getCategory(126)
		return ChannelCategory{chat.ChannleID, chat.CategoryID}
	}
	log.Printf("默认解析为SEO")
	chat.ChannleID = 5
	chat.CategoryID = getCategory(11)
	return ChannelCategory{chat.ChannleID, chat.CategoryID}
}

type SensorsData struct {
	DistinctId string `json:"distinctID"`
	Channel    int    `json:"channel"`
	Category   int    `json:"category"`
	Url        string `json:"url"`
}

// 访问神策API
func getSensorsData(sql string) string {
	sensorsUrl := "http://10.0.6.35:8107/api/sql/query?token=128d837f466684101710cfb308e7556de975b717c6c2465ba5fc2836d57a64c8&project=production&type=impala&q=" + url.QueryEscape(sql) + "&format=json"
	data := []byte("")
	log.Printf("REQ_URL:%s", sensorsUrl)
	req, err := http.NewRequest("POST", sensorsUrl, bytes.NewBuffer(data))
	if err != nil {
		log.Printf("ERROR:%s", err.Error())
		return err.Error()
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err.Error()
	}
	defer resp.Body.Close()
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err.Error()
	}
	var sensors Sensors
	json.Unmarshal([]byte(string(respBody)), &sensors)
	return sensors.LatestReferrer
}

// Sensors 神策数据结构体
type Sensors struct {
	Url            string `json:"$url"`
	LatestReferrer string `json:"$latest_referrer"`
}

type SysChannel struct {
	OriginalCategory string `json:"original_category"` // 主键ID
	CategoryId       string `json:"category_id"`       // 备注
}

func getCurrentPath() string {
	_, filename, _, _ := runtime.Caller(1)
	return path.Dir(filename)
}

func getCategory(OriginalCategory int) int {
	// 打开JSON文件
	//jsonFile, err := os.Open(getCurrentPath() + "/category_mapper.json")
	jsonFile, err := os.Open("category_mapper.json")
	if err != nil {
		fmt.Println(err)
		return -1
	}
	defer jsonFile.Close()
	// 读取文件内容
	byteValue, err := ioutil.ReadAll(jsonFile)
	if err != nil {
		fmt.Println(err)
		return -1
	}
	// 解析JSON数据
	var channel []SysChannel
	if err := json.Unmarshal(byteValue, &channel); err != nil {
		fmt.Println(err)
		return -1
	}
	for i := range channel {
		ori, _ := strconv.Atoi(channel[i].OriginalCategory)
		if ori == OriginalCategory {
			category, _ := strconv.Atoi(channel[i].CategoryId)
			return category
		}
	}
	return -1
}