package cn.qg.qaplatform.controller.zdata.vcc;

import cn.qg.qaplatform.config.SwitchDataSource;
import cn.qg.qaplatform.entity.vcc.Account;
import cn.qg.qaplatform.entity.vcc.AcsPayOrder;
import cn.qg.qaplatform.entity.vcc.RiskRecord;
import cn.qg.qaplatform.entity.vcc.UserQuotaRecord;
import cn.qg.qaplatform.entity.xyqbuser.User;
import cn.qg.qaplatform.entity.zdata.VccOpenResultVo;
import cn.qg.qaplatform.entity.zdata.VccUserEntity;
import cn.qg.qaplatform.enums.VccStatusEnum;
import cn.qg.qaplatform.process.Vcc;
import cn.qg.qaplatform.service.vcc.AccountService;
import cn.qg.qaplatform.service.vcc.AcsPayOrderService;
import cn.qg.qaplatform.service.vcc.RiskRecordService;
import cn.qg.qaplatform.service.vcc.UserQuotaRecordService;
import cn.qg.qaplatform.service.xyqbUser.UserService;
import cn.qg.qaplatform.service.zdata.risk.RuleEngineService;
import cn.qg.qaplatform.utils.HttpClientUtils;
import cn.qg.qaplatform.utils.Result;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jayway.jsonpath.JsonPath;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * vcc 相关接口
 * @author libo
 */
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/vcc")
public class VccController {

    @Autowired
    UserService userService;

    @Autowired
    AccountService accountService;

    @Autowired
    UserQuotaRecordService userQuotaRecordService;

    @Autowired
    RiskRecordService riskRecordService;

    @Autowired
    AcsPayOrderService acsPayOrderService;

    @Autowired
    RuleEngineService ruleEngineService;

