package com.yn.bftl.thirdparty.modules.chinaums.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import com.alibaba.fastjson.JSONObject;
import com.yn.bftl.common.common.exception.YnceError;
import com.yn.bftl.common.common.util.ByxRouteUtil;
import com.yn.bftl.common.common.util.RouteUtil;
import com.yn.bftl.common.modules.base.entity.BankLineNumber;
import com.yn.bftl.common.modules.base.vo.MetaFileVO;
import com.yn.bftl.common.modules.company.entity.ChinaumsAuthInfo;
import com.yn.bftl.common.modules.company.entity.Company;
import com.yn.bftl.common.modules.meta.entity.MetaFile;
import com.yn.bftl.thirdparty.common.constants.Constant;
import com.yn.bftl.thirdparty.common.enums.SmsTmpltCode;
import com.yn.bftl.thirdparty.common.exception.YnceErrorException;
import com.yn.bftl.thirdparty.common.service.BaseMemberService;
import com.yn.bftl.thirdparty.modules.baiduai.service.ClassCardService;
import com.yn.bftl.thirdparty.modules.baiduai.vo.BusinessLicenseInfoVO;
import com.yn.bftl.thirdparty.modules.baiduai.vo.IdcardInfoVO;
import com.yn.bftl.thirdparty.modules.business.service.MetaFileService;
import com.yn.bftl.thirdparty.modules.chinaums.dto.ChinaumsPostDTO;
import com.yn.bftl.thirdparty.modules.chinaums.dto.ChinaumsUploadImagesDTO;
import com.yn.bftl.thirdparty.modules.chinaums.dto.byx.ByxChinaumsQueryBillInfoDTO;
import com.yn.bftl.thirdparty.modules.chinaums.dto.byx.ByxSmsSendDTO;
import com.yn.bftl.thirdparty.modules.chinaums.dto.chinaums.ChinaumsAmountValidate;
import com.yn.bftl.thirdparty.modules.chinaums.repository.BankLineNumberRepository;
import com.yn.bftl.thirdparty.modules.chinaums.repository.ChinaumsAuthInfoRepository;
import com.yn.bftl.thirdparty.modules.chinaums.service.AuthService;
import com.yn.bftl.thirdparty.modules.chinaums.service.ToolService;
import com.yn.bftl.thirdparty.modules.chinaums.util.ByxChinaumsUtil;
import com.yn.bftl.thirdparty.modules.chinaums.util.ChinaumsUtil;
import com.yn.bftl.thirdparty.modules.chinaums.vo.BankLineNumberVO;
import com.yn.bftl.thirdparty.modules.chinaums.vo.ChinaumsImageVO;
import com.yn.bftl.thirdparty.modules.chinaums.vo.byx.ByxChinaumsQueryBillInfoVO;
import com.yn.bftl.thirdparty.modules.chinaums.vo.byx.ByxQueryBillInfoRow;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.ServletOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 银联工具服务实现
 *
 * @author huabiao
 * @create 2022/12/6  18:48
 **/
@Service
public class ToolServiceImpl extends BaseMemberService implements ToolService {

    @Resource
    private BankLineNumberRepository bankLineNumberRepository;
    @Resource
    private ChinaumsUtil chinaumsUtil;
    @Resource
    private ChinaumsAuthInfoRepository chinaumsAuthInfoRepository;
    @Resource
    private MetaFileService metaFileService;
    @Resource
    private ClassCardService classCardService;
    @Resource
    private ByxChinaumsUtil byxChinaumsUtil;
    @Resource
    private AuthService authService;

    @Override
    public ChinaumsImageVO uploadImage(MultipartFile file, String type) {
        ChinaumsImageVO chinaumsImageVO = new ChinaumsImageVO();
        if (StringUtils.isNotBlank(type)) {
            switch (type) {
                case "front":
                case "back":
                    IdcardInfoVO idcardInfoVO = classCardService.idcard(file, type);
                    chinaumsImageVO.setIdcardInfoVO(idcardInfoVO);
                    break;
                case "business_license":
                    BusinessLicenseInfoVO businessLicenseInfoVO = classCardService.businessLicense(file, true, false);
                    chinaumsImageVO.setBusinessLicenseInfoVO(businessLicenseInfoVO);
                    break;
                default:
            }
        }

        // 上传图片到银联
        String contentType = file.getContentType();
        String base64EncoderImg;
        try {
            // 图片转base64
            byte[] imageBytes;
            imageBytes = file.getBytes();
            Base64 base64Encoder = new Base64();
            base64EncoderImg = Base64.encodeBase64String(imageBytes);
        } catch (IOException ioException) {
            throw new YnceErrorException("图片转换异常");
        }
        ChinaumsUploadImagesDTO chinaumsUploadImagesDTO = ChinaumsUploadImagesDTO.builder()
                .file(base64EncoderImg)
                .filename(file.getOriginalFilename())
                .mimeType(contentType)
                .build();
        Map jsonObject = chinaumsUtil.execute(RouteUtil.ROUTE_WALLET_IMAGES, (JSONObject) JSONObject.toJSON(chinaumsUploadImagesDTO), Map.class);
        // 保存图片到服务器
        MetaFile metaFile = metaFileService.fileUpload(file);
        // 获取VO数据
        MetaFileVO metaFileVO = metaFileService.getMetaFileVO(metaFile);
        BeanUtils.copyProperties(metaFileVO, chinaumsImageVO);
        chinaumsImageVO.setMediaId(jsonObject.get("mediaId").toString());
        return chinaumsImageVO;
    }

