package com.izouma.nineth.service;

import com.alibaba.fastjson.JSONObject;
import com.anji.captcha.util.StringUtils;
import com.izouma.nineth.domain.*;
import com.izouma.nineth.dto.PageQuery;
import com.izouma.nineth.enums.AuthStatus;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.repo.IdentityAuthRepo;
import com.izouma.nineth.repo.UserBankCardRepo;
import com.izouma.nineth.repo.UserRepo;
import com.izouma.nineth.utils.sandpay.SandMethodEnum;
import com.izouma.nineth.utils.sandpay.SandpayAccountClient;
import com.ning.http.util.Base64;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URL;
import java.util.Objects;

/**
 * 杉德云账户
 */
@Service
@AllArgsConstructor
@Slf4j
public class SandAccountService {


    private SandpayAccountClient sandpayAccountClient;

    private UserRepo userRepo;

    private IdentityAuthRepo identityAuthRepo;

    private UserBankCardRepo userBankCardRepo;


    private String readFileToBase64(String url){
        try {
            URL urlObj = new URL(url);
            InputStream inputStream = urlObj.openStream();
            byte[] data = inputStream.readAllBytes();
            inputStream.close();

            return Base64.encode(data);
        } catch (Exception e) {
            throw new RuntimeException("读取证件资料失败:" + url , e);
        }

    }

    /**
     * 获取用户账号
     * @param userId
     * @return
     */
    private String getBizUserNo(Long userId){
        User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在"));
        String bizUserNo = user.getId().toString();
        return bizUserNo;
    }


    /**
     * 解析结果内容
     * @param wrappedData
     * @return
     */
    public JSONObject checkSuccessBody(String wrappedData){
        JSONObject resBodyJson = null;
        try {
            resBodyJson = sandpayAccountClient.checkAccountSuccessBody(wrappedData);
        } catch (Exception e) {
            log.error("数据解析失败：" + wrappedData , e);
            throw new BusinessException(e.getMessage());
        }
        return resBodyJson;
    }


