package com.ruoyi.xq.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.oss.core.OssClient;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.enums.FileTypeEnums;
import com.ruoyi.oss.factory.OssFactory;
import com.ruoyi.xq.domain.AuthOrder;
import com.ruoyi.xq.domain.CardAuthRecord;
import com.ruoyi.xq.domain.UserAuth;
import com.ruoyi.xq.domain.UserInfo;
import com.ruoyi.xq.dto.admin.authRecord.CardAuthRecordAdminVo;
import com.ruoyi.xq.dto.common.faceauth.CommitAuthRecordResp;
import com.ruoyi.xq.enums.common.AuditEnum;
import com.ruoyi.xq.enums.face.TokenStatusEnum;
import com.ruoyi.xq.enums.pay.PayStatusEnum;
import com.ruoyi.xq.executor.ExecutorConstant;
import com.ruoyi.xq.mapper.CardAuthRecordMapper;
import com.ruoyi.xq.service.*;
import com.ruoyi.xq.tencent.CreateAuthResp;
import com.ruoyi.xq.tencent.TencentAuthClient;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.faceid.v20180301.models.GetDetectInfoEnhancedResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 实名认证管理Service业务层处理
 *
 * @author 77
 * @date 2024-04-29
 */
@Service
@Slf4j
public class CardAuthRecordServiceImpl extends ServiceImpl<CardAuthRecordMapper,CardAuthRecord> implements CardAuthRecordService {

    @Autowired
    private AuthOrderService authOrderService;
    @Autowired
    private UserAuthService userAuthService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserService userService;

    @Override
    public CreateAuthResp createAuthRecord(String orderNo, String redirectUrl){
        AuthOrder authOrder = authOrderService.getByOrderNo(orderNo);
        if(authOrder == null || !PayStatusEnum.PAY.getCode().equals(authOrder.getPayStatus())){
            throw new ServiceException("请支付后再进行实名认证");
        }
        CreateAuthResp token;
        try {
            token = TencentAuthClient.createToken(orderNo, redirectUrl);
        } catch (TencentCloudSDKException e) {
            log.error("发起实名认证异常",e);
            throw new ServiceException("云服务异常，发起实名认证失败");
        }
        CardAuthRecord cardAuthRecord = new CardAuthRecord();
        cardAuthRecord.setUserId(authOrder.getUserId());
        cardAuthRecord.setUsercode(authOrder.getUsercode());
        cardAuthRecord.setOrderNo(orderNo);
        cardAuthRecord.setBizToken(token.getBizToken());
        cardAuthRecord.setTokenStatus(0);
        this.save(cardAuthRecord);
        return token;
    }


    @Override
    public CommitAuthRecordResp commitAuthRecord(String bizToken){
        CardAuthRecord cardAuthRecord = this.getOne(Wrappers.lambdaQuery(CardAuthRecord.class)
                .eq(CardAuthRecord::getBizToken, bizToken).last("limit 1"));
        if(cardAuthRecord == null){
            throw new ServiceException("未找到对应的实名认证");
        }
        GetDetectInfoEnhancedResponse detectInfo;
        try {
            detectInfo = TencentAuthClient.getDetectInfo(bizToken);
        } catch (TencentCloudSDKException e) {
            log.error("查询实名认证异常",e);
            throw new ServiceException("实名认证结果获取失败");
        }
        CardAuthRecordService bean = SpringUtils.getBean(CardAuthRecordService.class);
        boolean success = bean.updateCardRecordSuccess(cardAuthRecord, detectInfo);
        ExecutorConstant.SYNC_EXECUTOR.execute(() -> {
            bean.updateImage(cardAuthRecord,detectInfo);
        });
        CommitAuthRecordResp commitAuthRecordResp = new CommitAuthRecordResp();
        commitAuthRecordResp.setFaceSuccess(success);
        return commitAuthRecordResp;
    }


    private String getPath(String userCode,String token,String suffix){
        String uuid = IdUtil.fastSimpleUUID();
        return String.format("cardAuth/%s/%s/%s.%s", userCode, token, uuid, suffix);
    }

