package walmart

import (
	"context"
	"errors"
	"fmt"
	"kami/internal/consts"
	"kami/internal/model"
	"kami/internal/service"
	"kami/utility/cache"
	"kami/utility/integration/redeem"
	"kami/utility/utils"
	"time"

	"github.com/duke-git/lancet/v2/pointer"
	"github.com/duke-git/lancet/v2/retry"
	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/gclient"
	"github.com/gogf/gf/v2/os/glog"
	"github.com/gogf/gf/v2/text/gstr"
	"github.com/gogf/gf/v2/util/gconv"
)

func (w *Client) BindCard(ctx context.Context, input *redeem.CommonSendCardReq) (result *redeem.BindCardOutput, err error) {
	result = &redeem.BindCardOutput{}

	orderNo, _ := service.CardRedeemOrder().GetOrderOneByOrderNo(ctx, input.OrderNo, nil)
	if err = service.CardRedeemOrder().AddHistory(ctx, &model.RedeemCardOrderAddHistory{
		CardAmount:      input.OrderAmount,
		Amount:          0,
		OrderNo:         orderNo.OrderNo,
		Remark:          "开始绑卡",
		ResponseRawData: "",
		OperationStatus: consts.RedeemOrderOperationStartBind,
	}, nil); err != nil {
		glog.Error(ctx, "添加卡订单记录失败", err)
	}

	resp := gclient.New().SetTimeout(30*time.Second).PostBytes(ctx, "http://walmart:5009/walmart/bind/card", gjson.MustEncode(g.Map{
		"cookies":                   input.Cookie,
		"card_num":                  input.CardNo,
		"card_pwd":                  input.GiftCardPwd,
		"order_num":                 input.OrderNo,
		"is_different_amount_allow": input.IsAllowDifferentAmount,
	}))
	glog.Info(ctx, "绑卡请求", input, "绑卡返回", resp)
	var respSt BindCardResp
	err = gjson.DecodeTo(resp, &respSt)
	if err != nil {
		if err = service.CardRedeemOrder().AddHistory(ctx, &model.RedeemCardOrderAddHistory{
			CardAmount:      input.OrderAmount,
			Amount:          0,
			OrderNo:         orderNo.OrderNo,
			Remark:          fmt.Sprintf("绑卡失败：原始日志：%s, %s", string(resp), err.Error()),
			ResponseRawData: gjson.MustEncodeString(resp),
			OperationStatus: consts.RedeemOrderOperationEndBind,
		}, nil); err != nil {
			glog.Error(ctx, "添加卡订单记录失败", err)
		}
	}

	if err = service.CardRedeemOrder().AddHistory(ctx, &model.RedeemCardOrderAddHistory{
		CardAmount:      input.OrderAmount,
		Amount:          0,
		OrderNo:         orderNo.OrderNo,
		Remark:          fmt.Sprintf("原始日志：%s，%s", respSt.Remarks, respSt.Record),
		ResponseRawData: gjson.MustEncodeString(resp),
		OperationStatus: consts.RedeemOrderOperationEndBind,
	}, nil); err != nil {
		glog.Error(ctx, "添加卡订单记录失败", err)
	}

	queryCardResp := &redeem.BindCardOutput{}
	// 只有绑定成功后，才查询卡密
	if respSt.Code.Status() == consts.RedeemOrderSuccess {
		queryCardResp, err = w.QueryCard(ctx, input)
		if err != nil || pointer.IsNil(queryCardResp) {
			glog.Error(ctx, "查询卡信息失败", err)
		}

		if err = service.CardRedeemOrder().AddHistory(ctx, &model.RedeemCardOrderAddHistory{
			CardAmount:      0,
			Amount:          0,
			OrderNo:         orderNo.OrderNo,
			Remark:          fmt.Sprintf("查询充值卡余额：%.2f", queryCardResp.Amount),
			ResponseRawData: gjson.MustEncodeString(queryCardResp),
			OperationStatus: consts.RedeemOrderOperationQueryCardAmount,
		}, nil); err != nil {
			glog.Error(ctx, "添加卡订单记录失败", err)
		}
	}

	//过滤充值卡
	result = &redeem.BindCardOutput{
		RawData: utils.UnicodeToZh(gconv.String(respSt)),
		Amount:  queryCardResp.Amount,
		Status:  respSt.Code.Status(),
		Remarks: respSt.Remarks,
	}

	//if respSt.Code.Status() == consts.RedeemOrderFailWithCardUnknown {
	//	balanceRes, err2 := w.QueryBalance(ctx, &redeem.QueryBalanceReq{
	//		Cookie:    input.Cookie,
	//		AccountId: input.OrderNo,
	//	})
	//	if err2 != nil {
	//		glog.Error(ctx, "查询余额失败", err2)
	//	} else {
	//		if !balanceRes.Ok {
	//			result.Status = consts.RedeemOrderFailWithCKFail
	//			if err = service.CardRedeemOrder().AddHistory(ctx, &model.RedeemCardOrderAddHistory{
	//				CardAmount:      0,
	//				Amount:          0,
	//				OrderNo:         orderNo.OrderNo,
	//				Remark:          "账号检测，ck失效",
	//				ResponseRawData: gjson.MustEncodeString(queryCardResp),
	//				OperationStatus: consts.RedeemOrderOperationQueryCardAmount,
	//			}, nil); err != nil {
	//				glog.Error(ctx, "添加卡订单记录失败", err)
	//			}
	//		}
	//	}
	//}
	return
}

