package controllers

import (
	"FollowUp_Notice/Nats/NatsServer"
	"FollowUp_Notice/conf"
	"FollowUp_Notice/http"
	"FollowUp_Notice/http/submail"
	"FollowUp_Notice/lib"
	"FollowUp_Notice/logs"
	"FollowUp_Notice/models/Account"
	"FollowUp_Notice/models/Patient"
	"FollowUp_Notice/models/System"
	"encoding/json"
	"fmt"
	beego "github.com/beego/beego/v2/server/web"
	"github.com/robfig/cron/v3"
	"github.com/shopspring/decimal"
	"github.com/xuri/excelize/v2"
	"math"
	"os"
	"strings"
	"time"
)

type UserController struct {
	beego.Controller
	User Account.User
}

func (c *UserController) Prepare() {
	if Account.User_r != nil {
		c.User = *Account.User_r
	}
}

// 验证登录
func (c *UserController) Login_verification() {
	Admin_user := c.GetString("username")
	Admin_pass := c.GetString("password")

	type JSONS struct {
		//必须的大写开头
		Code   int16
		Msg    string
		Data   interface{} // 泛型
		UserId int
	}

	err, user_r := Account.Read_User_verification(Admin_user, Admin_pass)

	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "用户名或密码错误!"}
	} else {
		User_tokey := Account.Add_Tokey(user_r.T_uuid)
		c.Ctx.SetCookie("User_tokey", User_tokey, time.Second*60*60)
		c.Data["json"] = JSONS{Code: 200, Msg: "OK!", Data: User_tokey, UserId: user_r.Id}

		System.Add_UserLogs_T(user_r.T_uuid, "用户", "用户登陆", lib.GetUserLoginInfo(c.Ctx))
	}

	c.ServeJSON()
	return

}

// --------------------------------------------------------------------------------------------------------------

// 用户列表
func (c *UserController) List() {
	// 分页参数 初始化
	page, _ := c.GetInt("page")
	if page < 1 {
		page = 1
	}
	page_z, _ := c.GetInt("page_z")
	if page_z < 1 {
		page_z = conf.Page_size
	}

	// 查询
	T_name := c.GetString("T_name")

	R_List, R_cnt := Account.Read_User_List(T_name, page, page_z)

	var r_jsons lib.R_JSONS
	r_jsons.Num = R_cnt
	r_jsons.Data = R_List
	r_jsons.Page = page
	r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z)))

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
	c.ServeJSON()
	return
}

func (c *UserController) Get() {

	T_uuid := c.GetString("T_uuid")
	user, err := Account.Read_User_ByT_uuid(T_uuid)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
		c.ServeJSON()
		return
	}

	var r_jsons lib.R_JSONS
	r_jsons.Data = Account.UserToUser_R(user)

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
	c.ServeJSON()
	return
}

// 个人信息
func (c *UserController) Info() {
	type Info struct {
		User   Account.User_R
		Notice struct {
			Sms       int64
			VoiceCall int64
		}
	}
	month := time.Now().Format("2006-01")
	var info Info
	info.User = Account.UserToUser_R(c.User)
	info.Notice.Sms = Patient.Read_PatientSend_Count_Month(c.User.Id, 0, 1, month)
	info.Notice.VoiceCall = Patient.Read_PatientSend_Count_Month(c.User.Id, 0, 2, month)

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: info}
	c.ServeJSON()
	return
}

// 添加用户信息
func (c *UserController) Add() {

	T_user := c.GetString("T_user")
	T_pass := c.GetString("T_pass")
	T_phone := c.GetString("T_phone")
	T_arrears_notice, _ := c.GetInt("T_arrears_notice")
	T_State, _ := c.GetInt("T_State")

	if len(T_user) < 3 {
		c.Data["json"] = lib.JSONS{Code: 207, Msg: "用户名长度不足!"}
		c.ServeJSON()
		return
	}
	if len(T_pass) < 6 {
		c.Data["json"] = lib.JSONS{Code: 208, Msg: "密码异常!"}
		c.ServeJSON()
		return
	}

	temp, err := submail.SmsTemplate_Post(T_user)
	if err != nil || temp.Status != "success" {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "创建短信模板失败"}
		c.ServeJSON()
		return
	}

	var_ := Account.User{
		T_user:           T_user,
		T_pass:           T_pass,
		T_phone:          T_phone,
		T_template_id:    temp.Template_id,
		T_arrears_notice: T_arrears_notice,
		T_State:          T_State,
	}

	_, err = Account.Add_User(var_)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 209, Msg: "添加失败!"}
		c.ServeJSON()
		return
	}
	var_.T_pass = "******"

	System.Add_UserLogs_T(c.User.T_uuid, "用户", "新增", var_)

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return

}

