package com.fs.store.controller;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.fs.FSAdminApplication;
import com.fs.common.core.domain.R;
import com.fs.common.exception.CustomException;
import com.fs.erp.dto.*;
import com.fs.erp.http.JstErpHttpService;
import com.fs.erp.service.FsJstAftersalePushService;
import com.fs.erp.service.IErpGoodsService;
import com.fs.erp.service.IErpOrderService;
import com.fs.erp.utils.SignUtil;
import com.fs.huifuPay.dto.*;
import com.fs.pay.pay.domain.OrderResult;
import com.fs.pay.pay.dto.OrderQueryDTO;
import com.fs.pay.pay.service.PayService;
import com.fs.store.domain.*;
import com.fs.store.enums.IcgProcessStatusEnum;
import com.fs.store.mapper.FsMiniprogramSubNotifyTaskMapper;
import com.fs.store.mapper.FsStoreDeliversMapper;
import com.fs.store.mapper.FsStoreOrderMapper;
import com.fs.store.mapper.FsStorePaymentMapper;
import com.fs.store.service.IFsCouponScheduleService;
import com.fs.store.service.IFsStoreOrderService;
import com.fs.store.service.IFsStorePaymentService;
import com.fs.store.service.channel.HfPaymentHandler;
import com.fs.store.service.channel.YbPaymentHandler;
import com.fs.store.service.channel.param.PayProcessContext;
import com.fs.system.service.ISysConfigService;
import com.fs.task.ExpressTask;
import com.fs.task.MiniProgramSubTask;
import com.fs.task.StoreTask;
import com.fs.tzBank.TzBankService;
import com.fs.tzBank.utils.TzConfigUtils;
import com.fs.wx.domain.FsWxExpressTask;
import com.fs.wx.mapper.FsWxExpressTaskMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = FSAdminApplication.class)
@RequiredArgsConstructor
@Slf4j
public class FsStorePaymentControllerTest {

    @Autowired
    private FsStorePaymentController fsStorePaymentController;

    @Autowired
    private IFsCouponScheduleService fsCouponScheduleService;

    @Autowired
    IFsStorePaymentService fsStorePaymentService;

    @Autowired
    FsStorePaymentMapper fsStorePaymentMapper;

    @Autowired
    PayService payService;

    @Autowired
    private FsWxExpressTaskMapper fsWxExpressTaskMapper;

    @Autowired
    private FsStoreDeliversMapper fsStoreDeliversMapper;

    @Autowired
    private FsStoreOrderMapper fsStoreOrderMapper;

    @Autowired
    private StoreTask storeTask;


    @Autowired
    private JstErpHttpService httpService;

    @Autowired
    private IFsStoreOrderService fsStoreOrderService;

    @Autowired
    private IErpOrderService erpOrderService;

    @Autowired
    private IErpGoodsService erpGoodsService;

    @Autowired
    private FsJstAftersalePushService fsJstAftersalePushService;

    @Test
    public void pushJstTest(){
        fsJstAftersalePushService.pushJst();
    }
    @Test
    public void updateExpress(){
        storeTask.updateExpress();
    }

    @Test
    public void pushErp() throws ParseException {
        fsStoreOrderService.createOmsOrder(1370120L);
    }

    @Test
    public void getErpInfo() {
        ErpOrderQueryRequert request = new ErpOrderQueryRequert();
        request.setCode("28377458");
        ErpOrderQueryResponse order = erpOrderService.getOrder(request);
        log.info("订单信息: {}",order);
    }

