package tiktok_api

import (
	"encoding/json"
	"errors"
	instantShopping_notifyDeliveryStatus_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/instantShopping_notifyDeliveryStatus/request"
	instantShopping_reportRiderLocation_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/instantShopping_reportRiderLocation/request"
	logistics_indTrackPush_reqeust "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/logistics_indTrackPush/request"
	order_logisticsEdit_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/order_logisticsEdit/request"
	token_create_request "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/token_create/request"
	token_create_response "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/api/token_create/response"
	doudian_sdk "git.rosy.net.cn/baseapi/platformapi/tiktok_shop/sdk-golang/core"
	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/globals"
	"sync"
	"time"
)

type APIExpress struct {
	appKey         string
	appSecret      string
	accessToken    string
	refreshToken   string
	expiresIn      int64 // 当前时间的七天内为有效期
	locker         sync.RWMutex
	accessTokenObj *doudian_sdk.AccessToken // 存储数据库
}

func NewExpress(appKey, appSecret, accessToken string) *APIExpress {
	var access *doudian_sdk.AccessToken
	doudian_sdk.GlobalConfig.AppKey = appKey
	doudian_sdk.GlobalConfig.AppSecret = appSecret
	if accessToken != "" {
		if err := json.Unmarshal([]byte(accessToken), &access); err != nil {
			globals.SugarLogger.Debug("accessToken init err :", err)
			return nil
		}

		api := &APIExpress{
			appKey:         appKey,
			appSecret:      appSecret,
			accessToken:    access.AccessToken,
			refreshToken:   access.RefreshToken,
			expiresIn:      access.ExpiresIn,
			accessTokenObj: access,
		}
		if access.ExpiresIn < time.Now().Unix() {
			api.RefreshToken()
		}
		return api
	}
	return &APIExpress{
		appKey:         appKey,
		appSecret:      appSecret,
		accessTokenObj: new(doudian_sdk.AccessToken),
	}
}

// CreateToken 创建token只有第一次授权或者更新授权才需要,其他时候直接刷新就可以啦
func (a *APIExpress) CreateToken() (*token_create_response.TokenCreateData, error) {
	request := token_create_request.New()
	param := request.GetParams()
	param.Code = ""
	param.GrantType = "authorization_self"
	param.AuthId = TiktokExpressCode
	param.AuthSubjectType = "WuLiuShang"
	response, err := request.Execute(nil)
	if err != nil {
		return nil, err
	}
	if response.Code != RequestSuccessCode {
		return nil, errors.New(response.SubMsg + ":" + response.LogId)
	}

	a.accessToken = response.Data.AccessToken
	a.expiresIn = time.Now().Unix() + response.Data.ExpiresIn
	a.refreshToken = response.Data.RefreshToken

	a.accessTokenObj.CreateTokenData = doudian_sdk.CreateTokenData{
		AccessToken:  response.Data.AccessToken,
		ExpiresIn:    response.Data.ExpiresIn,
		Scope:        response.Data.Scope,
		ShopId:       response.Data.ShopId,
		ShopName:     response.Data.ShopName,
		RefreshToken: response.Data.RefreshToken,
		AuthorityId:  response.Data.AuthorityId,
	}
	return response.Data, nil
}

// RefreshToken 刷新token
func (a *APIExpress) RefreshToken() (*doudian_sdk.CreateTokenData, error) {
	doudian_sdk.GlobalConfig.AppKey = a.appKey
	doudian_sdk.GlobalConfig.AppSecret = a.appSecret
	refresh := doudian_sdk.NewRefreshTokenRequest()
	refresh.GetParam().RefreshToken = a.refreshToken
	refresh.GetParam().GrantType = "refresh_token"

	createToken, err := refresh.Execute(a.accessTokenObj)
	if err != nil {
		return nil, err
	}
	if createToken.Code != RequestSuccessCode {
		return nil, errors.New(createToken.SubMsg + ":" + createToken.LogId)
	}
	a.accessToken = createToken.Data.AccessToken
	a.refreshToken = createToken.Data.RefreshToken
	a.expiresIn = time.Now().Unix() + createToken.Data.ExpiresIn

	// 不要
	createToken.Data.ExpiresIn = a.expiresIn
	a.accessTokenObj.CreateTokenData = createToken.Data
	return &createToken.Data, nil
}

// OrderStatusAndPsInfoOld 三方配送同步骑手位置信息(老版本的运力回传)
// 抖音物流信息和抖音小时达完全区分开(这边的appKey和APPSecret完全不同于小时达)
func (a *APIExpress) OrderStatusAndPsInfoOld(param map[string]interface{}) error {
	// 组合参数
	request := logistics_indTrackPush_reqeust.New()
	psInfo := &logistics_indTrackPush_reqeust.LogisticsIndTrackPushParam{
		CurTime:   utils.Time2Str(time.Now()),
		Company:   TiktokExpressCode,
		TraceMsgs: nil,
		//AuthorityId: "",
	}
	traceMsgs := make([]logistics_indTrackPush_reqeust.TraceMsgList, 0, 1)
	traceMsg := logistics_indTrackPush_reqeust.TraceMsgList{
		TrackNo: param["third_carrier_order_id"].(string),
		Traces: []logistics_indTrackPush_reqeust.TracesList{
			{
				Opcode:            param["opcode"].(string),
				OpTime:            utils.Time2Str(time.Now()),
				Content:           param["logistics_context"].(string),
				ThirdPartyCompany: "dada",
				ExceptionCode:     "",
				ExceptionDesc:     "",
				CancelCode:        "",
				CancelDesc:        "",
			},
		},
	}
	if param["courier_name"] != "" && param["courier_name"] != nil {
		rider := logistics_indTrackPush_reqeust.ReiderInfo{
			Name:   param["courier_name"].(string),
			Mobile: param["courier_phone"].(string),
		}
		traceMsg.Traces[0].Rider = rider
	}

	traceMsgs = append(traceMsgs, traceMsg)
	psInfo.TraceMsgs = traceMsgs
	request.Param = psInfo

	if a.accessTokenObj == nil || a.accessTokenObj.CreateTokenData.AccessToken == "" {
		a.CreateToken()
	} else if a.expiresIn < time.Now().Unix() {
		a.RefreshToken()
	}

	result, err := request.Execute(a.accessTokenObj)
	if err != nil {
		return err
	}
	if result.Code != RequestSuccessCode {
		return errors.New(result.SubMsg + ":" + result.LogId)
	}
	return nil
}

