package com.fs.store.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.fs.common.annotation.DataScope;
import com.fs.common.config.FSSysConfig;
import com.fs.common.core.domain.R;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.IPUtils;
import com.fs.common.utils.ServletUtils;
import com.fs.company.domain.CompanyConfig;
import com.fs.company.domain.CompanyUser;
import com.fs.company.mapper.CompanyConfigMapper;
import com.fs.company.service.ICompanyService;
import com.fs.company.service.ICompanyUserService;
import com.fs.course.config.RedPacketConfig;
import com.fs.course.service.IFsCourseRedPacketLogService;
import com.fs.pay.pay.config.PayConfig;
import com.fs.pay.pay.domain.CreateWxOrderResult;
import com.fs.pay.pay.dto.WxJspayDTO;
import com.fs.pay.pay.service.PayService;
import com.fs.store.param.FsStoreStatisticsParam;
import com.fs.his.param.WxSendRedPacketParam;
import com.fs.store.vo.FsStorePaymentStatisticsVO;
import com.fs.system.service.ISysConfigService;
import com.fs.wx.miniapp.config.WxMaProperties;
import com.fs.wx.pay.config.WxPayProperties;
import com.fs.store.domain.FsUser;
import com.fs.store.param.FsStorePaymentPayParam;
import com.fs.store.param.FsStorePaymentParam;
import com.fs.store.service.IFsUserService;
import com.fs.store.vo.FsStorePaymentVO;
import com.fs.pay.service.IPayService;
import com.fs.pay.service.dto.CreatePayDTO;
import com.fs.pay.service.dto.PayDTO;
import com.fs.pay.service.dto.TradeOrder;
import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayTransferBatchesNotifyV3Result;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.transfer.*;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.TransferService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fs.store.mapper.FsStorePaymentMapper;
import com.fs.store.domain.FsStorePayment;
import com.fs.store.service.IFsStorePaymentService;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;

/**
 * 支付明细Service业务层处理
 *
 * @author fs
 * @date 2022-06-20
 */
@Service
public class FsStorePaymentServiceImpl implements IFsStorePaymentService
{
    Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private WxMaProperties properties;
    @Autowired
    private WxPayProperties wxPayProperties;
    @Autowired
    private IPayService payService;
    @Autowired
    private FSSysConfig sysConfig;
    @Autowired
    private FsStorePaymentMapper fsStorePaymentMapper;
    @Autowired
    private IFsUserService userService;

    @Autowired
    private ICompanyUserService companyUserService;
    @Autowired
    private ICompanyService companyService;
    @Autowired
    PayService ybPayService;
    @Autowired
    private ISysConfigService configService;

    @Autowired
    private IFsCourseRedPacketLogService redPacketLogService;

    @Autowired
    private CompanyConfigMapper companyConfigMapper;
    /**
     * 查询支付明细
     *
     * @param paymentId 支付明细ID
     * @return 支付明细
     */
    @Override
    public FsStorePayment selectFsStorePaymentById(Long paymentId)
    {
        return fsStorePaymentMapper.selectFsStorePaymentById(paymentId);
    }

    /**
     * 查询支付明细列表
     *
     * @param fsStorePayment 支付明细
     * @return 支付明细
     */
    @Override
    public List<FsStorePayment> selectFsStorePaymentList(FsStorePayment fsStorePayment)
    {
        return fsStorePaymentMapper.selectFsStorePaymentList(fsStorePayment);
    }

    /**
     * 新增支付明细
     *
     * @param fsStorePayment 支付明细
     * @return 结果
     */
    @Override
    public int insertFsStorePayment(FsStorePayment fsStorePayment)
    {
        fsStorePayment.setCreateTime(DateUtils.getNowDate());
        return fsStorePaymentMapper.insertFsStorePayment(fsStorePayment);
    }

    /**
     * 修改支付明细
     *
     * @param fsStorePayment 支付明细
     * @return 结果
     */
    @Override
    public int updateFsStorePayment(FsStorePayment fsStorePayment)
    {
        return fsStorePaymentMapper.updateFsStorePayment(fsStorePayment);
    }

    /**
     * 批量删除支付明细
     *
     * @param paymentIds 需要删除的支付明细ID
     * @return 结果
     */
    @Override
    public int deleteFsStorePaymentByIds(Long[] paymentIds)
    {
        return fsStorePaymentMapper.deleteFsStorePaymentByIds(paymentIds);
    }

