package uupt

import (
	"fmt"
	"strings"
	"time"

	tao "git.rosy.net.cn/baseapi/platformapi/tao_vegetable"
	"git.rosy.net.cn/jx-callback/business/partner/purchase/tao_vegetable"

	"git.rosy.net.cn/baseapi/platformapi/uuptapi"
	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/business/jxutils"
	"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
	"git.rosy.net.cn/jx-callback/business/model"
	"git.rosy.net.cn/jx-callback/business/model/dao"
	"git.rosy.net.cn/jx-callback/business/partner"
	"git.rosy.net.cn/jx-callback/business/partner/delivery"
	"git.rosy.net.cn/jx-callback/globals"
	"git.rosy.net.cn/jx-callback/globals/api"
)

const (
	//errCode 错误码说明
	ErrorParameter1                 = -101   //参数格式校验错误
	ErrorParameter2                 = -199   //参数格式校验错误
	ErrorTimestamp                  = -102   //timestamp错误
	ErrorAppID                      = -103   //appid无效
	ErrorSignatureCheck             = -104   //签名校验失败
	ErrorOpenIDInvalid              = -105   //openid无效
	ErrorUnableParseOrigin          = -1001  //无法解析起始地
	ErrorUnableParseDestination     = -1002  //无法解析目的地
	ErrorCantGetCityInformation     = -1003  //无法获取订单城市相关信息
	ErrorOrderCategory              = -1004  //订单小类出现错误
	ErrorNoUserInformation          = -1005  //没有用户信息
	ErrorCouponID                   = -1006  //优惠券ID错误
	ErrorPriceToken1                = -2001  //price_token无效
	ErrorPriceToken2                = -2002  //price_token无效
	ErrorPushType                   = -2003  //push_type错误
	ErrorSpecialType                = -2004  //special_type错误
	ErrorCallMeWithTake             = -2005  //callMe_withTake错误
	ErrorOrderPrice                 = -2006  //order_price错误
	ErrorBalancePayMoney            = -2007  //balance_payMoney错误
	ErrorOrderTotalMoney            = -2008  //订单总金额错误
	ErrorPayMoney                   = -2009  //支付金额错误
	ErrorUserNotMatch               = -2010  //用户不一致
	ErrorWrongPhone                 = -2011  //手机号错误
	ErrorNotExistBind               = -2012  //不存在绑定关系
	ErrorCancelReasonCantEmpty      = -4001  //取消原因不能为空
	ErrorOrderNumber1               = -4002  //订单编号无效
	ErrorOrderNumber2               = -5001  //订单编号无效
	ErrorOrderNumber3               = -5002  //订单编号无效
	ErrorOrderNumber4               = -5003  //订单编号无效
	ErrorFrequencyTooFast           = -10001 //发送频率过快，请稍候重试
	ErrorNeedCommitVerificationCode = -106   //接口返回base64图片需要提交对应图片验证码
)

var ErrCode = map[int]string{
	ErrorParameter1:                 "参数格式校验错误",
	ErrorParameter2:                 "参数格式校验错误",
	ErrorTimestamp:                  "timestamp错误",
	ErrorAppID:                      "appid无效",
	ErrorSignatureCheck:             "签名校验失败",
	ErrorOpenIDInvalid:              "openid无效",
	ErrorUnableParseOrigin:          "无法解析起始地",
	ErrorUnableParseDestination:     "无法解析目的地",
	ErrorCantGetCityInformation:     "无法获取订单城市相关信息",
	ErrorOrderCategory:              "订单小类出现错误",
	ErrorNoUserInformation:          "没有用户信息",
	ErrorCouponID:                   "优惠券ID错误",
	ErrorPriceToken1:                "price_token无效",
	ErrorPriceToken2:                "price_token无效",
	ErrorPushType:                   "push_type错误",
	ErrorSpecialType:                "special_type错误",
	ErrorCallMeWithTake:             "callMe_withTake错误",
	ErrorOrderPrice:                 "order_price错误",
	ErrorBalancePayMoney:            "balance_payMoney错误",
	ErrorOrderTotalMoney:            "订单总金额错误",
	ErrorPayMoney:                   "支付金额错误",
	ErrorUserNotMatch:               "用户不一致",
	ErrorWrongPhone:                 "手机号错误",
	ErrorNotExistBind:               "不存在绑定关系",
	ErrorCancelReasonCantEmpty:      "取消原因不能为空",
	ErrorOrderNumber1:               "订单编号无效",
	ErrorOrderNumber2:               "订单编号无效",
	ErrorOrderNumber3:               "订单编号无效",
	ErrorOrderNumber4:               "订单编号无效",
	ErrorFrequencyTooFast:           "发送频率过快，请稍候重试",
	ErrorNeedCommitVerificationCode: "接口返回base64图片需要提交对应图片验证码",
}
var (
	curDeliveryHandler *DeliveryHandler
)

