package contract

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"hongze/fms_api/controller/resp"
	"hongze/fms_api/global"
	"hongze/fms_api/models/base"
	"hongze/fms_api/models/crm"
	"hongze/fms_api/models/fms"
	"hongze/fms_api/models/system"
	crmService "hongze/fms_api/services/crm"
	fmsService "hongze/fms_api/services/fms"
	"hongze/fms_api/utils"
	"strconv"
	"strings"
	"time"
)

// // RegisterController 合同登记
type PreRegisterController struct{}

// InvoiceList
// @Title 开票/到款列表
// @Description 开票/到款列表
// @Param   Keyword			query	string	false	"关键词"
// @Success 200 {object} fms.ContractInvoiceItem
// @router /contract/pre_register/list [get]
func (rg *PreRegisterController) List(c *gin.Context) {
	var req fms.PreRegisterListReq
	if e := c.BindQuery(&req); e != nil {
		err, ok := e.(validator.ValidationErrors)
		if !ok {
			resp.FailData("参数解析失败", "Err:"+e.Error(), c)
			return
		}
		resp.FailData("参数解析失败", err.Translate(global.Trans), c)
		return
	}
	pageSize := req.PageSize
	pageIndex := req.Current
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if pageIndex <= 0 {
		pageIndex = 1
	}
	cond := ` invoice_type IN (3, 4) `
	pars := make([]interface{}, 0)
	if req.Keyword != "" {
		kw := "%" + req.Keyword + "%"
		cond += ` AND company_name LIKE ? `
		pars = append(pars, kw)
	}
	// 货币列表
	currencyOB := new(fms.CurrencyUnit)
	currencyCond := `enable = 1`
	currencyPars := make([]interface{}, 0)
	currencyList, e := currencyOB.List(currencyCond, currencyPars)
	if e != nil {
		resp.FailMsg("获取失败", "获取货币列表失败, Err: "+e.Error(), c)
		return
	}
	unitMap := make(map[string]string)
	for i := range currencyList {
		unitMap[currencyList[i].Code] = currencyList[i].UnitName
	}

	page := new(base.Page)
	page.SetPageSize(req.PageSize)
	page.SetCurrent(req.Current)
	sortTypeMap := map[int]bool{0: false, 1: true, 2: false}
	page.AddOrderItem(base.OrderItem{Column: "create_time", Asc: sortTypeMap[0]})

	total, list, e := fms.GetContractPreRegisterItemPageList(page, cond, pars)
	if e != nil {
		resp.FailMsg("获取失败", "获取预登记列表失败, Err: "+e.Error(), c)
		return
	}
	serviceMap := make(map[int]string, 0)
	registerIds := make([]int, 0)
	for i := range list {
		list[i].UnitName = unitMap[list[i].CurrencyUnit]
		registerIds = append(registerIds, list[i].ContractRegisterId)
	}

	if len(registerIds) > 0 {
		serviceMap, _, e = fmsService.GetContractServiceNameFormat(registerIds)
		if e != nil {
			resp.FailMsg("获取失败", e.Error(), c)
			return
		}
	}

	respList := make([]*fms.ContractPreRegisterList, 0)

	for _, v := range list {
		item := new(fms.ContractPreRegisterList)
		item.ContractPreRegisterItem = v
		item.ServicesName = serviceMap[v.ContractRegisterId]
		respList = append(respList, item)
	}

	page.SetTotal(total)
	baseData := new(base.BaseData)
	baseData.SetPage(page)
	baseData.SetList(respList)
	resp.OkData("获取成功", baseData, c)
}