    /**
     * 删除支付明细信息
     *
     * @param paymentId 支付明细ID
     * @return 结果
     */
    @Override
    public int deleteFsStorePaymentById(Long paymentId)
    {
        return fsStorePaymentMapper.deleteFsStorePaymentById(paymentId);
    }

    @Override
    @Transactional
    public R payment(FsStorePaymentPayParam payment) {
        if(payment.getPayMoney().compareTo(new BigDecimal(0.0))<1){
            return R.error("支付金额必须大于0");
        }
        // //获取OPENID
        // final WxMaService wxService = WxMaConfiguration.getMaService(properties.getConfigs().get(0).getAppid());
        String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
        // WxMaJscode2SessionResult session = null;
        // try {
        //     session = wxService.getUserService().getSessionInfo(payment.getCode());
        // } catch (WxErrorException e) {
        //     e.printStackTrace();
        // }
        CompanyUser companyUser=companyUserService.selectCompanyUserById(payment.getCompanyUserId());
        FsUser user=userService.selectFsUserById(payment.getUserId());
        // if(user==null){
        //     //写入
        //     user=new FsUser();
        //     user.setPhone("");
        //     user.setUsername("");
        //     user.setNickname("微信用户");
        //     user.setStatus(1);
        //     user.setOpenId(session.getOpenid());
        //     user.setLastIp(IpUtil.getRequestIp());
        //     user.setIsWeixinAuth(0);
        //     userService.insertFsUser(user);
        // }
        FsStorePayment storePayment=new FsStorePayment();
        storePayment.setCompanyId(payment.getCompanyId());
        storePayment.setCompanyUserId(payment.getCompanyUserId());
        storePayment.setStatus(0);
        storePayment.setPayCode(orderSn);
        storePayment.setPayMoney(payment.getPayMoney());
        storePayment.setCreateTime(new Date());
        storePayment.setPayTypeCode("weixin");
        storePayment.setBusinessType(1);
        storePayment.setRemark(payment.getRemark());
        storePayment.setOpenId(user.getMaOpenId());
        storePayment.setUserId(user.getUserId());
        if(companyUser==null){
            return R.error("销售帐号不存在");
        }
        storePayment.setDeptId(companyUser.getDeptId());
        fsStorePaymentMapper.insertFsStorePayment(storePayment);
        //易宝支付

        WxJspayDTO p = new WxJspayDTO();
        // 使用setter方法为对象赋值
        p.setPayMoney(storePayment.getPayMoney().toString());
        p.setLowOrderId("payment-"+storePayment.getPayCode());
        p.setBody("超重/肥胖/气血/代谢/美乳/慢病医学管理方案服务");
        p.setIsMinipg("1");
        p.setReturnUrl(PayConfig.notifyUrl);
        p.setOpenId(user.getMaOpenId());
        p.setAttach("");
        p.setStoreid("0");
        CreateWxOrderResult wxOrder = ybPayService.createWxOrder(p);
        if(wxOrder.getStatus().equals("100")){
            FsStorePayment ment=new FsStorePayment();
            ment.setPaymentId(storePayment.getPaymentId());
            ment.setTradeNo(wxOrder.getUpOrderId());
            fsStorePaymentMapper.updateFsStorePayment(ment);
            return R.ok().put("result",wxOrder.getPay_info());
        }
        else{
            return R.error(wxOrder.getMessage());
        }
        //小雨点支付
//        CreatePayDTO createPayDTO=new CreatePayDTO();
//        createPayDTO.setMerchOrderNo("payment-"+storePayment.getPayCode());
//        List<TradeOrder> orders=new ArrayList<>();
//        TradeOrder order=new TradeOrder();
//        order.setAmount(storePayment.getPayMoney().toString());
//        order.setSubMerchOrderNo("payment-"+storePayment.getPayCode());
//        order.setTradeName("超重/肥胖/气血/代谢/美乳/慢病医学管理方案服务");
//        order.setPayeeOutUserId(sysConfig.getPayPartnerId());
//        orders.add(order);
//        createPayDTO.setOrders(orders);
//        payService.createOrder(createPayDTO);
//        PayDTO payDTO=new PayDTO();
//        payDTO.setOrigMerchOrderNo("payment-"+storePayment.getPayCode());
//        payDTO.setOpenID(user.getMaOpenId());
//        payDTO.setAppID(wxPayProperties.getAppId());
//        payDTO.setPayerOutUserId(user.getUserId().toString());
//        payDTO.setPayerOutUserName(user.getNickname());
//        payDTO.setUserIp(IPUtils.getIpAddr(ServletUtils.getRequest()));
//        return R.ok().put("result",payService.payOrder(payDTO));


    }