    /**
     * 上传身份证正面
     * @return
     */
    public String uploadIdCardFront(String bizUserNo, String url){
        String fileContent = readFileToBase64(url);
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);
        param.put("fileContent", fileContent);
        //01—身份证国徽面
        param.put("fileType", "01");

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ELEC_PAPERS_UPLOAD);
        String fileNo = response.getString("fileNo");
        return fileNo;
    }

    /**
     * 上传身份证反面
     * @param bizUserNo
     * @param url
     * @return
     */
    public String uploadIdCardBack(String bizUserNo, String url){
        String fileContent = readFileToBase64(url);
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);
        param.put("fileContent", fileContent);
        //02—身份证人像面
        param.put("fileType", "02");

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ELEC_PAPERS_UPLOAD);
        String fileNo = response.getString("fileNo");
        return fileNo;
    }

    /**
     * 注册开户
     * @return
     */
    public JSONObject registerOpen(IdentityAuth identityAuth, String smsCode, String smsSerialNo){
        User user = userRepo.findById(identityAuth.getUserId()).orElseThrow(new BusinessException("用户不存在"));
        String bizUserNo = getBizUserNo(identityAuth.getUserId());
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号
        param.put("nickName", user.getNickname());
        param.put("name", user.getUsername());
        param.put("idType", "01");//身份证
        param.put("idNo", identityAuth.getIdNo());
        param.put("mobile", user.getPhone());
        param.put("smsCode", smsCode);
        param.put("smsSerialNo", smsSerialNo);

        //绑卡单独处理
//        UserBankCard userBankCard = userBankCardRepo.findByUserId(user.getId())
//                .stream().findAny()
//                .orElse(null);
//        if(userBankCard != null){
//            JSONObject bankInfo = new JSONObject();
//            bankInfo.put("cardNo", userBankCard.getBankNo());
//            bankInfo.put("bankMobile", userBankCard.getPhone());
//            param.put("bankInfo", bankInfo);
//        }

        JSONObject idImgList = new JSONObject();
        String frontImgNo = uploadIdCardFront(bizUserNo, identityAuth.getIdFront());
        String reverseImgNo = uploadIdCardBack(bizUserNo, identityAuth.getIdBack());
        idImgList.put("frontImgNo", frontImgNo);
        idImgList.put("reverseImgNo", reverseImgNo);

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ACCOUNT_REGISTER_OPEN_SERVER);
        return response;
    }

    /**
     * 通过快捷充值绑卡开户
     * @return
     */
    public JSONObject quickBindCardOpen(Long userId){
        User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在"));
        IdentityAuth identityAuth = identityAuthRepo.findFirstByUserIdAndStatusAndDelFalseOrderByCreatedAtDesc(userId, AuthStatus.SUCCESS)
                .orElseThrow(new BusinessException("用户未通过实名认证，无法快捷支付"));
        String bizUserNo = getBizUserNo(identityAuth.getUserId());
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号
        param.put("nickName", user.getNickname());
        param.put("name", user.getUsername());
        param.put("idType", "01");//身份证
        param.put("idNo", identityAuth.getIdNo());
        param.put("mobile", user.getPhone());
        String frontUrl = "";
        param.put("frontUrl", frontUrl);
        String notifyUrl = "";
        param.put("notifyUrl", notifyUrl);
        UserBankCard userBankCard = userBankCardRepo.findByUserId(user.getId())
                .stream().findAny()
                .orElse(null);
        if(userBankCard != null){
            JSONObject bankInfo = new JSONObject();
            bankInfo.put("cardNo", userBankCard.getBankNo());
            param.put("bankInfo", bankInfo);
        }

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ACCOUNT_QUICK_BINDCARD_OPEN);
        return response;

    }

    /**
     * 账户查询
     * @param userId
     * @return
     */
    public JSONObject memberInfoQuery(Long userId){
        String bizUserNo = getBizUserNo(userId);
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号
        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ELEC_MEMBER_INFO);
        return response;
    }

    /**
     * 绑卡操作
     * @return
     */
    public JSONObject bindCard(UserBankCard userBankCard){
        String bizUserNo = getBizUserNo(userBankCard.getUserId());
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号
        param.put("bankMobile", userBankCard.getPhone());
        //01：提现卡（默认）
        //02:快捷充值+提现卡
        param.put("relatedCardType", "02");
        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ELEC_BIND_CARD);
        return response;
    }

    /**
     * 解绑卡操作
     * @param userId
     * @param relatedCardNo
     * @return
     */
    public JSONObject unbindCard(Long userId, String relatedCardNo){
        String bizUserNo = getBizUserNo(userId);
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号
        param.put("relatedCardNo", relatedCardNo);//支付方的卡编号
        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ELEC_UNBIND_CARD);
        return response;
    }


    /**
     * 查询卡列表
     * @param userId
     * @return
     */
    public JSONObject cardQuery(Long userId){
        String bizUserNo = getBizUserNo(userId);
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号
        //param.put("relatedCardNo", relatedCardNo);//支付方的卡编号（可选）
        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ELEC_BIND_CARD_QUERY);
        return response;
    }


    /**
     * 绑卡确认(适用于关联快捷充值提现银行卡时进行短信确认)
     * @param userId
     * @param bindCardOrderNo
     * @param smsCode
     * @return
     */
    public JSONObject bindCardConfirm(Long userId, String bindCardOrderNo,
                                      String smsCode, String notifyUrl){
        String bizUserNo = getBizUserNo(userId);
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号
        param.put("notifyUrl", notifyUrl);
        param.put("oriCustomerOrderNo", bindCardOrderNo);
        param.put("smsCode", smsCode);

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ELEC_BIND_CARD_CONFIRM);
        return response;
    }


    /**
     * 密码管理
     * @param userId
     * @return
     */
    public JSONObject payPasswordManage(Long userId){
        String bizUserNo = getBizUserNo(userId);
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号
        param.put("pageType", "01");
        //01：设置/重置支付密码
        //02：修改支付密码
        //03: 重置会员手机号
        param.put("managementType", "01");
        String frontUrl = "";
        param.put("frontUrl", frontUrl);
        String notifyUrl = "";
        param.put("notifyUrl", notifyUrl);
        param.put("extend", "");
        //扩展信息
        param.put("merchExtendParams", new JSONObject());

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ACCOUNT_PAY_PASSWORD_MANAGE);
        return response;
    }


    /**
     * 支付密码状态
     * @param userId
     * @return
     */
    public JSONObject payPasswordStatus(Long userId){
        String bizUserNo = getBizUserNo(userId);
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ACCOUNT_PAY_PASSWORD_QUERY);
        return response;
    }



    /**
     * 余额查询
     * @param userId
     * @return
     */
    public JSONObject balanceQuery(Long userId){
        String bizUserNo = getBizUserNo(userId);
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号
        //01：支付电子户
        //02：权益账户
        //03：奖励金户
        param.put("accountType", "01");

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ELEC_QUERY_ACCOUNT_BALANCE);
        return response;
    }

    /**
     * 账户变动明细
     * @param userId
     * @return
     */
    public JSONObject changeDetails(Long userId, PageQuery pageQuery){
        String bizUserNo = getBizUserNo(userId);
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号

        int pageNo = pageQuery.getPage();
        if(pageNo <= 0 ){
            pageNo = 1;
        }
        int pageSize = pageQuery.getSize();
        String IoFlag = "00";//全部

        //00：全部（默认）
        //01: 出金
        //02：入金
        String queryIoFlag = Objects.toString(pageQuery.getQuery().get("IoFlag"), "");
        if(StringUtils.isNotEmpty(queryIoFlag)){
            IoFlag = queryIoFlag;
        }

        //其他参数支持,accountType,beginDate,endDate（8位数字） 最长七天
        String accountType = Objects.toString(pageQuery.getQuery().get("accountType"), "");
        String beginDate = Objects.toString(pageQuery.getQuery().get("beginDate"), "");
        String endDate = Objects.toString(pageQuery.getQuery().get("endDate"), "");



        param.put("pageSize", pageSize);
        param.put("pageNo", pageNo);
        param.put("IoFlag", IoFlag);
        param.put("accountType", accountType);
        param.put("beginDate", beginDate);
        param.put("endDate", endDate);

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ELEC_QUERY_CHANGE_DETAILS);
        return response;
    }

    /**
     * 验证码发送
     * @return
     */
    public JSONObject validateCodeSend(Long userId, String mobile){
        String bizUserNo = getBizUserNo(userId);
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号
        param.put("mobile", mobile);//手机号
        param.put("bizScene", "01");//开户
        //param.put("smsTemplateNo", "");//模板
        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_SERVER_SMS_SEND);
        return response;
    }


    /**
     * 账户充值
     * @return
     */
    public JSONObject quickRecharge(RechargeOrder rechargeOrder){
        String bizUserNo = getBizUserNo(rechargeOrder.getUserId());
        JSONObject param = new JSONObject();
        param.put("bizUserNo", bizUserNo);//会员编号
        param.put("orderTotalAmt", rechargeOrder.getOrderAmount());//订单金额
        param.put("walletAmt", rechargeOrder.getAmount());//充值金额

        //param.put("orderTimeOut", "");//超时时间,默认两小时

        //营销域
        //JSONObject marketingInfo = new JSONObject();
        param.put("notifyUrl", rechargeOrder.getNotifyUrl());

        param.put("frontUrl", rechargeOrder.getFrontUrl());

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ELEC_TRANS_QUICK_DEPOSIT_APPLY);
        return response;

    }


    /**
     * 账户充值
     * @return
     */
    public JSONObject recharge(RechargeOrder rechargeOrder){
        String bizUserNo = getBizUserNo(rechargeOrder.getUserId());
        JSONObject param = new JSONObject();
        param.put(sandpayAccountClient.ACCOUNT_CUSTOMER_ORDER_NO, rechargeOrder.getOrderNo());

        param.put("bizUserNo", bizUserNo);//会员编号
        //param.put("orderTimeOut", "");//超时时间,默认两小时
        String payTool = rechargeOrder.getPayTool();
        if(StringUtils.isEmpty(payTool)){
            payTool = "QUICKPAY";
        }
        param.put("payTool", payTool);


        JSONObject payExtend = new JSONObject();
        payExtend.put("relatedCardNo", rechargeOrder.getRelatedCardNo());

        param.put("payExtend", payExtend);
        param.put("walletAmt", rechargeOrder.getAmount());//充值金额

        //营销域
        //JSONObject marketingInfo = new JSONObject();
        param.put("extend", "");
        //param.put("userFeeAmt", "");//不支持
        param.put("notifyUrl", rechargeOrder.getNotifyUrl());
        param.put("frontUrl", rechargeOrder.getFrontUrl());

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_ELEC_TRANS_THIRD_PAYMENT_DEPOSIT);
        return response;

    }

    /**
     * 订单确认
     * @param smsCode
     * @return
     */
    public JSONObject orderConfirm(String orderNo, BigDecimal orderAmount, String smsCode){
        JSONObject param = new JSONObject();
        param.put("oriCustomerOrderNo", orderNo);//原订单号
        param.put("oriOrderAmt", orderAmount);
        param.put("smsCode", smsCode);
        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_SERVER_ORDER_CONFIRM);
        return response;
    }

    /**
     * 提现申请
     * @return
     */
    public JSONObject withdrawApply(WithdrawApply withdrawApply){
        String bizUserNo = getBizUserNo(withdrawApply.getUserId());
        JSONObject param = new JSONObject();
        param.put(sandpayAccountClient.ACCOUNT_CUSTOMER_ORDER_NO, withdrawApply.getOrderNo());
        param.put("bizUserNo", bizUserNo);//会员编号
        //01：支付电子户
        //02：宝易付权益电子户
        param.put("accountType", "01");

        param.put("relatedCardNo",withdrawApply.getRelatedCardNo());

        param.put("orderAmt", withdrawApply.getOrderAmount());

        param.put("postscript", "");//附言
        param.put("remark", "");//备注
        //param.put("userFeeAmt", "");//商户服务费

        param.put("notifyUrl", withdrawApply.getNotifyUrl());
        param.put("frontUrl", withdrawApply.getFrontUrl());

        JSONObject response = sandpayAccountClient.accountPostJson(param, SandMethodEnum.CEAS_SERVER_WITHDRAW_APPLY);
        return response;

    }



}