    @Override
    public Page<BankLineNumberVO> getBankList(String keyword, Pageable pageable) {
        Specification<BankLineNumber> specification = new Specification<BankLineNumber>() {
            @Override
            public Predicate toPredicate(Root<BankLineNumber> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if (StringUtils.isNotBlank(keyword)) {
                    // 如果包含空格则切分关键字
                    if (keyword.contains(" ")) {
                        String[] keywordList = keyword.split(" ");
                        for (String s : keywordList) {
                            predicates.add(criteriaBuilder.like(root.get("bankName"), "%" + s + "%"));
                        }
                    } else {
                        predicates.add(criteriaBuilder.like(root.get("bankName"), "%" + keyword + "%"));
                    }

                }
                query.where(predicates.toArray(new Predicate[predicates.size()]));
                query.orderBy(criteriaBuilder.desc(root.get("createdOn")));
                return query.getRestriction();
            }
        };
        Page<BankLineNumber> bankLineNumberPage = bankLineNumberRepository.findAll(specification, pageable);
        List<BankLineNumberVO> bankLineNumberVOList = new ArrayList<>();
        for (BankLineNumber bankLineNumber : bankLineNumberPage.getContent()) {
            BankLineNumberVO bankLineNumberVO = new BankLineNumberVO();
            BeanUtils.copyProperties(bankLineNumber, bankLineNumberVO);
            bankLineNumberVOList.add(bankLineNumberVO);
        }
        PageImpl<BankLineNumberVO> bankLineNumberVOPage = new PageImpl(bankLineNumberVOList, pageable, bankLineNumberPage.getTotalElements());
        return bankLineNumberVOPage;
    }

    @Override
    public Boolean amountValidate(BigDecimal amount) {
        Company company = getUser().getCompany();
        ChinaumsAuthInfo chinaumsAuthInfo = chinaumsAuthInfoRepository.findFirstByCompanyId(company.getId());
        if (chinaumsAuthInfo == null) {
            throw new YnceErrorException(YnceError.YNCE_218009);
        }
        ChinaumsAmountValidate chinaumsAmountValidate = ChinaumsAmountValidate
                .builder()
                .settleAcctId(chinaumsAuthInfo.getSettleAcctId())
                .payAmount(amount.multiply(new BigDecimal(100)).intValue())
                .build();
        chinaumsUtil.execute(RouteUtil.ROUTE_WALLET_ACCTS_VALIDATE, (JSONObject) JSONObject.toJSON(chinaumsAmountValidate), null);
        return true;
    }

    @Override
    public void smsCodes(String mobile) {
        smsCodes(mobile, SmsTmpltCode.COMMON,5);
    }

    @Override
    public String tradeBills(LocalDate billDate) {
//        JSONObject jsonObject = new JSONObject();
//        jsonObject.put("billDate", billDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
//        Map result = chinaumsUtil.execute(RouteUtil.ROUTE_WALLET_TRADE_BILLS, jsonObject, Map.class);
//        return result.get("downloadUrl").toString();

        ChinaumsAuthInfo chinaumsAuthInfo = authService.getCurrentAuthInfo();
        DateTime dateTime =ObjectUtil.isEmpty(billDate)?DateTime.now(): new DateTime(billDate);

        ByxChinaumsQueryBillInfoDTO billInfoDTO = new ByxChinaumsQueryBillInfoDTO();
        billInfoDTO.setStartDate(DateUtil.beginOfDay(dateTime).toString());
        billInfoDTO.setEndDate(DateUtil.endOfDay(dateTime).toString());
        billInfoDTO.setWalletId(chinaumsAuthInfo.getBalanceAcctId());
        ByxChinaumsQueryBillInfoVO byxChinaumsQueryBillInfoVO = byxChinaumsUtil.execute(ByxRouteUtil.ROUTE_WALLET_TRADE_BILLS, (JSONObject) JSONObject.toJSON(billInfoDTO), ByxChinaumsQueryBillInfoVO.class);

        if(Constant.RETURN_SUCCESS_CODE.equals(byxChinaumsQueryBillInfoVO.getRspCode())){
            // todo 生成excel并返回下载url
            export(byxChinaumsQueryBillInfoVO.getTransList());
        }

        return "";
    }