    @Override
    public FsStorePayment selectFsStorePaymentByCode(String payCode) {
        return fsStorePaymentMapper.selectFsStorePaymentByCode(payCode);
    }

    @Override
    public List<FsStorePaymentVO> selectFsStorePaymentListQuery(FsStorePaymentParam fsStorePayment) {
        return fsStorePaymentMapper.selectFsStorePaymentListQuery(fsStorePayment);
    }

    @Override
    public List<FsStorePaymentVO> exportFsStorePaymentList(FsStorePaymentParam fsStorePayment) {
        return fsStorePaymentMapper.exportFsStorePaymentList(fsStorePayment);
    }

    @Override
    @DataScope(deptAlias = "cu",userAlias = "cu")
    public List<FsStorePaymentVO> selectFsStorePaymentListQueryVO(FsStorePaymentParam fsStorePayment) {
        return fsStorePaymentMapper.selectFsStorePaymentListQueryVO(fsStorePayment);
    }

    @Override
    public List<FsStorePaymentVO> selectFsMyStorePaymentListQueryVO(FsStorePaymentParam fsStorePayment) {
        return fsStorePaymentMapper.selectFsMyStorePaymentListQueryVO(fsStorePayment);
    }

    @Override
    public List<FsStorePayment> selectFsStorePaymentByOrderId(Long orderId) {
        return fsStorePaymentMapper.selectFsStorePaymentByOrderId(orderId);
    }

    @Override
    public Long selectFsStorePaymentCount(int type,Long companyId) {
        return fsStorePaymentMapper.selectFsStorePaymentCount(type,companyId);
    }

    @Override
    @Transactional
    public String payConfirm(String payCode,String tradeNo,String bankTransactionId,String bankSerialNo) {
        //更新订单状态
        FsStorePayment storePayment=fsStorePaymentMapper.selectFsStorePaymentByCode(payCode);
        if(!storePayment.getStatus().equals(0)){
            return "";
        }
        storePayment.setStatus(1);
        storePayment.setPayTime(new Date());
        storePayment.setTradeNo(tradeNo);
        storePayment.setBankSerialNo(bankSerialNo);
        storePayment.setBankTransactionId(bankTransactionId);
        fsStorePaymentMapper.updateFsStorePayment(storePayment);
        //增加佣金
        if(storePayment.getCompanyId()!=null&&storePayment.getCompanyId()>0){
            companyService.addCompanyPaymentMoney(storePayment);
        }
        return "SUCCESS";
    }

    @Override
    @Transactional
    public String refund(String orderCode) {
        FsStorePayment payment=fsStorePaymentMapper.selectFsStorePaymentByCode(orderCode);
        payment.setStatus(-1);
        payment.setRefundTime(new Date());
        fsStorePaymentMapper.updateFsStorePayment(payment);
        //收款 减去所有
        if(payment.getCompanyId()!=null&&payment.getCompanyId()>0){
            companyService.subCompanyPaymentMoney(payment);
        }
        return "success";
    }

    @Override
    public List<JSONObject> selectFsStorePaymentCounts(Map<String, Object> toMap) {
        return fsStorePaymentMapper.selectFsStorePaymentCounts(toMap);
    }

    @Override
    public List<FsStorePaymentStatisticsVO> selectFsStorePaymentStatisticsList(FsStoreStatisticsParam param) {
        return fsStorePaymentMapper.selectFsStorePaymentStatisticsList(param);
    }

    @Override
    public List<FsStorePayment> selectFsStorePaymentByOrder(Long orderId) {
        return fsStorePaymentMapper.selectFsStorePaymentByOrder(orderId);
    }

    @Override
    public FsStorePayment selectFsStorePaymentByTradeNo(String tradeNo) {
        return fsStorePaymentMapper.selectFsStorePaymentByTradeNo(tradeNo);
    }