type DeliveryHandler struct {
}

func init() {
	if api.UuAPI != nil {
		curDeliveryHandler = new(DeliveryHandler)
		partner.RegisterDeliveryPlatform(curDeliveryHandler, true)
	}
}

func (d DeliveryHandler) GetVendorID() int {
	return model.VendorIDUUPT
}

func (d DeliveryHandler) CreateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (vendorStoreID string, status int, err error) {
	return "", 0, fmt.Errorf("uu跑腿暂不支持此操作")
}

func (d DeliveryHandler) GetStore(ctx *jxcontext.Context, storeID int, vendorStoreID string) (storeDetail *dao.StoreDetail2, err error) {
	//uu跑腿无门店概念
	store, err := dao.GetStoreDetail(dao.GetDB(), utils.Str2Int(vendorStoreID), model.VendorIDUUPT, "")
	if err == nil {
		storeDetail = &dao.StoreDetail2{
			Store: model.Store{
				Name:    store.Name,
				Tel1:    store.Tel1,
				Address: store.Address,
				Lat:     store.Lat,
				Lng:     store.Lng,
			},
			VendorID:      model.VendorIDUUPT,
			VendorStoreID: utils.Int2Str(storeID),
			CourierStatus: model.StoreStatusOpened,
		}
	}
	return storeDetail, err
}

func (d DeliveryHandler) IsErrStoreNotExist(err error) bool {
	return false
}

func (d DeliveryHandler) IsErrStoreExist(err error) bool {
	return false
}

func (d DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) {
	if maxDeliveryFee == model.NO {
		if order.EarningType != model.EarningTypePoints {
			fee, err := d.GetWaybillFee(order)
			if err != nil {
				return nil, err
			}
			if fee.DeliveryFee >= model.DefMaxDeliveryFee {
				return nil, fmt.Errorf("顺丰超最高限价, 所需运费:%s, 最高限价:%s", jxutils.IntPrice2StandardCurrencyString(fee.DeliveryFee), jxutils.IntPrice2StandardCurrencyString(model.DefMaxDeliveryFee))
			}
		}
	}
	//获取门店老板详情
	storeOwner, err := dao.GetStoreDetail(dao.GetDB(), getReallyStoreID(order.StoreID, order.JxStoreID), 0, "")
	if err != nil {
		return nil, err
	}
	//获取金额令牌，实际需要支付金额
	price, err := getOrderPrice(order)
	if err != nil {
		return nil, err
	}
	param := map[string]interface{}{
		"price_token":      price.PriceToken,
		"order_price":      price.TotalMoney,
		"balance_paymoney": price.NeedPayMoney,
		"receiver":         order.ConsigneeName,
		"receiver_phone":   order.ConsigneeMobile,
		"note":             fmt.Sprintf("%s#%s号单，", model.VendorChineseNames[order.VendorID], utils.Int2Str(order.OrderSeq)) + utils.FilterMb4("客户电话："+order.ConsigneeMobile+"，配送遇到问题，可联系18048531223取消配送单，禁止未配送直接完成订单"),
		"callback_url":     uuptapi.WaybillCallbackURL,
		"push_type":        uuptapi.PushTypeOpen,
		"pubusermobile":    storeOwner.Tel1, //老板电话
		"special_type":     uuptapi.SpecialTypeNo,
		"callme_withtake":  uuptapi.CallMeWithTakeYes,
	}
	if orderCode, originID, err := api.UuAPI.AddOrder(param); err != nil {
		return nil, err
	} else {
		bill = &model.Waybill{
			VendorOrderID:    order.VendorOrderID,
			OrderVendorID:    order.VendorID,
			VendorWaybillID:  orderCode,
			VendorWaybillID2: originID,
			WaybillVendorID:  model.VendorIDUUPT,
			DesiredFee:       jxutils.StandardPrice2Int(utils.Str2Float64(price.TotalMoney)),
		}
	}
	delivery.OnWaybillCreated(bill)
	return bill, err
}