// OrderStatusReportRiderLocation 同步骑手轨迹
func (a *API) OrderStatusReportRiderLocation(param *instantShopping_reportRiderLocation_request.InstantShoppingReportRiderLocationParam) error {
	request := instantShopping_reportRiderLocation_request.New()
	request.Param = param

	data, err := request.Execute(a.accessTokenObj)
	if err != nil {
		return err
	}
	if data.Code != RequestSuccessCode {
		return errors.New(data.SubMsg + ":" + data.LogId)
	}
	return nil
}

// OrderStatusAndPsInfoNew 三方配送同步骑手状态信息(新版本的运力回传)
// 抖音物流信息和抖音小时达完全区分开(这边的appKey和APPSecret完全不同于小时达)
// 新版本舍弃了物流链接平台的 appKey
func (a *API) OrderStatusAndPsInfoNew(param map[string]interface{}, vendorStoreId string) error {
	// 组合参数
	request := instantShopping_notifyDeliveryStatus_request.New()
	request.Param = &instantShopping_notifyDeliveryStatus_request.InstantShoppingNotifyDeliveryStatusParam{
		ShopOrderId:    param["order_id"].(string),
		RiderPhoneType: 0,
		ReportTime:     time.Now().Unix(),
		UpdateTime:     time.Now().Unix(),
	}
	if param["courier_name"].(string) != "" {
		request.Param.RiderName = utils.String2Pointer(param["courier_name"].(string))
	}
	if param["courier_phone"].(string) != "" {
		request.Param.RiderPhone = utils.String2Pointer(param["courier_phone"].(string))
	}

	request.Param.DistributionCode = JxLogistics2Tiktok(param["logistics_provider_code"].(string))
	request.Param.RiderLatitude = utils.String2Pointer(param["latitude"].(string))
	request.Param.RiderLongitude = utils.String2Pointer(param["longitude"].(string))
	request.Param.DistributionDeliveryId = param["order_id"].(string)

	switch param["opcode"].(string) {
	case TiktokLogisticsStatusCALLRIDER:
		// 已发货订单更换物流
		orderDetail, err := a.GetTiktokOrderDetail(param["order_id"].(string))
		if err != nil {
			return err
		}
		if orderDetail.OrderStatus >= CreateOrderStatusDelivery {
			logisticsEdit := order_logisticsEdit_request.New()
			logisticsEdit.Param = &order_logisticsEdit_request.OrderLogisticsEditParam{
				OrderId:       param["order_id"].(string),
				CompanyCode:   JxLogistics2Tiktok(param["logistics_provider_code"].(string)),
				LogisticsCode: param["order_id"].(string),
				StoreId:       utils.Str2Int64(vendorStoreId),
			}
			logisticsData, err := logisticsEdit.Execute(a.accessTokenObj)
			if err != nil {
				return err
			}
			if logisticsData.Code != RequestSuccessCode {
				return errors.New("logisticsData err :" + request.Param.ShopOrderId + ":" + logisticsData.SubMsg + ":" + logisticsData.LogId)
			}
		}

		request.Param.Status = 101
	case TiktokLogisticsORDERRECEIVED:
		request.Param.Status = 102
	case TiktokLogisticsRIDERARRIVED:
		request.Param.Status = 103
	case TiktokLogisticsRIDERPICKUP:
		request.Param.Status = 104
	case TiktokLogisticsDELIVERED:
		request.Param.Status = 200
	case TiktokLogisticsCANCELDELIVERY, TiktokLogisticsINDDELIVERYEXCEPTION:
		request.Param.Status = 300
		request.Param.CancelCode = utils.Int64ToPointer(200)             // 其他原因
		request.Param.CancelReason = utils.String2Pointer("骑手未能到店,更换骑手") // 其他原因
	}

	result, err := request.Execute(a.accessTokenObj)
	if err != nil {
		return err
	}
	if result.Code != RequestSuccessCode {
		return errors.New("OrderStatusAndPsInfoNew err :" + request.Param.ShopOrderId + ":" + result.SubMsg + ":" + result.LogId)
	}
	return nil
}

func JxLogistics2Tiktok(code string) string {
	switch code {
	case utils.DaDaCode, TiktokDeliveryTypeDaDa:
		return TiktokDeliveryTypeDaDa
	case utils.FnPsCode, TiktokDeliveryTypeFengNiao:
		return TiktokDeliveryTypeFengNiao
	case utils.UUPTCode, TiktokDeliveryTypeUU:
		return TiktokDeliveryTypeUU
	case utils.SFPSCode, TiktokDeliveryTypeSF:
		return TiktokDeliveryTypeSF
	case utils.MTPsCode, TiktokDeliveryTypeMeiTuan:
		return TiktokDeliveryTypeMeiTuan
	case utils.MyselfPsCode, TiktokDeliveryTypeMerchant:
		return TiktokDeliveryTypeMerchant
	default:
		return TiktokDeliveryTypeMerchant
	}
}
