package orderman

import (
	"fmt"
	"time"

	"git.rosy.net.cn/jx-callback/business/partner"

	"git.rosy.net.cn/baseapi/platformapi/dadaapi"

	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler"
	"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/globals"
	"github.com/astaxie/beego/client/orm"
)

var (
	waybillOrderStatusMap = map[int]int{
		model.WaybillStatusApplyFailedGetGoods:  model.OrderStatusApplyFailedGetGoods,
		model.WaybillStatusAgreeFailedGetGoods:  model.OrderStatusAgreeFailedGetGoods,
		model.WaybillStatusRefuseFailedGetGoods: model.OrderStatusRefuseFailedGetGoods,
		model.WaybillStatusDeliverFailed:        model.OrderStatusDeliverFailed,
	}
	complaintReasonsMap = map[int]string{
		1:  "骑手态度恶劣",
		2:  "骑手接单后未取货",
		3:  "骑手取货太慢",
		4:  "骑手送货太慢",
		5:  "货品未送达",
		6:  "货品有损坏",
		7:  "骑手违规收取顾客其他费用",
		69: "骑手恶意取消订单",
		71: "骑手提前点击取货/送达",
	}
)

func (w *OrderManager) LoadPendingWaybills() []*model.Waybill {
	db := orm.NewOrm()
	var bills []*model.Waybill
	tillTime := time.Now().Add(-pendingOrderGapMax)
	_, err := db.Raw(`
	SELECT t1.*
	FROM waybill t1
	JOIN goods_order t2 ON t2.vendor_order_id = t1.vendor_order_id
	AND t2.vendor_id = t1.order_vendor_id
	AND t2.order_created_at >= ?
	AND t2.status < ?
	WHERE t1.waybill_created_at >= ?
	AND t1.status < ?
	`, tillTime, model.OrderStatusEndBegin, tillTime, model.WaybillStatusEndBegin).QueryRows(&bills)
	if err != nil {
		return nil
	}
	return bills
}

func (w *OrderManager) OnWaybillNew(bill2 *model.Waybill, db *dao.DaoDB) (isDuplicated bool, err error) {
	isDuplicated, err = addOrderOrWaybillStatus(model.Waybill2Status(bill2), db)
	if err == nil && !isDuplicated {
		bill2.ID = 0
		bill2.WaybillCreatedAt = bill2.StatusTime
		bill2.WaybillFinishedAt = utils.DefaultTimeValue
		billCopied := *bill2
		bill := &billCopied
		created, _, err2 := db.Db.ReadOrCreate(bill, "VendorWaybillID", "WaybillVendorID")
		if err = err2; err == nil {
			if !created {
				bill.DuplicatedCount++
				if bill2.VendorOrderID == bill2.VendorWaybillID { // 购物平台（比如京东）重新建的运单，单号始终是与订单相同的
					bill2.ID = bill.ID
					bill2.CreatedAt = bill.CreatedAt
					bill2.DuplicatedCount = bill.DuplicatedCount
					err = utils.CallFuncLogError(func() error {
						_, err = db.Db.Update(bill2) //更新所有字段
						return err
					}, "onWaybillNew Update1")
				} else {
					isDuplicated = true
					err = utils.CallFuncLogError(func() error {
						_, err = db.Db.Update(bill, "DuplicatedCount")
						return err
					}, "onWaybillNew Update2")
				}
			} else {
				*bill2 = *bill
			}
		} else {
			globals.SugarLogger.Warnf("onWaybillNew create bill:%v, error:%v", bill2, err)
		}
	}
	return isDuplicated, err
}