// Add
// @Title 新增预登记
// @Description 新增预登记
// @Param	request  body  fms.PrepayAddReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /contract/pre_register/add [post]
func (rg *PreRegisterController) Add(c *gin.Context) {
	req := new(fms.PreRegisterAddReq)
	err := c.ShouldBind(&req)
	if err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
			return
		}
		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
		return
	}
	claims, _ := c.Get("adminInfo")
	adminInfo := claims.(*system.SysAdmin)

	// 日期校验
	var startDate, endDate time.Time
	if req.StartDate != "" && req.EndDate != "" {
		startDate, err = time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
		if err != nil {
			resp.FailMsg("约定开始日期格式有误", "合同开始日期格式有误, Err: "+err.Error(), c)
			return
		}
		endDate, err = time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
		if err != nil {
			resp.FailMsg("约定结束日期格式有误", "合同结束日期格式有误, Err: "+err.Error(), c)
			return
		}
	}

	var currencyUnit string
	if len(req.List) > 0 {
		currencyUnit = req.List[0].CurrencyUnit
	}
	// 获取销售分组信息
	sellerList, e := crmService.GetSellerDepartmentListWithGroupAndTeam()
	if e != nil {
		resp.FailData("获取销售失败", "Err:"+e.Error(), c)
		return
	}
	sellerMap := make(map[int]*crm.SellerAdminWithGroupTeam)
	for i := range sellerList {
		sellerMap[sellerList[i].SellerId] = sellerList[i]
	}

	admin := new(crm.Admin)
	sellerIds := strings.Split(req.SellerIds, ",")
	if len(sellerIds) > 2 {
		resp.Fail("最多只能选择两个销售", c)
		return
	}

	var sellers []*crm.Admin
	var pars []interface{}
	cond := ``
	if len(sellerIds) > 0 {
		cond = ` admin_id in (?) `
		pars = append(pars, sellerIds)
		sellers, e = admin.List(cond, pars)
		if e != nil {
			resp.FailMsg("获取销售信息失败", "获取销售信息失败, Err: "+e.Error(), c)
			return
		}
	}

	//新增合同
	ob := new(fms.ContractRegister)
	//ob.ContractCode = req.ContractCode
	ob.CompanyName = req.CompanyName
	ob.ProductIds = req.ProductIds
	ob.StartDate = startDate
	ob.EndDate = endDate
	ob.HasInvoice = 1
	ob.Set()
	ob.CurrencyUnit = currencyUnit
	if req.RegisterType == fms.ContractInvoiceTypePreMake {
		//sellerItem := sellerMap[r.SellerId]
		//if sellerItem == nil {
		//	resp.Fail("销售信息异常", c)
		//	return
		//}
		for _, v := range sellers {
			if v.DepartmentId == crm.SellerDepartmentId {
				ob.SellerId = v.AdminId
				ob.SellerName = v.AdminName
			} else if v.DepartmentId == crm.RaiSellerDepartmentId {
				ob.RaiSellerId = v.AdminId
				ob.RaiSellerName = v.AdminName
			}
		}
	}

	// 套餐信息
	serviceAmountMap := make(map[int]float64)
	serviceList, e := fmsService.HandleContractServiceAndDetail(req.Services, true, serviceAmountMap)
	if e != nil {
		resp.FailMsg("操作失败", "获取合同套餐详情失败, Err: "+e.Error(), c)
		return
	}

	if e = ob.Create(); e != nil {
		resp.FailMsg("操作失败", "新增合同失败, Err: "+e.Error(), c)
		return
	}
	if ob.ContractRegisterId == 0 {
		resp.FailMsg("操作失败", "新增合同失败,合同ID为0", c)
		return
	}

	if e = fms.CreateContractRegisterAndServicesAndPayMent(ob, serviceList); e != nil {
		resp.FailMsg("操作失败", "新增合同及套餐失败, Err: "+e.Error(), c)
		return
	}

	for _, r := range req.List {
		// 货币及汇率
		rateList, e := fmsService.GetTodayCurrencyRateList()
		if e != nil {
			resp.FailMsg("操作失败", "获取今日货币汇率失败, Err: "+e.Error(), c)
			return
		}
		var rate float64
		for i := range rateList {
			if r.CurrencyUnit == rateList[i].Code {
				rate = rateList[i].RMBRate
				break
			}
		}
		if rate <= 0 {
			resp.FailMsg("操作失败", "货币汇率信息有误", c)
			return
		}

		registerDate, e := time.Parse(utils.FormatDate, r.RegisterDate)
		if e != nil {
			resp.FailMsg("日期转换失败", "日期转换失败, Err: "+e.Error(), c)
			return
		}

		v := &fms.ContractInvoice{
			ContractRegisterId: ob.ContractRegisterId,
			OriginAmount:       r.Amount,
			CurrencyUnit:       r.CurrencyUnit,
			InvoiceType:        req.RegisterType,
			InvoiceDate:        registerDate,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			Remark:             r.Remark,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
			TimeBase:           base.TimeBase{},
		}
		v.Set()

		a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", v.OriginAmount/rate), 64)
		v.Amount = a

		sellerItem := sellerMap[r.SellerId]
		if sellerItem == nil {
			resp.Fail("销售信息异常", c)
			return
		}

		v.SellerId = sellerItem.SellerId
		v.SellerName = sellerItem.SellerName
		v.SellerGroupId = sellerItem.GroupId
		v.SellerGroupName = sellerItem.GroupName
		v.SellerTeamId = sellerItem.TeamId
		v.SellerTeamName = sellerItem.TeamName

		// 新增开票到款记录
		if e = v.Create(); e != nil {
			resp.FailMsg("操作失败", "新增预登记失败, Err: "+e.Error(), c)
			return
		}

		//预登记列表
		pp := &fms.ContractPreRegister{
			ContractRegisterId: ob.ContractRegisterId,
			CompanyName:        req.CompanyName,
			InvoiceType:        req.RegisterType,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
			TimeBase:           base.TimeBase{},
		}
		pp.Set()
		pp.CurrencyUnit = r.CurrencyUnit
		if pp.InvoiceType == fms.ContractInvoiceTypePreMake {
			//开票走开票字段
			pp.InvoiceId = v.ContractInvoiceId
			pp.InvoiceDate = registerDate
			pp.OriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.OriginAmount/rate), 64)
			pp.Amount = a
			pp.Remark = r.Remark
			sellerItem := sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}

			pp.SellerId = sellerItem.SellerId
			pp.SellerName = sellerItem.SellerName
			pp.SellerGroupId = sellerItem.GroupId
			pp.SellerGroupName = sellerItem.GroupName
			pp.SellerTeamId = sellerItem.TeamId
			pp.SellerTeamName = sellerItem.TeamName

			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
		} else {
			//到款
			pp.ArriveId = v.ContractInvoiceId
			pp.ArriveDate = registerDate
			pp.ArriveOriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.ArriveOriginAmount/rate), 64)
			pp.ArriveAmount = a
			pp.ArriveRemark = r.Remark

			sellerItem := sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}
			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
		}

		// 新增开票到款记录
		if pp.ContractRegisterId == 0 {
			resp.FailMsg("操作失败", "新增预登记失败,合同ID为0", c)
			return
		}
		if e = pp.Create(); e != nil {
			resp.FailMsg("操作失败", "新增预登记失败, Err: "+e.Error(), c)
			return
		}

		v.PreRegisterId = pp.PreRegisterId
		if e = v.Update([]string{"PreRegisterId"}); e != nil {
			fmt.Println("更新开票登记失败, Err: " + e.Error())
			return
		}
	}

	// 开票到款汇总
	go fmsService.SummaryInvoicePaymentByContractRegisterId(ob.ContractRegisterId)

	resp.Ok("操作成功", c)
}

