package cn.quantgroup.customer.service.impl;

import cn.quantgroup.customer.enums.ErrorCodeEnum;
import cn.quantgroup.customer.model.order.*;
import cn.quantgroup.customer.model.pay.UserCardInfo;
import cn.quantgroup.customer.rest.param.applyorder.ApplyOrderQuery;
import cn.quantgroup.customer.rest.param.card.ModifyReservePhone;
import cn.quantgroup.customer.rest.param.card.UnBindCardModel;
import cn.quantgroup.customer.rest.param.ordermapping.EarlySettleUpOrderQueryParam;
import cn.quantgroup.customer.rest.param.ordermapping.OperateEntryParam;
import cn.quantgroup.customer.rest.param.ordermapping.OrderQueryParam;
import cn.quantgroup.customer.rest.param.repay.RepayOrderInfoQuery;
import cn.quantgroup.customer.rest.param.repay.RepayOrderQuery;
import cn.quantgroup.customer.rest.vo.JsonResult;
import cn.quantgroup.customer.service.IXyqbService;
import cn.quantgroup.customer.service.http.IHttpService;
import cn.quantgroup.customer.util.JSONTools;
import cn.quantgroup.customer.util.SignUtil;
import cn.quantgroup.user.retbean.XUser;
import cn.quantgroup.user.vo.UserSysResult;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.google.common.reflect.TypeToken;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static cn.quantgroup.customer.constant.Constant.GSON;

@Slf4j
@Service("xyqbService")
public class XyqbServiceImpl implements IXyqbService {

    @Value("${api.http}")
    private String xyqbSysUrl;
    @Value("${fund.pay.api-host}")
    private String clothoSysUrl;
    @Value("${payapi.http}")
    private String payapi;

    private final IHttpService httpService;

    private final UserSdkImpl userSdk;


    @Autowired
    public XyqbServiceImpl(IHttpService httpService, UserSdkImpl userSdk) {
        this.httpService = httpService;
        this.userSdk = userSdk;
    }

    @Override
    public String findRepayOrders(RepayOrderQuery repayOrderQuery) {
        String phoneNo = repayOrderQuery.getPhoneNo();
        Long userId = repayOrderQuery.getUserId();
        String url = xyqbSysUrl + "/ex/repayment/repay_orders";
        Map<String, Object> param = Maps.newHashMap();
        if (StringUtils.isNotEmpty(phoneNo)) {
            param.put("phoneNo", phoneNo);
        }
        if (Objects.nonNull(userId)) {
            param.put("userId", userId);
        }
        String response = httpService.get(url, param);
        log.info("[xyqb][query repay orders ] param:{},请求业务系统返回值:{}", param, response);
        return response;
    }


    @Override
    public JsonResult<ApplyOrder> findApplyOrders(ApplyOrderQuery applyOrderQuery) {
        String logPre = "XyqbServiceImpl.findApplyOrders";
        log.info("{} 申请订单查询 applyOrderQuery={}", logPre, applyOrderQuery);
        String orderNo = applyOrderQuery.getOrderNo();
        Long loanId = applyOrderQuery.getLoanId();
        Long userId = applyOrderQuery.getUserId();
        String url = clothoSysUrl + "/ex/customer_sys/query/applyOrder";
        Map<String, Object> param = Maps.newHashMap();
        if (StringUtils.isNotEmpty(orderNo)) {
            param.put("orderNo", orderNo);
        }
        if (Objects.nonNull(userId)) {
            param.put("userId", userId.toString());
        }
        if (Objects.nonNull(loanId)) {
            param.put("loanId", loanId.toString());
        }
        Map<String, String> header = Maps.newHashMap();
        header.put("Content-Type", "application/x-www-form-urlencoded");
        String result = httpService.post(url, header, param);
        log.info("{} 用户申请订单列表 url={}, header={},param={},result={}", logPre, url, header, param, result);
        if (StringUtils.isBlank(result)) {
            log.error("{} 调用信用钱包失败 url={}, header={},param={},result={}", logPre, url, header, param, result);
            return JsonResult.buildErrorStateResult("申请订单查询失败", null);
        }

        TypeReference<JsonResult<ApplyOrder>> typeToken = new TypeReference<JsonResult<ApplyOrder>>() {
        };
        JsonResult<ApplyOrder> jsonResult = JSONTools.deserialize(result, typeToken);
        return jsonResult;
    }

