package com.sonic.frog.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.sonic.common.rpc.Page;
import com.sonic.common.utils.CloudFrontSignerUtils;
import com.sonic.cow.lib.client.ImageClient;
import com.sonic.daosupport.converter.PageConverter;
import com.sonic.frog.dao.AiUserAlbumDao;
import com.sonic.frog.dao.LikedDao;
import com.sonic.frog.domain.entity.AiUser;
import com.sonic.frog.domain.entity.AiUserAlbum;
import com.sonic.frog.domain.entity.Liked;
import com.sonic.frog.domain.input.*;
import com.sonic.frog.domain.output.AiAlbumDetailOutput;
import com.sonic.frog.domain.output.ListAiAlbumOutput;
import com.sonic.frog.domain.output.ViewUnlockAlbumImgOutput;
import com.sonic.frog.enums.LockStatusEnum;
import com.sonic.frog.enums.ToastResultCode;
import com.sonic.frog.event.inner.payload.AiUserStatPayload;
import com.sonic.frog.service.*;
import com.sonic.frog.utils.BeanConver;
import com.sonic.frog.utils.KeyGenerator;
import com.sonic.frog.utils.RegexUtil;
import com.sonic.lion.lib.client.PayClient;
import com.sonic.lion.lib.enums.BizType;
import com.sonic.lion.lib.input.BalanceCheckoutInput;
import com.sonic.pigeon.lib.bo.AttachBo;
import com.sonic.pigeon.lib.client.ImMessageClient;
import com.sonic.pigeon.lib.input.UpdateAiSendCustomImageMessageInput;
import com.sonic.frog.lib.output.AIUserAlbumApiOutput;
import com.sonic.shark.lib.client.S3BlurryImgClient;
import com.sonic.shark.lib.client.S3CheckClient;
import com.sonic.shark.lib.enums.BlurryImgBizTypeEnum;
import com.sonic.shark.lib.input.CopyAndBlurryImgInput;
import com.sonic.shark.lib.output.BlurryRecordOutput;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.InvalidKeyException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.sonic.frog.enums.Constants.PLATFORM_RATE;

/**
 * AI用户相册业务实现类
 */
@Service
@Slf4j
public class AiUserAlbumServiceImpl extends ServiceImpl<AiUserAlbumDao, AiUserAlbum> implements AiUserAlbumService {

    @Autowired
    private AiUserSearchService aiUserSearchService;
    @Autowired
    private LikedDao likedDao;
    @Autowired
    private AiUserAlbumDao aiUserAlbumDao;
    @Autowired
    private LikedService likedService;
    @Autowired
    private S3CheckClient s3CheckClient;
    @Autowired
    private S3BlurryImgClient copyAndBlurryImgClient;
    @Autowired
    private CloudFrontSignerUtils cloudFrontSignerUtils;
    @Autowired
    private AiUserAlbumUnlockService aiUserAlbumUnlockService;
    @Autowired
    private AiUserSetService aiUserSetService;
    @Autowired
    private CommonMessageService commonMessageService;
    @Autowired
    private ImMessageClient imMessageClient;
    @Autowired
    private UserAiMeetService userAiMeetService;
    @Autowired
    private CommonSendMqService commonSendMqService;
    @Autowired
    private PayClient payClient;
    @Autowired
    private ImageClient imageClient;
    @Autowired
    private AiUserHeartbeatRelationService aiUserHeartbeatRelationService;

