package cn.pluss.platform.jft.impl;

import cn.pluss.platform.api.Result;
import cn.pluss.platform.api.ResultCode;
import cn.pluss.platform.api.ResultGenerator;
import cn.pluss.platform.common.RiskBlacklistService;
import cn.pluss.platform.converter.Converter;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.ForbiddenException;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.jft.JftBankCardService;
import cn.pluss.platform.jft.JftMercBaseInfoService;
import cn.pluss.platform.jft.JftReceiptInfoService;
import cn.pluss.platform.jft.JftReceiptPaymentService;
import cn.pluss.platform.mapper.*;
import cn.pluss.platform.merchant.JftMercPaymentChannelService;
import cn.pluss.platform.userInfo.UserInfoService;
import cn.pluss.platform.util.*;
import cn.pluss.platform.vo.JftReceiptInfoVO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 收银呗缴费通收款单 服务实现类
 * </p>
 *
 * @author crystal
 * @since 2022-06-16
 */
@Service
@Slf4j
public class JftReceiptInfoServiceImpl extends ServiceImpl<JftReceiptInfoMapper, JftReceiptInfo> implements JftReceiptInfoService {

    @Resource
    private JftReceiptPaymentService jftReceiptPaymentService;

    @Resource
    private JftReceiptOrderMapper jftReceiptOrderMapper;

    @Resource
    private JftPaymentInfoMapper jftPaymentInfoMapper;

    @Resource
    private RiskBlacklistService riskBlacklistService;

    @Resource
    private JftMercBaseInfoService jftMercBaseInfoService;

    @Resource
    private JftMercPaymentChannelService jftMercPaymentChannelService;

    @Resource
    private JftBankCardService jftBankCardService;

    @Autowired
    private UserInfoService uiService;


    /**
     * 创建收款单
     * @param userApp
     * @param info
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createReceipt(UserApp userApp,JftReceiptInfo info) {
        UserInfo ui = uiService.getById(userApp.getUserId());

        if (!ui.getFaceCert().equals("1")) {
            throw new ForbiddenException("当前账号存在安全问题，需要进行人脸认证");
        }

        info.checkParams(userApp);
        try {
            String savePath = ParametersUtil.upload_save_path;
//            String savePath = "D:\\Pictures\\";
            File file = QRCodeMaxUtil.createQrCode(info.getQrCodeUrl(), savePath, "jpg", 300, 300);
            String imageUrl = OssOperatUtil.upload(file,"jpg");
            file.delete();
            info.setImageUrl(imageUrl);
            save(info);
            List<Long> paymentIds = info.getPaymentIds();
            if(paymentIds != null && paymentIds.size() > 0){
                List<JftReceiptPayment> list = new ArrayList<>(paymentIds.size());
                for (Long id:paymentIds) {
                    JftReceiptPayment receiptPayment = new JftReceiptPayment(info.getId(),id);
                    list.add(receiptPayment);
                }
                jftReceiptPaymentService.saveBatch(list);
            }
            return imageUrl;
        }catch (Exception e){
            MsgException.throwException("服务器异常！");
        }
        return null;
    }

    /**
     * 缴费账单分页查询
     * @param page
     * @param condition
     * @return
     */
    @Override
    public Page<JftReceiptInfoVO> pageInfo(Page<JftReceiptInfoVO> page, JftReceiptInfo condition) {
        return baseMapper.pageInfo(page,condition);
    }

    /**
     * 关闭收款单
     * @param info
     */
    @Override
    public void closeReceipt(JftReceiptInfo info) {
        MsgException.checkNull(info.getId(),"收款单数据有误");
        info.setStatus(JftReceiptInfo.CLOSE);
        baseMapper.updateById(info);
    }

    /**
     * 查看缴费通收款详情
     * @param info
     * @return
     */
    @Override
    public JftReceiptInfoVO receiptDetail(JftReceiptInfo info) {
        MsgException.checkNull(info.getId(),"收款单数据有误");
        JftReceiptInfo jftInfo = baseMapper.selectById(info.getId());
        MsgException.checkNull(jftInfo,"收款单数据异常");
        JftReceiptInfoVO vo = Converter.INSTANCE.toVO(jftInfo);
        List<JftReceiptOrder> list = jftReceiptOrderMapper.listByReceiptId(vo.getId(),JftReceiptOrder.PAY_STATUS_YES);
        BigInteger num = BigInteger.ZERO;
        BigDecimal totalAmount = BigDecimal.ZERO;
        if(!list.isEmpty()){
            for (JftReceiptOrder order : list) {
                num = num.add(BigInteger.ONE);
                totalAmount = totalAmount.add(order.getAmount());
            }
            vo.setPayNum(num.intValue());
            vo.setTotalAmount(totalAmount);
            vo.setOrderList(list);
        }
        return vo;
    }

    /**
     * 获取收款单对应付款信息配置项接口
     * @param info
     * @return
     */
    @Override
    public JftReceiptInfoVO getReceipt(JftReceiptInfo info) {
        MsgException.checkBlank(info.getToken(),"token参数为空");
        JftReceiptInfo entity = baseMapper.getByToken(info.getToken());
        MsgException.checkNull(info,"token参数有误");
        entity.checkDate();
        JftReceiptInfoVO vo = Converter.INSTANCE.toVO(entity);
        List<Long> pids = jftReceiptPaymentService.listByReceiptId(vo.getId());
        if(!pids.isEmpty()){
            List<JftPaymentInfo> list = jftPaymentInfoMapper.selectBatchIds(pids);
            if(!list.isEmpty()){
                List<String> codeList = new ArrayList<>(list.size());
                for (JftPaymentInfo pl:list) {
                    codeList.add(pl.getCode());
                }
                vo.setPaymentCodeList(codeList);
            }
        }
        return vo;
    }