    @Override
    public JsonResult<List<FlowNode>> findFlowChart(String orderNo) {
        String logPre = "XyqbServiceImpl.findFlowChart";
        log.info("{} 流程日志查询 orderNo={}", logPre, orderNo);
        String url = clothoSysUrl + "/ex/customer_sys/query/flow";
        if (StringUtils.isEmpty(orderNo)) {
            log.error("{} 申请订单号为空 orderNo={}", logPre, orderNo);
            return JsonResult.buildErrorStateResult("申请订单号为空", null);
        }
        Map<String, Object> param = Maps.newHashMap();
        param.put("orderNo", orderNo);

        Map<String, String> header = Maps.newHashMap();
        header.put("Content-Type", "application/x-www-form-urlencoded");
        String result = null;
        try {
            result = httpService.post(url, header, param);
        } catch (Exception e) {
            log.error("{} 通讯异常 url={},param={}", logPre, url, param, e);
            return JsonResult.buildErrorStateResult("通讯异常", null);
        }

        if (StringUtils.isBlank(result)) {
            log.error("{} 调用信用钱包失败 url={}, header={},param={},result={}", logPre, url, header, param, result);
            return JsonResult.buildErrorStateResult("流程日志查询失败", null);
        }
        TypeReference<JsonResult<List<FlowNode>>> typeToken = new TypeReference<JsonResult<List<FlowNode>>>() {
        };
        JsonResult<List<FlowNode>> jsonResult = JSONTools.deserialize(result, typeToken);
        return jsonResult;

    }

    @Override
    public JsonResult<LoanOrder> findLoanOrder(Long loanId) {
        String logPre = "XyqbServiceImpl.findLoanOrder";
        log.info("{} 提现订单详情 loanId={}", logPre, loanId);
        String url = clothoSysUrl + "/ex/customer_sys/loan/detail";
        if (Objects.isNull(loanId)) {
            log.error("{} 借款订单号为空 orderNo={}", logPre, loanId);
            return JsonResult.buildErrorStateResult("借款订单号为空", null);
        }
        Map<String, Object> param = Maps.newHashMap();
        param.put("loanId", loanId.toString());

        Map<String, String> header = Maps.newHashMap();
        header.put("Content-Type", "application/x-www-form-urlencoded");
        String result = null;
        try {
            result = httpService.post(url, header, param);
        } catch (Exception e) {
            log.error("{} 远程调用异常 url={},param={}", logPre, url, param, e);
            return JsonResult.buildErrorStateResult("网络异常", null);
        }

        if (StringUtils.isBlank(result)) {
            log.error("{} 调用信用钱包失败 url={}, header={},param={},result={}", logPre, url, header, param, result);
            return JsonResult.buildErrorStateResult("提现订单详情查询失败", null);
        }
        TypeReference<JsonResult<LoanOrder>> typeToken = new TypeReference<JsonResult<LoanOrder>>() {
        };
        JsonResult<LoanOrder> jsonResult = JSONTools.deserialize(result, typeToken);

        return jsonResult;
    }


    @Override
    public JsonResult<OrderRepayment> repaymentPlanQuery(Long loanId) {
        String logPre = "XyqbServiceImpl.findLoanOrder";
        log.info("{} 查询还款计划loanId={}", logPre, loanId);
        String url = xyqbSysUrl + "/ex/ka/loan_plan/query";
        Map<String, String> queryParam = new HashMap<>(2);
        queryParam.put("loanId", loanId.toString());
        String result = httpService.get(url, queryParam);
        if (StringUtils.isBlank(result)) {
            log.error("{} 查询还款计划失败 loanId={} result={}", logPre, loanId, result);
            return JsonResult.buildErrorStateResult("查询还款计划失败", null);
        } else {
            TypeReference<JsonResult<OrderRepayment>> typeToken = new TypeReference<JsonResult<OrderRepayment>>() {
            };
            JsonResult<OrderRepayment> result1 = JSONTools.deserialize(result, typeToken);
            if (result1 != null) {
                return result1;
            } else {
                return JsonResult.buildErrorStateResult("还款计划查询失败", null);
            }
        }

    }

