package controller

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"hongze/hongze_yb/controller/response"
	"hongze/hongze_yb/global"
	"hongze/hongze_yb/logic"
	"hongze/hongze_yb/models/request"
	respond "hongze/hongze_yb/models/response"
	"hongze/hongze_yb/models/tables/banner"
	"hongze/hongze_yb/models/tables/banner_view_history"
	"hongze/hongze_yb/models/tables/company"
	"hongze/hongze_yb/models/tables/wx_user"
	"hongze/hongze_yb/models/tables/yb_config"
	"hongze/hongze_yb/models/tables/yb_research_banner"
	"hongze/hongze_yb/models/tables/yb_research_signup_statistics"
	"hongze/hongze_yb/models/tables/yb_resource"
	"hongze/hongze_yb/models/tables/yb_suncode_pars"
	"hongze/hongze_yb/services"
	"hongze/hongze_yb/services/alarm_msg"
	"hongze/hongze_yb/services/user"
	"hongze/hongze_yb/services/wx_app"
	"hongze/hongze_yb/utils"
	"net/url"
	"os"
	"path"
	"strconv"
	"time"
)

// GetApplyVarietyList
// @Tags 公共模块
// @Summary  获取所有可以申请的品种权限列表
// @Description 获取所有可以申请的品种权限列表
// @Security ApiKeyAuth
// @securityDefinitions.basic BasicAuth
// @Param Authorization	header string true "微信登录后获取到的token"
// @Accept  json
// @Product json
// @Success 200 {object} []logic.ApplyVariety "获取成功"
// @failure 400 {string} string "获取失败"
// @Router /public/get_apply_variety_list [get]
func GetApplyVarietyList(c *gin.Context) {
	list, err := logic.GetApplyVarietyList()
	if err != nil {
		response.FailData("获取品种失败", "获取品种失败，Err:"+err.Error(), c)
		return
	}
	response.OkData("获取成功", list, c)
}

// Upload
// @Tags 公共模块
// @Summary  文件上传
// @Description 文件上传
// @Security ApiKeyAuth
// @securityDefinitions.basic BasicAuth
// @Param Authorization	header string true "微信登录后获取到的token"
// @Param file formData file false "操作描述"
// @Accept  multipart/form-data
// @Product json
// @Success 200 {object} string "上传成功"
// @failure 400 {string} string "上传失败，存储目录创建失败"
// @Router /public/upload [post]
func Upload(c *gin.Context) {
	// 单文件
	file, err := c.FormFile("file")
	fmt.Println("file", file)
	if err != nil {
		response.FailData("获取资源失败", "获取资源失败，Err:"+err.Error(), c)
		return
	}

	ext := path.Ext(file.Filename)
	dateDir := time.Now().Format("20060102")
	uploadDir := global.CONFIG.Serve.StaticDir + "hongze/" + dateDir
	err = os.MkdirAll(uploadDir, 0766)
	if err != nil {
		response.FailData("存储目录创建失败", "存储目录创建失败，Err:"+err.Error(), c)
		return
	}
	randStr := utils.GetRandStringNoSpecialChar(28)
	fileName := randStr + ext
	fpath := uploadDir + "/" + fileName

	// 上传文件至指定目录
	err = c.SaveUploadedFile(file, fpath)
	if err != nil {
		response.FailData("文件上传失败", "文件上传失败，Err:"+err.Error(), c)
		return
	}
	defer func() {
		os.Remove(fpath)
	}()

	//上传到阿里云
	resourceUrl, err := services.UploadAliyun(fileName, fpath)
	if err != nil {
		response.FailData("文件上传失败", "文件上传失败，Err:"+err.Error(), c)
		return
	}
	response.OkData("文件上传成功", resourceUrl, c)

}

