package order

import (
	"github.com/tiptok/gocomm/xtime"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/application/factory"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/domain"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/infrastructure/utils"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/log"
	"gitlab.fjmaimaimai.com/mmm-go/partner/pkg/protocol"
	"time"
)

// 订单详情
func Detail(header *protocol.RequestHeader, request *protocol.OrderDetailRequest) (rsp *protocol.OrderDetailResponse, err error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
		OrderResponsitory, _  = factory.CreateOrderBaseRepository(transactionContext)
		OrderDao, _           = factory.CreateOrderBaseDao(transactionContext)
		order                 *domain.OrderBase
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	rsp = &protocol.OrderDetailResponse{}

	// 订单详情
	if order, err = OrderResponsitory.FindOne(utils.ObjectJsonToMap(request)); err != nil {
		log.Error(err)
		return
	}
	rsp.Order = protocol.OrderDetail{
		Id:            order.Id,
		OrderNo:       order.OrderCode,
		DeliveryNo:    order.DeliveryCode,
		OrderStatus:   orderStatus(order),
		CreateTime:    order.CreateTime.Unix() * 1000,
		UpdateTime:    order.UpdateTime.Unix() * 1000,
		OrderDistrict: map[string]interface{}{"id": order.RegionInfo.RegionId, "name": order.RegionInfo.RegionName},
		Customer:      protocol.Customer{Uname: order.Buyer.BuyerName, Phone: order.Buyer.ContactInfo},
		Products:      orderProducts(order),
		Total:         orderTotalStatic(order),
	}

	// 更新已读(关联事件)
	if header.UserId == order.PartnerId && order.UpdateTime.After(order.LastViewTime) {
		if err = OrderDao.UpdateLastViewTime(order.Id, time.Now()); err != nil {
			return
		}
	}

	err = transactionContext.CommitTransaction()
	return
}
func orderStatus(order *domain.OrderBase) int {
	var hasBonus = false
	for i := range order.OrderGood {
		good := order.OrderGood[i]
		if good.BonusStatus == domain.BonusPaid {
			hasBonus = true
			break
		}
	}
	if hasBonus {
		if order.UseOrderCount >= 0 && order.UseOrderCount < order.PlanOrderCount {
			return 3 // 已支付退货
		}
		return 2 // 已支付分红
	}
	if !hasBonus {
		if order.UseOrderCount >= 0 && order.UseOrderCount < order.PlanOrderCount {
			return 4 // 待支付退货
		}
		return 1
	}
	return 1
}
func orderProducts(order *domain.OrderBase) interface{} {
	var products []map[string]interface{}
	for i := range order.OrderGood {
		good := order.OrderGood[i]
		static := good.OrderBonusStatic()
		item := make(map[string]interface{})
		item["productName"] = good.GoodName
		item["orderCount"] = good.PlanGoodNumber
		item["orderAmount"] = good.PlanAmount
		item["dividendPercent"] = good.PartnerBonusPercent
		item["dividendReceivable"] = static.OrderTotalReceivable() //应收分红
		item["dividendReceived"] = static.OrderBonusReceive()      //已收分红
		item["dividendUnReceive"] = static.OrderBonusWait()        // 未收分红
		item["dividendExpend"] = static.OrderBonusOutstanding()    //分红支出
		if len(good.Remark) > 0 {
			item["orderUpdateReason"] = good.Remark
		}
		item["dividendStatus"] = good.Status()
		if good.Status() > 2 {
			item["countAdjust"] = good.UseGoodNumber
			item["amountAdjust"] = good.UseAmount
		}
		products = append(products, item)
	}
	return products
}
func orderTotalStatic(order *domain.OrderBase) interface{} {
	item := make(map[string]interface{})
	static := order.OrderBonusStatic()
	item["totalCount"] = order.PlanOrderCount
	item["totalAmount"] = order.PlanOrderAmount
	item["totalDividendReceivable"] = static.OrderTotalReceivable()
	item["totalReceived"] = static.OrderBonusReceive()
	item["totalUnReceive"] = static.OrderBonusWait()
	item["totalExpend"] = static.OrderBonusOutstanding()
	if order.UseOrderCount > 0 {
		item["totalCountAdjust"] = order.UseOrderCount
		item["totalAmountAdjust"] = order.UseOrderAmount
	}
	return item
}