// 修改个人信息
func (c *UserController) Post() {

	T_pass := c.GetString("T_pass")

	user := c.User

	if len(T_pass) > 0 {
		if len(T_pass) < 8 {
			c.Data["json"] = lib.JSONS{Code: 206, Msg: "密码格式不正确!"}
			c.ServeJSON()
			return
		}
		user.T_pass = T_pass
	}

	if err := Account.Update_User(user, "T_pass"); err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败!"}
		c.ServeJSON()
		return
	}

	System.Add_UserLogs_T(c.User.T_uuid, "用户", "修改登录密码", "")

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return

}

// 修改用户信息
func (c *UserController) Edit() {

	T_uuid := c.GetString("T_uuid")
	T_pass := c.GetString("T_pass")
	T_phone := c.GetString("T_phone")
	T_arrears_notice, _ := c.GetInt("T_arrears_notice")
	T_State, _ := c.GetInt("T_State")

	var err error
	var user Account.User
	var cols []string

	if len(T_uuid) > 0 {
		user, err = Account.Read_User_ByT_uuid(T_uuid)
		if err != nil {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
			c.ServeJSON()
			return
		}
	}

	if len(T_pass) > 0 {
		if len(T_pass) < 6 {
			c.Data["json"] = lib.JSONS{Code: 206, Msg: "密码格式不正确!"}
			c.ServeJSON()
			return
		}
		user.T_pass = T_pass
		cols = append(cols, "T_pass")
	}
	if len(T_phone) > 0 {
		user.T_phone = T_phone
		cols = append(cols, "T_phone")
	}
	if T_arrears_notice > 0 {
		user.T_arrears_notice = T_arrears_notice
		cols = append(cols, "T_arrears_notice")
	}
	if T_State > 0 {
		user.T_State = T_State
		cols = append(cols, "T_State")
	}

	if err = Account.Update_User(user, cols...); err != nil {
		c.Data["json"] = lib.JSONS{Code: 208, Msg: "修改失败!"}
		c.ServeJSON()
		return
	}

	user.T_pass = "******"
	System.Add_UserLogs_T(c.User.T_uuid, "用户", "修改个人信息", user)

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return

}

// 删除用户信息
func (c *UserController) Del() {
	T_uuid := c.GetString("T_uuid")
	if len(T_uuid) == 0 {
		c.Data["json"] = lib.JSONS{Code: 201, Msg: "T_uuid Err!"}
		c.ServeJSON()
		return
	}

	user, err := Account.Read_User_ByT_uuid(T_uuid)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
		c.ServeJSON()
		return
	}
	if user.Id == 1 {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "禁止删除超级管理员!"}
		c.ServeJSON()
		return
	}

	temp, err := submail.SmsTemplate_Delete(user.T_template_id)
	if err != nil || temp.Status != "success" {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除短信模板失败"}
		c.ServeJSON()
		return
	}

	if err = Account.Delete_User(user); err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除失败!"}
		c.ServeJSON()
		return
	}

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return

}

// 充值
func (c *UserController) Pay() {
	T_uuid := c.GetString("T_uuid")
	T_balance, _ := c.GetFloat("T_balance")

	if len(T_uuid) == 0 {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
		c.ServeJSON()
		return
	}

	user, err := Account.Read_User_ByT_uuid(T_uuid)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
		c.ServeJSON()
		return
	}

	T_money64, _ := decimal.NewFromFloat(float64(user.T_money) + T_balance).Round(2).Float64()
	user.T_money = float32(T_money64)

	err = Account.Update_User(user, "T_money")
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "充值失败!"}
		c.ServeJSON()
		return
	}

	// 添加充值记录
	bill := Account.UserBill{
		T_uid:      user.Id,
		T_type:     Account.Pay,
		T_bill:     "充值",
		T_charging: float32(T_balance),
		T_balance:  float32(T_money64),
	}
	_, err = Account.Add_UserBill(bill)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "充值失败!"}
		c.ServeJSON()
		return
	}
	user.T_pass = "******"
	System.Add_UserLogs_T(c.User.T_uuid, "用户管理", "充值", user)
	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return
}