    @Test
    public void getGoods(){
        ErpGoodsQueryRequert erpGoodsQueryRequert = new ErpGoodsQueryRequert();
        erpGoodsQueryRequert.setCode("105220");
        ErpGoodsQueryResponse goods = erpGoodsService.getGoods(erpGoodsQueryRequert);

        log.info("查询结果: {}",goods);
    }
    @Test
    public void initJstToken() {
        GetInitTokenRequestDTO requestDTO = new GetInitTokenRequestDTO();
        requestDTO.setApp_key("bd7a7d06a6d54377842f883f9a4c502a");
        requestDTO.setGrant_type("authorization_code");
        requestDTO.setCharset("utf-8");
        requestDTO.setCode("zzzzzz");
        requestDTO.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));

        requestDTO.setSign(SignUtil.getSignNew("1d112cb9d21d41e187ff824b5852f4cf",requestDTO));

        log.info("请求参数: {}", JSON.toJSONString(requestDTO));
        GetInitTokenResponseDTO initToken = httpService.getInitToken(requestDTO);
        log.info(JSON.toJSONString(initToken));
    }


    /**
     * 补事务id
     */
    @Test
    public void fixTransactionNull(){
        List<FsStorePayment> list = fsStorePaymentMapper.queryNormalData();
        for (FsStorePayment fsStorePayment : list) {
            String json = configService.selectConfigByKey("store.pay");
            FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
            OrderQueryDTO orderQueryDTO = new OrderQueryDTO();
            orderQueryDTO.setAccount(fsPayConfig.getYbAccount());
            orderQueryDTO.setUpOrderId(fsStorePayment.getTradeNo());
            OrderResult order = payService.getOrder(orderQueryDTO);
            if(order != null) {
                fsStorePayment.setBankTransactionId(order.getBankTrxId());
                fsStorePayment.setBankSerialNo(order.getBankOrderId());
            }

            fsStorePaymentMapper.updateFsStorePayment(fsStorePayment);
        }
    }

    /**
     * 修复微信发货
     */
    @Test
    public void fixWxExpress(){
        List<String> bankTrxIds = Arrays.asList(
                "4200002772202508045830995186"
        );
        List<FsStorePayment> fsStorePaymentList = fsStorePaymentService.queryByBankTrxId(bankTrxIds);
        for (FsStorePayment fsStorePayment : fsStorePaymentList) {
            FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderById(fsStorePayment.getOrderId());
            List<FsStoreDelivers> byOrderId = fsStoreDeliversMapper.findByOrderId(order.getId());
            if(CollectionUtils.isEmpty(byOrderId)) {
                log.info("该单无物流信息 单号:{}",order.getId());
                continue;
            }
            FsStoreDelivers delivers = byOrderId.get(0);

            FsWxExpressTask fsWxExpressTask = new FsWxExpressTask();
            fsWxExpressTask.setUserId(order.getUserId());
            fsWxExpressTask.setStatus(0);
            fsWxExpressTask.setRetryCount(0);
            fsWxExpressTask.setCreateTime(LocalDateTime.now());
            fsWxExpressTask.setUpdateTime(LocalDateTime.now());
            fsWxExpressTask.setOrderCode(order.getOrderCode());
            fsWxExpressTask.setExpressCompany(delivers.getDeliverSn());
            fsWxExpressTask.setExpressNo(delivers.getDeliverId());
            fsWxExpressTask.setPayCode(fsStorePayment.getPayCode());

            try {
                fsWxExpressTaskMapper.insert(fsWxExpressTask);
            }catch (Exception e){
                log.error("插入失败",e);
            }
        }

    }
    @Test
    public void testTestPaymentSync() {
        fsStorePaymentService.paymentSync();
    }

    /**
     * 已支付 但是没有银行流水号数据修复
     */
    @Test
    public void updatePaymentsBankInfo(){
        String[] payCodeList = new String[]{
                "1899282845931667456"
        };

        for (String payCode : payCodeList) {
            FsStorePayment fsStorePayment = fsStorePaymentService.selectFsStorePaymentByCode(payCode);
            if(fsStorePayment != null){
                fsStorePaymentService.updateYbBankSerial(fsStorePayment);
            }
        }
    }

    @Autowired
    private MiniProgramSubTask miniProgramSubTask;
    @Test
    public void returnPayStatus() throws Exception {

        Authentication authentication = new UsernamePasswordAuthenticationToken(
                "admin",
                "sadmin#258",
                Collections.singletonList(new SimpleGrantedAuthority("ADMIN"))
        );

        // Set the Authentication in the SecurityContext
        SecurityContextHolder.getContext().setAuthentication(authentication);


        FsStorePayment fsStorePayment = new FsStorePayment();
        fsStorePayment.setPaymentId(01L);
        fsStorePayment.setStatus(1);
        fsStorePayment.setOrderId(1899279950347763712L);
        fsStorePayment.setPayTypeCode("weixin");
        fsStorePayment.setPayMoney(new BigDecimal("0.01"));
        fsStorePayment.setPayTime(new Date());
        fsStorePayment.setTradeNo("002900TOP3B250311101453P779ac1369bc00000");
        fsStorePayment.setUserId(520391L);
        fsStorePayment.setOpenId("obmfC6y5ZOuvq9b4UlL7GUayuYQE");
        fsStorePayment.setCompanyId(12L);
        fsStorePayment.setCompanyUserId(42L);
        fsStorePayment.setDeptId(144L);
        fsStorePayment.setBankSerialNo("1899279950347763712L");
        fsStorePayment.setPayMode("hf");
        R r = fsStorePaymentController.returnPayStatus(fsStorePayment);
    }

    @Test
    public void test() throws Exception {
        FsCouponSchedule fsCouponSchedule = new FsCouponSchedule();
        fsCouponSchedule.setOrderId(1899279950347763712L);
        fsCouponSchedule.setSetmealId(1800L);
        fsCouponSchedule.setSetmealTitle("甘草干姜汤（北京同仁堂）1盒");
        fsCouponSchedule.setMonth(4L);
        fsCouponSchedule.setCount(0L);
        fsCouponSchedule.setStatus(IcgProcessStatusEnum.PENDING.getCode());
        fsCouponSchedule.setOrderTime(LocalDateTime.now());
        fsCouponSchedule.setUserId(520391L);
        // 如果上次发送时间为空，那么预计发送时间等于=下单时间+1月
        fsCouponSchedule.setSendTime(fsCouponSchedule.getOrderTime().plusMonths(1L));
        fsCouponSchedule.setRetryCount(0);

        fsCouponScheduleService.insertFsCouponSchedule(fsCouponSchedule);
    }

    @Autowired
    private TzBankService tzBankService;

    @Autowired
    private YbPaymentHandler ybPaymentHandler;

    @Autowired
    private HfPaymentHandler hfPaymentHandler;

    @Autowired
    private ISysConfigService configService;
    @Test
    public void ybRefund(){
        PayProcessContext processContext = new PayProcessContext();
        processContext.setOrderId(null);
        processContext.setPayType(null);
        processContext.setPaymentId(1334828L);
        processContext.setPayCode("1929745734509264897");
        String json = configService.selectConfigByKey("store.pay");
        FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
        processContext.setFsPayConfig(fsPayConfig);
        processContext.setUserId(null);
        processContext.setGoodsInfo("商城订单支付");
        processContext.setOrderPrefix("store-");
        ybPaymentHandler.refundOrder(processContext);
    }


    @Test
    public void hfRefund(){
        PayProcessContext processContext = new PayProcessContext();
        processContext.setOrderId(null);
        processContext.setPayType(null);
        processContext.setPaymentId(1373304L);
        processContext.setPayCode("1980533834124152832");
        String json = configService.selectConfigByKey("store.pay");
        FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
        processContext.setFsPayConfig(fsPayConfig);
        processContext.setUserId(null);
        processContext.setGoodsInfo("商城订单支付");
        processContext.setOrderPrefix("store-");
        hfPaymentHandler.refundOrder(processContext);
    }

    /**
     * 手动退款
     */
    @Test
    public void refund(){
        String[] data = new String[]{
                "1947198650681655296"
        };
        TzConfigInfoDTO tzConfigInfoDTO = TzConfigUtils.getConfig();

        for (String datum : data) {
            FsStorePayment payment = fsStorePaymentService.selectFsStorePaymentByCode(datum);

            RequestDTO<TzPayRefundDTO> requestDTO = new RequestDTO<TzPayRefundDTO>();
            TzPayRefundDTO tzPayRefundDTO = new TzPayRefundDTO();
            tzPayRefundDTO.setOldPayOutOrderNo(payment.getPayCode());
            tzPayRefundDTO.setRefundOrderNo(payment.getPayCode()+"1");
            tzPayRefundDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            tzPayRefundDTO.setTrxSendTime(sdf.format(new Date()));
            tzPayRefundDTO.setRefundOrdTransAmt(payment.getPayMoney().subtract(BigDecimal.valueOf(0.1)));
            tzPayRefundDTO.setNotifyURL(tzConfigInfoDTO.getRefundNotifyUrl());
            requestDTO.setReqBody(tzPayRefundDTO);
            requestDTO.setReqHeader(TzReqHeaderDTO.getInstance(payment.getPayCode()));

            TzReqResultDTO<TzRefundNotifyDTO> resultDTO;

            try {

                resultDTO = tzBankService.payRefund(requestDTO);
                TzRefundNotifyDTO body = resultDTO.getBody();
                String refundOrdStatus = body.getRefundOrdStatus();
                log.info("退款支付单号:{} 返回结果：{}",datum, resultDTO);
                if("90".equals(refundOrdStatus) || "50".equals(refundOrdStatus)) {
                    payment.setRefundMoney(payment.getRefundMoney());
                    payment.setStatus(-1);
                    payment.setRefundTime(new Date());
                    fsStorePaymentService.updateFsStorePayment(payment);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {

            }
        }
        // 退款将定时发放优惠券的状态设置为已退款
//                fsCouponScheduleService.setScheduleCouponRefund(String.valueOf(payment.getOrderId()));

    }


    @Autowired
    private ExpressTask expressTask;

    @Test
    public void deliveryOp(){
        storeTask.deliveryOp();
    }

    @Test
    public void subscribeExpress(){
        expressTask.subscribeExpress();
    }

    @Test
    public void issueCoupon() throws Exception {
        fsCouponScheduleService.issueCoupon();
    }

    @Test
    public void notifyMiniAppSub(){
        miniProgramSubTask.notifyMiniAppSub();
    }

    @Test
    public void queryOrder() throws Exception {
        String payCode = "1909873348586766336";
        FsStorePayment payment = fsStorePaymentService.selectFsStorePaymentByCode(payCode);

        RequestDTO<QueryOrderRestDTO> requestDTO = new RequestDTO<>();

        QueryOrderRestDTO queryOrderRestDTO = new QueryOrderRestDTO();
        queryOrderRestDTO.setOrderFlowNo(payment.getTradeNo());
        TzConfigInfoDTO tzConfigInfoDTO = TzConfigUtils.getConfig();

        queryOrderRestDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());

        requestDTO.setReqBody(queryOrderRestDTO);
        requestDTO.setReqHeader(TzReqHeaderDTO.getInstance(payment.getPayCode()));

        TzReqResultDTO<QueryOrderInfoDTO> resultDTO = tzBankService.payQueryOrder(requestDTO);
        log.info("查询结果: {}",resultDTO);
        String retCode = resultDTO.getRetCode();
        if(!retCode.equals("00000000")){
            log.info("台州银行支付回调查询失败{}",resultDTO);
            throw new CustomException("台州银行支付回调查询失败! msg="+resultDTO.getRetCode());
        }
        QueryOrderInfoDTO body = resultDTO.getBody();

    }
}