    /**
     * vcc造数据
     * @param namespace 环境
     * @param phoneNo 手机号
     * @param channel 渠道号
     * @param status 状态,1-授信成功，2-授信失败，3-开户成功，4-开户失败
     * @param amount 授信金额
     * @return
     * @throws Exception
     */
    @PostMapping("/gen")
    public Result genVccUser(@RequestParam(value = "namespace") String namespace,
                             @RequestParam(value = "phoneNo") String phoneNo,
                             @RequestParam(value = "channel") String channel,
                             @RequestParam(value = "status") Integer status,
                             @RequestParam(value = "amount") Integer amount) throws Exception {
        if (status !=1 && status !=2 && status !=3 && status !=4) {
            return Result.buildErrorStateResult("用户状态错误！", false);
        }
        String vccChannel;
        if (channel.equals("214")) {
            vccChannel = "159904";
        } else if (channel.equals("217")) {
            vccChannel = "159905";
        } else {
            vccChannel = channel;
        }
        // 登录
        String token;
        String uuid;
        try {
            Map loginResult = Vcc.login(namespace, phoneNo, channel, channel);
            token = loginResult.get("token").toString();
            uuid = loginResult.get("uuid").toString();
        } catch (Exception e) {
            e.printStackTrace();
            return Result.buildErrorStateResult("登录失败，请检查xyqb_user2服务是否正常", false);
        }
        SwitchDataSource.dataSourceSwitch(namespace, "xyqb_user");
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("phone_no", phoneNo);
        User user = userService.getOne(userQueryWrapper);

        // 检查用户是否已有额度
        boolean haveQuota = Vcc.checkIfAlreadyHaveQuota(namespace, uuid);
        if (haveQuota) {
            return Result.buildErrorStateResult("该用户已申请过，请更换新用户申请！", false);
        }

        // 加入授信黑名单
        if (status == 2) {
            ruleEngineService.addBlackList(uuid);
            log.info("将用户 {} 加入授信黑名单！", uuid);
        }

        VccOpenResultVo vccOpenResultVo = new VccOpenResultVo();
        vccOpenResultVo.setPhoneNo(phoneNo);
        vccOpenResultVo.setOpenedChannel(channel);
        vccOpenResultVo.setUuid(uuid);
        vccOpenResultVo.setUserId(String.valueOf(user.getId()));

        // credit url
        String vccToken;
        try {
            vccToken = Vcc.creditUrl(namespace, token, vccChannel);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.buildErrorStateResult("vcc_talos报错，造数据失败，请检查vcc_talos", false);
        }

        // 身份证正面
        String uploadFrontResult = Vcc.uploadFrontIdCardNew(namespace, vccToken, uuid, vccChannel);
        if (JsonPath.read(uploadFrontResult, "$.business_code").toString().equals("1")) {
            return Result.buildErrorStateResult(uploadFrontResult, false);
        }
        // 身份证反面
        String uploadBackResult = Vcc.uploadBackIdCardNew(namespace, vccToken, uuid, vccChannel);
        if (JsonPath.read(uploadBackResult, "$.business_code").toString().equals("1")) {
            return Result.buildErrorStateResult(uploadBackResult, false);
        }
        // 放置身份证重复
        Vcc.modifyExistIdNo(namespace);

        // talos保存用户信息
        String saveUserDetailResult = Vcc.saveUserDetails(namespace, token, vccChannel);
        if (!JsonPath.read(saveUserDetailResult, "$.data").toString().equals("实名成功")) {
            return Result.buildErrorStateResult("保存用户信息失败，请查看spider-center服务日志", false);
        }
        // 提交ocr
        Vcc.submitOcrNew(namespace, vccToken, vccChannel);
        // 提交授信
        Vcc.submitCredit(namespace, token, vccChannel);
        // 授信结果查询
        int searchCreditCount = 0;
        while (true) {
            try {
                Thread.sleep(1000);
                searchCreditCount++;
                Map<String, Object> creditResult = Vcc.searchCreditResult(namespace, token, vccChannel);
                if (creditResult.get("status").equals("1") || creditResult.get("status").equals("2")) {
                    break;
                } else if (creditResult.get("status").equals("0") && searchCreditCount == 10) {
                    String riskNo = Vcc.getRiskNo(namespace, uuid);
                    Vcc.vccWindControlCreditCallback(namespace, uuid, riskNo, status != 2, amount);
                    break;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if (status == 1 || status == 2) {
            log.info("提交授信成功！");
            Thread.sleep(2000);
            SwitchDataSource.dataSourceSwitch(namespace,  "vcc_talos");
            QueryWrapper<Account> accountQueryWrapper = new QueryWrapper<>();
            accountQueryWrapper.eq("phone_no", phoneNo);
            Account account = accountService.getOne(accountQueryWrapper);
            vccOpenResultVo.setMsg(VccStatusEnum.getDescByCode(account.getStatus()));
            return Result.buildSuccessResult(vccOpenResultVo);
        }
        // 人脸识别回调
//        Vcc.appFaceCallback(namespace, token, vccChannel);
        // 基本信息
        String basicInfoResult = Vcc.basicInfo(namespace, token, vccChannel);
        if (!JsonPath.read(basicInfoResult, "$.businessCode").equals("0000")) {
            return Result.buildErrorStateResult("用户基本信息保存失败，请依次检查vcc-talos和spider-center", false);
        }
        // 发送验证码
        String requestId;
        try {
            requestId = Vcc.bindCardSms(namespace, token, vccChannel, "ABC", "6228272537046278993");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.buildErrorStateResult("发送绑卡验证码接口异常，请检查gu-bei服务日志", false);
        }
        // 额度激活
        JSONObject quotaActivationResult = Vcc.quotaActivation(namespace, token, vccChannel, "6228272537046278993", requestId);
        if (status == 3) {
            // 开户结果
            JSONObject result = Vcc.openResult(namespace, token, vccChannel);
            Map data = (Map) result.get("data");
            vccOpenResultVo.setAmount(data.get("amount").toString());
            vccOpenResultVo.setEacctNo(data.get("eacctNo").toString());
            vccOpenResultVo.setMsg("开户成功");
        }
        if (status == 4) {
            Map data = (Map) quotaActivationResult.get("data");
            if (data.get("status").equals("2")) {
                vccOpenResultVo.setMsg("开户失败");
            } else {
                vccOpenResultVo.setMsg("请找开发手动设置结果为开户失败！");
            }
        }
        return Result.buildSuccessResult(vccOpenResultVo);
    }

    /**
     * vcc捞数据
     * @param namespace 环境
     * @param status 状态
     * @param pageNum 第几页
     * @param pageSize 每页展示多少个
     * @return
     */
    @GetMapping("/getData")
    public Result getVccData(@RequestParam(value = "namespace") String namespace,
                             @RequestParam(value = "status") Integer status,
                             @RequestParam(defaultValue = "1") Integer pageNum,
                             @RequestParam(defaultValue = "10") Integer pageSize) {
        // 数据源切换到vcc_talos
        SwitchDataSource.dataSourceSwitch(namespace, "vcc_talos");
        IPage<Account> accountIPage = new Page<>(pageNum, pageSize);
        QueryWrapper<Account> accountQueryWrapper = new QueryWrapper<>();
        accountQueryWrapper.eq("status", status);
        IPage<Account> accountIPageResult = accountService.page(accountIPage, accountQueryWrapper);
        List<VccUserEntity> vccUserEntityList = new ArrayList<>();
        QueryWrapper<UserQuotaRecord> userQuotaRecordQueryWrapper = new QueryWrapper<>();
        // 数据源切换到vcc_quota
        SwitchDataSource.dataSourceSwitch(namespace, "vcc_quota");
        for (Account account: accountIPageResult.getRecords()) {
            VccUserEntity vccUserEntity = new VccUserEntity();
            vccUserEntity.setUserId(String.valueOf(account.getUserId()));
            vccUserEntity.setUuid(account.getUuid());
            vccUserEntity.setPhoneNo(account.getPhoneNo());
            vccUserEntity.setRegisteredFrom(account.getRegisteredFrom());
            vccUserEntity.setNextApplyTime(account.getNextApplyTime());
            vccUserEntity.setStatus(account.getStatus());
            vccUserEntity.setType(account.getType());
            vccUserEntity.setCreatedAt(account.getCreatedAt());
            userQuotaRecordQueryWrapper
                    .eq("uuid", account.getUuid())
                    .orderByDesc("id");
            List<UserQuotaRecord> userQuotaRecordList = userQuotaRecordService.list(userQuotaRecordQueryWrapper);
            if (userQuotaRecordList.size() > 0) {
                vccUserEntity.setRiskAmount(userQuotaRecordList.get(0).getRiskAmount());
                vccUserEntity.setEnableAmount(userQuotaRecordList.get(0).getEnableAmount());
            }
            vccUserEntityList.add(vccUserEntity);
            userQuotaRecordQueryWrapper.clear();
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("total", accountIPageResult.getTotal());
        resultMap.put("list", vccUserEntityList);
        return Result.buildSuccessResult(resultMap);
    }

    /**
     * vcc查数据
     * @param namespace 环境
     * @param phoneNo 手机号
     * @return
     */
    @GetMapping("/checkData")
    public Result checkUserData(String namespace, String phoneNo) {
        SwitchDataSource.dataSourceSwitch(namespace, "vcc_talos");
        QueryWrapper<Account> accountQueryWrapper = new QueryWrapper<>();
        accountQueryWrapper.eq("phone_no", phoneNo);
        Account account = accountService.getOne(accountQueryWrapper);
        if (account == null) {
            return Result.buildErrorStateResult("该用户不是VCC用户", false);
        }
        return Result.buildSuccessResult(account);
    }

    /**
     * VCC风控授信回调
     * @param namespace 环境
     * @param phoneNo 手机号
     * @param result 回调结果，true-授信成功，false-授信失败
     * @param amount
     * @return
     */
    @GetMapping("/risk")
    public Result vccRiskControl(String namespace, String phoneNo, Boolean result, Integer amount)  {
        if (amount == null) {
            amount = 10000;
        }
        SwitchDataSource.dataSourceSwitch(namespace, "xyqb_user");
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("phone_no", phoneNo);
        User user = userService.getOne(userQueryWrapper);
        if (user == null) {
            return Result.buildErrorStateResult("用户不存在", false);
        }
        String uuid = user.getUuid();
        SwitchDataSource.dataSourceSwitch(namespace, "vcc_talos");
        QueryWrapper<RiskRecord> riskRecordQueryWrapper = new QueryWrapper<>();
        riskRecordQueryWrapper.eq("uuid", uuid).orderByDesc("id");
        List<RiskRecord> riskRecordList = riskRecordService.list(riskRecordQueryWrapper);
        if (riskRecordList.size() == 0) {
            return Result.buildErrorStateResult("risk_record未找到授信提交记录", false);
        }
        if (riskRecordList.get(0).getApplyStatus() == 1) {
            return Result.buildErrorStateResult("用户已风控授信拒绝，无法重新授信回调！", false);
        }
        if (riskRecordList.get(0).getApplyStatus() == 2) {
            return Result.buildErrorStateResult("用户已完成授信，无法重新授信回调!", false);
        }
        String riskNo = riskRecordList.get(0).getRiskNo();
        JSONObject creditResult = Vcc.vccWindControlCreditCallback(namespace, uuid, riskNo, result, amount);
        if (creditResult.get("content").toString().equals("success")) {
            return Result.buildSuccessResult("授信回调成功！");
        } else {
            return Result.buildErrorStateResult("授信回调失败，请依次检查vcc_talos、acs_service、vcc_quota是否有报错", false);
        }
    }

    /**
     * vcc还款回调
     * @param namespace 环境
     * @param phoneNo 手机号
     * @param result 回调结果
     * @return
     */
    @GetMapping("/repay/callback")
    public Result vccRepayCallback(String namespace, String phoneNo, Integer result) {
        String url = "https://acs-" + namespace + ".liangkebang.net/ex/paycenter/repay_notify";
        SwitchDataSource.dataSourceSwitch(namespace, "xyqb_user");
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("phone_no", phoneNo);
        User user = userService.getOne(userQueryWrapper);
        if (user == null)  {
            return Result.buildErrorStateResult("该用户不存在！", false);
        }
        SwitchDataSource.dataSourceSwitch(namespace, "acsdb");
        QueryWrapper<AcsPayOrder> acsPayOrderQueryWrapper = new QueryWrapper<>();
        acsPayOrderQueryWrapper.eq("user_id", user.getId()).orderByDesc("id");
        List<AcsPayOrder> acsPayOrderList = acsPayOrderService.list(acsPayOrderQueryWrapper);
        if (acsPayOrderList.size() == 0) {
            return Result.buildErrorStateResult("acs_pay_order未查到用户有还款记录", false);
        }
        Integer orderNo = acsPayOrderList.get(0).getId();
        Map<String, Object> formData = new HashMap<>();
        formData.put("orderNo", orderNo);
        if (result.equals(1)) {
            formData.put("remark", "还款成功");
        }
        if (result.equals(2)) {
            formData.put("remark", "还款失败");
        }
        formData.put("payStatus", result);
        formData.put("orderData", "{\"payApproachDesc\":\"易宝-广达小贷-VCC专用\",\"orderId\":\"79884519018498\",\"payApproach\":\"65\",\"payApproachName\":\"YEE_PAY_GDXD_VCC\",\"payGateway\":\"0\",\"cardNo\":\"6217000025253636858\",\"payGatewayName\":\"YEE_PAY\"}");
        JSONObject response = HttpClientUtils.doPost(url, formData);
        log.info("{}环境，用户{}，VCC还款回调结果：{}", namespace, phoneNo, response);
        try {
            if (response.get("content").equals("SUCCESS")) {
                return Result.buildSuccessResult("还款回调成功！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.buildErrorStateResult(JSON.toJSONString(response), false);
        }
        return Result.buildSuccessResult("还款回调成功！");
    }
}