// 账单下载
func (c *UserController) Bill() {

	// 分页参数 初始化
	page, _ := c.GetInt("page")
	if page < 1 {
		page = 1
	}
	page_z, _ := c.GetInt("page_z")
	if page_z < 1 {
		page_z = conf.Page_size
	}
	T_uuid := c.GetString("T_uuid")
	//T_type 1 充值 2扣费
	T_type, _ := c.GetInt("T_type")
	user, err := Account.Read_User_ByT_uuid(T_uuid)
	if err != nil {
		user = c.User
	}
	Bill_List, cnt := Account.Read_UserBill_List(user.Id, "", T_type, page, page_z)
	var r_jsons lib.R_JSONS
	r_jsons.Num = cnt
	r_jsons.Data = Bill_List
	r_jsons.Page = page
	r_jsons.Page_size = int(math.Ceil(float64(cnt) / float64(page_z)))

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
	c.ServeJSON()
	return

}

// 账单下载
func (c *UserController) Bill_Excel() {

	T_month := c.GetString("T_month")
	T_uuid := c.GetString("T_uuid")
	user, err := Account.Read_User_ByT_uuid(T_uuid)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_uuid Err!"}
		c.ServeJSON()
		return
	}
	filename := fmt.Sprintf("%s账单", user.T_user)

	if len(T_month) > 0 {
		_, err := time.Parse("2006-01", T_month)
		if err != nil {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"}
			c.ServeJSON()
			return
		}
		year, month := strings.Split(T_month, "-")[0], strings.Split(T_month, "-")[1]
		filename = fmt.Sprintf("%s%s年%s月账单", c.User.T_user, year, month)
	}

	f := excelize.NewFile()

	Style1, _ := f.NewStyle(
		&excelize.Style{
			Font:      &excelize.Font{Bold: true, Size: 16, Family: "宋体"},
			Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
		})

	Style2, _ := f.NewStyle(
		&excelize.Style{
			Font:      &excelize.Font{Bold: true, Size: 14, Family: "宋体"},
			Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
			Border: []excelize.Border{
				{Type: "left", Color: "000000", Style: 1},
				{Type: "top", Color: "000000", Style: 1},
				{Type: "bottom", Color: "000000", Style: 1},
				{Type: "right", Color: "000000", Style: 1},
			},
		})
	f.MergeCell("Sheet1", "A1", "G1")
	f.SetRowStyle("Sheet1", 1, 1, Style1)
	f.SetCellValue("Sheet1", "A1", filename)
	f.SetRowHeight("Sheet1", 1, 30)

	f.SetCellStyle("Sheet1", "A2", "F2", Style2)
	f.SetRowHeight("Sheet1", 2, 25)
	// 这里设置表头
	f.SetCellValue("Sheet1", "A2", "编号")
	f.SetCellValue("Sheet1", "B2", "消费项目")
	f.SetCellValue("Sheet1", "C2", "扣费/充值")
	f.SetCellValue("Sheet1", "D2", "金额(元)")
	f.SetCellValue("Sheet1", "E2", "余额(元)")
	f.SetCellValue("Sheet1", "F2", "时间")
	// 设置列宽
	f.SetColWidth("Sheet1", "A", "A", 10)
	f.SetColWidth("Sheet1", "B", "B", 15)
	f.SetColWidth("Sheet1", "C", "C", 12)
	f.SetColWidth("Sheet1", "D", "D", 15)
	f.SetColWidth("Sheet1", "E", "E", 15)
	f.SetColWidth("Sheet1", "F", "F", 20)

	line := 2
	//T_type 1 充值 2扣费
	Bill_List, _ := Account.Read_UserBill_List(user.Id, T_month, 0, 0, 9999)

	// 循环写入数据
	for i, v := range Bill_List {
		line++

		f.SetCellValue("Sheet1", fmt.Sprintf("A%d", line), i+1)
		f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), v.T_bill)
		f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), v.T_type)
		f.SetCellValue("Sheet1", fmt.Sprintf("D%d", line), v.T_charging)
		f.SetCellValue("Sheet1", fmt.Sprintf("E%d", line), v.T_balance)
		f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), v.CreateTime)

	}
	Style4, _ := f.NewStyle(
		&excelize.Style{
			Font:      &excelize.Font{Size: 12, Family: "宋体"},
			Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
			Border: []excelize.Border{
				{Type: "left", Color: "000000", Style: 1},
				{Type: "top", Color: "000000", Style: 1},
				{Type: "bottom", Color: "000000", Style: 1},
				{Type: "right", Color: "000000", Style: 1},
			},
		})

	f.SetCellStyle("Sheet1", "A2", fmt.Sprintf("F%d", line), Style4)

	timeStr := filename + fmt.Sprintf("(%s)", lib.GetRandstring(8, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 0))
	// 保存文件
	if err = f.SaveAs("ofile/" + timeStr + ".xlsx"); err != nil {
		fmt.Println(err)
	}

	var url string
	//// 上传 OSS
	url, is := NatsServer.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+timeStr+".xlsx", "ofile/"+timeStr+".xlsx")
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"}
		c.ServeJSON()
		return
	}
	//删除目录
	err = os.Remove("ofile/" + timeStr + ".xlsx")
	if err != nil {
		fmt.Println(err)
	}

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url}
	c.ServeJSON()
	return

}