func (w *OrderManager) OnWaybillStatusChanged(bill *model.Waybill) (err error) {
	var isDuplicated bool
	if bill.ActualFee == 0 {
		bill.ActualFee = bill.DesiredFee + bill.TipFee
	}
	bill.CourierMobile = jxutils.FormalizeMobile(bill.CourierMobile)
	db := dao.GetDB()
	txDB, _ := dao.Begin(db)
	defer func() {
		if r := recover(); r != nil {
			dao.Rollback(db, txDB)
			panic(r)
		}
	}()
	duplicatedCount := 0
	if bill.Status == model.WaybillStatusNew {
		isDuplicated, err = w.OnWaybillNew(bill, db)
		if isDuplicated {
			duplicatedCount = 1
		}
	} else {
		existingBill, err2 := w.LoadWaybill(bill.VendorWaybillID, bill.WaybillVendorID)
		// todo
		if err2 == nil {
			bill.DeliveryFlag = existingBill.DeliveryFlag
		}
		if bill.Status == model.WaybillStatusAccepted { // 处理美团配送丢失新运单消息的情况
			if err2 != nil {
				if dao.IsNoRowsError(err2) || err2 == ErrCanNotFindWaybill {
					existingBill = bill
					billCopy := *bill
					billCopy.Status = model.WaybillStatusNew
					if isDuplicated, err = w.OnWaybillNew(&billCopy, db); err != nil {
						dao.Rollback(db, txDB)
						return err
					}
					dao.Commit(db, txDB)
					// 进运单调度器OnWaybillStatusChanged之前要确保事务是提交了的，否则会导致死锁
					// 加载数据到当前系统调度器当中
					scheduler.CurrentScheduler.OnWaybillStatusChanged(&billCopy, false)
					dao.Begin(db)
				} else {
					dao.Rollback(db, txDB)
					return err2
				}
			}
			// 运单消息错序，之前已经结束了，直接返回
			if existingBill.Status >= model.WaybillStatusEndBegin {
				dao.Commit(db, txDB)
				return nil
			}
		}
		addParams := orm.Params{}
		if bill.Status >= model.WaybillStatusAccepted {
			//if bill.Status == model.WaybillStatusAccepted {等于10的时候没有运费
			if bill.DesiredFee > 0 {
				addParams["desired_fee"] = bill.DesiredFee
			}
			if bill.ActualFee > 0 {
				addParams["actual_fee"] = bill.ActualFee
			}
			//}
			//单独增加顺丰派送取消运单修改配送费逻辑
			if (bill.WaybillVendorID == model.VendorIDSFPS || bill.WaybillVendorID == model.VendorIDMTWM) && bill.Status == model.WaybillStatusCanceled {
				addParams["desired_fee"] = bill.DesiredFee
				addParams["actual_fee"] = bill.ActualFee
			}
			if bill.CourierMobile != "" {
				addParams["courier_name"] = bill.CourierName
				addParams["courier_mobile"] = bill.CourierMobile
			}
			if bill.Status >= model.WaybillStatusEndBegin {
				addParams["waybill_finished_at"] = bill.StatusTime
			}
		}
		duplicatedCount, err = w.addWaybillStatus(bill, db, addParams)
		if err != nil {
			dao.Rollback(db, txDB)
			return err
		}
	}
	if err == nil {
		dao.Commit(db, txDB)
		if duplicatedCount == 0 {
			scheduler.CurrentScheduler.OnWaybillStatusChanged(bill, false)
		}
	} else {
		dao.Rollback(db, txDB)
	}
	if bill.VendorOrderID == bill.VendorWaybillID {
		if status, ok := waybillOrderStatusMap[bill.Status]; ok {
			fakeOrderStatus := &model.OrderStatus{
				VendorOrderID:    bill.VendorOrderID,
				VendorID:         bill.OrderVendorID,
				OrderType:        model.OrderTypeOrder,
				RefVendorOrderID: bill.VendorOrderID,
				RefVendorID:      bill.OrderVendorID,
				Status:           status,
				VendorStatus:     bill.VendorStatus,
				StatusTime:       bill.StatusTime,
				Remark:           bill.Remark + ",订单运费:" + fmt.Sprintf("%d", bill.DesiredFee),
			}
			w.OnOrderStatusChanged(bill.VendorOrgCode, fakeOrderStatus)
		}
	}
	return err
}