// 订单统计
func Statistics(header *protocol.RequestHeader, request *protocol.OrderStatisticsRequest) (rsp *protocol.OrderStatisticsResponse, err error) {
	var (
		transactionContext, _      = factory.CreateTransactionContext(nil)
		OrderDao, _                = factory.CreateOrderBaseDao(transactionContext)
		BusinessBonusRepository, _ = factory.CreateBusinessBonusRepository(transactionContext)
	)
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	rsp = &protocol.OrderStatisticsResponse{Statistics: protocol.OrderStatics{}}

	// 当天订单/累计订单
	if rsp.Statistics.TodayRealQuantity, rsp.Statistics.TodayRealMoney, err = OrderDao.OrderStatics(&domain.OrderStaticQuery{
		BeginTime: utils.GetDayBegin().Unix() * 1000,
		EndTime:   utils.GetDayEnd().Unix() * 1000,
		OrderType: domain.OrderReal,
		PartnerId: header.UserId,
	}); err != nil {
		return
	}
	if rsp.Statistics.CumulativeQuantity, rsp.Statistics.CumulativeMoney, err = OrderDao.OrderStatics(&domain.OrderStaticQuery{
		EndTime:   time.Now().Unix() * 1000,
		OrderType: domain.OrderReal,
		PartnerId: header.UserId,
	}); err != nil {
		return
	}
	rsp.Statistics.TodayRealMoney = utils.Decimal(rsp.Statistics.TodayRealMoney)
	rsp.Statistics.CumulativeMoney = utils.Decimal(rsp.Statistics.CumulativeMoney)

	//事业分红/业务分红
	var careerBonus, businessBonus, total float64 //,developBonus,appBonus
	if bonus, e := OrderDao.OrderBonusStatics(domain.OrderBonusQuery{PartnerId: header.UserId, OrderType: domain.OrderReal}); e == nil {
		careerBonus = bonus.Bonus
		total += careerBonus
	}
	if bonus, e := BusinessBonusRepository.FindOne(map[string]interface{}{"partner_id": header.UserId, "isDisable": 1}); e == nil {
		businessBonus = bonus.Bonus
		total += businessBonus
		rsp.Statistics.BusinessMoney = bonus.Bonus
	}
	if total != 0 {
		rsp.Statistics.CareerPercent = utils.DecimalToNumber(careerBonus * 100 / total)
		rsp.Statistics.BusinessPercent = utils.DecimalToNumber(businessBonus * 100 / total)
	}

	err = transactionContext.CommitTransaction()
	return
}

// 订单列表
func List(header *protocol.RequestHeader, request *protocol.OrderListRequest) (rsp *protocol.OrderListResponse, err error) {
	var (
		transactionContext, _ = factory.CreateTransactionContext(nil)
		OrderResponsitory, _  = factory.CreateOrderBaseRepository(transactionContext)
		OrderDao, _           = factory.CreateOrderBaseDao(transactionContext)
		orders                []*domain.OrderBase
		total                 int64
	)

	rsp = &protocol.OrderListResponse{
		List: make([]*protocol.OrderListItem, 0),
	}
	if err = transactionContext.StartTransaction(); err != nil {
		return nil, err
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()

	// 查询订单列表
	queryOption := &domain.OrderQueryOption{
		PartnerId:        header.UserId,
		Limit:            request.PageSize,
		Offset:           request.PageSize * request.PageIndex,
		SortByUpdateTime: domain.DESC,
	}
	if request.StartTime > 0 {
		queryOption.BeginTime = time.Unix(request.StartTime/1000, 0)
	}
	if request.EndTime > 0 {
		queryOption.EndTime = time.Unix(request.EndTime/1000, 0)
	}
	queryOption.OrderType = request.OrderType
	total, orders, _ = OrderResponsitory.Find(utils.ObjectJsonToMap(queryOption))
	if len(orders) != 0 {
		for i := range orders {
			rsp.List = append(rsp.List, DomainOrderToOrderListItem(orders[i]))
		}
	}

	// 查询统计数据
	if request.PageIndex == 0 {
		var (
			cumulativeQuantity int
		)
		//累计实发订单
		cumulativeQuantity, _, err = OrderDao.OrderStatics(&domain.OrderStaticQuery{
			EndTime:   time.Now().Unix() * 1000,
			OrderType: domain.OrderReal,
			PartnerId: header.UserId,
		})
		rsp.Total = cumulativeQuantity
	}
	// 今天累计数量特殊处理,不需要返回所有订单总数(因为要复用rsp.Total字段)
	if request.StartTime > 0 && request.EndTime > 0 {
		zero := time.Time(xtime.XTime(time.Now()).DayBefore(0)).Unix()
		if request.StartTime == (zero * 1000) {
			rsp.Total = int(total)
		}
	}

	err = transactionContext.CommitTransaction()
	return
}
func DomainOrderToOrderListItem(order *domain.OrderBase) *protocol.OrderListItem {
	bonusStatic := order.OrderBonusStatic()
	return &protocol.OrderListItem{
		Id:          order.Id,
		OrderType:   order.OrderType,
		OrderNo:     order.OrderCode,
		DeliveryNo:  order.DeliveryCode,
		OrderAmount: order.PlanOrderAmount,
		UpdateTime:  order.UpdateTime.Unix() * 1000,
		MyDividend:  bonusStatic.OrderTotalReceivable(),
		IsRead:      order.IsRead(),
	}
}