// 通知记录
func (c *UserController) Send() {

	// 分页参数 初始化
	page, _ := c.GetInt("page")
	T_month := c.GetString("T_month")
	if page < 1 {
		page = 1
	}
	page_z, _ := c.GetInt("page_z")
	if page_z < 1 {
		page_z = conf.Page_size
	}
	T_uuid := c.GetString("T_uuid")
	user, err := Account.Read_User_ByT_uuid(T_uuid)
	if err != nil {
		user = c.User
	}
	T_patient_uuid := c.GetString("T_patient_uuid")
	T_patient_Id := 0
	if len(T_patient_uuid) > 0 {
		patient, err := Patient.Read_Patient_ByT_uuid(T_patient_uuid)
		if err != nil {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_patient_uuid Err!"}
			c.ServeJSON()
			return
		}
		T_patient_Id = patient.Id
	}

	// 1 短信 2 电话
	T_type, _ := c.GetInt("T_type")

	send_List, cnt := Patient.Read_PatientSend_List(user.Id, T_patient_Id, T_type, T_month, page, page_z)
	var r_jsons lib.R_JSONS
	r_jsons.Num = cnt
	r_jsons.Data = send_List
	r_jsons.Page = page
	r_jsons.Page_size = int(math.Ceil(float64(cnt) / float64(page_z)))

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
	c.ServeJSON()
	return

}