// GetSharePoster
// @Tags 公共模块
// @Summary  获取分享海报
// @Description 获取分享海报
// @Security ApiKeyAuth
// @securityDefinitions.basic BasicAuth
// @Param	request	body services.SharePosterReq true "type json string"
// @Accept  application/json
// @Success 200 {object} string "获取成功"
// @failure 400 {string} string "获取失败"
// @Router /public/get_share_poster [post]
func GetSharePoster(c *gin.Context) {
	// 是否为备用小程序
	copyYb := c.Request.Header.Get("CopyYb")
	var req services.SharePosterReq
	if c.ShouldBind(&req) != nil {
		response.Fail("参数异常", c)
		return
	}
	if req.Source == "" {
		response.Fail("来源有误", c)
		return
	}
	imgUrl, err := services.CreatePosterFromSourceV2(req.CodePage, req.CodeScene, req.Source, req.Version, req.Pars, copyYb)
	if err != nil {
		response.FailData("获取分享海报失败", "获取分享海报失败, Err: "+err.Error(), c)
		return
	}
	response.OkData("获取成功", imgUrl, c)
}

// GetSuncodeScene 获取小程序太阳码scene值
// @Tags 公共模块
// @Summary  获取小程序太阳码scene值
// @Description 获取小程序太阳码scene值
// @Security ApiKeyAuth
// @Param Authorization	header string true "Bearer 31a165baebe6dec616b1f8f3207b4273"
// @Param scene_key query string true "scene_key值"
// @Success 200 {string} string "获取成功"
// @failure 400 {string} string "获取失败"
// @Router /public/get_suncode_scene [get]
func GetSuncodeScene(c *gin.Context) {
	reqKey := c.DefaultQuery("scene_key", "")
	if reqKey == "" {
		response.Fail("参数有误", c)
	}
	pars, err := yb_suncode_pars.GetSceneByKey(reqKey)
	if err != nil && err != utils.ErrNoRow {
		response.FailMsg("获取失败", "GetSuncodeScene获取失败, Err: "+err.Error(), c)
		return
	}
	scene := ""
	if pars != nil {
		scene = pars.Scene
	}
	response.OkData("获取成功", scene, c)
}

// GetVarietyTagTree 标签树
// @Tags 公共模块
// @Summary  标签树
// @Description 标签树
// @Security ApiKeyAuth
// @Param Authorization	header string true "Bearer 31a165baebe6dec616b1f8f3207b4273"
// @Param scene_key query string true "scene_key值"
// @Success 200 {string} string "获取成功"
// @failure 400 {string} string "获取失败"
// @Router /public/get_variety_tag_tree [get]
func GetVarietyTagTree(c *gin.Context) {
	questionId, _ := strconv.Atoi(c.Query("community_question_id"))
	list, err := services.GetTagTree(questionId)
	if err != nil {
		response.FailMsg("获取标签树失败", "获取标签树失败, Err: "+err.Error(), c)
		return
	}
	response.OkData("获取成功", list, c)
}

// WechatWarning 小程序前端预警提示
// @Tags 公共模块
// @Description 小程序前端预警提示
// @Param content	query  string  true  "预警信息"
// @Success 200 {string} string "操作成功"
// @failure 400 {string} string "操作失败"
// @Router /public/wechat_warning [post]
func WechatWarning(c *gin.Context) {
	var req request.WechatWarningReq
	if err := c.Bind(&req); err != nil {
		response.Fail("参数有误", c)
		return
	}
	if req.Content != "" {
		tips := fmt.Sprintf("研报小程序前端报错预警-ErrMsg: %s", req.Content)
		global.LOG.Warning(tips)
		go alarm_msg.SendAlarmMsg(tips, 2)
	}
	response.Ok("操作成功", c)
}