    /**
     * 查询绑定卡列表
     *
     * @param userId
     * @return
     */
    @Override
    public String queryCardLists(Long userId) {
        String url = xyqbSysUrl + "/ex/customer_sys/query/bankcard";
        Map<String, Object> param = new HashMap<>(4);
        if (Objects.nonNull(userId)) {
            param.put("userId", userId);
        }
        String response = null;
        try {
            response = httpService.post(url, param);
            log.info("[queryCardLists] param:{},请求业务系统返回值:{}", param, response);
        } catch (Exception e) {
            log.error("[queryCardLists] param:{},请求业务系统异常:{}", param, e);
        }
        return response;
    }

    @Override
    public String queryCardRelation(Long bankId) {
        String url = xyqbSysUrl + "/ex/customer_sys/query/cardrelation";
        Map<String, Object> param = new HashMap<>(4);
        if (Objects.nonNull(bankId)) {
            param.put("bankId", bankId);
        }

        String response = null;
        try {
            response = httpService.post(url, param);
            log.info("[queryCardRelation] param:{},请求业务系统返回值:{}", param, response);
        } catch (Exception e) {
            log.error("[queryCardRelation] param:{},请求业务系统异常:{}", param, e);
        }
        return response;
    }

    @Override
    public String unBindCardRelation(UnBindCardModel unBindCardModel) {
        String url = xyqbSysUrl + "/ex/customer_sys/unbundle/relation";
        Map<String, Object> param = new HashMap<>(4);
        Long userId = unBindCardModel.getUserId();
        Long bindCardRecordId = unBindCardModel.getBindCardRecordId();
        if (Objects.nonNull(bindCardRecordId)) {
            param.put("bindCardRecordId", bindCardRecordId);
        }
        if (Objects.nonNull(userId)) {
            param.put("userId", userId);
        }
        String response = null;
        try {
            response = httpService.post(url, param);
            log.info("[unBindCardRelation] param:{},请求业务系统返回值:{}", param, response);
        } catch (Exception e) {
            log.error("[unBindCardRelation] param:{},请求业务系统异常:{}", param, e);
        }
        return response;
    }

    @Override
    public String modifyReservePhone(ModifyReservePhone modifyReservePhone) {
        String url = xyqbSysUrl + "/ex/customer_sys/modify/reservedphone";
        Map<String, Object> param = new HashMap<>(8);
        Long userId = modifyReservePhone.getUserId();
        Long bankId = modifyReservePhone.getBankId();
        String phoneNo = modifyReservePhone.getPhoneNo();
        if (Objects.nonNull(bankId)) {
            param.put("bankId", bankId);
        }
        if (Objects.nonNull(userId)) {
            param.put("userId", userId);
        }
        if (StringUtils.isNotBlank(phoneNo)) {
            param.put("phoneNo", phoneNo);
        }

        String response = null;
        try {
            response = httpService.post(url, param);
            log.info("[modifyReservePhone] param:{},请求业务系统返回值:{}", param, response);
        } catch (Exception e) {
            log.error("[modifyReservePhone] param:{},请求业务系统异常:{}", param, e);
        }
        return response;
    }

    @Override
    public String queryRepayInfo(RepayOrderInfoQuery repayOrderQuery) {
        String url = xyqbSysUrl + "/ex/customer_sys/query/repayment";
        Map<String, Object> param = new HashMap<>(4);
        Long loanId = repayOrderQuery.getLoanId();
        Integer termNo = repayOrderQuery.getTermNo();
        if (Objects.nonNull(loanId)) {
            param.put("loanId", loanId);
        }
        if (Objects.nonNull(termNo)) {
            param.put("termNo", termNo);
        }

        String response = null;
        try {
            response = httpService.post(url, param);
            log.info("[queryRepayInfo] param:{},请求业务系统返回值:{}", param, response);
        } catch (Exception e) {
            log.error("[queryRepayInfo] param:{},请求业务系统异常:{}", param, e);
        }
        return response;
    }