// 通知记录下载
func (c *UserController) Send_Excel() {

	T_month := c.GetString("T_month")
	T_uuid := c.GetString("T_uuid")
	T_type, _ := c.GetInt("T_type")
	user, err := Account.Read_User_ByT_uuid(T_uuid)
	if err != nil {
		user = c.User
	}

	T_patient_uuid := c.GetString("T_patient_uuid")
	T_patient_Id := 0
	if len(T_patient_uuid) > 0 {
		patient, err := Patient.Read_Patient_ByT_uuid(T_patient_uuid)
		if err != nil {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_patient_uuid Err!"}
			c.ServeJSON()
			return
		}
		T_patient_Id = patient.Id
	}
	var T_type_str string
	if T_type == 1 {
		T_type_str = "短信"
	}
	if T_type == 2 {
		T_type_str = "电话"
	}

	filename := fmt.Sprintf("%s%s通知记录", user.T_user, T_type_str)

	if len(T_month) > 0 {
		_, err := time.Parse("2006-01", T_month)
		if err != nil {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"}
			c.ServeJSON()
			return
		}
		year, month := strings.Split(T_month, "-")[0], strings.Split(T_month, "-")[1]
		filename = fmt.Sprintf("%s%s%s年%s月通知记录", user.T_user, T_type_str, year, month)
	}

	f := excelize.NewFile()

	Style1, _ := f.NewStyle(
		&excelize.Style{
			Font:      &excelize.Font{Bold: true, Size: 16, Family: "宋体"},
			Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
		})

	Style2, _ := f.NewStyle(
		&excelize.Style{
			Font:      &excelize.Font{Bold: true, Size: 14, Family: "宋体"},
			Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
			Border: []excelize.Border{
				{Type: "left", Color: "000000", Style: 1},
				{Type: "top", Color: "000000", Style: 1},
				{Type: "bottom", Color: "000000", Style: 1},
				{Type: "right", Color: "000000", Style: 1},
			},
		})
	f.MergeCell("Sheet1", "A1", "D1")
	f.SetRowStyle("Sheet1", 1, 1, Style1)
	f.SetCellValue("Sheet1", "A1", filename)
	f.SetRowHeight("Sheet1", 1, 30)

	f.SetCellStyle("Sheet1", "A2", "D2", Style2)
	f.SetRowHeight("Sheet1", 2, 25)
	// 这里设置表头
	f.SetCellValue("Sheet1", "A2", "编号")
	f.SetCellValue("Sheet1", "B2", "通知电话")
	f.SetCellValue("Sheet1", "C2", "通知类型")
	f.SetCellValue("Sheet1", "D2", "时间")
	// 设置列宽
	f.SetColWidth("Sheet1", "A", "A", 10)
	f.SetColWidth("Sheet1", "B", "B", 15)
	f.SetColWidth("Sheet1", "C", "C", 12)
	f.SetColWidth("Sheet1", "D", "D", 30)

	line := 2
	//T_type 1 充值 2扣费
	send_List, _ := Patient.Read_PatientSend_List(user.Id, T_patient_Id, T_type, T_month, 0, 9999)

	// 循环写入数据
	for i, v := range send_List {
		line++

		f.SetCellValue("Sheet1", fmt.Sprintf("A%d", line), i+1)
		f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), v.T_phone)
		if v.T_type == 1 {
			T_type_str = "短信"
		}
		if v.T_type == 2 {
			T_type_str = "电话"
		}
		f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), T_type_str)
		f.SetCellValue("Sheet1", fmt.Sprintf("D%d", line), v.CreateTime)

	}
	Style4, _ := f.NewStyle(
		&excelize.Style{
			Font:      &excelize.Font{Size: 12, Family: "宋体"},
			Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true},
			Border: []excelize.Border{
				{Type: "left", Color: "000000", Style: 1},
				{Type: "top", Color: "000000", Style: 1},
				{Type: "bottom", Color: "000000", Style: 1},
				{Type: "right", Color: "000000", Style: 1},
			},
		})

	f.SetCellStyle("Sheet1", "A2", fmt.Sprintf("D%d", line), Style4)

	timeStr := filename + fmt.Sprintf("(%s)", lib.GetRandstring(8, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 0))
	// 保存文件
	if err = f.SaveAs("ofile/" + timeStr + ".xlsx"); err != nil {
		fmt.Println(err)
	}

	var url string
	//// 上传 OSS
	url, is := NatsServer.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+timeStr+".xlsx", "ofile/"+timeStr+".xlsx")
	if !is {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"}
		c.ServeJSON()
		return
	}
	//删除目录
	err = os.Remove("ofile/" + timeStr + ".xlsx")
	if err != nil {
		fmt.Println(err)
	}

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url}
	c.ServeJSON()
	return

}