func (d DeliveryHandler) CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error) {
	if err = api.UuAPI.CancelOrder(bill.VendorWaybillID, uuptapi.CancelReasonNormal); err != nil {
		return err
	}
	bill.Status = model.WaybillStatusCanceled
	bill.Remark = cancelReason
	partner.CurOrderManager.OnWaybillStatusChanged(bill)
	return nil
}

func (d DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *partner.WaybillFeeInfo, err error) {
	if orderPrice, err := getOrderPrice(order); err != nil {
		return nil, err
	} else {
		deliveryFeeInfo = &partner.WaybillFeeInfo{}
		deliveryFeeInfo.RefAddFee = jxutils.StandardPrice2Int(utils.Str2Float64(orderPrice.NeedPayMoney)) // 优惠后金额
		deliveryFeeInfo.DeliveryFee = jxutils.StandardPrice2Int(utils.Str2Float64(orderPrice.TotalMoney)) // 原始金额
	}
	return deliveryFeeInfo, err
}

func (c *DeliveryHandler) GetWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (tipFee int64, err error) {
	// uu跑腿没有获取小费的接口,直接返回系统支付的金额
	//order, err := api.UuAPI.GetOrderDetail(vendorOrderID)
	//if err == nil {
	//	tipFee = jxutils.StandardPrice2Int(order.Tips)
	//}
	//return tipFee, err
	return 0, nil
}

func (c *DeliveryHandler) UpdateWaybillTip(ctx *jxcontext.Context, vendorOrgCode, vendorStoreID, vendorOrderID, vendorWaybillID, vendorWaybillID2, cityCode string, tipFee int64) (err error) {
	return api.UuAPI.AddTip(vendorOrderID, vendorWaybillID, int(tipFee))
}

func (d DeliveryHandler) ComplaintRider(bill *model.Waybill, resonID int, resonContent string) (err error) {
	return fmt.Errorf("UU跑腿暂不支持此操作")
}

