package com.crm.ucard.service.impl;

import com.alibaba.fastjson.JSON;
import com.crm.rely.backend.core.constant.ConfigConstants;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.dto.base.PageDto;
import com.crm.rely.backend.core.dto.base.ResultWithPagerDto;
import com.crm.rely.backend.core.dto.custom.file.CustomFileDto;
import com.crm.rely.backend.core.dto.ucard.CardKycSingleStatusDto;
import com.crm.rely.backend.core.dto.ucard.CardKycStatusDto;
import com.crm.rely.backend.core.entity.base.SingleLongEntity;
import com.crm.rely.backend.core.entity.custom.kyc.CustomKycVerifyRecodeEntity;
import com.crm.rely.backend.core.entity.custom.kyc.WebsdkLinkAliEntity;
import com.crm.rely.backend.core.entity.ucard.CardKycApproveEntity;
import com.crm.rely.backend.core.entity.ucard.CardKycStatusPageEntity;
import com.crm.rely.backend.core.enums.CardOperateTypeEnum;
import com.crm.rely.backend.core.pojo.table.*;
import com.crm.rely.backend.core.pojo.table.ucard.CardKycStatusTable;
import com.crm.rely.backend.core.pojo.table.ucard.CardMerchantUserTable;
import com.crm.rely.backend.core.pojo.table.ucard.CardOperateTable;
import com.crm.rely.backend.core.pojo.table.ucard.UcardWalletTable;
import com.crm.rely.backend.exception.ServiceException;
import com.crm.rely.backend.service.EmailService;
import com.crm.rely.backend.util.CustomInfoUtil;
import com.crm.ucard.dao.mapper.CardKycStatusMapper;
import com.crm.ucard.dao.repository.*;
import com.crm.ucard.service.*;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Slf4j
@Service
public class KycServiceImpl implements KycService {

    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private CardMerchantUserRepository merchantUserRepository;
    @Autowired
    private CardKycStatusRepository kycStatusRepository;
    @Autowired
    private CardOperateRepository cardOperateRepository;
    @Autowired
    private CustomInfoRepository customInfoRepository;
    @Autowired
    private CustomKycApproveRepository customKycApproveRepository;
    @Autowired
    private UcardWalletRepository ucardWalletRepository;
    @Autowired
    private CardKycStatusMapper kycStatusMapper;
    @Autowired
    private CustomKycImageRepository customKycImageRepository;
    @Autowired
    private CustomFileRepository customFileRepository;
    @Autowired
    private UcardEmailService ucardEmailService;
    @Autowired
    private EmailService emailService;
    @Autowired
    private KycFeignService kycFeignService;
    @Autowired
    private SysKycConfigService sysKycConfigService;