    @Override
    public List<Long> batchAddAlbum(Long currentUserId, BatchAddAlbumInput addAlbum) {
        List<AiAlbumImageInfo> images = addAlbum.getImages().stream().filter(info -> RegexUtil.isOssStartUrl(info.getUrl())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(images)) {
            return null;
        }
        //最多添加一张
        ToastResultCode.ALBUM_ADD_MAX_ONE.check(images.size() > 1);
        //判断添加的图片是否是ai生成的6张图
        imageClient.checkImageIsAIGenerated(currentUserId, images.stream().map(AiAlbumImageInfo::getUrl).collect(Collectors.toList()));
        //权限检验，只有主人才能修改
        AiUser aiUser = aiUserSearchService.getAiUserByAiId(addAlbum.getAiId());
        ToastResultCode.SYS_PERMISSION_DENIED.check(aiUser == null || (aiUser.getUserId() != null && !aiUser.getUserId().equals(currentUserId)));
        //TODO 校验提交的图片地址是不是符合规范的,是否已经鉴黄通过
//        s3CheckClient.checkImage(images.stream().map(AiAlbumImageInfo::getUrl).collect(Collectors.toList()));
        List<Long> idList = Lists.newArrayList();
        //相册模糊处理
        List<CopyAndBlurryImgInput> copyAndBlurryImgInputList = Lists.newArrayList();
        for (AiAlbumImageInfo imageInfo : images) {
            AiUserAlbum aiUserAlbum = AiUserAlbum.builder()
                    .imgUrl(imageInfo.getUrl())
                    .sourceImgUrl(imageInfo.getUrl())
                    .width(imageInfo.getWidth())
                    .height(imageInfo.getHeight())
                    .aiId(addAlbum.getAiId())
                    .userId(currentUserId)
                    .isDelete(false)
                    .isDefault(false)
                    .unlockPrice(imageInfo.getUnlockPrice())
                    .createTime(LocalDateTime.now())
                    .editTime(LocalDateTime.now())
                    .build();
            save(aiUserAlbum);
            idList.add(aiUserAlbum.getId());

            //解锁价格大于0 需要模糊处理
            if (imageInfo.getUnlockPrice() > 0) {
                CopyAndBlurryImgInput copyAndBlurryImgInput = new CopyAndBlurryImgInput();
                copyAndBlurryImgInput.setSourceFileUrl(imageInfo.getUrl());
                copyAndBlurryImgInput.setUserId(currentUserId);
                copyAndBlurryImgInput.setBizType(BlurryImgBizTypeEnum.ALBUM);
                copyAndBlurryImgInput.setBizId(aiUserAlbum.getId());
                copyAndBlurryImgInputList.add(copyAndBlurryImgInput);
            }
        }
        if (CollectionUtils.isNotEmpty(copyAndBlurryImgInputList)) {
            //调用oss服务内部api模糊处理
            Map<Long, String> blurryAlbumImgMap = copyAndBlurryImgClient.copyAndBlurryAlbumImg(copyAndBlurryImgInputList);
            List<AiUserAlbum> updateUserAlbumList = Lists.newArrayList();
            for (CopyAndBlurryImgInput copyAndBlurryImgInput : copyAndBlurryImgInputList) {
                Long bizId = copyAndBlurryImgInput.getBizId();
                AiUserAlbum userAlbum = new AiUserAlbum();
                userAlbum.setId(bizId);
                userAlbum.setImgUrl(blurryAlbumImgMap.get(bizId));
                updateUserAlbumList.add(userAlbum);
            }
            //批量更新
            if (CollectionUtils.isNotEmpty(updateUserAlbumList)) {
                updateBatchById(updateUserAlbumList);
            }
        }
        return idList;
    }

    @Override
    public void setDefaultAlbum(Long currentUserId, Long aiId, Long albumId) {
        //权限检验，只有主人才能修改
        AiUserAlbum aiUserAlbum = getOne(Wrappers.<AiUserAlbum>lambdaQuery().eq(AiUserAlbum::getId, albumId));
        ToastResultCode.SYS_PERMISSION_DENIED.check(aiUserAlbum == null);
        ToastResultCode.SYS_PERMISSION_DENIED.check(!aiUserAlbum.getUserId().equals(currentUserId));
        //之前的默认图变成非默认图
        update(Wrappers.<AiUserAlbum>lambdaUpdate().eq(AiUserAlbum::getAiId, aiUserAlbum.getAiId())
                .eq(AiUserAlbum::getIsDefault, true)
                .set(AiUserAlbum::getIsDefault, false));
        //设置为默认图片
        update(Wrappers.<AiUserAlbum>lambdaUpdate()
                .eq(AiUserAlbum::getId, albumId)
                .set(AiUserAlbum::getIsDefault, true)
                .set(AiUserAlbum::getImgUrl, aiUserAlbum.getSourceImgUrl())
                .set(AiUserAlbum::getUnlockPrice, 0));
        //该图片替换为虚拟角色的个人主页头图，卡片主图，聊天背景（但不影响用户自定义设置的聊天背景）-需求变更-7.9
        aiUserSetService.setHomeImageUrl(aiId, aiUserAlbum.getSourceImgUrl());
    }

    @Override
    public void delAlbum(Long currentUserId, Long albumId) {
        //权限检验，只有主人才能修改
        AiUserAlbum aiUserAlbum = getOne(Wrappers.<AiUserAlbum>lambdaQuery().eq(AiUserAlbum::getId, albumId));
        ToastResultCode.ALBUM_NOT_EXIST.check(aiUserAlbum == null);
        ToastResultCode.SYS_PERMISSION_DENIED.check(!aiUserAlbum.getUserId().equals(currentUserId));
        ToastResultCode.ALBUM_IS_DELETED.check(aiUserAlbum.getIsDelete());
        //不能删除默认图片 不可删除封面默认图片，该图片会作为在个人主页头图，卡片主图，聊天背景
        ToastResultCode.ALBUM_DEFAULT_CAN_NOT_DELETE.check(aiUserAlbum.getIsDefault());
        //设置为为删除
        update(Wrappers.<AiUserAlbum>lambdaUpdate().eq(AiUserAlbum::getId, albumId).set(AiUserAlbum::getIsDelete, true));
    }