// Edit
// @Title 编辑预登记
// @Description 编辑预登记
// @Param	request  body  fms.ContractRegisterEditReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /contract/pre_register/edit [post]
func (rg *PreRegisterController) Edit(c *gin.Context) {
	req := new(fms.PreRegisterEditReq)
	err := c.ShouldBind(&req)
	if err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
			return
		}
		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
		return
	}
	claims, _ := c.Get("adminInfo")
	adminInfo := claims.(*system.SysAdmin)

	// 日期校验
	var startDate, endDate time.Time
	if req.StartDate != "" && req.EndDate != "" {
		startDate, err = time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
		if err != nil {
			resp.FailMsg("约定开始日期格式有误", "合同开始日期格式有误, Err: "+err.Error(), c)
			return
		}
		endDate, err = time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
		if err != nil {
			resp.FailMsg("约定结束日期格式有误", "合同结束日期格式有误, Err: "+err.Error(), c)
			return
		}
	}

	var currencyUnit string
	if len(req.List) > 0 {
		currencyUnit = req.List[0].CurrencyUnit
	}
	// 获取销售分组信息
	sellerList, e := crmService.GetSellerDepartmentListWithGroupAndTeam()
	if e != nil {
		resp.FailData("获取销售失败", "Err:"+e.Error(), c)
		return
	}
	sellerMap := make(map[int]*crm.SellerAdminWithGroupTeam)
	for i := range sellerList {
		sellerMap[sellerList[i].SellerId] = sellerList[i]
	}

	admin := new(crm.Admin)
	sellerIds := strings.Split(req.SellerIds, ",")
	if len(sellerIds) > 2 {
		resp.Fail("最多只能选择两个销售", c)
		return
	}
	var sellers []*crm.Admin
	var pars []interface{}
	cond := ``
	if len(sellerIds) > 0 {
		cond = ` admin_id in (?) `
		pars = append(pars, sellerIds)
		sellers, e = admin.List(cond, pars)
		if e != nil {
			resp.FailMsg("获取销售信息失败", "获取销售信息失败, Err: "+e.Error(), c)
			return
		}
	}

	//修改合同
	ob := new(fms.ContractRegister)
	//ob.ContractCode = req.ContractCode
	ob.ContractRegisterId = req.ContractRegisterId
	ob.CompanyName = req.CompanyName
	ob.ProductIds = req.ProductIds
	ob.StartDate = startDate
	ob.EndDate = endDate
	ob.ModifyTime = time.Now().Local()
	ob.CurrencyUnit = currencyUnit
	if req.RegisterType == fms.ContractInvoiceTypePreMake {
		//sellerItem := sellerMap[r.SellerId]
		//if sellerItem == nil {
		//	resp.Fail("销售信息异常", c)
		//	return
		//}
		for _, v := range sellers {
			if v.DepartmentId == crm.SellerDepartmentId {
				ob.SellerId = v.AdminId
				ob.SellerName = v.AdminName
			} else if v.DepartmentId == crm.RaiSellerDepartmentId {
				ob.RaiSellerId = v.AdminId
				ob.RaiSellerName = v.AdminName
			}
		}
	}

	// 套餐信息
	serviceAmountMap := make(map[int]float64)
	serviceList, e := fmsService.HandleContractServiceAndDetail(req.Services, true, serviceAmountMap)
	if e != nil {
		resp.FailMsg("操作失败", "获取合同套餐详情失败, Err: "+e.Error(), c)
		return
	}
	updateCols := []string{
		"ProductIds", "CompanyName", "SellerId", "SellerName", "StartDate", "EndDate",
		"RaiSellerId", "RaiSellerName", "ModifyTime", "CurrencyUnit",
	}

	invoiceList := make([]*fms.ContractInvoice, 0)
	ppList := make([]*fms.ContractPreRegister, 0)
	for _, r := range req.List {
		// 货币及汇率
		rateList, e := fmsService.GetTodayCurrencyRateList()
		if e != nil {
			resp.FailMsg("操作失败", "获取今日货币汇率失败, Err: "+e.Error(), c)
			return
		}
		var rate float64
		for i := range rateList {
			if r.CurrencyUnit == rateList[i].Code {
				rate = rateList[i].RMBRate
				break
			}
		}
		if rate <= 0 {
			resp.FailMsg("操作失败", "货币汇率信息有误", c)
			return
		}

		registerDate, e := time.Parse(utils.FormatDate, r.RegisterDate)
		if e != nil {
			resp.FailMsg("日期转换失败", "日期转换失败, Err: "+e.Error(), c)
			return
		}

		v := &fms.ContractInvoice{
			ContractInvoiceId:  r.InvoiceId,
			ContractRegisterId: ob.ContractRegisterId,
			OriginAmount:       r.Amount,
			CurrencyUnit:       r.CurrencyUnit,
			InvoiceType:        req.RegisterType,
			InvoiceDate:        registerDate,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			Remark:             r.Remark,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
		}
		v.TimeBase.ModifyTime = time.Now().Local()

		a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", v.OriginAmount/rate), 64)
		v.Amount = a

		sellerItem := sellerMap[r.SellerId]
		if sellerItem == nil {
			resp.Fail("销售信息异常", c)
			return
		}

		v.SellerId = sellerItem.SellerId
		v.SellerName = sellerItem.SellerName
		v.SellerGroupId = sellerItem.GroupId
		v.SellerGroupName = sellerItem.GroupName
		v.SellerTeamId = sellerItem.TeamId
		v.SellerTeamName = sellerItem.TeamName

		//预登记列表
		pp := &fms.ContractPreRegister{
			PreRegisterId:      r.PreRegisterId,
			ContractRegisterId: ob.ContractRegisterId,
			CompanyName:        req.CompanyName,
			InvoiceType:        req.RegisterType,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
			TimeBase:           base.TimeBase{},
		}
		pp.Set()
		pp.CurrencyUnit = r.CurrencyUnit
		ppUpdateCols := make([]string, 0)
		if pp.InvoiceType == fms.ContractInvoiceTypePreMake {
			//开票走开票字段
			pp.Remark = r.Remark
			pp.InvoiceDate = registerDate
			pp.OriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.OriginAmount/rate), 64)
			pp.Amount = a

			sellerItem := sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}

			pp.InvoiceId = v.ContractInvoiceId
			pp.SellerId = sellerItem.SellerId
			pp.SellerName = sellerItem.SellerName
			pp.SellerGroupId = sellerItem.GroupId
			pp.SellerGroupName = sellerItem.GroupName
			pp.SellerTeamId = sellerItem.TeamId
			pp.SellerTeamName = sellerItem.TeamName
			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
			ppUpdateCols = append(ppUpdateCols, "InvoiceDate", "Amount", "OriginAmount", "SellerId",
				"SellerName", "SellerGroupId", "SellerGroupName", "SellerTeamId", "SellerTeamName", "InvoiceId",
				"PaymentSellerId", "PaymentSellerName", "PaymentSellerGroupId", "PaymentSellerGroupName", "PaymentSellerTeamId", "PaymentSellerTeamName")
		} else {
			//到款
			pp.ArriveRemark = r.Remark
			pp.ArriveDate = registerDate
			pp.ArriveId = v.ContractInvoiceId
			pp.ArriveOriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.ArriveOriginAmount/rate), 64)
			pp.ArriveAmount = a

			sellerItem := sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}

			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
			ppUpdateCols = append(ppUpdateCols, "CurrencyUnit", "ArriveDate", "ArriveAmount", "ArriveOriginAmount", "ArriveId",
				"PaymentSellerId", "PaymentSellerName", "PaymentSellerGroupId", "PaymentSellerGroupName", "PaymentSellerTeamId", "PaymentSellerTeamName")
		}

		if pp.PreRegisterId == 0 {
			if e = pp.Create(); e != nil {
				resp.FailMsg("操作失败", "新增预登记失败, Err: "+e.Error(), c)
				return
			}
			v.PreRegisterId = pp.PreRegisterId
		} else {
			ppUpdateCols = append(ppUpdateCols,
				"CurrencyUnit", "CompanyName", "Remark", "ArriveRemark", "InvoiceTime", "ArriveTime",
				"ServiceProductId", "CurrencyUnit", "StartDate", "EndDate", "ModifyTime")
			if e = pp.Update(ppUpdateCols); e != nil {
				resp.FailMsg("操作失败", "更新预登记记录失败, Err: "+e.Error(), c)
				return
			}
		}

		invoiceList = append(invoiceList, v)
		ppList = append(ppList, pp)
	}
	invoiceUpdateCols := []string{
		"CurrencyUnit", "OriginAmount", "Amount", "InvoiceDate", "AdminId", "AdminName", "Remark",
		"ServiceProductId", "StartDate", "EndDate", "ModifyTime","SellerId", "SellerName", "SellerGroupId","SellerGroupName","SellerTeamId","SellerTeamName",
	}
	// 更新合同登记、套餐、开票到款
	if e = fms.UpdateContractPreRegister(ob, updateCols, serviceList, invoiceList, invoiceUpdateCols, req.DelInvoiceIds, req.DelPreRegisterIds, ppList); e != nil {
		resp.FailMsg("操作失败", "更新合同及套餐失败, Err: "+e.Error(), c)
		return
	}

	// 开票到款汇总
	go fmsService.SummaryInvoicePaymentByContractRegisterId(ob.ContractRegisterId)

	resp.Ok("操作成功", c)
}