    /**
     * 身份认证获取web链接
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto getWebsdkLink(WebsdkLinkAliEntity entity, Long id) throws ServiceException {

        CustomInfoTable table = customInfoRepository.findFirstById(id);
        if (table == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        CardMerchantUserTable merchantUserTable = merchantUserRepository.findFirstById(entity.getCardId());
        if (merchantUserTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        if (1 == merchantUserTable.getAuthStatus()) {
            return BaseResultDto.result(201, "已认证");
        }
        CardKycStatusTable kycStatusTable = kycStatusRepository.findFirstByUniqueId(merchantUserTable.getUniqueId());
        if (2 == kycStatusTable.getStatus()) {
            throw ServiceException.exception("已手动审核成功");
        }

        CustomKycApproveTable approveTable = customKycApproveRepository.findFirstByCustomIdAndStatus(table.getId(), 1);
        if (null != approveTable) {
            throw ServiceException.exception("正在审核中");
        }
        SysConfigTable sysConfigTable = sysConfigService.getByCode(ConfigConstants.CUSTOM_VERIFY_KYC_PROPERTY);
        if (sysConfigTable == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        SysKycConfigTable kycConfig = sysKycConfigService.getByCodeAndCountryAndEnable(sysConfigTable.getValue(),
                table.getCountry(), 1);
        if (kycConfig == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }

        if (2 == kycConfig.getKycType() && !Strings.isNullOrEmpty(merchantUserTable.getKycVerifyUrl())) {
            return BaseResultDto.success(Constants.SUCCESS, merchantUserTable.getKycVerifyUrl());
        }
        String cardType = table.getCardType();
        if ("CN".equals(merchantUserTable.getCountry()) && "PASSPORT".equals(merchantUserTable.getIdType())) {
            cardType = "PASSPORT";
        }

        CustomKycVerifyRecodeEntity customKycVerifyRecodeEntity = new CustomKycVerifyRecodeEntity();
        customKycVerifyRecodeEntity.setCountry(merchantUserTable.getCountry());
        customKycVerifyRecodeEntity.setConfig(ConfigConstants.CUSTOM_VERIFY_KYC_PROPERTY);
        customKycVerifyRecodeEntity.setCardType(cardType);
        customKycVerifyRecodeEntity.setVerifyId(merchantUserTable.getId());
        customKycVerifyRecodeEntity.setVerifyType(6);
        customKycVerifyRecodeEntity.setCustomAuth(table.getAuthStatus());
        customKycVerifyRecodeEntity.setEndUserId(Strings.isNullOrEmpty(table.getEndUserId()) ?
                UUID.randomUUID().toString() : table.getEndUserId());
        customKycVerifyRecodeEntity.setCustomId(table.getId());

        /*if (3 != kycConfig.getKycType()) {*/
//        merchantUserTable.setExternalUserId(customKycVerifyRecodeEntity.getEndUserId());
        merchantUserTable.setExternalUserId(Strings.isNullOrEmpty(table.getExternalUserId()) ?
                UUID.randomUUID().toString() : table.getExternalUserId());
        customKycVerifyRecodeEntity.setExternalUserId(merchantUserTable.getExternalUserId());
            /*String applicantId = kycFeignService.createApplicant(customKycVerifyRecodeEntity);

            customKycVerifyRecodeEntity.setApplicantId(applicantId);
            List<CustomFileTable> fileList = customFileDao.findFileByType(table.getId());
            if(fileList != null && fileList.size() > 0){
                customKycVerifyRecodeEntity.setVerifyType(1);
                customKycVerifyRecodeEntity.setVerifyFile(fileList.stream().map(CustomFileTable::getPath).collect
        (Collectors.joining(",")));
                kycFeignService.uploadImage(customKycVerifyRecodeEntity);
            }*//*

            bankTable.setApplicantId(applicantId);
        }*/

//        merchantUserTable.setAuthStatus(0);
        //bankTable.setExternalUserId(Strings.isNullOrEmpty(customKycVerifyRecodeEntity.getExternalUserId()) ?
        // UUIDUtil.getUUID() : customKycVerifyRecodeEntity.getExternalUserId());

        customKycVerifyRecodeEntity.setMetaInfo(entity.getMetaInfo());
        //customKycVerifyRecodeEntity.setExternalUserId(bankTable.getExternalUserId());
        //customKycVerifyRecodeEntity.setApplicantId(bankTable.getApplicantId());
        log.info(String.format("customKycVerifyRecodeEntity is :%s", JSON.toJSONString(customKycVerifyRecodeEntity)));
        BaseResultDto<CustomKycVerifyRecodeEntity> dto = kycFeignService.getWebsdkLink(customKycVerifyRecodeEntity);
        CustomKycVerifyRecodeEntity recodeEntity = dto.getData();
        if (2 == kycConfig.getKycType() && Strings.isNullOrEmpty(merchantUserTable.getKycVerifyUrl())) {
            merchantUserTable.setKycVerifyUrl(recodeEntity.getWebUrl());
            merchantUserTable.setApplicantId(recodeEntity.getApplicantId());
        }
        merchantUserRepository.save(merchantUserTable);

        if (Strings.isNullOrEmpty(table.getEndUserId())) {
            table.setEndUserId(recodeEntity.getEndUserId());
        }
        if (Strings.isNullOrEmpty(table.getExternalUserId())) {
            table.setExternalUserId(recodeEntity.getExternalUserId());
        }
        customInfoRepository.save(table);
        if (Strings.isNullOrEmpty(kycStatusTable.getExternalUserId())) {
            kycStatusTable.setExternalUserId(table.getExternalUserId());
            kycStatusRepository.save(kycStatusTable);
        }

