/**
* @Author: zou.yingbin
* @Create  : 2020/12/2 9:18
* @Modify  : 2020/12/2 9:18
 */

package erms3

import (
	"encoding/json"
	"mtp2_if/global/app"
	"mtp2_if/global/e"
	"mtp2_if/logger"
	"mtp2_if/models"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
)

// 去除多余的冒号
func tripColon(str string) string {
	if len(str) >= 3 && str[0] == '"' {
		return str[1 : len(str)-1]
	}

	return str
}

type sFloat64 float64

func (r *sFloat64) UnmarshalJSON(buf []byte) error {
	str := tripColon(string(buf))
	if d, err := strconv.ParseFloat(str, 64); err == nil {
		*r = sFloat64(d)
	} else {
		return err
	}

	return nil
}

type sInt32 int32

func (r *sInt32) UnmarshalJSON(buf []byte) error {
	str := tripColon(string(buf))
	if d, err := strconv.ParseInt(str, 10, 64); err == nil {
		*r = sInt32(d)
	} else {
		return err
	}
	return nil
}

type sInt64 int64

func (r *sInt64) UnmarshalJSON(buf []byte) error {
	str := tripColon(string(buf))
	if d, err := strconv.ParseInt(str, 10, 64); err == nil {
		*r = sInt64(d)
	} else {
		return err
	}
	return nil
}

// 解析定价明细Json字段
type SpotPriceJson struct {
	Price  sFloat64
	Qty    sFloat64
	Amount sFloat64
}

// 解析点价明细Json字段
type SpotPointJson struct {
	GoodsID   sInt32
	GoodsName string
	Qty       sFloat64
	Basic     sFloat64
	StartDate string
	EndDate   string
}

// 解析合同申请表Json字段
type DetailJSON struct {
	WrStandardID         sInt64
	WrStandardName       string
	ProductType          sInt32
	ProductTypeName      string
	DeliveryGoodsID      sInt32
	DeliveryGoodsName    string
	DeliveryGoodsDesc    string
	WarehouseID          sInt32
	WarehouseName        string
	UnitName             string
	PointDesc            string
	SpotPriceOrderList   []SpotPriceJson
	SpotPointOrderVoList []SpotPointJson
}

// 查询待审核合同请求
type QryAuditContractReq struct {
	AccountIDs   string `form:"accountids" binding:"required"`    // 请求账号ID列表
	ContractType int32  `form:"contracttype" binding:"required"` // 合同类型
	ContractMode uint32 `form:"contractmode" binding:"required"` // 合同模式
}

// 查询待审核合同应答
type QryAuditContractRsp struct {
	SpotContractId    string  `json:"spotcontractid"  xorm:"'SPOTCONTRACTID'" binding:"required"`       // 合同ID
	MatchCustomerName string  `json:"matchcustomername"  xorm:"'MATCHCUSTOMERNAME'" binding:"required"` // 销售方ID
	MatchAccountId    string  `json:"matchaccountid"  xorm:"'MATCHACCOUNTID'"`                          // 业务员ID
	AccountId         string  `json:"accountid"  xorm:"'ACCOUNTID'"`                                    // 交易员ID
	CustomerName      string  `json:"customername"  xorm:"'CUSTOMERNAME'"`                              // 采购方ID
	WrstandardName    string  `json:"wrstandardname"  xorm:"'WRSTANDARDNAME'"`                          // 商品名称
	Wrstandardcode    string  `json:"-"`                                                                // 商品代码
	PricedQty         float64 `json:"pricedqty"  xorm:"'PRICEDQTY'"`                                    // 定价量
	UnpricedQty       float64 `json:"unpricedqty"  xorm:"'UNPRICEDQTY'"`                                // 未定价量
	TotaldQty         float64 `json:"totaldqty"  xorm:"'TOTALDQTY'"`                                    // 合同量
	DeliveryQty       uint64  `json:"deliveryqty"  xorm:"'DELIVERYQTY'"`                                // 交收量
	CurDeliveryQty    uint64  `json:"curdeliveryqty"  xorm:"'CURDELIVERYQTY'"`                          // 未交收量
	DeliveryGoodsID   string  `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`                        // 品种ID
	DeliveryGoodsName string  `json:"-"`                                                                // 品种名称
	DeliveryGoodscode string  `json:"-"`                                                                // 品种代码
	ApplyStatus       uint32  `json:"applystatus"  xorm:"'APPLYSTATUS'"`                                // 申请状态 - 0:未审核 1:审核通过 2:审核中 3:审核失败 4已撤销 5:审核拒绝
	EnumdicName       string  `json:"enumdicname"  xorm:"'ENUMDICNAME'"`                                // 单位名称
	SignDate          string  `json:"signdate"  xorm:"'SIGNDATE'"`                                      // 签订日期

	deliverGoods map[int32]models.Deliverygoods  // 不参与json编码,作为id转code缓存
	wrStandards  map[int64]models.WRStandardInfo // 不参与json编码,作为id转code缓存
}