// 通知记录
func (c *UserController) Send_Test() {
	// 1 短信 2 电话
	T_type, _ := c.GetInt("T_type")
	T_phone := c.GetString("T_phone")
	if c.User.Id != 1 {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "没有权限!"}
		c.ServeJSON()
		return
	}
	//发送短信通知
	if T_type == 1 {
		res, err := submail.SmsXSend("mDZSZ3", T_phone, "张三", time.Now().AddDate(0, 0, 1).Format("2006年01月02日"))
		if err != nil {
			c.Data["json"] = lib.JSONS{Code: 200, Msg: "短信发送失败!"}
			c.ServeJSON()
			return
		}

		// 保存短信发送记录
		smsSend := Patient.PatientSend{
			T_uid:    c.User.Id,
			T_pid:    0,
			T_phone:  T_phone,
			T_type:   1,
			T_id:     res.Send_id,
			T_remark: res.Status,
			T_fee:    res.Fee,
			T_code:   res.Code,
			T_State:  1,
		}
		if res.Status == "error" {
			smsSend.T_State = 0
		}
		_, err = Patient.Add_PatientSend(smsSend)
		if err != nil {
			System.Add_SysLogs_T("复诊通知", "添加短信发送记录失败", smsSend)
		}

		if res.Status == "error" {
			c.Data["json"] = lib.JSONS{Code: 200, Msg: "短信发送失败!"}
			c.ServeJSON()
			return
		}

	}

	if T_type == 2 {
		// 华为语音通知
		//playInfoList := http.GetPlayInfoList(conf.VoiceCall_Template, []string{"某某医院消化内科", "张三", time.Now().AddDate(0, 0, 1).Format("2006/01/02")})
		//res, err := http.VoiceNotifyAPI(conf.VoiceCall_Phone, "+86"+T_phone, playInfoList)
		//if err != nil {
		//	c.Data["json"] = lib.JSONS{Code: 202, Msg: "电话通知失败!"}
		//	c.ServeJSON()
		//	return
		//}
		// 保存短信发送记录
		//send := Patient.PatientSend{
		//	T_uid:   c.User.Id,
		//	T_pid:   0,
		//	T_phone: T_phone,
		//	T_type:  2,
		//	T_id:    res.SessionId,
		//	T_code:  -1,
		//	T_State: 0,
		//}
		//
		//_, err = Patient.Add_PatientSend(send)
		//if err != nil {
		//	System.Add_SysLogs_T("复诊通知", "添加发送记录失败", send)
		//}
		//
		//if res.Resultcode != "0" {
		//	c.Data["json"] = lib.JSONS{Code: 202, Msg: "电话通知失败!"}
		//	c.ServeJSON()
		//	return
		//}

		res, err := submail.VoiceXSend(T_phone, "某某医院某某科室", "张三", time.Now().AddDate(0, 0, 1).Format("2006年01月02日"))
		if err != nil {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "电话通知失败!"}
			c.ServeJSON()
			return
		}

		// 保存短信发送记录
		send := Patient.PatientSend{
			T_uid:   c.User.Id,
			T_pid:   0,
			T_phone: T_phone,
			T_type:  2,
			T_id:    res.Send_id,
			T_fee:   res.Fee,
			T_code:  res.Code,
			T_State: 1,
		}

		if res.Status == "error" {
			send.T_State = 0
		}
		_, err = Patient.Add_PatientSend(send)
		if err != nil {
			System.Add_SysLogs_T("复诊通知", "添加语音发送记录失败", send)
		}

		if res.Status == "error" {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "语音通知失败!"}
			c.ServeJSON()
			return
		}

	}

	// 发送满意度调查短信
	if T_type == 3 {
		playInfoList := http.GetSatisfactionPlayInfoList([]string{"张三", "某某医院消化内科"})
		res, err := http.VoiceNotifyAPI(conf.VoiceCall_Phone, "+86"+T_phone, playInfoList)
		if err != nil {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "电话通知失败!"}
			c.ServeJSON()
			return
		}

		// 保存电话通知发送记录
		send := Patient.PatientSend{
			T_uid:   c.User.Id,
			T_pid:   0,
			T_phone: T_phone,
			T_type:  3,
			T_id:    res.SessionId,
			T_code:  res.Resultcode,
			T_State: 0,
		}

		_, err = Patient.Add_PatientSend(send)
		if err != nil {
			System.Add_SysLogs_T("复诊通知", "添加发送记录失败", send)
		}

		if res.Resultcode != "0" {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "满意度调查失败!"}
			c.ServeJSON()
			return
		}
	}

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
	c.ServeJSON()
	return

}

// 获取微信支付二维码
func (c *UserController) Get_Weixin_QR_Code() {
	Total, _ := c.GetFloat("Total")
	Title := "复诊通知" + c.User.T_user
	res, err := http.PayTransactionNative(Title, Total)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
		c.ServeJSON()
		return
	}
	if res.Code != 200 {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: res.Message}
		c.ServeJSON()
		return
	}

	var_ := Account.UserPayOrder{
		T_uid:      c.User.Id,
		T_type:     "微信",
		T_title:    Title,
		T_total:    Total,
		T_order_no: res.OrderNo,
	}

	_, err = Account.Add_UserPayOrder(var_)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "添加失败!"}
		c.ServeJSON()
		return
	}

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: res}
	c.ServeJSON()
	return

}