    @Override
    public boolean updateImage(CardAuthRecord cardAuthRecord, GetDetectInfoEnhancedResponse detectInfo){
        OssClient storage = OssFactory.instance();
        String usercode = cardAuthRecord.getUsercode();
        String bizToken = cardAuthRecord.getBizToken();
        CardAuthRecord update = new CardAuthRecord();
        update.setId(cardAuthRecord.getId());
        boolean updateFlag = false;
        // 保存身份证
        if(detectInfo.getIdCardData() != null){
            if(StringUtils.isNotBlank(detectInfo.getIdCardData().getOcrFront())){
                try {
                    byte[] dataByte = Base64.decode(detectInfo.getIdCardData().getOcrFront());
                    String path = getPath(usercode, bizToken, FileTypeEnums.JPG.getSuffix());
                    UploadResult upload = storage.upload(dataByte, path, FileTypeEnums.JPG.getContentType());
                    update.setCardFront(upload.getUrl());
                    updateFlag = true;
                }catch (Exception e){
                    log.error("上传 身份证失败！recordId={}",cardAuthRecord.getId(),e);
                }
            }
            if(StringUtils.isNotBlank(detectInfo.getIdCardData().getOcrBack())){
                try {
                    byte[] dataByte = Base64.decode(detectInfo.getIdCardData().getOcrBack());
                    String path = getPath(usercode, bizToken, FileTypeEnums.JPG.getSuffix());
                    UploadResult upload = storage.upload(dataByte, path, FileTypeEnums.JPG.getContentType());
                    update.setCardBack(upload.getUrl());
                    updateFlag = true;
                }catch (Exception e){
                    log.error("上传 身份证失败！recordId={}",cardAuthRecord.getId(),e);
                }
            }
        }
        if(detectInfo.getBestFrame() != null){
            if(StringUtils.isNotBlank(detectInfo.getBestFrame().getBestFrame())){
                try {
                    byte[] dataByte = Base64.decode(detectInfo.getBestFrame().getBestFrame());
                    String path = getPath(usercode, bizToken, FileTypeEnums.JPG.getSuffix());
                    UploadResult upload = storage.upload(dataByte, path, FileTypeEnums.JPG.getContentType());
                    update.setBestFrame(upload.getUrl());
                    updateFlag = true;
                }catch (Exception e){
                    log.error("上传 bestFrame 失败！recordId={}",cardAuthRecord.getId(),e);
                }
            }
        }
        if(detectInfo.getVideoData() != null){
            if(StringUtils.isNotBlank(detectInfo.getVideoData().getLivenessVideo())){
                try {
                    byte[] dataByte = Base64.decode(detectInfo.getVideoData().getLivenessVideo());
                    String path = getPath(usercode, bizToken, FileTypeEnums.MP4.getSuffix());
                    UploadResult upload = storage.upload(dataByte, path, FileTypeEnums.MP4.getContentType());
                    update.setLivenessVideo(upload.getUrl());
                    updateFlag = true;
                }catch (Exception e){
                    log.error("上传 视频认证失败！recordId={}",cardAuthRecord.getId(),e);
                }
            }
        }
        if(!updateFlag){
            return false;
        }
        this.updateById(update);
        return true;
    }

    @Override
    public boolean refreshUserCardByAdmin(Long authRecordId){
        CardAuthRecord cardAuthRecord = this.getById(authRecordId);
        if(cardAuthRecord == null){
            throw new ServiceException("实名认证不存在!");
        }
        GetDetectInfoEnhancedResponse detectInfo = null;
        try {
            detectInfo = TencentAuthClient.getDetectInfo(cardAuthRecord.getBizToken());
        } catch (TencentCloudSDKException e) {
            log.error("查询实名认证异常",e);
            throw new ServiceException("实名认证结果获取失败");
        }
        boolean pass = TencentAuthClient.faceDetectIsPass(detectInfo);
        CardAuthRecord updateRecord = new CardAuthRecord();
        updateRecord.setId(cardAuthRecord.getId());
        if(!pass){
            updateRecord.setTokenStatus(TokenStatusEnum.FAIL.getCode());
        }else{
            updateRecord.setTokenStatus(TokenStatusEnum.SUCCESS.getCode());
        }
        if(detectInfo.getText() != null){
            updateRecord.setIdCard(detectInfo.getText().getIdCard());
            updateRecord.setName(detectInfo.getText().getName());
            if(detectInfo.getText().getOcrNation() != null){
                updateRecord.setNation(detectInfo.getText().getOcrNation()+"族");
            }
        }
        this.updateById(updateRecord);
        GetDetectInfoEnhancedResponse finalDetectInfo = detectInfo;
        ExecutorConstant.SYNC_EXECUTOR.execute(() -> {
            this.updateImage(cardAuthRecord, finalDetectInfo);
        });
        return pass;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCardRecordSuccess(CardAuthRecord cardAuthRecord, GetDetectInfoEnhancedResponse detectInfo){
        boolean pass = TencentAuthClient.faceDetectIsPass(detectInfo);
        CardAuthRecord updateRecord = new CardAuthRecord();
        updateRecord.setId(cardAuthRecord.getId());
        if(!pass){
            updateRecord.setTokenStatus(TokenStatusEnum.FAIL.getCode());
        }else{
            updateRecord.setTokenStatus(TokenStatusEnum.SUCCESS.getCode());
        }
        if(detectInfo.getText() != null){
            updateRecord.setIdCard(detectInfo.getText().getIdCard());
            updateRecord.setName(detectInfo.getText().getName());
            if(detectInfo.getText().getOcrNation() != null){
                updateRecord.setNation(detectInfo.getText().getOcrNation()+"族");
            }
        }
        this.updateById(updateRecord);
        if(pass){
            userAuthService.update(Wrappers.lambdaUpdate(UserAuth.class)
                    .eq(UserAuth::getUserId, cardAuthRecord.getUserId())
                    .set(UserAuth::getCardNumAuth, AuditEnum.SUCCESS.getCode()));
            userAuthService.checkAuthNum(cardAuthRecord.getUserId());
            userInfoService.update(Wrappers.lambdaUpdate(UserInfo.class)
                    .eq(UserInfo::getUserId, cardAuthRecord.getUserId())
                    .set(UserInfo::getIdCard, detectInfo.getText().getIdCard())
                    .set(UserInfo::getRealName, detectInfo.getText().getName()));
        }
        return pass;
    }

    @Override
    public Page<CardAuthRecordAdminVo> pageAdmin(PageQuery pageQuery, CardAuthRecordAdminVo bo) {
        return baseMapper.pageAdmin(pageQuery.build(), bo);
    }
}