    @Override
    public void delByAiId(Long aiId) {
        //删除ai相册所有图片
        update(Wrappers.<AiUserAlbum>lambdaUpdate().eq(AiUserAlbum::getAiId, aiId).set(AiUserAlbum::getIsDelete, true));
    }

    @Override
    public void likeOrCancelPic(Long currentUserId, LikeOrCancelPicInput input) {
        //获取相册信息
        AiUserAlbum userAlbum = getById(input.getAlbumId());
        ToastResultCode.ALBUM_NOT_EXIST.check(userAlbum == null);
        //校验用户是否拥有操作权限
        aiUserAlbumUnlockService.checkAlbumLockStatus(currentUserId, userAlbum);
        //加密图片不能点赞或取消点赞
        Boolean isUnlockAlbumId = aiUserAlbumUnlockService.isUnlockAlbumId(currentUserId, input.getAlbumId());
        ToastResultCode.ALBUM_ENCRYPT_CAN_NOT_LIKE.check(!isUnlockAlbumId && userAlbum.getUnlockPrice() != null && userAlbum.getUnlockPrice() > 0);
        //查询点赞信息
        Liked liked = likedDao.selectOne(Wrappers.<Liked>lambdaQuery()
                .eq(Liked::getBizId, input.getAlbumId())
                .eq(Liked::getBizType, Liked.BizType.ALBUM_PIC)
                .eq(Liked::getLikedUserId, currentUserId));
        //如果数据库状态与传过来的状态一致，不处理
        if (liked != null && liked.getLikedStatus() == input.getLikedStatus()) {
            return;
        }
        //点赞或取消点赞
        likedDao.likeOrCancel(Liked.builder()
                .bizId(input.getAlbumId())
                .bizType(Liked.BizType.ALBUM_PIC)
                .aiId(userAlbum.getAiId())
                .likedUserId(currentUserId)
                .likedStatus(input.getLikedStatus()).build());
        //点赞的话，点赞数加1，取消点赞减1
        aiUserAlbumDao.incrementLikedCount(input.getAlbumId(), input.getLikedStatus() == Liked.LikedStatus.LIKED ? 1 : -1);
    }