// 转换交割商品ID为商品代码
func (r *QryAuditContractRsp) DeliverGoodsId2Code(id int32) string {

	// init
	if r.deliverGoods == nil || len(r.deliverGoods) == 0 {
		r.deliverGoods = make(map[int32]models.Deliverygoods)
		if dg, err := models.GetDeliverGoods(); err == nil {
			for _, v := range dg {
				r.deliverGoods[v.Deliverygoodsid] = v
			}
		}
	}

	if v, ok := r.deliverGoods[id]; ok {
		return v.Deliverygoodscode
	}

	return ""
}

// 转换仓单商品ID为代code
func (r *QryAuditContractRsp) WrStandardID2Code(id int64) string {

	// init
	if r.wrStandards == nil || len(r.wrStandards) == 0 {
		r.wrStandards = make(map[int64]models.WRStandardInfo)
		if wg, err := models.GetWrstandards(); err == nil {
			for _, v := range wg {
				r.wrStandards[v.Wrstandardid] = v
			}
		}
	}

	if v, ok := r.wrStandards[id]; ok {
		return v.Wrstandardcode
	}

	return ""
}

// 构建响应数据
func (r *QryAuditContractRsp) ParseFromModel(val models.AuditContractModel) error {
	r.SpotContractId = val.SpotContractId
	r.MatchAccountId = val.MatchAccountId
	r.MatchCustomerName = val.MatchCustomerName
	r.AccountId = val.AccountId
	r.CustomerName = val.CustomerName
	r.ApplyStatus = val.ApplyStatus

	// 解析DetailJSON字段
	details := make([]DetailJSON, 0)
	if err := json.Unmarshal([]byte(val.DetailJSON), &details); err != nil {
		logger.GetLogger().Errorf("parse detailJson field fail:%v", err)
		return err
	}

	// 现在合同只有一张单
	detail := details[0]

	r.WrstandardName = detail.WrStandardName
	r.DeliveryGoodsName = detail.DeliveryGoodsName
	r.EnumdicName = detail.UnitName

	// 汇总未定价量
	r.UnpricedQty = 0
	for _, v := range detail.SpotPointOrderVoList {
		r.UnpricedQty += float64(v.Qty)
	}

	// 汇总定价量
	r.PricedQty = 0
	for _, v := range detail.SpotPriceOrderList {
		r.PricedQty += float64(v.Qty)
	}

	// 总量
	r.TotaldQty = r.UnpricedQty + r.PricedQty

	// 转换仓单商品ID为代code
	r.Wrstandardcode = r.WrStandardID2Code(int64(detail.WrStandardID))

	// 转换交割商品ID为商品代码
	r.DeliveryGoodscode = r.DeliverGoodsId2Code(int32(detail.DeliveryGoodsID))

	r.WrstandardName = r.WrstandardName + "/" + r.Wrstandardcode
	r.DeliveryGoodsID = r.DeliveryGoodsName + "/" + r.DeliveryGoodscode

	return nil
}

// 构建响应数据
func (r *QryAuditContractRsp) ParseFromHGModel(val models.AutditContractHGModel) error {
	r.SpotContractId = val.SpotContractId
	r.MatchCustomerName = val.MatchCustomerName
	r.AccountId = val.AccountId
	r.CustomerName = val.CustomerName
	r.EnumdicName = val.EnumdicName
	r.WrstandardName = val.WrstandardName + "/" + val.Wrstandardcode
	r.Wrstandardcode = val.Wrstandardcode
	r.ApplyStatus = val.ApplyStatus
	r.SignDate = val.SignDate
	r.MatchAccountId = val.MatchAccountId
	r.TotaldQty = val.ContractQty

	return nil
}

