package svc

import (
	"applet/app/e"
	"applet/app/md"
	"applet/app/utils"
	"applet/app/utils/cache"
	db "code.fnuoos.com/zhimeng/model.git/src"
	"code.fnuoos.com/zhimeng/model.git/src/super/implement"
	"code.fnuoos.com/zhimeng/model.git/src/super/model"
	"fmt"
	"github.com/gin-gonic/gin"
	"time"
)

func FinancialDynamicsMediumSave(c *gin.Context, req md.FinancialDynamicsMediumSaveReq) {
	// 加锁 防止并发提取
	mutexKey := fmt.Sprintf("%s:FinancialDynamicsMediumSave", c.GetString("mid"))
	withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 5, "NX")
	if err != nil {
		e.OutErr(c, 400, err)

		return
	}
	if withdrawAvailable != "OK" {
		e.OutErr(c, 400, e.NewErr(400000, "请求过于频繁,请稍后再试"))
		return
	}
	engine := db.Db
	sess := engine.NewSession()
	defer sess.Close()
	sess.Begin()
	var data model.MediumFinancialDynamics
	data.CreateAt = time.Now().Format("2006-01-02 15:04:05")
	data.MediumId = utils.StrToInt(req.Uid)
	data.Amount = req.Amount
	data.Memo = req.Memo
	data.Uuid = utils.StrToInt(c.GetString("mid"))
	data.BusinessKind = utils.StrToInt(req.BusinessKind)
	data.Certificate = req.Certificate
	data.PayMethod = utils.StrToInt(req.PayMethod)
	data.PayTime = time.Now().Format("2006-01-02 15:04:05")
	data.UpdateAt = time.Now().Format("2006-01-02 15:04:05")
	insert, _ := engine.Insert(&data)
	if insert == 0 {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "创建失败"))
		return
	}
	err = DealMediumAmount(sess, md.DealMediumAmount{
		Mid:      c.GetString("mid"),
		Type:     md.FinMediumFlowDirectionIncome,
		Kind:     md.FinancialDynamicsKindForMediumFlow,
		OrdId:    utils.IntToStr(data.Id),
		MediumId: utils.StrToInt(req.Uid),
		Amount:   utils.StrToFloat64(req.Amount),
		Memo:     md.FinancialDynamicsTitleKindForMediumFlow,
	})
	if err != nil {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "创建失败"))
		return
	}
	sess.Commit()
	e.OutSuc(c, "success", nil)
	return
}
func FinancialDynamicsMediumList(c *gin.Context, req md.FinancialDynamicsMediumListReq) md.FinancialDynamicsMediumListRes {
	engine := db.Db
	NewMediumFinancialDynamicsDb := implement.NewMediumFinancialDynamicsDb(engine)
	list, total, _ := NewMediumFinancialDynamicsDb.FindMediumFinancialDynamics(c.GetString("mid"), req.Uid, req.StartTime, req.EndTime, utils.StrToInt(req.Page), utils.StrToInt(req.Limit))
	data := make([]md.FinancialDynamicsMediumListData, 0)
	if len(list) > 0 {
		for _, v := range list {
			var tmp = md.FinancialDynamicsMediumListData{
				Id:           utils.IntToStr(v.Id),
				PayTime:      v.PayTime,
				Amount:       v.Amount,
				PayMethod:    utils.IntToStr(v.PayMethod),
				Certificate:  v.Certificate,
				Memo:         v.Memo,
				BusinessKind: utils.IntToStr(v.BusinessKind),
			}
			medium := GetMediumInfo(c, v.MediumId)
			if medium != nil {
				tmp.Name = medium["name"]
			}
			data = append(data, tmp)
		}
	}
	user := make([]md.SelectData, 0)
	res := md.FinancialDynamicsMediumListRes{
		List:         data,
		Total:        total,
		PayMethod:    md.PayMethod,
		BusinessKind: md.BusinessKind,
	}
	var userList []model.MediumList
	db.Db.Where("settlement_type=4").Find(&userList)
	for _, v := range userList {
		tmp := md.SelectData{
			Name:  v.CompanyName,
			Value: utils.IntToStr(v.MediumId),
		}
		if v.CompanyAbbreviation != "" {
			tmp.Name = v.CompanyAbbreviation
		}
		user = append(user, tmp)
	}
	res.User = user
	return res
}
func FinancialDynamicsMediumTotal(c *gin.Context, req md.FinancialDynamicsMediumTotalReq) md.FinancialDynamicsMediumTotalRes {
	engine := db.Db
	sql := `select sum(amount) as amount,COUNT(*) as count from %s where %s`
	where := "uuid=" + c.GetString("mid")
	if req.Uid != "" {
		where += " and medium_id=" + req.Uid
	}
	sql1 := fmt.Sprintf(sql, "medium_list", where)
	res := md.FinancialDynamicsMediumTotalRes{
		BalanceAmount: "0.00",
		AllAmount:     "0.00",
		UseAmount:     "0.00",
		PayCount:      "0",
	}
	nativeString, _ := db.QueryNativeString(engine, sql1)
	for _, v := range nativeString {
		if utils.StrToFloat64(v["amount"]) > 0 {
			res.BalanceAmount = v["amount"]
		}
	}
	sql2 := fmt.Sprintf(sql, "medium_financial_dynamics", where)
	nativeString2, _ := db.QueryNativeString(engine, sql2)
	for _, v := range nativeString2 {
		if utils.StrToFloat64(v["amount"]) > 0 {
			res.AllAmount = v["amount"]
		}
		if utils.StrToFloat64(v["count"]) > 0 {
			res.PayCount = v["count"]
		}
	}
	res.UseAmount = utils.Float64ToStr(utils.StrToFloat64(res.AllAmount) - utils.StrToFloat64(res.BalanceAmount))
	return res
}