    @Override
    public Page<ListAiAlbumOutput> listAlbums(AlbumListInput input, Long currentUserId) {
        //当前用户解锁过的相册id列表
        List<Long> unlockAlbumIds = aiUserAlbumUnlockService.getUnlockAlbumIds(currentUserId);
        //分页查询
        IPage<AiUserAlbum> albumPage = aiUserAlbumDao.listAlbumsPage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<AiUserAlbum>(input.getPage().getPn(), input.getPage().getPs()), input.getAiId(), unlockAlbumIds);
        List<AiUserAlbum> aiUserAlbumList = albumPage != null ? albumPage.getRecords() : Lists.newArrayList();
        //没有数据，直接返回
        if (CollectionUtils.isEmpty(aiUserAlbumList)) {
            return new Page<>();
        }
        //当前登录用户对各相册点赞状态Map
        Map<Long, Liked.LikedStatus> albumIdLikedStatusMap = ImmutableMap.of();
        if (currentUserId != null) {
            //业务主键id
            List<Long> bizIds = aiUserAlbumList.stream().map(AiUserAlbum::getId).collect(Collectors.toList());
            albumIdLikedStatusMap = likedService.list(Wrappers.<Liked>lambdaQuery()
                    .in(Liked::getBizId, bizIds)
                    .eq(Liked::getBizType, Liked.BizType.ALBUM_PIC)
                    .eq(Liked::getLikedUserId, currentUserId)
            ).stream().collect(Collectors.toMap(Liked::getBizId, Liked::getLikedStatus));
        }
        Map<Long, Liked.LikedStatus> finalAlbumIdLikedStatusMap = albumIdLikedStatusMap;
        //内部调用oss服务api，获取图片的模糊图片
        List<Long> blurBizIds = aiUserAlbumList.stream().filter(aiUserAlbum -> aiUserAlbum.getUnlockPrice() > 0).map(AiUserAlbum::getId).collect(Collectors.toList());
        //相册模糊Map
        Map<Long, BlurryRecordOutput> blurryRecordOutputMap = new HashMap<>(16);
        //相册锁状态Map
        Map<Long, LockStatusEnum> aiUserAlbumLockStatusMap = new HashMap<>(16);
        if (CollectionUtils.isNotEmpty(blurBizIds)) {
            //查询相册是否对访问用户解锁
            aiUserAlbumLockStatusMap = aiUserAlbumUnlockService.queryAlbumUnlock(currentUserId, aiUserAlbumList);
            //批量查询相册模糊图片的基础信息
            blurryRecordOutputMap = copyAndBlurryImgClient.blurryRecordBizIdMap(BlurryImgBizTypeEnum.ALBUM.name(), blurBizIds);
        }
        Map<Long, BlurryRecordOutput> finalBlurryRecordOutputMap = blurryRecordOutputMap;
        Map<Long, LockStatusEnum> finalAiUserAlbumLockStatusMap = aiUserAlbumLockStatusMap;
        return PageConverter.convert(albumPage, aiUserAlbum -> {
            ListAiAlbumOutput albumOutput = BeanConver.copeBean(aiUserAlbum, ListAiAlbumOutput.class);
            albumOutput.setLikedStatus(finalAlbumIdLikedStatusMap.getOrDefault(aiUserAlbum.getId(), Liked.LikedStatus.CANCELED));
            albumOutput.setAlbumId(aiUserAlbum.getId());
            //私密图片 自己访问自己，锁状态一定为上锁，显示原图，如果是其他人访问，则需要看当前用户是否解锁该图片，如果付费解锁过，则解锁，显示原图，否则为上锁，显示模糊图片
            if (aiUserAlbum.getUnlockPrice() > 0) {
                blurImgHandle(aiUserAlbum, albumOutput, finalBlurryRecordOutputMap, finalAiUserAlbumLockStatusMap, input.getIpAddress());
            }
            return albumOutput;
        });
    }

    @Override
    public List<ListAiAlbumOutput> listByIds(Long currentUserId, List<Long> idList) {
        List<AiUserAlbum> aiUserAlbumList = (List<AiUserAlbum>) listByIds(idList);
        //没有数据，直接返回
        if (CollectionUtils.isEmpty(aiUserAlbumList)) {
            return Lists.newArrayList();
        }
        //当前登录用户对各相册点赞状态Map
        Map<Long, Liked.LikedStatus> albumIdLikedStatusMap = ImmutableMap.of();
        if (currentUserId != null) {
            //业务主键id
            List<Long> bizIds = aiUserAlbumList.stream().map(AiUserAlbum::getId).collect(Collectors.toList());
            albumIdLikedStatusMap = likedService.list(Wrappers.<Liked>lambdaQuery()
                    .in(Liked::getBizId, bizIds)
                    .eq(Liked::getBizType, Liked.BizType.ALBUM_PIC)
                    .eq(Liked::getLikedUserId, currentUserId)
            ).stream().collect(Collectors.toMap(Liked::getBizId, Liked::getLikedStatus));
        }
        Map<Long, Liked.LikedStatus> finalAlbumIdLikedStatusMap = albumIdLikedStatusMap;
        //内部调用oss服务api，获取图片的模糊图片
        List<Long> blurBizIds = aiUserAlbumList.stream().filter(aiUserAlbum -> aiUserAlbum.getUnlockPrice() > 0).map(AiUserAlbum::getId).collect(Collectors.toList());
        //相册模糊Map
        Map<Long, BlurryRecordOutput> blurryRecordOutputMap = new HashMap<>(16);
        //相册锁状态Map
        Map<Long, LockStatusEnum> aiUserAlbumLockStatusMap = new HashMap<>(16);
        if (CollectionUtils.isNotEmpty(blurBizIds)) {
            //查询相册是否对访问用户解锁
            aiUserAlbumLockStatusMap = aiUserAlbumUnlockService.queryAlbumUnlock(currentUserId, aiUserAlbumList);
            //批量查询相册模糊图片的基础信息
            blurryRecordOutputMap = copyAndBlurryImgClient.blurryRecordBizIdMap(BlurryImgBizTypeEnum.ALBUM.name(), blurBizIds);
        }
        Map<Long, BlurryRecordOutput> finalBlurryRecordOutputMap = blurryRecordOutputMap;
        Map<Long, LockStatusEnum> finalAiUserAlbumLockStatusMap = aiUserAlbumLockStatusMap;

        List<ListAiAlbumOutput> outputList = Lists.newArrayList();
        for (AiUserAlbum aiUserAlbum : aiUserAlbumList) {
            ListAiAlbumOutput albumOutput = BeanConver.copeBean(aiUserAlbum, ListAiAlbumOutput.class);
            albumOutput.setLikedStatus(finalAlbumIdLikedStatusMap.getOrDefault(aiUserAlbum.getId(), Liked.LikedStatus.CANCELED));
            albumOutput.setAlbumId(aiUserAlbum.getId());
            //私密图片 自己访问自己，锁状态一定为上锁，显示原图，如果是其他人访问，则需要看当前用户是否解锁该图片，如果付费解锁过，则解锁，显示原图，否则为上锁，显示模糊图片
            if (aiUserAlbum.getUnlockPrice() > 0) {
                blurImgHandle(aiUserAlbum, albumOutput, finalBlurryRecordOutputMap, finalAiUserAlbumLockStatusMap, null);
            }
            outputList.add(albumOutput);
        }
        return outputList;
    }

    public AiAlbumDetailOutput rcDetail(Long albumId) throws InvalidKeyException {
        //获取相册图片
        AiUserAlbum album = getById(albumId);
        //没有数据，直接返回
        if (album == null) {
            return null;
        }
        //构造出参对象
        AiAlbumDetailOutput output = BeanConver.copeBean(album, AiAlbumDetailOutput.class);
        output.setAiId(album.getAiId());
        output.setAlbumId(albumId);
        //设置出参
        Long expTime = System.currentTimeMillis() + 3650 * 24 * 60 * 60 * 1000L;
        output.setImg1(cloudFrontSignerUtils.signer(album.getImgUrl() + CloudFrontSignerUtils.BLURRY_IMG_468_600, new Date(expTime), null));
        output.setImg2(cloudFrontSignerUtils.signer(album.getImgUrl() + CloudFrontSignerUtils.BLURRY_IMG_800_800, new Date(expTime), null));
        output.setImg3(cloudFrontSignerUtils.signer(album.getImgUrl() + CloudFrontSignerUtils.BLURRY_ORG_IMG, new Date(expTime), null));
        return output;
    }

    /**
     * 模糊图片处理
     * 私密图片 自己访问自己，锁状态一定为上锁，显示原图，如果是其他人访问，则需要看当前用户是否订阅过该用户，如果订阅，则解锁，显示原图，否则为上锁，显示模糊图片
     *
     * @param userAlbum
     * @param albumOutput
     * @param blurryRecordOutputMap
     * @param aiUserAlbumLockStatusMap
     * @param ipAddress
     */
    private void blurImgHandle(AiUserAlbum userAlbum, ListAiAlbumOutput albumOutput, Map<Long, BlurryRecordOutput> blurryRecordOutputMap, Map<Long, LockStatusEnum> aiUserAlbumLockStatusMap, String ipAddress) {
        try {
            albumOutput.setImgUrl(null);
            //设置图片的解锁状态
            albumOutput.setLockStatus(aiUserAlbumLockStatusMap.get(userAlbum.getId()));
            if (LockStatusEnum.LOCK == aiUserAlbumLockStatusMap.get(userAlbum.getId())) {
                //上锁，显示模糊图片
                BlurryRecordOutput blurryRecordOutput = blurryRecordOutputMap.get(userAlbum.getId());
                if (blurryRecordOutput == null) {
                    log.info("===> blurryRecordOutput is null, id : {}", userAlbum.getId());
                    return;
                }
                albumOutput.setImg1(blurryRecordOutput.getImg1());
                albumOutput.setImg2(blurryRecordOutput.getImg2());
                albumOutput.setImg3(blurryRecordOutput.getImg3());
                return;
            }
            //解锁，需要ip和过期时间签名的图片
            String fileUrl = userAlbum.getImgUrl();
            //计算图片的失效时间从当前时间开始+12小时
            Long expTime = System.currentTimeMillis() + 12 * 60 * 60 * 1000L;
            //如果是ipv4 则把日期和ip一起签名
            String img1Url = cloudFrontSignerUtils.signer(fileUrl + CloudFrontSignerUtils.IMG_468_600, new Date(expTime), ipAddress);
            String img2Url = cloudFrontSignerUtils.signer(fileUrl + CloudFrontSignerUtils.IMG_800_800, new Date(expTime), ipAddress);
            String img3Url = cloudFrontSignerUtils.signer(fileUrl + CloudFrontSignerUtils.ORG_IMG, new Date(expTime), ipAddress);
            albumOutput.setImg1(img1Url);
            albumOutput.setImg2(img2Url);
            albumOutput.setImg3(img3Url);
        } catch (Exception e) {
            log.error("===> blurImgHandle error : ", e);
            ToastResultCode.SYS_SYSTEM_EXCEPTION.check(true);
        }
    }

    @Override
    public void addDefaultAlbum(Long currentUserId, Long aiId, String imageUrl, String width, String height) {
        //添加默认相册前，需要所之前的默认图片置为非默认
        update(Wrappers.<AiUserAlbum>lambdaUpdate()
                .eq(AiUserAlbum::getAiId, aiId)
                .eq(AiUserAlbum::getIsDefault, true)
                .set(AiUserAlbum::getIsDefault, false)
        );
        //添加保存默认相册图片
        AiUserAlbum aiUserAlbum = AiUserAlbum.builder()
                .imgUrl(imageUrl)
                .sourceImgUrl(imageUrl)
                .width(width)
                .height(height)
                .aiId(aiId)
                .userId(currentUserId)
                .isDelete(false)
                .isDefault(true)
                .unlockPrice(0L)
                .createTime(LocalDateTime.now())
                .editTime(LocalDateTime.now())
                .build();
        save(aiUserAlbum);
        //该图片替换为虚拟角色的个人主页头图，卡片主图，聊天背景（但不影响用户自定义设置的聊天背景）-需求变更-7.9
        aiUserSetService.setHomeImageUrl(aiId, imageUrl);
    }

    @Override
    public void setAlbumUnlockPrice(Long currentUserId, SetAlbumUnlockPriceInput input) {
        //权限检验，只有主人才能修改
        AiUserAlbum aiUserAlbum = getOne(Wrappers.<AiUserAlbum>lambdaQuery().eq(AiUserAlbum::getId, input.getAlbumId()));
        ToastResultCode.SYS_PERMISSION_DENIED.check(aiUserAlbum == null);
        ToastResultCode.SYS_PERMISSION_DENIED.check(!aiUserAlbum.getUserId().equals(currentUserId));
        ToastResultCode.ALBUM_DEFAULT_CAN_NOT_MODIFY_PAY.check(aiUserAlbum.getIsDefault());
        List<CopyAndBlurryImgInput> copyAndBlurryImgInputList = Lists.newArrayList();
        //解锁价格大于0 需要模糊处理
        if (input.getUnlockPrice() > 0) {
            //判断图片是否已经生成模糊图片
            Map<Long, BlurryRecordOutput> blurryRecordOutputMap = copyAndBlurryImgClient.blurryRecordBizIdMap(BlurryImgBizTypeEnum.ALBUM.name(), Lists.newArrayList(aiUserAlbum.getId()));
            if (blurryRecordOutputMap == null || blurryRecordOutputMap.get(aiUserAlbum.getId()) == null) {
                CopyAndBlurryImgInput copyAndBlurryImgInput = new CopyAndBlurryImgInput();
                copyAndBlurryImgInput.setSourceFileUrl(aiUserAlbum.getSourceImgUrl());
                copyAndBlurryImgInput.setUserId(currentUserId);
                copyAndBlurryImgInput.setBizType(BlurryImgBizTypeEnum.ALBUM);
                copyAndBlurryImgInput.setBizId(aiUserAlbum.getId());
                copyAndBlurryImgInputList.add(copyAndBlurryImgInput);
            }
            if (CollectionUtils.isNotEmpty(copyAndBlurryImgInputList)) {
                //调用oss服务内部api模糊处理
                Map<Long, String> blurryAlbumImgMap = copyAndBlurryImgClient.copyAndBlurryAlbumImg(copyAndBlurryImgInputList);
                List<AiUserAlbum> updateUserAlbumList = Lists.newArrayList();
                for (CopyAndBlurryImgInput copyAndBlurryImgInput : copyAndBlurryImgInputList) {
                    Long bizId = copyAndBlurryImgInput.getBizId();
                    AiUserAlbum userAlbum = new AiUserAlbum();
                    userAlbum.setId(bizId);
                    userAlbum.setImgUrl(blurryAlbumImgMap.get(bizId));
                    updateUserAlbumList.add(userAlbum);
                }
                //批量更新
                if (CollectionUtils.isNotEmpty(updateUserAlbumList)) {
                    updateBatchById(updateUserAlbumList);
                }
            } else {
                //更新图片地址
                update(Wrappers.<AiUserAlbum>lambdaUpdate().set(AiUserAlbum::getImgUrl, aiUserAlbum.getImgUrl()).eq(AiUserAlbum::getId, input.getAlbumId()));
            }
        } else {
            //之前是付费，设置成免费，图片地址要恢复成源图片
            update(Wrappers.<AiUserAlbum>lambdaUpdate().set(AiUserAlbum::getImgUrl, aiUserAlbum.getSourceImgUrl()).eq(AiUserAlbum::getId, input.getAlbumId()));
        }
        //更新相册解锁价格
        update(Wrappers.<AiUserAlbum>lambdaUpdate().set(AiUserAlbum::getUnlockPrice, input.getUnlockPrice()).eq(AiUserAlbum::getId, input.getAlbumId()));
    }

    @Override
    public ViewUnlockAlbumImgOutput unlockAlbumImg(Long userId, UnlockAlbumImgInput input) {
        Long albumId = input.getAlbumId();
        AiUserAlbum aiUserAlbum = getOne(Wrappers.<AiUserAlbum>lambdaQuery().eq(AiUserAlbum::getId, albumId));
        ToastResultCode.ALBUM_NOT_EXIST.check(aiUserAlbum == null);
        //判断Ai是否存在
        AiUser aiUser = aiUserSearchService.getAiUserByAiId(input.getAiId());
        ToastResultCode.AI_USER_NOT_EXIST.check(aiUser == null);
        //ai是否删除或设置成私密
        Boolean isDelete = aiUser.getIsDelete();
        //解锁价格
        Long unlockPrice = aiUserAlbum.getUnlockPrice();

        ViewUnlockAlbumImgOutput output = new ViewUnlockAlbumImgOutput();
        //已解锁，不执行
        Boolean unlockAlbumId = aiUserAlbumUnlockService.isUnlockAlbumId(userId, aiUserAlbum.getId());
        if (unlockAlbumId) {
            output.setImg1(aiUserAlbum.getSourceImgUrl());
            output.setImg2(aiUserAlbum.getSourceImgUrl());
            output.setImg3(aiUserAlbum.getSourceImgUrl());
            return output;
        }
        //价格大于0时，才处理
        if (unlockPrice > 0L) {
            //平台抽取50%作为手续费,向下取整，平台少收服务费
            Long platformFee = new BigDecimal(unlockPrice).multiply(PLATFORM_RATE).divide(new BigDecimal(100),0, RoundingMode.FLOOR).multiply(new BigDecimal(100)).longValue();
            //生成订单编号
            String orderNo = KeyGenerator.instance().generatorUniqueKey("");
            //调用支付服务扣款
            BalanceCheckoutInput balanceCheckoutInput = BalanceCheckoutInput.builder()
                    .platform("Balance")
                    .outTradeNo(orderNo)
//                    .bizType(aiUser.getIsDelete() ? BizType.IMAGE_UNLOCK_TO_P : BizType.IMAGE_UNLOCK)
                    .bizType(BizType.IMAGE_UNLOCK)
                    .name("图片解锁")
                    //付款人
                    .srcAccountId(userId)
                    //收款人
                    .desAccountId(aiUserAlbum.getUserId())
                    //礼物总金额
                    .productAmount(unlockPrice)
                    //平台抽取的金额
                    .platformFee(isDelete ? unlockPrice : platformFee)
                    //折扣金额
                    .promoAmount(0L)
                    .build();
            payClient.checkoutToUser(balanceCheckoutInput);

            //保存解锁记录
            aiUserAlbumUnlockService.addUnlockAlbumRecord(userId, albumId, orderNo);
            //保存关系数据
            aiUserHeartbeatRelationService.initAiUserHeartbeatRelation(userId, input.getAiId());
//            //绑定meet关系(直接写到数据库中)
//            userAiMeetService.addMeet(userId, input.getAiId());
            //如果有消息的话，需要修改消息内容
            if (input.getMessageServerId() != null) {
                UpdateAiSendCustomImageMessageInput updateAiSendCustomImageMessageInput = UpdateAiSendCustomImageMessageInput.builder()
                        .messageServerId(input.getMessageServerId())
                        .userId(userId)
                        .aiId(aiUserAlbum.getAiId())
                        .attachment(AttachBo.builder()
                                .type("IMAGE")
                                .unlockPrice(0L)
                                .url(aiUserAlbum.getSourceImgUrl())
                                .height(aiUserAlbum.getHeight())
                                .width(aiUserAlbum.getWidth())
                                .build())
                        .build();
                imMessageClient.updateAiSendCustomImageMessage(updateAiSendCustomImageMessageInput);
            }

            //ai未删除且不是设置私密才发送系统通知,ai Coin数统计
            if (!isDelete) {
                //解锁图片后发送系统通知
                //用户实际所得金额
                commonMessageService.unlockAlbumImgSendMessage(userId, aiUserAlbum.getAiId(), aiUserAlbum.getId(), unlockPrice);
                //发送ai ai图片解锁赚取，Coin数统计
                commonSendMqService.aiUserStatMq(aiUserAlbum.getAiId(), AiUserStatPayload.Type.UNLOCK_IMG, unlockPrice);
            }
            //解锁后返回图片可访问
            output = viewUnlockAlbumImg(userId, ViewUnlockAlbumImgInput.builder().aiId(aiUserAlbum.getAiId()).albumId(albumId).build());
        } else {
            //价格为0，免费时直接返源图给用户
            output.setImg1(aiUserAlbum.getSourceImgUrl());
            output.setImg2(aiUserAlbum.getSourceImgUrl());
            output.setImg3(aiUserAlbum.getSourceImgUrl());
        }
        return output;
    }

    @Override
    public ViewUnlockAlbumImgOutput viewUnlockAlbumImg(Long currentUserId, ViewUnlockAlbumImgInput input) {
        Long albumId = input.getAlbumId();
        AiUserAlbum aiUserAlbum = getOne(Wrappers.<AiUserAlbum>lambdaQuery().eq(AiUserAlbum::getId, albumId));
        ToastResultCode.ALBUM_NOT_EXIST.check(aiUserAlbum == null);
        //判断用户是否解锁该图片
        aiUserAlbumUnlockService.checkAlbumLockStatus(currentUserId, aiUserAlbum);
        //解锁，需要ip和过期时间签名的图片
        String fileUrl = aiUserAlbum.getImgUrl();
        //计算图片的失效时间从当前时间开始+12小时
        Long expTime = System.currentTimeMillis() + 12 * 60 * 60 * 1000L;
        String ipAddress = input.getIpAddress();
        //如果是ipv4 则把日期和ip一起签名
        String img1Url = null;
        String img2Url = null;
        String img3Url = null;
        try {
            img1Url = cloudFrontSignerUtils.signer(fileUrl + CloudFrontSignerUtils.IMG_468_600, new Date(expTime), ipAddress);
            img2Url = cloudFrontSignerUtils.signer(fileUrl + CloudFrontSignerUtils.IMG_800_800, new Date(expTime), ipAddress);
            img3Url = cloudFrontSignerUtils.signer(fileUrl + CloudFrontSignerUtils.ORG_IMG, new Date(expTime), ipAddress);
        } catch (Exception e) {
            log.error("viewUnlockAlbumImg 图片签名失败", e);
        }
        ViewUnlockAlbumImgOutput output = new ViewUnlockAlbumImgOutput();
        output.setImg1(img1Url);
        output.setImg2(img2Url);
        output.setImg3(img3Url);

        //如果有消息的话，需要修改消息内容
        if (input.getMessageServerId() != null) {
            UpdateAiSendCustomImageMessageInput updateAiSendCustomImageMessageInput = UpdateAiSendCustomImageMessageInput.builder()
                    .messageServerId(input.getMessageServerId())
                    .userId(currentUserId)
                    .aiId(aiUserAlbum.getAiId())
                    .attachment(AttachBo.builder()
                            .type("IMAGE")
                            .unlockPrice(0L)
                            .url(aiUserAlbum.getSourceImgUrl())
                            .height(aiUserAlbum.getHeight())
                            .width(aiUserAlbum.getWidth())
                            .build())
                    .build();
            imMessageClient.updateAiSendCustomImageMessage(updateAiSendCustomImageMessageInput);
        }

        return output;
    }

    @Override
    public AIUserAlbumApiOutput getRandomLockImage(GetRandomLockImageInput input) throws InvalidKeyException {
        List<AIUserAlbumApiOutput> imageList = aiUserAlbumDao.getRandomLockImage(input.getUserId(), input.getAiId());
        if (CollectionUtils.isEmpty(imageList)) {
            return null;
        }
        //随机处理
        Collections.shuffle(imageList);
        AIUserAlbumApiOutput output = imageList.get(0);
        //计算图片的失效时间从当前时间开始+ 10年
        Long expTime = System.currentTimeMillis() + 3650 * 24 * 60 * 60 * 1000L;
        if (output.getUserId().equals(input.getUserId())) {
            //图片不加密
            output.setImgUrl(cloudFrontSignerUtils.signer(output.getImgUrl() + CloudFrontSignerUtils.IMG_800_800, new Date(expTime), null));
            //价格设置为0
            output.setUnlockPrice(0L);
        } else {
            output.setImgUrl(cloudFrontSignerUtils.signer(output.getImgUrl() + CloudFrontSignerUtils.BLURRY_IMG_800_800, new Date(expTime), null));
        }
        return output;
    }

}