    @Override
    public String queryRepayOptRecords(String businessFlowNo) {
        String url = xyqbSysUrl + "/ex/customer_sys/repayment/detail";
        Map<String, Object> param = new HashMap<>(4);
        if (StringUtils.isNotBlank(businessFlowNo)) {
            param.put("businessFlowNo", businessFlowNo);
        }

        String response = null;
        try {
            response = httpService.post(url, param);
            log.info("[queryRepayOptRecords] param:{},请求业务系统返回值:{}", param, response);
        } catch (Exception e) {
            log.error("[queryRepayOptRecords] param:{},请求业务系统异常:{}", param, e);
        }
        return response;
    }

    /**
     * 查询订单状态
     *
     * @param orderQuery
     * @return
     */
    @Override
    public JsonResult<OrderStatus> orderStatusQuery(OrderQueryParam orderQuery) {
        String logPre = "[XyqbServiceImpl.orderStatusQuery] 查询订单状态";
        String url = xyqbSysUrl + "/ex/ka/order/status";
        Map<String, String> queryParam = new HashMap<>(4);
        queryParam.put("orderNo", orderQuery.getApplyOrderNo());
        if (Objects.nonNull(orderQuery.getLoanId())) {
            queryParam.put("loanId", String.valueOf(orderQuery.getLoanId()));
        }
        log.info("{} 请求参数 orderQuery={},queryParam={}", logPre, orderQuery, queryParam);
        Map param = SignUtil.sign(SignUtil.KA_API_KEY, queryParam);
        Map<String, String> header = new HashMap<>(2);
        header.put("Accept", "application/json");
        header.put("Content-Type", "application/x-www-form-urlencoded");
        String result = httpService.post(url, header, param);
        log.info("{} 返回结果 result：{}", logPre, result);
        if (StringUtils.isBlank(result)) {
            log.error("{} 处理失败 queryParam={} result={}", logPre, queryParam, result);
            return JsonResult.buildErrorStateResult("查询订单状态失败，返回为空", ErrorCodeEnum.RETURN_ERROR);
        } else {
            TypeReference<JsonResult<OrderStatusXyqb>> typeToken = new TypeReference<JsonResult<OrderStatusXyqb>>() {
            };
            JsonResult<OrderStatusXyqb> jsonResult = JSONTools.deserialize(result, typeToken);
            if (Objects.isNull(jsonResult) || Objects.isNull(jsonResult.getData())) {
                return JsonResult.buildErrorStateResult("查询订单状态失败", ErrorCodeEnum.RETURN_ERROR);
            } else {
                return JsonResult.buildSuccessResult("查询订单状态成功", jsonResult.getData().getCurrentStatus());
            }
        }
    }

    @Override
    public JsonResult<List<EarlySettleUpOrder>> findLoanOrder4EarlySettleUp(EarlySettleUpOrderQueryParam orderQuery) {
        String logPre = "[XyqbServiceImpl.findLoanOrder4EarlySettleUp] 查询一次性结清订单相关信息";
        String url = xyqbSysUrl + "/ex/operate/config/earlysettle/query";
        Map<String, Object> queryParam = new HashMap<>(8);
        if (Objects.isNull(orderQuery.getUserId()) &&
                Objects.isNull(orderQuery.getLoanId()) &&
                StringUtils.isBlank(orderQuery.getFundOrder())) {
            log.error("{} 请求参数都为空，不允许查询 orderQuery={}", logPre, orderQuery);
            return JsonResult.buildErrorStateResult("查询参数都为空,不允许查询", null);
        }

        if(Objects.nonNull(orderQuery.getLoanId())){
            queryParam.put("loan_id", String.valueOf(orderQuery.getLoanId()));
        }

        if(Objects.nonNull(orderQuery.getUserId())){
            queryParam.put("user_id", String.valueOf(orderQuery.getUserId()));
        }

        if(StringUtils.isNotBlank(orderQuery.getFundOrder())){
            queryParam.put("fund_order_no", orderQuery.getFundOrder());
        }


        log.info("{} 请求参数 orderQuery={},queryParam={}", logPre, orderQuery, queryParam);
        Map<String, String> header = new HashMap<>(2);
        header.put("Accept", "application/json");
        header.put("Content-Type", "application/x-www-form-urlencoded");
        String result = httpService.post(url, header, queryParam);
        log.info("{} 返回结果 result：{}", logPre, result);
        if (StringUtils.isBlank(result)) {
            log.error("{} 处理失败 queryParam={} result={}", logPre, queryParam, result);
            return JsonResult.buildErrorStateResult("[查询失败，返回为空]", ErrorCodeEnum.RETURN_ERROR);
        } else {
            TypeReference<JsonResult<List<EarlySettleUpOrder>>> typeToken = new TypeReference<JsonResult<List<EarlySettleUpOrder>>>() {
            };
            JsonResult<List<EarlySettleUpOrder>> jsonResult = JSONTools.deserialize(result, typeToken);
            if (Objects.isNull(jsonResult)) {
                return JsonResult.buildErrorStateResult("操作失败,xyqb返回错误", null);
            } else {
                if(!jsonResult.isSuccess()){
                    return JsonResult.buildErrorStateResult(StringUtils.isNotBlank(jsonResult.getMsg())?jsonResult.getMsg():"操作失败,xyqb返回错误", null);
                }
                return jsonResult;
            }
        }
    }