// QueryBalance 查询余额
// FIXME: 查询余额接口目前不可用
func (w *Client) QueryBalance(ctx context.Context, input *redeem.QueryBalanceReq) (result *redeem.QueryBalanceRes, err error) {
	resp := gclient.New().SetTimeout(3*time.Second).PostBytes(ctx, "http://walmart:5009/walmart/account/query", gjson.MustEncode(g.Map{
		"cookie":    input.Cookie,
		"accountId": input.AccountId,
	}))
	var respSt BalanceResp
	err = gjson.DecodeTo(resp, &respSt)
	glog.Info(ctx, "查询余额返回", resp)
	return &redeem.QueryBalanceRes{
		Ck:    input.Cookie,
		Money: gconv.Float64(respSt.Data.Balance),
		Ok:    respSt.Code == 100,
	}, err
}

// QueryBalanceWithCache FIXME: 查询余额接口目前不可用
func (w *Client) QueryBalanceWithCache(ctx context.Context, input *redeem.QueryBalanceReq, duration time.Duration) (result *redeem.QueryBalanceRes, err error) {
	newCache, err := cache.NewCache().Get(ctx, cache.PrefixWalmartAccountQueryBalanceWithCookie.Key(input.Cookie))
	if err == nil && newCache != nil && !newCache.IsNil() {
		err = newCache.Scan(&result)
		return
	}
	result, err = w.QueryBalance(ctx, input)
	_, err = cache.NewCache().SetIfNotExist(ctx, cache.PrefixWalmartAccountQueryBalanceWithCookie.Key(input.Cookie), result, duration)
	return
}

func (w *Client) QueryUserInfoWithCache(ctx context.Context, cookie string, duration time.Duration) (result *redeem.QueryUserInfoRes, err error) {
	return &redeem.QueryUserInfoRes{
		NickName: "",
		Username: "",
		Ok:       true,
	}, nil
}

func (w *Client) QueryUserInfo(ctx context.Context, cookie string) (result *redeem.QueryUserInfoRes, err error) {
	return &redeem.QueryUserInfoRes{
		NickName: "",
		Username: "",
		Ok:       true,
	}, nil
}

func (w *Client) QueryCard(ctx context.Context, input *redeem.CommonSendCardReq) (result *redeem.BindCardOutput, err error) {
	result = &redeem.BindCardOutput{}
	err = retry.Retry(func() error {
		resp := gclient.New().SetTimeout(20*time.Second).PostBytes(ctx, "http://walmart_side:5007/api/v2/walmart/card/query", gjson.MustEncode(g.Map{
			"card_num": input.CardNo,
		}))
		glog.Info(ctx, "查询充值卡余额", resp)
		var respSt QueryCardResp
		if err = gjson.DecodeTo(resp, &respSt); err != nil {
			glog.Error(ctx, "查询充值卡余额失败", err, gconv.String(resp))
			return err
		}
		if gconv.Float64(respSt.Data.Money) == 0 {
			glog.Error(ctx, "查询充值卡余额失败")
			return errors.New("查询充值卡余额失败")
		}
		result = &redeem.BindCardOutput{
			RawData: gconv.String(respSt),
			Amount:  gconv.Float64(respSt.Data.Money),
			Status:  consts.RedeemOrderSuccess,
		}
		return nil
	}, retry.Context(ctx), retry.RetryTimes(3), retry.RetryWithLinearBackoff(1*time.Second))
	return
}

func (w *Client) CheckCard(ctx context.Context, input *redeem.CommonCardTrimAndCheckerInput) (output *redeem.CommonCardTrimAndCheckerOutput) {
	output = &redeem.CommonCardTrimAndCheckerOutput{
		CommonCardTrimAndCheckerInput: &redeem.CommonCardTrimAndCheckerInput{
			CardNo:      gstr.TrimAll(input.CardNo),
			GiftCardPwd: gstr.TrimAll(input.GiftCardPwd),
		},
		IsOk: false,
	}
	if gstr.HasPrefix(input.CardNo, "2326") &&
		gstr.IsNumeric(input.CardNo) &&
		gstr.IsNumeric(input.GiftCardPwd) &&
		gstr.LenRune(input.CardNo) == 19 &&
		gstr.LenRune(input.GiftCardPwd) == 6 {
		output.IsOk = true
	}
	return
}

// CheckAllowedAmount 规则
func (w *Client) CheckAllowedAmount(ctx context.Context, amount float64) bool {
	return true
}