func (d DeliveryHandler) GetRiderInfo(orderId string, deliveryId int64, uuWaybillID string) (rider *utils.RiderInfo, err error) {
	waybill, err := api.UuAPI.GetOrderDetail(uuWaybillID)
	if err != nil {
		return nil, err
	}
	param := &utils.RiderInfo{
		OrderId:             orderId,
		ThirdCarrierOrderId: waybill.OrderCode,
		CourierName:         waybill.DriverName,
		CourierPhone:        waybill.DriverMobile,
		//LogisticsProviderCode: utils.UUPTCode,
		LogisticsProviderCode: "10005",
		LogisticsStatus:       utils.Str2Int(waybill.State),
	}
	if len(waybill.DriverLastloc) == 0 {
		if waybill.State == uuptapi.StateOrderCancel {
			param.Longitude = waybill.FromLng
			param.Latitude = waybill.FromLat
		} else if waybill.State == uuptapi.StateReceiverGetGoods {
			param.Longitude = waybill.ToLng
			param.Latitude = waybill.ToLat
		}
	} else {
		temp := strings.Split(waybill.DriverLastloc, ",") //格式:113.71776,34.767501
		param.Longitude = temp[0]
		param.Latitude = temp[1]
	}
	switch waybill.State {
	case uuptapi.StateConfirmSuccess:
		param.LogisticsStatus = model.WaybillStatusNew
		param.LogisticsContext = model.RiderWaitRider
	case uuptapi.StateRMGrabsOrder:
		param.LogisticsStatus = model.WaybillStatusCourierAssigned
		param.LogisticsContext = model.RiderGetOrder
	case uuptapi.StateArrivedStore:
		param.LogisticsStatus = model.WaybillStatusCourierArrived
		param.LogisticsContext = model.RiderToStore
	case uuptapi.StatePickUp, uuptapi.StateArrivedDestination:
		param.LogisticsStatus = model.WaybillStatusDelivering
		param.LogisticsContext = model.RiderGetOrderDelivering
	case uuptapi.StateReceiverGetGoods:
		param.LogisticsStatus = model.WaybillStatusDelivered
		param.LogisticsContext = model.RiderGetOrderDelivered
	case uuptapi.StateOrderCancel:
		param.LogisticsStatus = model.WaybillStatusCanceled
		param.LogisticsContext = model.RiderGetOrderCanceled
	}
	return param, nil
}

func (c *DeliveryHandler) GetDeliverLiquidatedDamages(orderId string, deliverId string) (money int64, err error) {
	return api.UuAPI.GetOrderLiquidatedDamages(deliverId, orderId)
}

func (c *DeliveryHandler) GetRidderPosition(ctx *jxcontext.Context, vendorOrgCode, vendorOrderID, vendorWaybillID, vendorWaybillID2 string) (lng, lat float64, err error) {
	if rider, err := api.UuAPI.GetOrderDetail(vendorWaybillID); err == nil && len(rider.DriverLastloc) > 0 {
		te := strings.Split(rider.DriverLastloc, ",")
		if len(te) > 0 {
			lng = utils.Str2Float64(te[0])
			lat = utils.Str2Float64(te[1])
		}
		return lng, lat, nil
	}
	return 0, 0, err
}

//辅助函数
func getOrderPrice(order *model.GoodsOrder) (orderPrice *uuptapi.GetOrderPriceResp, err error) {
	var (
		fromLat float64
		fromLng float64
		toLat   float64
		toLng   float64
	)
	store, err := dao.GetStoreDetail(dao.GetDB(), getReallyStoreID(order.StoreID, order.JxStoreID), 0, "")
	if err != nil {
		return nil, err
	}
	//转换百度坐标系
	//var coords []*baidunavi.Coordinate
	//coords = append(coords, &baidunavi.Coordinate{
	//	Lng: jxutils.IntCoordinate2Standard(store.Lng),
	//	Lat: jxutils.IntCoordinate2Standard(store.Lat),
	//}, &baidunavi.Coordinate{
	//	Lat: jxutils.IntCoordinate2Standard(order.ConsigneeLat),
	//	Lng: jxutils.IntCoordinate2Standard(order.ConsigneeLng),
	//})
	//coords, err = api.BaiDuNaviAPI.BatchCoordinateConvert(coords, baidunavi.CoordSysGCJ02, baidunavi.CoordSysBaiDu)
	//if err != nil || len(coords) == 0 {
	//	return nil, nil
	//} else {
	//	fromLat = coords[0].Lat
	//	fromLng = coords[0].Lng
	//	toLat = coords[1].Lat
	//	toLng = coords[1].Lng
	//}
	fromLng, fromLat = jxutils.GaodeCoord2BaiDu(jxutils.IntCoordinate2Standard(store.Lng), jxutils.IntCoordinate2Standard(store.Lat))
	toLng, toLat = jxutils.GaodeCoord2BaiDu(jxutils.IntCoordinate2Standard(order.ConsigneeLng), jxutils.IntCoordinate2Standard(order.ConsigneeLat))

	weight := 4
	tempWeight := 0
	if order.Weight/1000 >= weight {
		tempWeight = weight
	} else if order.Weight/1000 < 1 {
		tempWeight = 1
	} else {
		tempWeight = int(order.Weight / 1000)
	}

	//地址特殊判断
	cityName := store.CityName
	districtName := store.DistrictName
	address := ""
	if !strings.Contains(store.Address, cityName) { //城市
		address += cityName
	}
	if !strings.Contains(store.Address, districtName) { //行政区
		address += districtName
	}
	address += store.Address

	param := map[string]interface{}{
		"origin_id":     order.VendorOrderID,
		"from_address":  address,
		"from_usernote": "京西菜市(" + store.Store.Name + ")",
		"to_address":    order.ConsigneeAddress,
		"city_name":     store.CityName,
		"send_type":     uuptapi.SendTypeHelpMeDeliver,
		"from_lat":      fromLat,
		"from_lng":      fromLng,
		"to_lat":        toLat,
		"to_lng":        toLng,
		"goods_weight":  tempWeight,
	}

	if orderPrice, err = api.UuAPI.GetOrderPrice(param); err != nil {
		return nil, err
	} else {
		return orderPrice, nil
	}
}