    @Override
    public JsonResult<Boolean> setOrCancelSettleUpWhiteList(OperateEntryParam operateEntryParam) {
        String logPre = "[XyqbServiceImpl.setOrCancelSettleUpWhiteList] 处理新增或删除白名单操作";
        String url = xyqbSysUrl + "/ex/operate/config/earlysettle/opt_white_list";
        Map<String, Object> queryParam = new HashMap<>(8);
        if (Objects.isNull(operateEntryParam.getLoanId()) &&
                Objects.isNull(operateEntryParam.getOpState())) {
            log.error("{} 请求参数都为空，不允许操作 orderQuery={}", logPre, operateEntryParam);
            return JsonResult.buildErrorStateResult("查询参数都为空,不允许操作", null);
        }
        queryParam.put("loan_id", String.valueOf(operateEntryParam.getLoanId()));
        if (operateEntryParam.getOpState() == 1) {
            queryParam.put("opt", "ADD");
        } else {
            queryParam.put("opt", "DEL");
        }

        log.info("{} 请求参数 orderQuery={},queryParam={}", logPre, operateEntryParam, queryParam);
        Map<String, String> header = new HashMap<>(2);
        header.put("Accept", "application/json");
        header.put("Content-Type", "application/x-www-form-urlencoded");
        String result;
        try {
            result = httpService.post(url, header, queryParam);
        } catch (Exception e) {
            log.error("{} 系统异常 e:{}", logPre, ExceptionUtils.getStackTrace(e));
            return JsonResult.buildErrorStateResult("[处理失败]", Boolean.FALSE);
        }

        log.info("{} 返回结果 result：{}", logPre, result);
        if (StringUtils.isBlank(result)) {
            log.error("{} 处理失败 queryParam={} result={}", logPre, queryParam, result);
            return JsonResult.buildErrorStateResult("[处理失败]", Boolean.FALSE);
        } else {
            TypeReference<JsonResult> typeToken = new TypeReference<JsonResult>() {
            };
            JsonResult<JsonResult> jsonResult = JSONTools.deserialize(result, typeToken);
            if (Objects.isNull(jsonResult)) {
                return JsonResult.buildErrorStateResult("操作失败,xyqb返回错误", Boolean.FALSE);
            } else {
                if (!jsonResult.isSuccess()) {
                    return JsonResult.buildErrorStateResult(StringUtils.isNotBlank(jsonResult.getMsg()) ? jsonResult.getMsg() : "操作失败,xyqb返回错误", Boolean.FALSE);
                }
                return JsonResult.buildSuccessResult("[操作成功]", Boolean.TRUE);
            }
        }
    }