    @Override
    @Transactional
    public R sendRedPacket(WxSendRedPacketParam param) {
        String json;
        RedPacketConfig config = new RedPacketConfig();
        // 根据红包模式获取配置
        switch (param.getRedPacketMode()){
            case 1:
                json = configService.selectConfigByKey("redPacket.config");
                config = JSONUtil.toBean(json, RedPacketConfig.class);
                break;
            case 2:
                json = configService.selectConfigByKey("redPacket.config");
                config = JSONUtil.toBean(json, RedPacketConfig.class);
                break;
        }
        //H5的用公众号的appid发，小程序的用小程序的appid来发
        if (param.getSource()==2){
            config.setAppId(config.getMiniappId());
        }
        //组合返回参数
        R result = new R();
        // 根据 isNew 判断使用哪种发红包方式
        if (config.getIsNew() != null && config.getIsNew() == 1) {
            result = sendRedPacketV3Internal(param, config);
        } else {
            result= sendRedPacketLegacyInternal(param, config);
        }
        result.put("isNew",config.getIsNew());
//        result.put("mchId",config.getMchId());

        result.put("mchId",config.getMchId());
        System.out.println("发红包返回"+result);
        return result;
    }

    // 内部方法：处理新版本的发红包逻辑
    private R sendRedPacketV3Internal(WxSendRedPacketParam param, RedPacketConfig config) {
        WxPayConfig payConfig = new WxPayConfig();
        BeanUtils.copyProperties(config, payConfig);
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        TransferService transferService = wxPayService.getTransferService();

        TransferBillsRequest request = new TransferBillsRequest();
        request.setAppid(config.getAppId());
        System.out.println("appid:"+config.getAppId());
        request.setOpenid(param.getOpenId());

        String code = String.valueOf(IdUtil.getSnowflake(0, 0).nextId());
        request.setOutBillNo("fsCourse" + code);

        Integer amount = WxPayUnifiedOrderRequest.yuanToFen(param.getAmount() != null ? param.getAmount().toString() : "0.1");
        request.setTransferAmount(amount);
        request.setTransferRemark("活动奖励");
        request.setUserRecvPerception("活动奖励");
        request.setNotifyUrl(config.getNotifyUrl());
        request.setTransferSceneId("1000");

        // 设置场景信息
        List<TransferBillsRequest.TransferSceneReportInfo> transferSceneReportInfos = new ArrayList<>();
        TransferBillsRequest.TransferSceneReportInfo info1 = new TransferBillsRequest.TransferSceneReportInfo();
        info1.setInfoType("活动名称");
        info1.setInfoContent("新会员有礼");
        transferSceneReportInfos.add(info1);

        TransferBillsRequest.TransferSceneReportInfo info2 = new TransferBillsRequest.TransferSceneReportInfo();
        info2.setInfoType("奖励说明");
        info2.setInfoContent("注册会员抽奖一等奖");
        transferSceneReportInfos.add(info2);
        request.setTransferSceneReportInfos(transferSceneReportInfos);

        try {
            TransferBillsResult transferBillsResult = transferService.transferBills(request);
            logger.info("商家转账支付完成:[msg:{}]", transferBillsResult);
            return R.ok("发送红包成功").put("data", transferBillsResult);
        } catch (WxPayException e) {
            e.printStackTrace();
            logger.info("商家转账支付失败：[msg:{}]", e.getMessage());
            return R.error("发送失败");
        }
    }

    // 内部方法：处理旧版本的发红包逻辑
    private R sendRedPacketLegacyInternal(WxSendRedPacketParam param, RedPacketConfig config) {
        WxPayConfig payConfig = new WxPayConfig();
        BeanUtils.copyProperties(config, payConfig);
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        TransferService transferService = wxPayService.getTransferService();

        TransferBatchesRequest request = new TransferBatchesRequest();
        request.setAppid(config.getAppId());
        String code = IdUtil.getSnowflake(0, 0).nextIdStr();
        request.setOutBatchNo("fsCourse" + code);
        request.setBatchRemark("课堂答题奖励");
        request.setBatchName("课堂答题奖励");
        Integer amount = WxPayUnifiedOrderRequest.yuanToFen(param.getAmount().toString());
        request.setTotalAmount(amount);
        request.setTotalNum(1);
        request.setNotifyUrl(config.getNotifyUrl());

        ArrayList<TransferBatchesRequest.TransferDetail> transferDetailList = new ArrayList<>();
        TransferBatchesRequest.TransferDetail transferDetail = new TransferBatchesRequest.TransferDetail();
        transferDetail.setOpenid(param.getOpenId());
        String code1 = IdUtil.getSnowflake(0, 0).nextIdStr();
        transferDetail.setOutDetailNo("fsCourse" + code1);
        transferDetail.setTransferAmount(amount);
        transferDetail.setTransferRemark("恭喜同学，认真听课，奖励你一朵小红花!");
        transferDetailList.add(transferDetail);
        request.setTransferDetailList(transferDetailList);

        try {
            TransferBatchesResult transferBatchesResult = transferService.transferBatches(request);
            return R.ok("发送红包成功").put("orderCode", transferBatchesResult.getOutBatchNo());
        } catch (WxPayException e) {
            e.printStackTrace();
            return R.error("发送失败");
        }
    }