func OnWaybillMsg(req *uuptapi.WaybillCallbackParam, good *model.GoodsOrder) (resp *uuptapi.CallbackResponse) {
	param := &model.Waybill{
		VendorOrderID:   req.OriginID,
		VendorWaybillID: req.OrderCode,
		WaybillVendorID: model.VendorIDUUPT,
		CourierName:     req.DriverName,
		CourierMobile:   req.DriverMobile,
		VendorStatus:    req.State,
		StatusTime:      time.Now(),
		Remark:          req.StateText,
	}
	var reallyPrice int64
	param.OrderVendorID = good.VendorID
	//查询运单价格
	uuPrice, err := api.UuAPI.GetOrderDetail(req.OrderCode)
	if err != nil {
		reallyPrice = 0
	} else {
		reallyPrice = int64(utils.Str2Float64(uuPrice.OrderPrice) * 100)
	}

	store, _ := dao.GetStoreDetail(dao.GetDB(), good.JxStoreID, good.VendorID, good.VendorOrgCode)
	reallyPrice += int64(store.FreightMarkup)

	actualFee := int64((utils.Str2Float64(uuPrice.OrderPrice)-utils.Str2Float64(uuPrice.PriceOff))*100) - int64(utils.WayBillDeliveryMarkUp)
	switch req.State {
	case uuptapi.StateConfirmSuccess:
		param.Status = model.WaybillStatusNew //5 待调度
		param.DesiredFee = reallyPrice
		param.ActualFee = actualFee
	case uuptapi.StateRMGrabsOrder:
		param.Status = model.WaybillStatusCourierAssigned
		param.Remark = req.DriverName + "," + req.DriverMobile
		param.DesiredFee = reallyPrice
		param.ActualFee = actualFee
	case uuptapi.StateArrivedStore:
		param.Status = model.WaybillStatusCourierArrived
		param.DesiredFee = reallyPrice
		param.ActualFee = actualFee
	case uuptapi.StatePickUp:
		param.Status = model.WaybillStatusUuPickUp
		param.DesiredFee = reallyPrice
		param.ActualFee = actualFee
	case uuptapi.StateArrivedDestination:
		param.Status = model.WaybillStatusUuArrivedDestination
		param.DesiredFee = reallyPrice
		param.ActualFee = actualFee
	case uuptapi.StateReceiverGetGoods:
		param.Status = model.WaybillStatusDelivered
		param.DesiredFee = reallyPrice
		param.ActualFee = actualFee
	case uuptapi.StateOrderCancel:
		param.Status = model.WaybillStatusCanceled
	default:
		globals.SugarLogger.Warnf("onWaybillMsg unknown State:%v", req.State)
	}
	if err := partner.CurOrderManager.OnWaybillStatusChanged(param); err != nil {
		return uuptapi.Err2CallbackResponse(err)
	}
	//推送抖音
	switch param.OrderVendorID {
	case model.VendorIDDD:
		Lng, Lat, _ := partner.GetRidderPositionGetter(param.WaybillVendorID).GetRidderPosition(nil, param.VendorOrderID, param.VendorOrderID, param.VendorWaybillID, param.VendorWaybillID2)
		tiktokStatusPush(param, req.State, utils.Float64ToStr(Lng), utils.Float64ToStr(Lat), good.VendorOrgCode)
	case model.VendorIDMTWM, model.VendorIDTaoVegetable, model.VendorIDEBAI, model.VendorIDJD:
		delivery.GetOrderRiderInfoToPlatform(param.VendorOrderID, param.Status) // 骑手位置更新
		if good.VendorID == model.VendorIDTaoVegetable && req.State == uuptapi.StateRMGrabsOrder {
			tao_vegetable.PushDelivererChangeInfo(good, param, tao.TaoDeliveryTypeOther)
		}
	}
	return uuptapi.Err2CallbackResponse(nil)
}