    /**
     * 缴费通校验tk参数
     * @param tk
     * @param request
     * @return
     */
    @Override
    public JftReceiptInfo wapCheckTk(String tk, HttpServletRequest request) {
        String ua = request.getHeader("user-agent").toLowerCase();
        if (!ua.contains("alipay")) {
            MsgException.throwException("请使用支付宝扫码！");
        }
        JftReceiptInfo byToken = baseMapper.getByToken(tk);
        MsgException.checkNull(byToken, "无效tk参数");
        String ipAddr = IpUtils.getIpAddr(request);
        if(StringUtil.isNotEmpty(byToken.getIp()) && !ipAddr.equals(byToken.getIp())){
            MsgException.throwException("当前付款码已被其他用户使用，请重新生成");
        }
        byToken.setIp(ipAddr);
        baseMapper.updateById(byToken);
        QueryWrapper<RiskBlacklist> queryWrapper = new QueryWrapper<RiskBlacklist>().eq("userId",byToken.getUserId());
        List<RiskBlacklist> list = riskBlacklistService.list(queryWrapper);
        MsgException.check(!list.isEmpty(),"黑名单用户，不允许使用该功能");
        Date now = DateUtils.currentDate();
        MsgException.check(JftReceiptInfo.CLOSE.equals(byToken.getStatus()), "当前收款单已关闭");
        MsgException.check(now.before(byToken.getCreateTime()) || now.after(byToken.getEndTime()), "当前收款单已过期");
        String urlString = ParametersUtil.domain + "/wap/jft/pay?tk="+tk;
        String ali_appid = ParametersUtil.ZY_ALI_APP_ID;
        String cookieValue = CookieUtils.getCookieValue(request, byToken.getUserId().toString(), true);
        if(StringUtil.isNotEmpty(cookieValue)){
            urlString +=  "&userId=" + cookieValue;
        }
        try {
            String rurl  = java.net.URLEncoder.encode(urlString, "utf-8");
            if(StringUtil.isEmpty(cookieValue)){
                String jmpUrl = "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=" + ali_appid + "&scope=auth_base&redirect_uri=" + rurl;
                return byToken.setJumpUrl(jmpUrl);
            }else{
                log.info("url:{}",urlString);
                return byToken.setJumpUrl(urlString);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            MsgException.throwException("url转码异常");
        }
        return null;
    }

    /**
     * 获取支付宝支付参数信息
     * @param request
     * @param tk
     * @param auth_code
     * @param userId
     */
    @Override
    public void getPayInfo(HttpServletRequest request, HttpServletResponse response, String tk, String auth_code, String userId) {
        request.setAttribute("token",tk);
        JftReceiptInfo info = wapCheckTk(tk,request);
        List<JftReceiptOrder> list = jftReceiptOrderMapper.listByReceiptId(info.getId(), JftReceiptOrder.PAY_STATUS_YES);
        MsgException.check(!list.isEmpty(),"当前付款码已支付，请重新生成！");
        JftMercBaseInfo baseInfo = jftMercBaseInfoService.getMercBaseInfo(info.getUserId());
        MsgException.checkNull(baseInfo,"商户信息异常");
        request.setAttribute("merchantName",baseInfo.getMerchantName());
        request.setAttribute("amount",info.getAmount());
        request.setAttribute("tk",tk);
        JftMercPaymentChannel channel = jftMercPaymentChannelService.getByUserId(info.getUserId());
        MsgException.checkNull(channel,"商户进件信息异常");
        MsgException.check(!"3".equals(channel.getStatus()),"商户状态不可用，请联系客服处理");
        JftBankCard bankCardInfo = jftBankCardService.getByUserId(baseInfo.getUserId());
        MsgException.checkNull(bankCardInfo,"结算卡信息异常");
        if(StringUtil.isNotEmpty(auth_code)){
            log.info("【缴费通】支付宝授权,tk:{},授权code:{}",info.getToken(),auth_code);
            try {
                AlipaySystemOauthTokenResponse tokenResponse = AliUtil.getAliUserIdV2(auth_code, ParametersUtil.ZY_PRI, ParametersUtil.ZY_PUB, ParametersUtil.ZY_ALI_APP_ID);
                userId = tokenResponse.getUserId();
                log.info("【缴费通】支付宝授权,tk:{},授权回调结果:{}",info.getToken(), JSON.toJSONString(tokenResponse));
                CookieUtils.setCookie(response,baseInfo.getUserId().toString(),userId,true);
            }catch (Exception e){
                e.printStackTrace();
                log.info("【缴费通】支付宝授权异常,tk:{},异常信息:{}",info.getToken(), e.getMessage());
                MsgException.throwException(e.getMessage());
            }
        }
        List<Long> ids = jftReceiptPaymentService.listByReceiptId(info.getId());
        if(ids.size() > 0){
            List<JftPaymentInfo> paymentList = jftPaymentInfoMapper.selectBatchIds(ids);
            request.setAttribute("paymentList", JSONArray.toJSON(paymentList));
        }
        request.setAttribute("pName",info.getProjectName());
        request.setAttribute("userId",userId);
        request.setAttribute("cpName",StringUtil.hideSecret(bankCardInfo.getBankHolder()));
        request.setAttribute("cpPhone",StringUtil.isHideMobile(bankCardInfo.getPhone()));

    }

}