func (w *OrderManager) addWaybillStatus(bill *model.Waybill, db *dao.DaoDB, addParams orm.Params) (duplicatedCount int, err error) {
	waybillStatus := model.Waybill2Status(bill)
	isDuplicated, err := addOrderOrWaybillStatus(waybillStatus, db)
	if err == nil && !isDuplicated {
		if waybillStatus.Status > model.WaybillStatusUnknown { // todo 这里应该和addOrderStatus一样的改法，状态不能回绕
			params := utils.MergeMaps(orm.Params{
				"status":        bill.Status,
				"vendor_status": bill.VendorStatus,
				"status_time":   bill.StatusTime,
			}, addParams)
			utils.CallFuncLogError(func() error {
				_, err = db.Db.QueryTable("waybill").Filter("vendor_waybill_id", bill.VendorWaybillID).Filter("waybill_vendor_id", bill.WaybillVendorID).Filter("status__lte", bill.Status).Update(params)
				return err
			}, "addWaybillStatus update waybill status, bill:%v", bill)
		} else {
			duplicatedCount = -1
		}
	} else {
		duplicatedCount = 1
	}
	return duplicatedCount, err
}

func (c *OrderManager) LoadWaybill(vendorWaybillID string, waybillVendorID int) (bill *model.Waybill, err error) {
	db := orm.NewOrm()
	bill = &model.Waybill{
		VendorWaybillID: vendorWaybillID,
		WaybillVendorID: waybillVendorID,
	}
	if err = db.Read(bill, "VendorWaybillID", "WaybillVendorID"); err != nil {
		bill = nil
		if err == orm.ErrNoRows {
			err = ErrCanNotFindWaybill
		}
	}
	return bill, err
}

func GetComplaintReasons() (complaintReasonList []*dadaapi.ComplaintReason) {
	for k, v := range complaintReasonsMap {
		complaintReason := &dadaapi.ComplaintReason{
			ID:     k,
			Reason: v,
		}
		complaintReasonList = append(complaintReasonList, complaintReason)
	}
	return complaintReasonList
}

func ComplaintRider(ctx *jxcontext.Context, vendorOrderID string, waybillVendorID string, complaintID int, waybillID string) (err error) {
	wayBillList, err := dao.GetComplaintList(dao.GetDB(), vendorOrderID, waybillID)
	if err != nil {
		return err
	}
	if len(wayBillList) != model.YES {
		return fmt.Errorf("订单所属运单不存在,或运单为分配骑手,无法投诉")
	}

	if err == nil && len(wayBillList) > 0 {
		switch wayBillList[0].WaybillVendorID {
		case model.VendorIDFengNiao, model.VendorIDDada, model.VendorIDMTPS, model.VendorIDUUPT, model.VendorIDSFPS:
			tripartiteDelivery := partner.GetDeliveryPlatformFromVendorID(wayBillList[0].WaybillVendorID)
			if tripartiteDelivery != nil {
				err = tripartiteDelivery.Handler.ComplaintRider(wayBillList[0], complaintID, complaintReasonsMap[complaintID])
			} else {
				err = fmt.Errorf("投诉三方配送获取运单失败")
			}
		case model.VendorIDMTWM, model.VendorIDDD, model.VendorIDJD, model.VendorIDEBAI, model.VendorIDTaoVegetable:
			platformDelivery := partner.GetPurchaseOrderHandlerFromVendorID(wayBillList[0].WaybillVendorID)
			if platformDelivery != nil {
				err = platformDelivery.ComplaintRider(wayBillList[0].VendorOrderID, complaintID, complaintReasonsMap[complaintID])
			} else {
				err = fmt.Errorf("投诉平台配送获取运单失败")
			}
		}
	}

	return err
}

// GetComplaintList 获取投诉列表
func GetComplaintList(orderId string) ([]*model.Waybill, error) {
	return dao.GetComplaintList(dao.GetDB(), orderId, "")
}