func tiktokStatusPush(param *model.Waybill, orderStatus string, lng, lat, vendorOrgCode string) {
	result := &utils.RiderInfo{
		OrderId:               param.VendorOrderID,
		ThirdCarrierOrderId:   param.VendorWaybillID,
		CourierName:           param.CourierName,
		CourierPhone:          param.CourierMobile,
		LogisticsProviderCode: utils.UUPTCode,
		LogisticsStatus:       param.Status,
		OpCode:                "",
		Longitude:             lng,
		Latitude:              lat,
	}
	switch orderStatus {
	case uuptapi.StateConfirmSuccess: //下单成功
		result.LogisticsStatus = model.WaybillStatusNew
		result.LogisticsContext = model.RiderWaitRider
	case uuptapi.StateRMGrabsOrder: //骑手已接单
		result.LogisticsStatus = model.WaybillStatusCourierAssigned // 分配骑手
		result.LogisticsContext = model.RiderWaitGetGoods
	case uuptapi.StateArrivedStore: //骑手到店
		result.LogisticsStatus = model.WaybillStatusCourierArrived
		result.LogisticsContext = model.RiderToStore
	case uuptapi.StatePickUp: //已取件
		result.LogisticsStatus = model.WaybillStatusUuPickUp
		result.LogisticsContext = model.RiderPickUp
	case uuptapi.StateArrivedDestination: //到达取件人地址处
		result.LogisticsStatus = model.WaybillStatusUuArrivedDestination
		result.LogisticsContext = model.RiderArrivedDestination
	case uuptapi.StateReceiverGetGoods: //取件人收货
		result.LogisticsStatus = model.WaybillStatusDelivered
		result.LogisticsContext = model.RiderGetOrderDelivered
	case uuptapi.StateOrderCancel: //运单取消
		result.LogisticsStatus = model.WaybillStatusCanceled
		result.LogisticsContext = model.RiderGetOrderCanceled
	default:
		result.LogisticsStatus = 0
		result.LogisticsContext = model.RiderGetOrderDeliverOther
	}
	delivery.PullTiktokRiderInfo(result, vendorOrgCode)
}

//辅助函数
func getReallyStoreID(storeID, jxStoreID int) int {
	if storeID == 0 && jxStoreID == 0 {
		return 0
	}
	if storeID == 0 {
		return jxStoreID
	} else {
		return storeID
	}
}

func (c *DeliveryHandler) UpdateStoreName(storeId, name string) (err error) {
	return err
}

func (c *DeliveryHandler) GetPlatformBalance() (balance int64, err error) {
	return 0, fmt.Errorf("暂不支持此功能")
}
func (c *DeliveryHandler) BalanceRecharge(param *utils.RechargeBalance) (url string, err error) {
	return "", fmt.Errorf("此平台暂不支持充值")
}