// Del
// @Title 删除到款预登记
// @Description 删除到款预登记
// @Param	request  body  fms.ContractRegisterDelReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /contract/pre_register/del [post]
func (rg *PreRegisterController) Del(c *gin.Context) {
	req := new(fms.PreRegisterDelReq)
	err := c.ShouldBind(&req)
	if err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
			return
		}
		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
		return
	}

	if req.InvoiceId != 0 {
		ob := new(fms.ContractInvoice)
		item, e := ob.Fetch(req.InvoiceId)
		if e != nil {
			if e == utils.ErrNoRow {
				resp.Fail("合同登记不存在或已被删除", c)
				return
			}
			resp.FailMsg("获取合同登记失败", "Err:"+e.Error(), c)
			return
		}
		e = item.Delete()
		if e != nil {
			resp.FailMsg("删除记录失败", "Err:"+e.Error(), c)
			return
		}
	}

	if req.ArriveId != 0 {
		ob := new(fms.ContractInvoice)
		item, e := ob.Fetch(req.ArriveId)
		if e != nil {
			if e == utils.ErrNoRow {
				resp.Fail("合同登记不存在或已被删除", c)
				return
			}
			resp.FailMsg("获取合同登记失败", "Err:"+e.Error(), c)
			return
		}
		e = item.Delete()
		if e != nil {
			resp.FailMsg("删除记录失败", "Err:"+e.Error(), c)
			return
		}
	}

	ob := new(fms.ContractPreRegister)
	item, e := ob.Fetch(req.PreRegisterId)
	if e != nil {
		if e == utils.ErrNoRow {
			resp.Fail("预登记记录不存在或已被删除", c)
			return
		}
		resp.FailMsg("获取预登记失败", "Err:"+e.Error(), c)
		return
	}
	e = item.Delete()
	if e != nil {
		resp.FailMsg("删除预登记记录失败", "Err:"+e.Error(), c)
		return
	}

	e = fms.DeleteInvoicePaymentSummaryByInvoiceIdAndPaymentId(req.InvoiceId, req.ArriveId, req.ContractRegisterId)
	if e != nil {
		resp.FailMsg("删除统计记录失败", "Err:"+e.Error(), c)
		return
	}
	//todo 合同看情况要不要删

	resp.Ok("操作成功", c)
}