// 微信支付回调
func (c *UserController) Weixin_Notify() {

	type RequestBody struct {
		TradeNo string
		Status  string
	}
	type JSON struct {
		Code    int
		Message string
	}

	logs.Info("Body:", string(c.Ctx.Input.RequestBody))

	//解密
	adc_str, err := lib.AesDeCrypt(c.Ctx.Input.RequestBody, []byte(conf.Weixin_PwdKey))
	//adc_str, _ := lib.AesDeCrypt(buf[0:n], []byte(conf.Weixin_PwdKey))

	var body RequestBody
	logs.Info("data================ ", string(adc_str))
	err = json.Unmarshal(adc_str, &body)
	if err != nil {
		c.Data["json"] = JSON{Code: 202, Message: "json.Unmarshal is err:" + err.Error()}
		c.ServeJSON()
	}

	UserPayOrder, err := Account.Get_UserPayOrder_ByT_order_no(body.TradeNo)
	if err != nil {
		c.Data["json"] = JSON{Code: 202, Message: "查询失败!"}
		c.ServeJSON()
		return
	}
	//交易状态
	//SUCCESS：支付成功
	//REFUND：转入退款
	//NOTPAY：未支付
	//CLOSED：已关闭
	//REVOKED：已撤销（付款码支付）
	//USERPAYING：用户支付中（付款码支付）
	//PAYERROR：支付失败(其他原因，如银行返回失败)
	UserPayOrder.T_status = body.Status
	err = Account.Update_UserPayOrder(UserPayOrder, "T_status")
	if err != nil {
		c.Data["json"] = JSON{Code: 202, Message: "更新状态失败!"}
		c.ServeJSON()
		return
	}
	// 添加充值记录
	// 余额加上充值金额
	if body.Status == "SUCCESS" {
		T_money64, _ := decimal.NewFromFloat(float64(c.User.T_money) + UserPayOrder.T_total).Round(2).Float64()
		c.User.T_money = float32(T_money64)
		// 修改用户余额
		err = Account.Update_User(c.User, "T_money")
		if err != nil {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "充值失败!"}
			c.ServeJSON()
			return
		}

		// 添加充值记录
		bill := Account.UserBill{
			T_uid:      c.User.Id,
			T_type:     Account.Pay,
			T_bill:     "充值（微信）",
			T_charging: float32(UserPayOrder.T_total),
			T_balance:  float32(T_money64),
		}
		_, err = Account.Add_UserBill(bill)
		if err != nil {
			c.Data["json"] = lib.JSONS{Code: 202, Msg: "充值失败!"}
			c.ServeJSON()
			return
		}
		user := c.User
		user.T_pass = "******"
		System.Add_UserLogs_T(c.User.T_uuid, "用户管理", "充值", user)
	}

	c.Data["json"] = JSON{Code: 200, Message: "成功"}
	c.ServeJSON()
	return

}

// 获取微信支付订单状态
func (c *UserController) GetWxOrderState() {
	OrderNo := c.GetString("OrderNo")
	UserPayOrder, err := Account.Get_UserPayOrder_ByT_order_no(OrderNo)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
		c.ServeJSON()
		return
	}
	c.Data["json"] = lib.JSONS{Code: 200, Msg: "成功", Data: UserPayOrder}
	c.ServeJSON()
	return
}

// 满意度统计
func (c *UserController) Satisfaction_Stats() {
	list, err := Patient.Read_PatientSatisfaction_ByT_uid(c.User.Id)
	if err != nil {
		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
		c.ServeJSON()
		return
	}
	type Json struct {
		Count map[string]map[string]int
		Title map[string]string
	}

	countMap := make(map[string]map[string]int)
	for _, v := range list {
		updateCountMap(countMap, "question1", v.T_question1)
		updateCountMap(countMap, "question2", v.T_question2)
		updateCountMap(countMap, "question3", v.T_question3)
		updateCountMap(countMap, "question4", v.T_question4)
		updateCountMap(countMap, "question5", v.T_question5)
	}
	title := make(map[string]string)
	title["question1"] = Patient.Question1
	title["question2"] = Patient.Question2
	title["question3"] = Patient.Question3
	title["question4"] = Patient.Question4
	title["question5"] = Patient.Question5

	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Json{Count: countMap, Title: title}}

	c.ServeJSON()
	return

}