func FinancialDynamicsAgentSave(c *gin.Context, req md.FinancialDynamicsAgentSaveReq) {
	// 加锁 防止并发提取
	mutexKey := fmt.Sprintf("%s:FinancialDynamicsAgentSave", c.GetString("mid"))
	withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 5, "NX")
	if err != nil {
		e.OutErr(c, 400, err)

		return
	}
	if withdrawAvailable != "OK" {
		e.OutErr(c, 400, e.NewErr(400000, "请求过于频繁,请稍后再试"))
		return
	}
	engine := db.Db
	sess := engine.NewSession()
	defer sess.Close()
	sess.Begin()
	var data model.AgentFinancialDynamics
	data.CreateAt = time.Now().Format("2006-01-02 15:04:05")
	data.AgentId = utils.StrToInt(req.Uid)
	data.Amount = req.Amount
	data.Memo = req.Memo
	data.Uuid = utils.StrToInt(c.GetString("mid"))
	data.BusinessKind = utils.StrToInt(req.BusinessKind)
	data.Certificate = req.Certificate
	data.PayMethod = utils.StrToInt(req.PayMethod)
	data.PayTime = time.Now().Format("2006-01-02 15:04:05")
	data.UpdateAt = time.Now().Format("2006-01-02 15:04:05")
	insert, _ := engine.Insert(&data)
	if insert == 0 {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "创建失败"))
		return
	}
	err = DealAgentAmount(sess, md.DealAgentAmount{
		Mid:     c.GetString("mid"),
		Type:    md.FinAgentFlowDirectionIncome,
		Kind:    md.FinancialDynamicsKindForAgentFlow,
		OrdId:   utils.IntToStr(data.Id),
		AgentId: utils.StrToInt(req.Uid),
		Amount:  utils.StrToFloat64(req.Amount),
		Memo:    md.FinancialDynamicsTitleKindForAgentFlow,
	})
	if err != nil {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "创建失败"))
		return
	}
	sess.Commit()
	e.OutSuc(c, "success", nil)
	return
}
func FinancialDynamicsAgentList(c *gin.Context, req md.FinancialDynamicsAgentListReq) md.FinancialDynamicsAgentListRes {
	engine := db.Db
	NewAgentFinancialDynamicsDb := implement.NewAgentFinancialDynamicsDb(engine)
	list, total, _ := NewAgentFinancialDynamicsDb.FindAgentFinancialDynamics(c.GetString("mid"), req.Uid, req.StartTime, req.EndTime, utils.StrToInt(req.Page), utils.StrToInt(req.Limit))
	data := make([]md.FinancialDynamicsAgentListData, 0)
	if len(list) > 0 {
		for _, v := range list {
			var tmp = md.FinancialDynamicsAgentListData{
				Id:           utils.IntToStr(v.Id),
				PayTime:      v.PayTime,
				Amount:       v.Amount,
				PayMethod:    utils.IntToStr(v.PayMethod),
				Certificate:  v.Certificate,
				Memo:         v.Memo,
				BusinessKind: utils.IntToStr(v.BusinessKind),
			}
			agent := GetAgentInfo(c, v.AgentId)
			if agent != nil {
				tmp.Name = agent["name"]
			}
			data = append(data, tmp)
		}
	}
	user := make([]md.SelectData, 0)
	res := md.FinancialDynamicsAgentListRes{
		List:         data,
		Total:        total,
		PayMethod:    md.PayMethod,
		BusinessKind: md.BusinessKind,
	}
	var userList []model.AgentList
	db.Db.Where("settlement_type=4").Find(&userList)
	for _, v := range userList {
		tmp := md.SelectData{
			Name:  v.CompanyName,
			Value: utils.IntToStr(v.AgentId),
		}
		if v.CompanyAbbreviation != "" {
			tmp.Name = v.CompanyAbbreviation
		}
		user = append(user, tmp)
	}
	res.User = user
	return res
}
func FinancialDynamicsAgentTotal(c *gin.Context, req md.FinancialDynamicsAgentTotalReq) md.FinancialDynamicsAgentTotalRes {
	engine := db.Db
	sql := `select sum(amount) as amount,COUNT(*) as count from %s where %s`
	where := "uuid=" + c.GetString("mid")
	if req.Uid != "" {
		where += " and agent_id=" + req.Uid
	}
	sql1 := fmt.Sprintf(sql, "agent_list", where)
	res := md.FinancialDynamicsAgentTotalRes{
		BalanceAmount: "0.00",
		AllAmount:     "0.00",
		UseAmount:     "0.00",
		PayCount:      "0",
	}
	nativeString, _ := db.QueryNativeString(engine, sql1)
	for _, v := range nativeString {
		if utils.StrToFloat64(v["amount"]) > 0 {
			res.BalanceAmount = v["amount"]
		}
	}
	sql2 := fmt.Sprintf(sql, "agent_financial_dynamics", where)
	nativeString2, _ := db.QueryNativeString(engine, sql2)
	for _, v := range nativeString2 {
		if utils.StrToFloat64(v["amount"]) > 0 {
			res.AllAmount = v["amount"]
		}
		if utils.StrToFloat64(v["count"]) > 0 {
			res.PayCount = v["count"]
		}
	}
	res.UseAmount = utils.Float64ToStr(utils.StrToFloat64(res.AllAmount) - utils.StrToFloat64(res.BalanceAmount))
	return res
}