    @Override
    public R sendRedPacketV3(WxSendRedPacketParam param) {
        return null;
    }

    @Override
    public String transferNotify(String notifyData, HttpServletRequest request) {
        logger.info("zyp \n【收到转账回调】：{}",notifyData);
        try {
            String json = configService.selectConfigByKey("redPacket.config");
            RedPacketConfig config = JSONUtil.toBean(json, RedPacketConfig.class);
            //创建微信订单
            WxPayConfig payConfig = new WxPayConfig();
            BeanUtils.copyProperties(config,payConfig);
            System.out.println(payConfig);
            logger.info("到零钱回调：{}",payConfig);
            WxPayService wxPayService = new WxPayServiceImpl();
            wxPayService.setConfig(payConfig);
            SignatureHeader signatureHeader = new SignatureHeader();
            signatureHeader.setTimeStamp(request.getHeader("Wechatpay-Timestamp"));
            signatureHeader.setNonce(request.getHeader("Wechatpay-Nonce"));
            signatureHeader.setSerial(request.getHeader("Wechatpay-Serial"));
            signatureHeader.setSignature(request.getHeader("Wechatpay-Signature"));
            WxPayTransferBatchesNotifyV3Result result = wxPayService.parseTransferBatchesNotifyV3Result(notifyData,signatureHeader);
            logger.info("到零钱回调：{}",result.getResult());
            if (result.getResult().getBatchStatus().equals("FINISHED")) {
                R r = redPacketLogService.syncRedPacket(result.getResult().getOutBatchNo());
                logger.info("result:{}",r);
                if (r.get("code").equals(200)){
                    return WxPayNotifyResponse.success("处理成功");
                }else {
                    return WxPayNotifyResponse.fail("");
                }
            }else {
                return WxPayNotifyResponse.fail("");
            }
        } catch (WxPayException e) {
            logger.error("zyp \n【转账回调异常】：{}", e.getReturnMsg());
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }

    @Override
    public String v3TransferNotify(String notifyData, HttpServletRequest request) {
        logger.info("zyp \n【收到转账回调】：{}",notifyData);
        try {
            String json = configService.selectConfigByKey("redPacket.config");
            RedPacketConfig config = JSONUtil.toBean(json, RedPacketConfig.class);
            //创建微信订单
            WxPayConfig payConfig = new WxPayConfig();
            BeanUtils.copyProperties(config,payConfig);
            WxPayService wxPayService = new WxPayServiceImpl();
            wxPayService.setConfig(payConfig);
            SignatureHeader signatureHeader = new SignatureHeader();
            signatureHeader.setTimeStamp(request.getHeader("Wechatpay-Timestamp"));
            signatureHeader.setNonce(request.getHeader("Wechatpay-Nonce"));
            signatureHeader.setSerial(request.getHeader("Wechatpay-Serial"));
            signatureHeader.setSignature(request.getHeader("Wechatpay-Signature"));
            TransferBillsNotifyResult result = wxPayService.parseTransferBillsNotifyV3Result(notifyData,signatureHeader);
            logger.info("到零钱回调：{}",result.getResult());
            if (result.getResult().getState().equals("SUCCESS")) {
                R r = redPacketLogService.syncRedPacket(result.getResult().getOutBillNo());
                logger.info("result:{}",r);
                if (r.get("code").equals(200)){
                    return WxPayNotifyResponse.success("处理成功");
                }else {
                    return WxPayNotifyResponse.fail("");
                }
            }else {
                return WxPayNotifyResponse.fail("");
            }
        } catch (WxPayException e) {
            logger.error("zyp \n【转账回调异常】：{}", e.getReturnMsg(),e);
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }
}