    @Override
    public void smsCodesForResetPassword() {
        JSONObject jsonObject = new JSONObject();
        ChinaumsAuthInfo chinaumsAuthInfo = chinaumsAuthInfoRepository.findFirstByCompanyId(getUser().getCompany().getId());
        if (chinaumsAuthInfo == null) {
            throw new YnceErrorException(YnceError.YNCE_218009);
        }
//        jsonObject.put("balanceAcctId", chinaumsAuthInfo.getBalanceAcctId());
//        chinaumsUtil.execute(RouteUtil.ROUTE_WALLET_UPAPI_ACCT_PASSWORD_SMS_CODES, jsonObject, null);
        smsCodes(chinaumsAuthInfo.getLegalPersonMobileNumber(), SmsTmpltCode.COMMON,2);
    }

    @Override
    public JSONObject postTool(ChinaumsPostDTO chinaumsPostDTO) {
        return chinaumsUtil.execute(chinaumsPostDTO.getUrl(), chinaumsPostDTO.getJsonObject(), JSONObject.class);
    }


    private void smsCodes(String mobile,SmsTmpltCode smsTmpltCode) {
        smsCodes(mobile, smsTmpltCode, null);
    }

    /**
     *
     * @param mobile 需要验证的手机号码
     * @param smsTmpltCode COMMON：一般验证码 REGIST：开户 ACTIVATE：激活 TRADE：交易 可直接使用一般验证码
     * @param smsBizType 1：绑定第三方用户 2：重置密码 3：变更手机号 4：开户 5：银行卡签约 6：交易
     */
    private void smsCodes(String mobile,SmsTmpltCode smsTmpltCode,Integer smsBizType) {
//        JSONObject jsonObject = new JSONObject();
//        jsonObject.put("mobileNumber", mobile);
//        chinaumsUtil.execute(RouteUtil.ROUTE_WALLET_SMS_CODES, jsonObject, null);
        ByxSmsSendDTO byxSmsSendDTO = new ByxSmsSendDTO();
        byxSmsSendDTO.setMobileNo(mobile);
        byxSmsSendDTO.setSmsTmpltCode(smsTmpltCode.getValue());
        byxSmsSendDTO.setSmsBizType(smsBizType);
        byxChinaumsUtil.execute(ByxRouteUtil.ROUTE_WALLET_SMS_CODES, (JSONObject) JSONObject.toJSON(byxSmsSendDTO), JSONObject.class);
    }

    private void export(List<ByxQueryBillInfoRow> transList){
        // 1.获取ExcelWriter对象
        ExcelWriter writer = ExcelUtil.getBigWriter();
        // 2.写出表头
        // 自定义标题别名
        writer.addHeaderAlias("name", "姓名");
        writer.addHeaderAlias("age", "年龄");
        writer.addHeaderAlias("hobby", "爱好");
        // ...
        // 3.定义表头单元格样式(可选)
        StyleSet style = writer.getStyleSet();
        CellStyle headCellStyle = style.getHeadCellStyle();
        // 自动换行
        headCellStyle.setWrapText(true);
        // 水平居中
        headCellStyle.setAlignment(HorizontalAlignment.CENTER);
        // 上下居中
        headCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 设置表头字体大小
        Font headFont = writer.createFont();
        headFont.setFontName("宋体");
        headFont.setFontHeightInPoints((short) 15); // 设置字体大小为15磅
        headCellStyle.setFont(headFont);
        // 4.定义内容单元格样式(可选)
        CellStyle cellStyle = style.getCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.LEFT);
        // 设置字体大小
        Font font = writer.createFont();
        font.setFontName("宋体");
        cellStyle.setFont(font);
        // 5.其他设置(可选)
        // 只写出设置别名的属性
        writer.setOnlyAlias(true);
        // 冻结行
        writer.setFreezePane(1);
        // 6.写入数据 设置列宽
        writer.write(transList);
        writer.autoSizeColumnAll();
        // 7.开启筛选(可选)
        // 这里数值为列数
        String rangeString = CellReference.convertNumToColString(3) + "1";
        CellRangeAddress filterRange = CellRangeAddress.valueOf("A1:" + rangeString);
        writer.getSheet().setAutoFilter(filterRange);
        // 8.导出
//        response.setCharacterEncoding(CharsetUtil.UTF_8);
//        response.setHeader("Content-Disposition","attachment;filename=test.xlsx");
//        response.setContentType("application/vnd.ms-excel;" + CharsetUtil.UTF_8);
//        try (ServletOutputStream outputStream = response.getOutputStream()) {
//            writer.flush(outputStream);
//            writer.close();
//        } catch (Exception e) {
//            log.warn("批量导出出错：{}", e.getMessage());
//        }
    }

}