        CardOperateTable operateTable = new CardOperateTable();
        operateTable.setOperateUser(table.getCId());
        operateTable.setOperateType(CardOperateTypeEnum.GET_FACE_AUTH_LINK.getCode());
        operateTable.setStatus(Constants.SUCCESS);
        operateTable.setAddTime(new Date());
        operateTable.setUniqueId(merchantUserTable.getUniqueId());
        cardOperateRepository.save(operateTable);

        return BaseResultDto.success(Constants.SUCCESS, recodeEntity.getWebUrl());
    }

    /**
     * kyc认证详情
     */
    @Override
    public BaseResultDto kycStatusSingle(SingleLongEntity entity) throws ServiceException {
        CardKycSingleStatusDto dto = kycStatusMapper.getKycApproveById(entity.getId());
        if (dto == null) {
            throw ServiceException.exception(Constants.INFO_NOT_FOUND);
        }
        dto.setInfoName(CustomInfoUtil.getNameByCountry(dto.getInfoFirstName(), dto.getInfoLastName(),
                dto.getMiddle(), dto.getCountry()));
        List<CustomFileDto> cardFiles = new ArrayList<>();
        if (StringUtils.isNotEmpty(dto.getIdBackUrl())) {
            CustomFileDto backDto = new CustomFileDto();
            backDto.setPath(dto.getIdBackUrl());
            cardFiles.add(backDto);
        }
        if (StringUtils.isNotEmpty(dto.getIdFrontUrl())) {
            CustomFileDto frontDto = new CustomFileDto();
            frontDto.setPath(dto.getIdFrontUrl());
            cardFiles.add(frontDto);
        }
        if (StringUtils.isNotEmpty(dto.getIdHoldUrl())) {
            CustomFileDto holdDto = new CustomFileDto();
            holdDto.setPath(dto.getIdHoldUrl());
            cardFiles.add(holdDto);
        }
        dto.setCardFiles(cardFiles);
        dto.setCardName(CustomInfoUtil.getNameByCountry(dto.getFirstName(), null, dto.getLastName(), dto.getCountry()));
        List<CustomFileDto> kycFiles = new ArrayList<>();
        // 查询认证文件，判断国家是否是中国，不是中国直接使用externalUserId查询，
        // 中国，因为kyc审核表的externalUserId每次都会变，导致存在多次记录的情况直接用externalUserId查询认证文件表会查询不到数据
        // 根据用户的id(bankId)按照时间倒序查询 所有审核通过的externalUserId
        // 批量查询所有文件信息 按照时间倒序匹配有文件信息的数据
        if (dto.getKycAuthStatus() != null && dto.getKycAuthStatus().equals(1)) {
            List<CustomKycImageTable> imagefiles = null;
            if ("CN".equals(dto.getMerchantCountry())) {
                List<CustomKycApproveTable> approveTables =
                        customKycApproveRepository.findByCIdAndStatusOrderByAddTimeDesc(dto.getCId(), 2);
                if (CollectionUtils.isNotEmpty(approveTables)) {
                    List<String> externalUserIds = approveTables.stream()
                            .map(CustomKycApproveTable::getExternalUserId)
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());

                    // 批量查询所有相关的图片
                    List<CustomKycImageTable> allImages =
                            customKycImageRepository.findAllByExternalUserIdIn(externalUserIds);

                    // 按 externalUserId 分组
                    Map<String, List<CustomKycImageTable>> imagesByExternalUserId = allImages.stream()
                            .collect(Collectors.groupingBy(CustomKycImageTable::getExternalUserId));

                    for (CustomKycApproveTable approveTable : approveTables) {
                        List<CustomKycImageTable> images = imagesByExternalUserId.get(approveTable.getExternalUserId());
                        if (CollectionUtils.isNotEmpty(images)) {
                            dto.setKycStatus(approveTable.getStatus());
                            dto.setKycIdNumber(approveTable.getKycIdNumber());
                            dto.setKycNumber(approveTable.getKycNumber());
                            dto.setKycName(approveTable.getKycName());
                            dto.setKycApproveId(approveTable.getId());
                            dto.setKycAuthStatus(approveTable.getStatus());
                            imagefiles = images;
                            break;
                        }
                    }
                }
            } else {
                imagefiles = customKycImageRepository.findAllByExternalUserId(dto.getExternalUserId());
            }
            if (CollectionUtils.isNotEmpty(imagefiles)) {
                for (CustomKycImageTable fileTable : imagefiles) {
                    CustomFileDto fileDto = new CustomFileDto();
                    fileDto.setPath(fileTable.getFileUrl());
                    fileDto.setType(fileTable.getType());
                    kycFiles.add(fileDto);
                }
                dto.setKycFiles(kycFiles);
            }
        }

        List<CustomFileDto> infoFiles = new ArrayList<>();
        List<CustomFileTable> fileTables = customFileRepository.getAllByCustomId(dto.getCustomId());
        for (CustomFileTable fileTable : fileTables) {
            CustomFileDto fileDto = new CustomFileDto();
            BeanUtils.copyProperties(fileTable, fileDto);
            infoFiles.add(fileDto);
        }
        dto.setInfoFiles(infoFiles);
        return BaseResultDto.success(dto);
    }

    /**
     * 手动KYC认证
     *
     * @param entity 认证请求参数
     * @return 认证结果
     * @throws ServiceException 服务异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto manualSubmitKyc(CardKycApproveEntity entity) throws ServiceException {
        CardKycStatusTable table = kycStatusRepository.findFirstById(entity.getId());
        if (table == null) {
            throw new ServiceException("认证信息不存在");
        }
        if (table.getStatus().equals(entity.getStatus())) {
            return BaseResultDto.success();
        }
        if (1 != table.getStatus()) {
            throw new ServiceException("用户已认证");
        }

        BeanUtils.copyProperties(entity, table);
        table.setModifyTime(new Date());
        kycStatusRepository.save(table);

        String status = null;
        CardMerchantUserTable merchantUserTable = merchantUserRepository.findByUniqueId(table.getUniqueId());
        if (Constants.REJECTED_STATUS.equals(table.getStatus())) {
            merchantUserTable.setKycVerifyUrl(null);
            merchantUserTable.setApplicantId(null);
            merchantUserRepository.save(merchantUserTable);
            status = Constants.FAIL;
        } else if (Constants.PASSED_STATUS.equals(table.getStatus())) {
            UcardWalletTable walletTable = ucardWalletRepository.findFirstByCId(merchantUserTable.getCId());
            if (walletTable == null) {
                walletTable = new UcardWalletTable();
                walletTable.setCustomId(merchantUserTable.getCustomId());
                walletTable.setCId(merchantUserTable.getCId());
                walletTable.setUniqueId(merchantUserTable.getUniqueId());
                walletTable.setBalance(BigDecimal.ZERO);
                walletTable.setAddTime(new Date());
                ucardWalletRepository.save(walletTable);
            }
            status = Constants.SUCCESS;
        }
        CardOperateTable operateTable = new CardOperateTable();
        operateTable.setOperateUser(entity.getCId());
        operateTable.setOperateType(CardOperateTypeEnum.KYC_MANUAL_REVIEW.getCode());
        operateTable.setStatus(status);
        operateTable.setAddTime(new Date());
        operateTable.setUniqueId(merchantUserTable.getUniqueId());
        cardOperateRepository.save(operateTable);

        if (Constants.REJECTED_STATUS.equals(table.getStatus())) {
            ucardEmailService.sendUserInfoReviewFailEmail(merchantUserTable, Long.valueOf(entity.getApproveDesc()));
        } else if (Constants.PASSED_STATUS.equals(table.getStatus())) {
            ucardEmailService.sendUserInfoReviewSuccessEmail(merchantUserTable);
        }

        return BaseResultDto.success();
    }

    /**
     * 获取kyc认证分页列表
     */
    @Override
    public ResultWithPagerDto<CardKycStatusDto> getKycPageList(CardKycStatusPageEntity entity) throws ServiceException {
        try {
            // 获取总数
            Integer count = kycStatusMapper.countList(entity);
            PageDto pageDto = PageDto.format(entity, count);
            if (count == null || count <= 0) {
                return ResultWithPagerDto.success(pageDto);
            }

            List<CardKycStatusDto> dtos = kycStatusMapper.pageList(entity);

            return ResultWithPagerDto.success(pageDto, dtos);
        } catch (Exception e) {
            log.error("获取卡片类型分页列表失败", e);
            throw new ServiceException("获取卡片类型分页列表失败");
        }
    }


}