// Detail
// @Title 预登记记录详情
// @Description 预登记记录详情
// @Param	request  body  fms.PreRegisterDetailReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /contract/pre_register/detail [post]
func (rg *PreRegisterController) Detail(c *gin.Context) {
	req := new(fms.PreRegisterDetailReq)
	err := c.ShouldBind(&req)
	if err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
			return
		}
		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
		return
	}

	ob := new(fms.ContractRegister)
	item, e := ob.Fetch(req.ContractRegisterId)
	if e != nil {
		if e == utils.ErrNoRow {
			resp.Fail("合同登记不存在或已被删除", c)
			return
		}
		resp.FailMsg("获取合同登记失败", "Err:"+e.Error(), c)
		return
	}

	nItme := fms.ContractRegisterItem{
		ContractRegisterId: item.ContractRegisterId,
		ContractCode:       item.ContractCode,
		RelateContractCode: item.RelateContractCode,
		CrmContractId:      item.CrmContractId,
		ContractSource:     item.ContractSource,
		CompanyName:        item.CompanyName,
		ActualCompanyName:  item.ActualCompanyName,
		ProductIds:         item.ProductIds,
		SellerId:           item.SellerId,
		SellerName:         item.SellerName,
		RaiSellerId:        item.RaiSellerId,
		RaiSellerName:      item.RaiSellerName,
		ContractType:       item.ContractType,
		ContractAmount:     item.ContractAmount,
		InvoicedAmount:     item.InvoicedAmount,
		PaymentAmount:      item.PaymentAmount,
		CurrencyUnit:       item.CurrencyUnit,
		RMBRate:            item.RMBRate,
		StartDate:          item.StartDate.Format(utils.FormatDate),
		EndDate:            item.EndDate.Format(utils.FormatDate),
		SignDate:           item.SignDate.Format(utils.FormatDate),
		AgreedPayTime:      item.AgreedPayTime,
		ContractStatus:     item.ContractStatus,
		RegisterStatus:     item.RegisterStatus,
		Remark:             item.Remark,
		ServiceRemark:      item.ServiceRemark,
		HasPayment:         item.HasPayment,
		NewCompany:         item.NewCompany,
		CreateTime:         item.CreateTime.Format(utils.FormatDateTime),
	}

	if nItme.StartDate == "0001-01-01" {
		nItme.StartDate = ""
	}
	if nItme.EndDate == "0001-01-01" {
		nItme.EndDate = ""
	}

	cond := ``
	pars := make([]interface{}, 0)

	if req.InvoiceId == 0 && req.ArriveId == 0 {
		cond = `contract_register_id = ? AND invoice_type = ? `
		pars = append(pars, req.ContractRegisterId, req.InvoiceType)
	} else {
		cond = `contract_register_id = ? AND invoice_type = ?  AND contract_invoice_id =? `
		pars = append(pars, req.ContractRegisterId, req.InvoiceType)
	}

	if req.InvoiceType == 4 {
		pars = append(pars, req.ArriveId)
	} else {
		pars = append(pars, req.InvoiceId)
	}
	list, e := fms.GetContractInvoiceDetailItemList(cond, pars)
	if e != nil {
		err = fmt.Errorf("获取开票到款列表失败, Err: %s", e.Error())
		return
	}

	dupList, e := fms.GetDuplicateContractInvoiceDetailItemListWithType(nItme.CompanyName, nItme.StartDate, nItme.EndDate, req.InvoiceType)
	if e != nil {
		err = fmt.Errorf("获取开票到款列表失败, Err: %s", e.Error())
		return
	}
	for _, v := range dupList {
		if v.ContractRegisterId != req.ContractRegisterId{
			list = append(list, v)
		}
	}


	//获取ficc小套餐品种
	sysConf := new(system.SysConfig)
	confCond := `config_code = ?`
	confPars := make([]interface{}, 0)
	confPars = append(confPars, system.ConfigKeyCrmPermissionFiccClassify)
	confItem, e := sysConf.FetchByCondition(confCond, confPars)
	if e != nil {
		resp.FailData("获取失败", "Err:"+e.Error(), c)
		return
	}
	if confItem.ConfigValue == "" {
		resp.FailData("获取失败", "FICC品种分类配置为空", c)
		return
	}
	classifyArr := strings.Split(confItem.ConfigValue, ",")
	if len(classifyArr) == 0 {
		resp.FailData("获取失败", "FICC品种分类配置为空", c)
		return
	}
	// 获取FICC权限
	ficcCond := `enabled = 1 AND permission_type = 0 AND product_id = ? AND classify_name IN ?`
	ficcPars := make([]interface{}, 0)
	ficcPars = append(ficcPars, 1, classifyArr)
	items, e := crm.GetPermissionSetItemsByCondition(ficcCond, ficcPars)
	if e != nil {
		resp.FailData("获取失败", "获取FICC权限信息失败, Err: "+e.Error(), c)
		return
	}
	ficcItemMap := make(map[string][]*crm.PermissionSetItem, 0)
	for i := range items {
		if ficcItemMap[items[i].ClassifyName] == nil {
			ficcItemMap[items[i].ClassifyName] = make([]*crm.PermissionSetItem, 0)
		}
		ficcItemMap[items[i].ClassifyName] = append(ficcItemMap[items[i].ClassifyName], items[i])
	}

	sTempIdMap := make(map[string]int, 0)

	for i := range classifyArr {
		if classifyArr[i] == "市场策略" {
			continue
		}
		checkList := make([]int, 0)
		if classifyArr[i] == "宏观经济" {
			checkList = append(checkList, 1)
		}

		pItem := fms.ContractServiceTemplateItem{
			ServiceTemplateId: 90000 + i*100,
		}

		ficcItems := ficcItemMap[classifyArr[i]]
		for _, ficcItem := range ficcItems {
			sTempIdMap[strconv.Itoa(ficcItem.ChartPermissionId)] = pItem.ServiceTemplateId + ficcItem.ChartPermissionId
		}
	}

	services, e := fms.GetContractServiceAndDetailList(req.ContractRegisterId)
	if e != nil {
		err = fmt.Errorf(fmt.Sprint("查找合同服务异常", e))
		return
	}

	serviceTemplateIdSlice := make([]string, 0)
	for _, service := range services {
		if service.Title == "FICC小套餐" {
			serviceTemplateIdSlice = strings.Split(service.ChartPermissionIds, ",")
		}
	}

	serviceTemplateIds := make([]int, 0)
	for _, v := range serviceTemplateIdSlice {
		serviceTemplateIds = append(serviceTemplateIds, sTempIdMap[v])
	}
	respItem := fms.ContractPreRegisterDetail{
		ContractRegisterItem: &nItme,
		List:                 list,
		Services:             services,
		ServiceTemplateIds:   serviceTemplateIds,
	}

	resp.OkData("获取成功", respItem, c)
}