// UploadAudio 上传音频文件
// @Tags 公共模块
// @Description 上传音频文件
// @Param file  query  string  true  "音频文件"
// @Success 200 {string} string "上传成功"
// @failure 400 {string} string "上传失败"
// @Router /public/upload_audio [post]
func UploadAudio(c *gin.Context) {
	file, err := c.FormFile("file")
	if err != nil {
		response.FailMsg("获取资源失败", "获取资源失败, Err:"+err.Error(), c)
		return
	}
	ext := path.Ext(file.Filename)
	if ext != ".mp3" {
		response.Fail("暂仅支持mp3格式", c)
		return
	}
	dateDir := time.Now().Format("20060102")
	localDir := global.CONFIG.Serve.StaticDir + "hongze/" + dateDir
	if err := os.MkdirAll(localDir, 0766); err != nil {
		response.FailMsg("存储目录创建失败", "UploadAudio 存储目录创建失败, Err:"+err.Error(), c)
		return
	}
	randStr := utils.GetRandStringNoSpecialChar(28)
	filtName := randStr + ext
	fpath := localDir + "/" + filtName
	defer func() {
		_ = os.Remove(fpath)
	}()
	// 生成文件至指定目录
	if err := c.SaveUploadedFile(file, fpath); err != nil {
		response.FailMsg("文件生成失败", "UploadAudio 文件生成失败, Err:"+err.Error(), c)
		return
	}
	//// 获取音频文件时长
	//fByte, err := ioutil.ReadFile(fpath)
	//if err != nil {
	//	response.FailMsg("读取本地文件失败", "UploadAudio 读取本地文件失败", c)
	//	return
	//}
	//if len(fByte) <= 0 {
	//	response.FailMsg("文件大小有误", "UploadAudio 文件大小有误", c)
	//	return
	//}
	seconds, err := utils.GetVideoPlaySeconds(fpath) //services.GetMP3PlayDuration(fByte)
	if err != nil {
		response.FailMsg("读取文件时长失败", "UploadAudio 读取文件时长失败", c)
		return
	}
	// 音频大小MB
	fi, err := os.Stat(fpath)
	if err != nil {
		response.FailMsg("读取文件大小失败", "UploadAudio 读取文件大小失败", c)
		return
	}
	mb := utils.Bit2MB(fi.Size(), 2)
	// 上传文件至阿里云
	ossDir := "yb_wx/audio/"
	resourceUrl, err := services.UploadAliyunToDir(filtName, fpath, ossDir)
	if err != nil {
		response.FailMsg("文件上传失败", "UploadAudio 文件上传失败, Err:"+err.Error(), c)
		return
	}
	resp := &respond.CommunityQuestionAudioUpload{
		AudioURL:         resourceUrl,
		AudioPlaySeconds: fmt.Sprint(seconds),
		AudioSize:        fmt.Sprint(mb),
	}
	// 记录文件
	go func() {
		extendData := struct {
			FileName         string
			AudioURL         string
			AudioPlaySeconds string
			AudioSize        string
		}{
			file.Filename,
			resourceUrl,
			fmt.Sprint(seconds),
			fmt.Sprint(mb),
		}
		dataByte, e := json.Marshal(extendData)
		if e != nil {
			return
		}
		re := new(yb_resource.YbResource)
		re.ResourceUrl = resourceUrl
		re.ResourceType = yb_resource.ResourceTypeAudio
		re.ExtendData = string(dataByte)
		re.CreateTime = time.Now().Local()
		if e = re.Create(); e != nil {
			return
		}
	}()
	response.OkData("上传成功", resp, c)
}

// UpdateViewLog
// @Description 更新各模块访问/点击日志(有时间的话统一改版做一个入口,统一访问日志)
// @Success 200 {string} string "更新成功"
// @Router /public/view_log/update [post]
func UpdateViewLog(c *gin.Context) {
	var req request.ViewLogUpdateReq
	if err := c.Bind(&req); err != nil {
		response.Fail("参数有误:"+err.Error(), c)
		return
	}
	if req.Id <= 0 {
		response.Fail("参数有误", c)
		return
	}
	if req.Source <= 0 {
		response.Fail("来源有误", c)
		return
	}

	userInfo := user.GetInfoByClaims(c)
	err := services.UpdateViewLogBySource(int(userInfo.UserID), req.Id, req.StopSeconds, req.Source)
	if err != nil {
		fmt.Println(err.Error())
		response.FailMsg("更新日志失败", err.Error(), c)
		return
	}
	response.Ok("更新成功", c)
}

// GetTelAreaList 获取手机号区号列表
func GetTelAreaList(c *gin.Context) {
	type TelAreaList struct {
		Name  string `json:"name"`
		Value string `json:"value"`
	}
	// 读取配置
	var cond string
	var pars []interface{}
	cond += `config_code = ?`
	pars = append(pars, yb_config.TelAreaList)
	confDao := new(yb_config.YbConfig)
	conf, e := confDao.Fetch(cond, pars)
	if e != nil {
		response.FailMsg("获取失败", "获取手机号区号配置失败, Err: "+e.Error(), c)
		return
	}
	if conf.ConfigID <= 0 || conf.ConfigValue == "" {
		response.FailMsg("获取失败", "获取手机号区号配置失败", c)
		return
	}
	respList := make([]*TelAreaList, 0)
	if e = json.Unmarshal([]byte(conf.ConfigValue), &respList); e != nil {
		response.FailMsg("获取失败", "手机号区号配置解析失败, Err: "+e.Error(), c)
		return
	}
	response.OkData("获取成功", respList, c)
}

