package com.gree.mall.manager.logic.settle.repair;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gree.mall.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.bean.settle.repair.DailyBankAccountVO;
import com.gree.mall.manager.bean.settle.repair.SettleDailyBankTransferRecordVO;
import com.gree.mall.manager.bean.settle.repair.cmc.BankCardInfoBean;
import com.gree.mall.manager.commonmapper.CommonMapper;
import com.gree.mall.manager.constant.Constant;
import com.gree.mall.manager.enums.ExamineStatusEnum;
import com.gree.mall.manager.enums.UserTypeEnum;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.common.CommonLogic;
import com.gree.mall.manager.logic.common.SMSLogic;
import com.gree.mall.manager.logic.settle.repair.cmc.CmcBankLogic;
import com.gree.mall.manager.plus.entity.*;
import com.gree.mall.manager.plus.service.*;
import com.gree.mall.manager.utils.CommonUtils;
import com.gree.mall.manager.utils.RedisUtil;
import com.gree.mall.manager.utils.excel.ExcelUtils;
import com.gree.mall.manager.zfire.bean.ZfireParamBean;
import com.gree.mall.manager.zfire.util.FieldUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class RepairSettleAccountLogic {
    private final CommonLogic commonLogic;
    private final CommonMapper commonMapper;
    private final SettleDailyBankAccountService settleDailyBankAccountService;
    private final UserService userService;
    private final WebsitUserService websitUserService;
    private final AdminWebsitService adminWebsitService;
    private final SMSLogic smsLogic;
    private final SettleDailyBankTransferRecordService settleDailyBankTransferRecordService;
    private final SettleDailyBankCardBalanceService settleDailyBankCardBalanceService;
    private final RedisUtil redisUtil;
    private final CmcBankLogic cmcBankLogic;
    private final DailyWithholdLogic dailyWithholdLogic;

    public IPage<DailyBankAccountVO> page(ZfireParamBean zfireParamBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        FieldUtils.supplyParam(zfireParamBean, DailyBankAccountVO.class, adminUser);

        return commonMapper.repairSettleBankAccountList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
    }

    public SettleDailyBankAccount detail(String id) {
        return settleDailyBankAccountService.getById(id);
    }


    public void add(SettleDailyBankAccount dailyBankAccount) {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        if (adminUser.getType() == 2) {
            throw new RemoteServiceException("平台账号禁止操作");
        }

        String idcard = dailyBankAccount.getIdcard();
        List<SettleDailyBankAccount> count = settleDailyBankAccountService.lambdaQuery().eq(SettleDailyBankAccount::getIdcard, idcard).list();
        if (count.size() > 0) {
            if (count.get(0).getIdcard().equals(dailyBankAccount.getIdcard())) {
                throw new RemoteServiceException("身份证已存在:" + idcard);
            }

            if (count.get(0).getBankAccount().equals(dailyBankAccount.getBankAccount())) {
                throw new RemoteServiceException("银行卡已存在:" + idcard);
            }
        }

        List<User> userList = userService.lambdaQuery()
                .eq(User::getCompanyWechatId, adminUser.getAdminCompanyWechat().getCompanyWechatId())
                .eq(User::getIdCard, dailyBankAccount.getIdcard())
                .eq(User::getType, UserTypeEnum.WORKER.getKey())
                .list();
        if (CollectionUtil.isEmpty(userList)) {
            throw new RemoteServiceException("身份证在系统不存在:" + idcard);
        }
        if (!dailyBankAccount.getDepositBank().contains("招商银行") && StringUtils.isBlank(dailyBankAccount.getBankAddr())) {
            throw new RemoteServiceException("卡号【" + dailyBankAccount.getBankAccount() + "】非招商银行，请补充开户行");
        }
        dailyBankAccount.setBankAccount(dailyBankAccount.getBankAccount().replaceAll(" ", ""));

        List<SettleDailyBankAccount> accountList = new ArrayList<>();
        // 检查师傅已入驻网点并创建相应网点记录
        final List<WebsitUser> websitUserList = websitUserService.lambdaQuery()
                .eq(WebsitUser::getCompanyWechatId, adminUser.getAdminCompanyWechat().getCompanyWechatId())
                .eq(WebsitUser::getExamineStatus, ExamineStatusEnum.OK.getKey())
                .in(WebsitUser::getUserId, userList.stream().map(User::getUserId).distinct().collect(Collectors.toList()))
                .list();

        final List<String> websits = websitUserList.stream().map(WebsitUser::getWebsitId).distinct().collect(Collectors.toList());

        final Map<String, WebsitUser> websitUserMap = websitUserList.stream()
                .collect(Collectors.toMap(WebsitUser::getWebsitId, Function.identity(), (key1, key2) -> key2));

        final List<AdminWebsit> adminWebsits = adminWebsitService.lambdaQuery()
                .eq(AdminWebsit::getCompanyWechatId, adminUser.getAdminCompanyWechat().getCompanyWechatId())
                .in(AdminWebsit::getWebsitId, websits)
                .list();

        final Map<String, String> websitMap = adminWebsits.stream()
                .collect(Collectors.toMap(AdminWebsit::getWebsitId, AdminWebsit::getName));

        for (String websit : websits) {
            final String websitName = websitMap.get(websit);
            final WebsitUser websitUser = websitUserMap.get(websit);
            SettleDailyBankAccount account = new SettleDailyBankAccount();
            BeanUtils.copyProperties(dailyBankAccount, account);
            account.setCompanyWechatId(adminUser.getAdminCompanyWechat().getCompanyWechatId())
                    .setCompanyName(adminUser.getAdminCompanyWechat().getCompanyName())
                    .setWebsitId(websit)
                    .setWebsitName(websitName)
                    .setWorkerNumber(websitUser.getWorkerNumber());
            accountList.add(account);
        }

        settleDailyBankAccountService.saveBatch(accountList);
    }

    public void update(SettleDailyBankAccount dailyBankAccount) {
//        AdminUserCom adminUser = commonLogic.getAdminUser();

        final SettleDailyBankAccount oldAccount = settleDailyBankAccountService.getById(dailyBankAccount.getId());
        dailyBankAccount.setIdcard(oldAccount.getIdcard());

        List<SettleDailyBankAccount> oldList = settleDailyBankAccountService.lambdaQuery()
                .eq(SettleDailyBankAccount::getIdcard, dailyBankAccount.getIdcard())
                .list();

        for (SettleDailyBankAccount bean : oldList) {
            bean.setWorkerName(dailyBankAccount.getWorkerName())
                    .setMobile(dailyBankAccount.getMobile())
                    .setBankAccount(dailyBankAccount.getBankAccount())
                    .setBankAccountName(dailyBankAccount.getBankAccountName())
                    .setDepositBank(dailyBankAccount.getDepositBank())
                    .setBankAddr(dailyBankAccount.getBankAddr())
                    .setRemark(dailyBankAccount.getRemark());
        }
        settleDailyBankAccountService.updateBatchById(oldList);
    }

    public void delete(String id) {
        settleDailyBankAccountService.removeById(id);
    }

    public void importData(MultipartFile file) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        if (adminUser.getType() == 2) {
            throw new RemoteServiceException("平台账号禁止操作");
        }
        List<Object> objects = ExcelUtils.importExcel(file);
        List<SettleDailyBankAccount> importList = new ArrayList<>();

        List<String> distinctIdcard = new ArrayList<>();
        for (Object o : objects) {
            List<Object> row = (List<Object>) o;
            CommonUtils.initList2(row, row.size() + 1);
            String workerName = (String) row.get(0);//服务人员名称
            String idcard = (String) row.get(1);//身份证号码
            String mobile = (String) row.get(2);//手机号
            String bankAccount = (String) row.get(3);//银行卡号
            String bankAccountName = (String) row.get(4);//户名
            String depositBank = (String) row.get(5);//开户行名称
            String bankAddr = (String) row.get(6);//开户行地址
            String remark = (String) row.get(7);//备注
            if (StringUtils.isEmpty(workerName)) {
                continue;
            }
            if (StringUtils.isEmpty(workerName) || StringUtils.isEmpty(idcard) || StringUtils.isEmpty(bankAccount) ||
                    StringUtils.isEmpty(depositBank) || StringUtils.isEmpty(mobile) || StringUtils.isEmpty(bankAccountName)) {
                throw new RemoteServiceException("师傅【" + workerName + "】服务人员名称/身份证号码/银行卡号/开户行名称/手机号/户名都为必填项");
            }
            if (!depositBank.contains("招商银行") && StringUtils.isEmpty(bankAddr)) {
                throw new RemoteServiceException("师傅【" + workerName + "】非招行开户行必填");
            }
            if (distinctIdcard.contains(idcard)) {
                throw new RemoteServiceException("师傅【" + workerName + "】身份证:" + idcard + "重复");
            }
            distinctIdcard.add(idcard);

            List<User> userList = userService.lambdaQuery()
                    .eq(User::getCompanyWechatId, adminUser.getAdminCompanyWechat().getCompanyWechatId())
                    .eq(User::getIdCard, idcard)
                    .eq(User::getType, UserTypeEnum.WORKER.getKey())
                    .list();
            if (CollectionUtil.isEmpty(userList)) {
                throw new RemoteServiceException("身份证在系统不存在:" + idcard);
            }
            //删除
            settleDailyBankAccountService.lambdaUpdate().eq(SettleDailyBankAccount::getIdcard, idcard).remove();

            SettleDailyBankAccount dailyBankAccount = new SettleDailyBankAccount();
            dailyBankAccount.setCompanyWechatId(adminUser.getAdminCompanyWechat().getCompanyWechatId());
            dailyBankAccount.setCompanyName(adminUser.getAdminCompanyWechat().getCompanyName());
            dailyBankAccount.setWorkerName(workerName);
            dailyBankAccount.setIdcard(idcard);
            dailyBankAccount.setMobile(mobile);
            dailyBankAccount.setBankAccount(bankAccount);
            dailyBankAccount.setBankAccountName(bankAccountName);
            dailyBankAccount.setDepositBank(depositBank);
            dailyBankAccount.setBankAddr(bankAddr);
            dailyBankAccount.setRemark(remark);
            dailyBankAccount.setBankAccount(dailyBankAccount.getBankAccount().replaceAll(" ", ""));

            // 检查师傅已入驻网点并创建相应网点记录
            final List<WebsitUser> websitUserList = websitUserService.lambdaQuery()
                    .eq(WebsitUser::getCompanyWechatId, adminUser.getAdminCompanyWechat().getCompanyWechatId())
                    .eq(WebsitUser::getExamineStatus, ExamineStatusEnum.OK.getKey())
                    .in(WebsitUser::getUserId, userList.stream().map(User::getUserId).distinct().collect(Collectors.toList()))
                    .list();

            final List<String> websits = websitUserList.stream().map(WebsitUser::getWebsitId).distinct().collect(Collectors.toList());

            final Map<String, WebsitUser> websitUserMap = websitUserList.stream()
                    .collect(Collectors.toMap(WebsitUser::getWebsitId, Function.identity(), (key1, key2) -> key2));

            final List<AdminWebsit> adminWebsits = adminWebsitService.lambdaQuery()
                    .eq(AdminWebsit::getCompanyWechatId, adminUser.getAdminCompanyWechat().getCompanyWechatId())
                    .in(AdminWebsit::getWebsitId, websits)
                    .list();

            final Map<String, String> websitMap = adminWebsits.stream()
                    .collect(Collectors.toMap(AdminWebsit::getWebsitId, AdminWebsit::getName));

            for (String websit : websits) {
                final String websitName = websitMap.get(websit);
                final WebsitUser websitUser = websitUserMap.get(websit);
                SettleDailyBankAccount account = new SettleDailyBankAccount();
                BeanUtils.copyProperties(dailyBankAccount, account);
                account.setCompanyWechatId(adminUser.getAdminCompanyWechat().getCompanyWechatId())
                        .setCompanyName(adminUser.getAdminCompanyWechat().getCompanyName())
                        .setWebsitId(websit)
                        .setWebsitName(websitName)
                        .setWorkerNumber(websitUser.getWorkerNumber());
                importList.add(account);
            }
        }

        if (CollectionUtil.isNotEmpty(importList))
            settleDailyBankAccountService.saveBatch(importList);
    }

    public void sendMsg(String mobile, String type) throws Exception {
        if (!Validator.isMobile(mobile)) {
            throw new RemoteServiceException("手机号格式不正确。");
        }
        // 向手机号发送验证码
        String sendType = Constant.RedisPrefix.BALANCE_SEL_MOBILE_SMS;
        if (type != null && type.equals("issue")) {
            sendType = Constant.RedisPrefix.ISSUE_SAL_MOBILE_SMS;
        }
        smsLogic.sendSms(sendType, mobile, "BALANCE_SEL", Constant.SMS_EXPIRE);
    }

    public IPage<SettleDailyBankTransferRecordVO> transferList(ZfireParamBean zfireParamBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        FieldUtils.supplyParam(zfireParamBean, DailyBankAccountVO.class, adminUser);

        return commonMapper.transferList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean, adminUser.getCompanyWechatIds());
    }

    public IPage<SettleDailyBankCardBalance> companyAccountList(Integer pageNo, Integer pageSize) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        return settleDailyBankCardBalanceService.lambdaQuery()
                .in(CollectionUtil.isNotEmpty(adminUser.getCompanyWechatIds()), SettleDailyBankCardBalance::getCompanyWechatId, adminUser.getCompanyWechatIds())
                .orderByDesc(SettleDailyBankCardBalance::getCreateTime)
                .page(new Page<>(pageNo, pageSize));
    }

    /**
     * 查询银行卡余额
     */
    @Transactional
    public SettleDailyBankCardBalance selBankCardBalance(Integer id ,String mobile,String code) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        if (adminUser.getType() == 2) {
            throw new RemoteServiceException("平台账号禁止操作");
        }

        Object validMessageCode = redisUtil.get(Constant.RedisPrefix.BALANCE_SEL_MOBILE_SMS + mobile);
        if(validMessageCode == null || code == null){
            throw new RemoteServiceException("请先发送验证码");
        }
        if (!code.equals(validMessageCode.toString())){
            throw new RemoteServiceException("短信验证码输入错误");
        }

        SettleDailyBankCardBalance bankCardBalance = settleDailyBankCardBalanceService.getById(id);
        if(bankCardBalance == null){
            throw new RemoteServiceException("公司信息不存在");
        }
        List<BankCardInfoBean> list = new ArrayList<>();
        BankCardInfoBean bankCardInfoBean = new BankCardInfoBean();
        bankCardInfoBean.setAuthType("1");
        bankCardInfoBean.setBankAccount(bankCardBalance.getBankCardId());
        bankCardInfoBean.setBankOrgCode(bankCardBalance.getOpenBankOrgId());
        list.add(bankCardInfoBean);
        Map<String,Object> response = cmcBankLogic.getAccountBalance(list,bankCardBalance.getSummaryNumber());
        if (Objects.isNull(response)) {
            throw new RemoteServiceException("调用银行接口出错, 返回空结果, 请联系管理者查看具体错误日志!");
        }
        JSONObject head = JSONObject.parseObject(response.get("head").toString());

        if(head != null && head.get("resultcode").equals("SUC0000")){
            Map<String,Map<String,Object>> body = (Map<String, Map<String, Object>>) response.get("body");
            List<Map<String,Object>> ntqadinfz = (List<Map<String,Object>>) body.get("ntqadinfz");
            bankCardBalance.setBalanceAmount(new BigDecimal(ntqadinfz.get(0).get("avlblv").toString()));
            bankCardBalance.setUpdateTime(new Date());
            bankCardBalance.updateById();
        }else {
            throw new RemoteServiceException("查询失败" + response.get("errtxt"));
        }

        return bankCardBalance;
    }

    /**
     * 查询银行卡余额
     */