    @Override
    public JsonResult<EarlySettleUpTrial> earlySettleUpTrial(Long loanId) {
        String logPre = "[XyqbServiceImpl.earlySettleUpTrial] 提前一次性结清金额试算";
        String url = xyqbSysUrl + "/ex/operate/config/earlysettle/trial_order";
        Map<String, Object> queryParam = new HashMap<>(8);
        if (Objects.isNull(loanId)) {
            log.error("{} 请求参数为空，不允许操作 loanId={}", logPre, loanId);
            return JsonResult.buildErrorStateResult("借据单号为空,不允许操作", null);
        }
        queryParam.put("loan_id", String.valueOf(loanId));
        log.info("{} 请求参数 loanId={},queryParam={}", logPre, loanId, queryParam);
        Map<String, String> header = new HashMap<>(2);
        header.put("Accept", "application/json");
        header.put("Content-Type", "application/x-www-form-urlencoded");
        String result = httpService.post(url, header, queryParam);
        log.info("{} 返回结果 result：{}", logPre, result);
        if (StringUtils.isBlank(result)) {
            log.error("{} 处理失败 queryParam={} result={}", logPre, queryParam, result);
            return JsonResult.buildErrorStateResult("[处理失败]", null);
        } else {
            TypeReference<JsonResult<EarlySettleUpTrial>> typeToken = new TypeReference<JsonResult<EarlySettleUpTrial>>() {
            };
            JsonResult<EarlySettleUpTrial> jsonResult = JSONTools.deserialize(result, typeToken);
            if (Objects.isNull(jsonResult)) {
                return JsonResult.buildErrorStateResult("操作失败,xyqb返回错误", null);
            } else {
                if(!jsonResult.isSuccess()){
                    return JsonResult.buildErrorStateResult(StringUtils.isNotBlank(jsonResult.getMsg())?jsonResult.getMsg():"操作失败,xyqb返回错误", null);
                }
                return jsonResult;
            }
        }
    }

    /**
     * 查询用户在支付中心绑卡信息
     *
     * @param userId
     * @return
     */
    @Override
    public List<UserCardInfo> findUserPayCardList(Long userId) {
        List<UserCardInfo> userCardInfoList = Lists.newArrayList();
        UserSysResult<XUser> userByUser = userSdk.getService().findUserByUserId(userId);
        if (userByUser == null) {
            log.error("查询用户信息失败,user为空.userId:{}", userId);
            return userCardInfoList;
        }
        String uuid = userByUser.getData().getUuid();
        Map<String, String> map = new HashMap<>();
        map.put("uuid", uuid);
        Map<String, String> kefu = (Map<String, String>) SignUtil.sign("kefu", map);
        log.info("向支付中心获取卡列表,req:{}", map);
        String result = httpService.get(payapi.concat("/ex/common/kefu/card/list"), kefu);
        log.info("向支付中心获取卡列表,result:{}", result);
        JsonResult cardListResult = GSON.fromJson(result, new TypeToken<JsonResult>() {}.getType());
        if (cardListResult == null || !cardListResult.isSuccess()) {
            log.error("查询用户支付中心卡信息失败,userId:{}", userId);
            return userCardInfoList;
        }
        if (cardListResult.getData() != null && ((List) cardListResult.getData()).size() > 0) {
            userCardInfoList = GSON.fromJson(GSON.toJson(cardListResult.getData()), new TypeToken<List<UserCardInfo>>() {
            }.getType());
        }
        return userCardInfoList;
    }

    /**
     * 修改用户支付中心卡预留手机号
     * @param cardId
     * @param phoneNo
     * @return
     */
    @Override
    public Boolean changePayCardReservedPhoneNo(String cardId, String phoneNo) {

        if (cardId == null || StringUtils.isEmpty(phoneNo)) {
            log.error("修改预留手机号失败,cardId或phoneNo为空");
            return false;
        }

        Map<String, Object> map = new HashMap<>();
        map.put("cardId", cardId);
        map.put("phoneNo", phoneNo);
        Map<String, String> kefu = (Map<String, String>) SignUtil.sign("kefu", map);

        log.info("向支付中心修改预留手机号,req:{}", map);
        String result = httpService.get(payapi.concat("/ex/common/kefu/card/change/phone_no"), kefu);
        log.info("向支付中心修改预留手机号,result:{}", result);
        JsonResult jsonResult = GSON.fromJson(result, new TypeToken<JsonResult>() {}.getType());
        if (jsonResult == null || !jsonResult.isSuccess()) {
            log.error("修改预留手机号失败,支付中心修改预留手机号 cardId:{},phoneNo:{}", cardId, phoneNo);
            return false;
        }
        return true;
    }
}