// BannerMark banner图埋点
// @Tags 公共模块
// @Summary  banner图埋点
// @Description banner图埋点
// @Security ApiKeyAuth
// @securityDefinitions.basic BasicAuth
// @Param email	query string true "电子邮箱账号"
// @Accept  json
// @Product json
// @Success 200 {string} string 获取验证码成功
// @Failure 400 {string} string 请输入邮箱地址
// @Router /banner/mark [post]
func BannerMark(c *gin.Context) {
	userInfo := user.GetInfoByClaims(c)
	var req request.BannerMarkReq
	if err := c.Bind(&req); err != nil {
		response.Fail("参数有误:"+err.Error(), c)
		return
	}

	//if req.BannerUrl == "" {
	//	response.FailMsg("参数有误", "BannerUrl不能为空", c)
	//	return
	//}

	if req.FirstSource <= 0 {
		response.FailMsg("参数有误", "FirstSource不能为空", c)
		return
	}

	if req.SecondSource <= 0 {
		response.FailMsg("参数有误", "SecondSource", c)
	}

	if req.Id <= 0 {
		response.FailMsg("参数有误", "Id错误", c)
	}

	item, err := banner.GetBannerById(req.Id)
	if err != nil {
		fmt.Println("GetByUserId:", err.Error())
		return
	}

	// 联系人信息
	strInt64 := strconv.FormatUint(userInfo.UserID, 10)
	id, _ := strconv.Atoi(strInt64)
	wxUserInfo, err := wx_user.GetByUserId(id)
	if err != nil {
		fmt.Println("GetByUserId:", err.Error())
		return
	}
	companyInfo, tmpErr := company.GetByCompanyId(wxUserInfo.CompanyID)
	if tmpErr != nil {
		err = tmpErr
		if tmpErr == utils.ErrNoRow {
			err = errors.New("找不到该客户")
			return
		}
		return
	}

	//新增userViewHistory记录
	banner_view_history := &banner_view_history.BannerViewHistory{
		UserID:          userInfo.UserID,
		Mobile:          wxUserInfo.Mobile,
		Email:           wxUserInfo.Email,
		RealName:        wxUserInfo.RealName,
		CompanyName:     companyInfo.CompanyName,
		CreatedTime:     time.Now(),
		LastUpdatedTime: time.Now(),
		FirstSource:     req.FirstSource,
		SecondSource:    req.SecondSource,
		BannerUrl:       item.ImageUrlMobile,
		StartDate:       item.StartDate,
		EndDate:         item.EndDate,
		Remark:          item.Remark,
	}
	err = banner_view_history.AddBannerViewHistory()
	if err != nil {
		fmt.Println("AddUserViewHistory err", err.Error())
	}

	response.Ok("成功", c)
}

// BannerList banner图列表
// @Tags 公共模块
// @Summary  banner图列表
// @Description banner图列表
// @Security ApiKeyAuth
// @securityDefinitions.basic BasicAuth
// @Accept  json
// @Product json
// @Success 200 {string} string 获取验证码成功
// @Failure 400 {string} string 请输入邮箱地址
// @Router /banner/list [get]
func BannerList(c *gin.Context) {
	isHomepage, _ := strconv.Atoi(c.Query("is_homepage"))
	page, _ := strconv.Atoi(c.Query("page"))
	limit, _ := strconv.Atoi(c.Query("limit"))
	cond := " enable = 1 "

	if isHomepage != 1 {
		cond += " AND remark <> '调研合集' "
	}

	list, err := banner.GetBannerList(cond, page, limit)
	if err != nil {
		response.FailMsg("获取失败", "获取banner失败, Err: "+err.Error(), c)
		return
	}

	response.OkData("获取成功", list, c)
}