//    public void warnBalanceExcute() throws Exception {
//        List<SettleDailyBankCardBalance> bankList = settleDailyBankCardBalanceService.lambdaQuery()
//                .list();
//        if (bankList.size() == 0) {
//            log.info("warnBalanceExcute :公司信息不存在。");
//            throw new RemoteServiceException("公司信息不存在。");
//        }
//        //获取余额预警值
//        List<SysDictCompany> warnDict = dailyWithholdLogic.getConfig(DictCodeEnum.BANLANCE_WARN_VALUE.toString());
//        if (warnDict.size() == 0) {
//            log.info("warnBalanceExcute :余额预警值未配置。");
//            throw new RemoteServiceException("余额预警值未配置。");
//        }
//        BigDecimal warnvalue = new BigDecimal(warnDict.get(0).getDictValue());
//
//        for (SettleDailyBankCardBalance cardBalance : bankList) {
//            //组装请求参数
//            List<BankCardInfoBean> list = new ArrayList<>();
//            BankCardInfoBean bankCardInfoBean = new BankCardInfoBean();
//            bankCardInfoBean.setAuthType("1");
//            bankCardInfoBean.setBankAccount(cardBalance.getBankCardId());
//            bankCardInfoBean.setBankOrgCode(cardBalance.getOpenBankOrgId());
//            list.add(bankCardInfoBean);
//            //查询余额
//            Map<String, Object> response = cmcBankLogic.getAccountBalance(list, cardBalance.getSummaryNumber());
//
//            JSONObject head = JSONObject.parseObject(response.get("head").toString());
//            if (head != null && head.get("resultcode").equals("SUC0000")) {
//                Map<String, Map<String, Object>> body = (Map<String, Map<String, Object>>) response.get("body");
//                List<Map<String, Object>> ntqadinfz = (List<Map<String, Object>>) body.get("ntqadinfz");
//                BigDecimal balance = new BigDecimal(ntqadinfz.get(0).get("avlblv").toString());
//                if (balance.doubleValue() < warnvalue.doubleValue()) {
//                    log.info("向 {} 发送余额预警短信 余额为： {}",cardBalance.getAccountName(),balance);
//                    sendWarnMsg(cardBalance.getCompanyWechatName());
//                }
//
//            } else {
//                log.warn("warnBalanceExcute :查询失败" + response.get("errtxt"));
//                // throw new RemoteServiceException("查询失败" + response.get("errtxt"));
//            }
//        }
//
//    }

//    public void sendWarnMsg(String companyName) throws Exception {
//
//        String dayFmt = DateUtil.format(new Date(), "yyyy年MM月dd日");
//        List<Dict> list = dailyWithholdLogic.getConfig(DictCodeEnum.SELECT_BANLANCE.toString());
//        for (Dict dict : list) {
//            if (dict.getDescription().contains(companyName)) {
//                HashMap<String,String> params = new HashMap<>();
//                params.put("date",dayFmt);
//                params.put("accountName",companyName);
//                smsLogic.send(dict.getDictValue(), DailyConstant.WARN_TEMPLEATE, params);
//            }
//        }
//
//    }

}