// QueryPendingAuditContract  查询待审核合同
// @Summary 查询待审核合同
// @Produce json
// @Security ApiKeyAuth
// @Param accountids query string true "资金账号ID列表,逗号隔开"
// @Param contracttype query int true "合同类型 1-采购 -1-销售"
// @Param contractmode query int true "合同模式 1-普通 2-回购"
// @Success 200 {array} QryAuditContractRsp
// @Failure 500 {object} app.Response
// @Router /Erms3/QueryPendingAuditContract [get]
// @Tags 风险管理v3
func QueryPendingAuditContract(c *gin.Context) {
	appG := app.Gin{C: c}
	var req QryAuditContractReq
	if err := c.ShouldBind(&req); err != nil {
		logger.GetLogger().Errorf("parse query pending audit contract, %v", err)
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	// 参数检查
	if req.ContractMode != 1 && req.ContractMode != 2 {
		logger.GetLogger().Errorf("ContractMode not in(1, 2)")
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	if req.ContractMode == 1 {
		if req.ContractType != 1 && req.ContractType != -1 {
			logger.GetLogger().Errorf("ContractType not in(1, -1) when ContractMode=1")
			appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
			return
		}
	}

	// 去除最后的逗号
	if len(req.AccountIDs) > 0 && req.AccountIDs[len(req.AccountIDs)-1] == ',' {
		req.AccountIDs = req.AccountIDs[0 : len(req.AccountIDs)-1]
	}

	switch req.ContractMode {
	case 1: // 普通合同
		var m models.AuditContractModel
		if d, err := m.GetData(req.AccountIDs, req.ContractType); err == nil {
			rsp := make([]QryAuditContractRsp, 0)
			for _, v := range d {
				var rv QryAuditContractRsp
				if err := rv.ParseFromModel(v); err == nil {
					rsp = append(rsp, rv)
				} else {
					appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
					return
				}
			}
			appG.Response(http.StatusOK, e.SUCCESS, rsp)
		}
	case 2: // 回购合同
		var m models.AutditContractHGModel
		if d, err := m.GetData(req.AccountIDs); err == nil {
			rsp := make([]QryAuditContractRsp, 0)
			for _, v := range d {
				var rv QryAuditContractRsp
				if err := rv.ParseFromHGModel(v); err == nil {
					rsp = append(rsp, rv)
				} else {
					appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
					return
				}
			}
			appG.Response(http.StatusOK, e.SUCCESS, rsp)
		}
	default:
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
	}
}

// 查询待审核业务请求
type QryPendingBizReq struct{
	AccountIDs   string `form:"accountids" binding:"required"`    // 请求资金账号列表,逗号隔开
}

// 查询待审核业务响应
type QryPendingBizRsp models.PendingAuditBizModel

// QueryPendingBusiness  查询待审核基差贸易业务
// @Summary 查询待审核基差贸易业务
// @Produce json
// @Security ApiKeyAuth
// @Param accountids query string true "资金账号ID列表,逗号隔开"
// @Success 200 {array} QryPendingBizRsp
// @Failure 500 {object} app.Response
// @Router /Erms3/QueryPendingBusiness [get]
// @Tags 风险管理v3
func QueryPendingBusiness(c *gin.Context) {
	appG := app.Gin{C: c}
	var req QryPendingBizReq
	if err := c.ShouldBind(&req); err != nil {
		logger.GetLogger().Errorf("bind QryAuditContractReq, %v", err)
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	// 去除最后的逗号
	if len(req.AccountIDs) > 0 && req.AccountIDs[len(req.AccountIDs)-1] == ',' {
		req.AccountIDs = req.AccountIDs[0 : len(req.AccountIDs)-1]
	}

	var m models.PendingAuditBizModel
	if d, err := m.GetData(req.AccountIDs); err == nil{
		appG.Response(http.StatusOK, e.SUCCESS, d)
	}else {
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
	}
}