// Save
// @Title 预登记保存
// @Description 预登记保存
// @Param	request  body  fms.PrepayAddReq  true  "type json string"
// @Success 200 string "操作成功"
// @router /contract/pre_register/save [post]
func (rg *PreRegisterController) Save(c *gin.Context) {
	req := new(fms.PreRegisterSaveReq)
	err := c.ShouldBind(&req)
	if err != nil {
		errs, ok := err.(validator.ValidationErrors)
		if !ok {
			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
			return
		}
		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
		return
	}
	claims, _ := c.Get("adminInfo")
	adminInfo := claims.(*system.SysAdmin)

	// 日期校验
	var startDate, endDate time.Time
	if req.StartDate != "" && req.EndDate != "" {
		startDate, err = time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
		if err != nil {
			resp.FailMsg("约定开始日期格式有误", "合同开始日期格式有误, Err: "+err.Error(), c)
			return
		}
		endDate, err = time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
		if err != nil {
			resp.FailMsg("约定结束日期格式有误", "合同结束日期格式有误, Err: "+err.Error(), c)
			return
		}
	}

	// 获取销售分组信息
	sellerList, e := crmService.GetSellerDepartmentListWithGroupAndTeam()
	if e != nil {
		resp.FailData("获取销售失败", "Err:"+e.Error(), c)
		return
	}
	sellerMap := make(map[int]*crm.SellerAdminWithGroupTeam)
	for i := range sellerList {
		sellerMap[sellerList[i].SellerId] = sellerList[i]
	}

	admin := new(crm.Admin)
	sellerIds := strings.Split(req.SellerIds, ",")
	if len(sellerIds) > 2 {
		resp.Fail("最多只能选择两个销售", c)
		return
	}

	var sellers []*crm.Admin
	var pars []interface{}
	cond := ``
	if len(sellerIds) > 0 {
		cond = ` admin_id in (?) `
		pars = append(pars, sellerIds)
		sellers, e = admin.List(cond, pars)
		if e != nil {
			resp.FailMsg("获取销售信息失败", "获取销售信息失败, Err: "+e.Error(), c)
			return
		}
	}
	updateCols := []string{"CompanyName", "ProductIds", "StartDate", "EndDate", "ModifyTime"}

	//更新合同
	ob := new(fms.ContractRegister)
	//ob.ContractCode = req.ContractCode
	ob.ContractRegisterId = req.ContractRegisterId
	ob.CompanyName = req.CompanyName
	ob.ProductIds = req.ProductIds
	ob.StartDate = startDate
	ob.EndDate = endDate
	ob.ModifyTime = time.Now()
	ob.CurrencyUnit = req.List[0].CurrencyUnit
	if req.RegisterType == fms.ContractInvoiceTypePreMake {
		//sellerItem := sellerMap[r.SellerId]
		//if sellerItem == nil {
		//	resp.Fail("销售信息异常", c)
		//	return
		//}
		for _, v := range sellers {
			if v.DepartmentId == crm.SellerDepartmentId {
				ob.SellerId = v.AdminId
				ob.SellerName = v.AdminName
				updateCols = append(updateCols, "SellerId", "SellerName")
			} else if v.DepartmentId == crm.RaiSellerDepartmentId {
				ob.RaiSellerId = v.AdminId
				ob.RaiSellerName = v.AdminName
				updateCols = append(updateCols, "RaiSellerId", "RaiSellerName")
			}
		}
	}

	// 套餐信息
	serviceAmountMap := make(map[int]float64)
	serviceList, e := fmsService.HandleContractServiceAndDetail(req.Services, true, serviceAmountMap)
	if e != nil {
		resp.FailMsg("操作失败", "获取合同套餐详情失败, Err: "+e.Error(), c)
		return
	}
	invoiceUpdateCols := make([]string, 0)
	invoiceHandleType := 0
	invoiceList := make([]*fms.ContractInvoice, 0)
	ppList := make([]*fms.ContractPreRegister, 0)
	for _, r := range req.List {
		// 货币及汇率
		rateList, e := fmsService.GetTodayCurrencyRateList()
		if e != nil {
			resp.FailMsg("操作失败", "获取今日货币汇率失败, Err: "+e.Error(), c)
			return
		}
		var rate float64
		for i := range rateList {
			if r.CurrencyUnit == rateList[i].Code {
				rate = rateList[i].RMBRate
				break
			}
		}
		if rate <= 0 {
			resp.FailMsg("操作失败", "货币汇率信息有误", c)
			return
		}

		registerDate, e := time.Parse(utils.FormatDate, r.RegisterDate)
		if e != nil {
			resp.FailMsg("日期转换失败", "日期转换失败, Err: "+e.Error(), c)
			return
		}

		v := &fms.ContractInvoice{
			ContractInvoiceId:  r.InvoiceId,
			ContractRegisterId: ob.ContractRegisterId,
			OriginAmount:       r.Amount,
			CurrencyUnit:       r.CurrencyUnit,
			InvoiceType:        req.RegisterType,
			InvoiceDate:        registerDate,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			Remark:             r.Remark,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
			TimeBase:           base.TimeBase{},
		}
		v.TimeBase.ModifyTime = time.Now()

		a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", v.OriginAmount/rate), 64)
		v.Amount = a

		sellerItem := sellerMap[r.SellerId]
		if sellerItem == nil {
			resp.Fail("销售信息异常", c)
			return
		}

		v.SellerId = sellerItem.SellerId
		v.SellerName = sellerItem.SellerName
		v.SellerGroupId = sellerItem.GroupId
		v.SellerGroupName = sellerItem.GroupName
		v.SellerTeamId = sellerItem.TeamId
		v.SellerTeamName = sellerItem.TeamName
		invoiceUpdateCols = append(invoiceUpdateCols, "SellerId", "SellerName", "SellerGroupId",
			"SellerGroupName", "SellerTeamId", "SellerTeamName")

		// 新增开票到款记录
		if v.ContractInvoiceId != 0 {
			//更新
			invoiceHandleType = 1
			invoiceUpdateCols = append(invoiceUpdateCols, "OriginAmount", "CurrencyUnit",
				"InvoiceDate", "Remark", "ServiceProductId", "StartDate", "EndDate", "ModifyTime")
		} else {
			//新增
			invoiceHandleType = 2
		}
		invoiceList = append(invoiceList, v)

		//预登记列表
		ppUpdateCols := make([]string, 0)
		pp := &fms.ContractPreRegister{
			PreRegisterId:      r.PreRegisterId,
			ContractRegisterId: ob.ContractRegisterId,
			CompanyName:        req.CompanyName,
			InvoiceType:        req.RegisterType,
			InvoiceDate:        registerDate,
			AdminId:            int(adminInfo.AdminId),
			AdminName:          adminInfo.AdminName,
			ServiceProductId:   r.ServiceProductId,
			IsPrePay:           1,
			StartDate:          startDate,
			EndDate:            endDate,
			TimeBase:           base.TimeBase{},
		}
		pp.Set()
		pp.CurrencyUnit = r.CurrencyUnit
		if pp.InvoiceType == fms.ContractInvoiceTypePreMake {
			//开票走开票字段
			pp.Remark = r.Remark
			pp.InvoiceDate = registerDate
			pp.OriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.OriginAmount/rate), 64)
			pp.Amount = a

			sellerItem := sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}

			pp.SellerId = sellerItem.SellerId
			pp.SellerName = sellerItem.SellerName
			pp.SellerGroupId = sellerItem.GroupId
			pp.SellerGroupName = sellerItem.GroupName
			pp.SellerTeamId = sellerItem.TeamId
			pp.SellerTeamName = sellerItem.TeamName
			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
			ppUpdateCols = append(ppUpdateCols, "InvoiceDate", "Amount", "OriginAmount", "SellerId",
				"SellerName", "SellerGroupId", "SellerGroupName", "SellerTeamId", "SellerTeamName", "Remark",
				"PaymentSellerId", "PaymentSellerName", "PaymentSellerGroupId", "PaymentSellerGroupName", "PaymentSellerTeamId", "PaymentSellerTeamName")
		} else {
			//到款
			pp.ArriveRemark = r.Remark
			pp.ArriveDate = registerDate
			pp.ArriveOriginAmount = r.Amount
			a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", pp.ArriveOriginAmount/rate), 64)
			pp.ArriveAmount = a

			sellerItem := sellerMap[r.SellerId]
			if sellerItem == nil {
				resp.Fail("销售信息异常", c)
				return
			}

			pp.PaymentSellerId = sellerItem.SellerId
			pp.PaymentSellerName = sellerItem.SellerName
			pp.PaymentSellerGroupId = sellerItem.GroupId
			pp.PaymentSellerGroupName = sellerItem.GroupName
			pp.PaymentSellerTeamId = sellerItem.TeamId
			pp.PaymentSellerTeamName = sellerItem.TeamName
			ppUpdateCols = append(ppUpdateCols, "ArriveRemark", "CurrencyUnit", "ArriveDate", "ArriveAmount", "ArriveOriginAmount",
				"PaymentSellerId", "PaymentSellerName", "PaymentSellerGroupId", "PaymentSellerGroupName", "PaymentSellerTeamId", "PaymentSellerTeamName")
		}

		ppUpdateCols = append(ppUpdateCols,
			"CompanyName", "AdminId", "AdminName", "ServiceProductId",
			"CurrencyUnit", "StartDate", "EndDate", "ModifyTime")

		if e = pp.Update(ppUpdateCols); e != nil {
			resp.FailMsg("操作失败", "更新预登记记录失败, Err: "+e.Error(), c)
			return
		}
		ppList = append(ppList, pp)
	}
	if e = fms.UpdateContractRegisterPre(ob, updateCols, serviceList, invoiceList, invoiceUpdateCols, invoiceHandleType, ppList); e != nil {
		resp.FailMsg("操作失败", "新增合同及套餐失败, Err: "+e.Error(), c)
		return
	}
	// 开票到款汇总
	go fmsService.SummaryInvoicePaymentByContractRegisterId(ob.ContractRegisterId)

	resp.Ok("操作成功", c)
}