// BannerHistoryList banner历史图列表
// @Tags 公共模块
// @Summary  banner图列表
// @Description banner图列表
// @Security ApiKeyAuth
// @securityDefinitions.basic BasicAuth
// @Accept  json
// @Product json
// @Success 200 {string} string 获取验证码成功
// @Failure 400 {string} string 请输入邮箱地址
// @Router /banner_history/list [get]
func BannerHistoryList(c *gin.Context) {
	page, _ := strconv.Atoi(c.Query("page"))
	limit, _ := strconv.Atoi(c.Query("limit"))
	cond := ""
	cond += " enable = 0 "

	total, err := banner.GetBannerListCount(cond)
	if err != nil {
		response.FailMsg("获取失败", "获取banner总数失败, Err: "+err.Error(), c)
		return
	}
	list, err := banner.GetBannerList(cond, page, limit)
	if err != nil {
		response.FailMsg("获取失败", "获取banner失败, Err: "+err.Error(), c)
		return
	}
	var resp respond.BannerRespItem
	resp.Paging = respond.GetPaging(page, limit, int(total))
	resp.List = list
	response.OkData("获取成功", resp, c)
}

// BannerList banner图详情
// @Tags 公共模块
// @Summary  banner图详情
// @Description banner图详情
// @Security ApiKeyAuth
// @securityDefinitions.basic BasicAuth
// @Accept  json
// @Product json
// @Success 200 {string} string 获取验证码成功
// @Failure 400 {string} string 请输入邮箱地址
// @Router /banner/detail [get]
func BannerDetail(c *gin.Context) {
	bannerId, _ := strconv.Atoi(c.Query("banner_id"))

	item, err := banner.GetBannerById(bannerId)
	if err != nil {
		response.FailMsg("获取失败", "获取banner失败, Err: "+err.Error(), c)
		return
	}

	response.OkData("获取成功", item, c)
}

// BannerGetQRCode banner历史图列表
// @Tags 公共模块
// @Summary  banner图列表
// @Description banner图列表
// @Security ApiKeyAuth
// @securityDefinitions.basic BasicAuth
// @Accept  json
// @Product json
// @Success 200 {string} string 获取验证码成功
// @Failure 400 {string} string 请输入邮箱地址
// @Router /banner/get_qrcode [get]
func BannerGetQRCode(c *gin.Context) {
	userId, _ := strconv.Atoi(c.Query("UserId"))
	bannerId, _ := strconv.Atoi(c.Query("BannerId"))
	remark := c.Query("Remark")
	wxUserInfo, err := wx_user.GetByUserId(userId)
	if err != nil {
		response.Ok(err.Error(), c)
		return
	}
	companyInfo, tmpErr := company.GetByCompanyId(wxUserInfo.CompanyID)
	if tmpErr != nil {
		err = tmpErr
		if tmpErr == utils.ErrNoRow {
			response.Fail(err.Error(), c)
			err = errors.New("找不到该客户")
			return
		}
		response.Fail(err.Error(), c)
		return
	}
	companyName := companyInfo.CompanyName

	companyNameCode := url.QueryEscape(companyName) // 进行URL编码
	remarkCode := url.QueryEscape(remark)           // 进行URL编码
	url := "pages-report/signUpPage/signUpPage?RealName=%s&CompanyName=%s&Mobile=%s&BannerId=%d&Title=%s"
	url = fmt.Sprintf(url, wxUserInfo.RealName, companyNameCode, wxUserInfo.Mobile, bannerId, remarkCode)

	picByte, err := wx_app.GetSunCodeV2(url)
	if err != nil {
		return
	}
	// 生成图片
	localPath := "./static/img"
	fileName := utils.GetRandStringNoSpecialChar(28) + ".png"
	fpath := fmt.Sprint(localPath, "/", fileName)
	f, err := os.Create(fpath)
	if err != nil {
		return
	}
	if _, err = f.Write(picByte); err != nil {
		return
	}
	defer func() {
		f.Close()
		os.Remove(fpath)
	}()

	//上传到阿里云
	resourceUrl, err := services.UploadAliyun(fileName, fpath)
	if err != nil {
		response.FailData("文件上传失败", "文件上传失败，Err:"+err.Error(), c)
		return
	}

	response.OkData("获取成功", resourceUrl, c)
}