// 辅助函数：更新选项计数
func updateCountMap(countMap map[string]map[string]int, question string, value string) {
	if question == "question2" {
		if strings.Contains("12", value) {
			if countMap[question] == nil {
				countMap[question] = map[string]int{
					"1": 0,
					"2": 0,
				}
			}
			countMap[question][value]++
		}
	} else {
		if strings.Contains("123", value) {
			if countMap[question] == nil {
				countMap[question] = map[string]int{
					"1": 0,
					"2": 0,
					"3": 0,
				}
			}
			countMap[question][value]++
		}
	}

}

// 满意度列表
func (c *UserController) Satisfaction_List() {
	// 分页参数 初始化
	page, _ := c.GetInt("page")
	if page < 1 {
		page = 1
	}
	page_z, _ := c.GetInt("page_z")
	if page_z < 1 {
		page_z = conf.Page_size
	}
	Patient.Read_Patient_All_Map(c.User.Id)
	list, cnt := Patient.Read_PatientSatisfaction_List(c.User.Id, page, page_z)

	var r_jsons lib.R_JSONS
	r_jsons.Num = cnt
	r_jsons.Data = list
	r_jsons.Page = page
	r_jsons.Page_size = int(math.Ceil(float64(cnt) / float64(page_z)))
	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
	c.ServeJSON()
	return

}

// 用户定时任务
func Cron_User() {

	//创建一个定时任务对象
	c := cron.New(cron.WithSeconds())
	//给对象增加定时任务
	//c.AddFunc("0 */1 * * * ?", Cron_User_Money_Bill)
	c.AddFunc("0 0 7 * * *", Cron_User_Money_Bill)

	//启动定时任务
	c.Start()
	defer c.Stop()

	//查询语句，阻塞，让main函数不退出，保持程序运行
	select {}

}

// 用户扣费，并生成账单，每天2点执行
func Cron_User_Money_Bill() {

	yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02")
	logs.Info("开始进行" + yesterday + "用户账单扣费统计")
	userList, _ := Account.Read_User_List("", 0, 9999)
	for _, user := range userList {
		// 1 短信 2 电话
		smsCount := Patient.Read_PatientSend_Count_Yesterday(user.Id, 0, 1, yesterday)
		voiceCallCount := Patient.Read_PatientSend_Count_Yesterday(user.Id, 0, 2, yesterday)
		money := float64(smsCount)*conf.SUBMAIL_Sms_Fee + float64(voiceCallCount)*conf.VoiceCall_Fee
		if money == 0 {
			continue
		}
		sendMsg := false
		moneyFlag := ""
		var_ := Account.User{Id: user.Id, T_money: user.T_money - float32(money)}
		if user.T_money >= 100 && var_.T_money < 100 {
			sendMsg = true
			moneyFlag = "不足100元"
		} else if user.T_money >= 10 && var_.T_money < 10 {
			sendMsg = true
			moneyFlag = "不足10元"
		} else if user.T_money >= 0 && var_.T_money < 0 {
			sendMsg = true
			moneyFlag = "欠费"
		}
		err := Account.Update_User(var_, "T_money")
		if err != nil {
			System.Add_SysLogs_T("用户扣费", "扣费失败", var_)
		}

		// 添加扣费记录
		bill := Account.UserBill{
			T_uid:      user.Id,
			T_type:     Account.FeeDeduction,
			T_bill:     yesterday + "通知自动扣除",
			T_charging: float32(money),
			T_balance:  user.T_money - float32(money),
		}
		_, err = Account.Add_UserBill(bill)
		if err != nil {
			System.Add_SysLogs_T("用户扣费", "添加扣费记录失败", bill)
		}
		if sendMsg {
			_, err = submail.SmsXSendBill(user.T_phone, user.T_user, moneyFlag)
			info := fmt.Sprintf("T_uid:%v, T_phone:%v, T_user:%v, moneyFlag:%v", user.Id, user.T_phone, user.T_user, moneyFlag)
			if err != nil {
				System.Add_SysLogs_T("复诊通知-账单", "短信通知失败", info)
			} else {
				System.Add_SysLogs_T("复诊通知-账单", "短信通知成功", info)
			}
		}

	}
	logs.Info("用户账单扣费统计结束")

}