// ResearchSignUp 报名
// @Tags 公共模块
// @Summary  banner图列表
// @Description banner图列表
// @Security ApiKeyAuth
// @securityDefinitions.basic BasicAuth
// @Accept  json
// @Product json
// @Success 200 {string} string 获取验证码成功
// @Failure 400 {string} string 请输入邮箱地址
// @Router /banner/signup [get]
func ResearchSignUp(c *gin.Context) {
	//inviteCode := c.Query("InviteCode")
	realName := c.Query("RealName")
	companyName := c.Query("CompanyName")
	mobile := c.Query("Mobile")
	bannerId, _ := strconv.Atoi(c.Query("BannerId"))
	customName := c.Query("CustomName")
	customMobile := c.Query("CustomMobile")
	customCompanyName := c.Query("CustomCompanyName")
	//userInfo := user.GetInfoByClaims(c)
	//userDetail, err, errMsg := userLogic.GetUserInfo(userInfo)
	//if err != nil {
	//	if errMsg != "" {
	//		errMsg = "获取失败"
	//	}
	//	response.Fail(errMsg, c)
	//	return
	//}
	count, err := yb_research_signup_statistics.GetSignUpCountByMobileAndBannerId(customMobile, bannerId)
	if err != nil {
		response.FailData("查询失败", "查询失败，Err:"+err.Error(), c)
		return
	}
	if count > 0 {
		response.FailData("该手机号已报名!", "该手机号已报名", c)
		return
	}
	ob := &yb_research_signup_statistics.YbResearchSignupStatistics{
		Mobile:            mobile,
		CustomCompanyName: customCompanyName,
		CompanyName:       companyName,
		BannerId:          bannerId,
		CustomName:        customName,
		RealName:          realName,
		CustomMobile:      customMobile,
		CreateTime:        time.Now(),
	}
	err = ob.Create()
	if err != nil {
		response.FailData("报名失败", "报名失败，Err:"+err.Error(), c)
		return
	}

	response.Ok("报名成功", c)
}

// BannerGetQRCode banner调研图下载
// @Tags 公共模块
// @Summary  banner调研图下载
// @Description banner调研图下载
// @Security ApiKeyAuth
// @securityDefinitions.basic BasicAuth
// @Accept  json
// @Product json
// @Success 200 {string} string 获取验证码成功
// @Failure 400 {string} string 请输入邮箱地址
// @Router /banner/download [get]
func BannerDowload(c *gin.Context) {
	var req request.BannerDownloadReq
	if err := c.Bind(&req); err != nil {
		response.Fail("参数有误:"+err.Error(), c)
		return
	}
	obj := yb_research_banner.YbResearchBanner{}
	item, err := obj.Fetch(req.UserId, req.BannerId)
	if err != nil && err != utils.ErrNoRow {
		response.Fail(err.Error(), c)
		return
	}
	resourceUrl := ""

	if item.ImgURL == "" {
		randStr := utils.GetRandStringNoSpecialChar(28)
		jpegPath := `./static/` + randStr + ".jpeg"
		err := services.ReportToJpeg(req.BannerUrl, jpegPath)
		if err != nil {
			response.FailData("图片转jpeg失败", "图片转jpeg失败，Err:"+err.Error(), c)
			return
		}
		dateDir := time.Now().Format("20060102")
		uploadDir := global.CONFIG.Serve.StaticDir + "hongze/" + dateDir
		err = os.MkdirAll(uploadDir, 0766)
		if err != nil {
			response.FailData("存储目录创建失败", "存储目录创建失败，Err:"+err.Error(), c)
			return
		}

		defer func() {
			os.Remove(jpegPath)
		}()

		//上传到阿里云
		resourceUrl, err = services.UploadAliyun(randStr+".jpeg", jpegPath)
		if err != nil {
			response.FailData("文件上传失败", "文件上传失败，Err:"+err.Error(), c)
			return
		}
		obj.BannerID = req.BannerId
		obj.UserID = req.UserId
		obj.ImgURL = resourceUrl
		err = obj.Create()
		if err != nil {
			response.FailData("创建banner长图记录失败", "创建banner长图记录失败，Err:"+err.Error(), c)
			return
		}
	} else {
		resourceUrl = item.ImgURL
	}
	response.OkData("获取成功", resourceUrl, c)
}
