package com.ycwl.basic.service.mobile.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ycwl.basic.biz.OrderBiz;
import com.ycwl.basic.biz.TaskStatusBiz;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.constant.StorageConstant;
import com.ycwl.basic.image.watermark.ImageWatermarkFactory;
import com.ycwl.basic.image.watermark.entity.WatermarkInfo;
import com.ycwl.basic.image.watermark.enums.ImageWatermarkOperatorEnum;
import com.ycwl.basic.image.watermark.exception.ImageWatermarkException;
import com.ycwl.basic.image.watermark.operator.IOperator;
import com.ycwl.basic.mapper.*;
import com.ycwl.basic.model.mobile.goods.*;
import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
import com.ycwl.basic.model.mobile.order.PriceObj;
import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
import com.ycwl.basic.model.pc.mp.MpConfigEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
import com.ycwl.basic.model.pc.source.entity.SourceWatermarkEntity;
import com.ycwl.basic.model.pc.source.req.SourceReqQuery;
import com.ycwl.basic.model.pc.source.resp.SourceRespVO;
import com.ycwl.basic.model.pc.task.entity.TaskEntity;
import com.ycwl.basic.model.pc.template.resp.TemplateRespVO;
import com.ycwl.basic.model.pc.video.entity.MemberVideoEntity;
import com.ycwl.basic.model.pc.video.req.VideoReqQuery;
import com.ycwl.basic.model.pc.video.resp.VideoRespVO;
import com.ycwl.basic.repository.DeviceRepository;
import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.repository.OrderRepository;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.repository.VideoTaskRepository;
import com.ycwl.basic.service.mobile.GoodsService;
import com.ycwl.basic.repository.TemplateRepository;
import com.ycwl.basic.service.task.TaskService;
import com.ycwl.basic.storage.StorageFactory;
import com.ycwl.basic.storage.adapters.IStorageAdapter;
import com.ycwl.basic.storage.enums.StorageAcl;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.WxMpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Author：longbinbin
 * @Date：2024/12/5 15:04
 */
@Slf4j
@Service
public class GoodsServiceImpl implements GoodsService {
    @Autowired
    private VideoMapper videoMapper;
    @Autowired
    private SourceMapper sourceMapper;
    @Autowired
    private ScenicMapper scenicMapper;
    @Autowired
    private FaceMapper faceMapper;
    @Autowired
    private TemplateRepository templateRepository;
    @Autowired
    private VideoTaskRepository videoTaskRepository;
    @Autowired
    private TaskService taskTaskService;
    @Autowired
    private ScenicRepository scenicRepository;
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private OrderBiz orderBiz;
    @Autowired
    private FaceRepository faceRepository;
    @Autowired
    private TaskStatusBiz taskStatusBiz;
    @Autowired
    private DeviceRepository deviceRepository;

    public ApiResponse<List<GoodsPageVO>> goodsList(GoodsReqQuery query) {
        //查询原素材
        List<GoodsPageVO> goodsList = new ArrayList<>();
        VideoReqQuery videoReqQuery = new VideoReqQuery();
        videoReqQuery.setScenicId(query.getScenicId());
        videoReqQuery.setIsBuy(query.getIsBuy());
        videoReqQuery.setFaceId(query.getFaceId());
        videoReqQuery.setMemberId(Long.valueOf(BaseContextHandler.getUserId()));
        //查询成片vlog
        List<VideoRespVO> videoList = videoMapper.queryByRelation(videoReqQuery);
        videoList.forEach(videoRespVO -> {
            GoodsPageVO goodsPageVO = new GoodsPageVO();
            goodsPageVO.setGoodsName(videoRespVO.getTemplateName());
            goodsPageVO.setScenicId(videoRespVO.getScenicId());
            goodsPageVO.setScenicName(videoRespVO.getScenicName());
            goodsPageVO.setGoodsType(0);
            goodsPageVO.setFaceId(videoRespVO.getFaceId());
            goodsPageVO.setGoodsId(videoRespVO.getId());
            goodsPageVO.setTemplateName(videoRespVO.getTemplateName());
            goodsPageVO.setTemplateCoverUrl(videoRespVO.getTemplateCoverUrl());
            goodsList.add(goodsPageVO);
        });

        SourceReqQuery sourceReqQuery = new SourceReqQuery();
        sourceReqQuery.setScenicId(query.getScenicId());
        sourceReqQuery.setIsBuy(query.getIsBuy());
        sourceReqQuery.setFaceId(query.getFaceId());
        sourceReqQuery.setMemberId(Long.valueOf(BaseContextHandler.getUserId()));
        //查询源素材
        List<SourceRespVO> sourceList = sourceMapper.queryByRelation(sourceReqQuery);
        ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(query.getScenicId());
        List<GoodsPageVO> sourceGoods = sourceList.stream().collect(Collectors.groupingBy(SourceRespVO::getFaceId)).entrySet().stream().flatMap((faceEntry) -> {
            Long faceId = faceEntry.getKey();
            List<SourceRespVO> goods = faceEntry.getValue();
            return goods.stream().collect(Collectors.groupingBy(SourceRespVO::getType)).keySet().stream().filter(type -> {
                if (Integer.valueOf(1).equals(type)) {
                    if (Integer.valueOf(1).equals(scenicConfig.getDisableSourceVideo())) {
                        return false;
                    }
                } else if (Integer.valueOf(2).equals(type)) {
                    if (Integer.valueOf(1).equals(scenicConfig.getDisableSourceImage())) {
                        return false;
                    }
                }
                return true;
            }).map(type -> {
                GoodsPageVO goodsPageVO = new GoodsPageVO();
                goodsPageVO.setTemplateCoverUrl(goods.getFirst().getUrl());
                goodsPageVO.setFaceId(faceId);
                if (type == 1) {
                    goodsPageVO.setGoodsName("录像集");
                    goodsPageVO.setGoodsType(1);
                } else {
                    goodsPageVO.setGoodsName("照片集");
                    goodsPageVO.setGoodsType(2);
                }
                goodsPageVO.setScenicId(query.getScenicId());
                return goodsPageVO;
            });
        }).collect(Collectors.toList());
        if (!sourceGoods.isEmpty()) {
            if (goodsList.size() > 2) {
                goodsList.addAll(2, sourceGoods);
            } else {
                goodsList.addAll(sourceGoods);
            }
        }
        return ApiResponse.success(goodsList);
    }

    @Override
    public List<GoodsDetailVO> sourceGoodsList(GoodsReqQuery query) {
        FaceEntity face = faceRepository.getFace(query.getFaceId());
        if (face == null) {
            return Collections.emptyList();
        }
        Integer sourceType = query.getSourceType();
        SourceReqQuery sourceReqQuery = new SourceReqQuery();
        sourceReqQuery.setScenicId(query.getScenicId());
        sourceReqQuery.setIsBuy(query.getIsBuy());
        sourceReqQuery.setMemberId(face.getMemberId());
        sourceReqQuery.setType(sourceType);
        sourceReqQuery.setFaceId(query.getFaceId());
        List<SourceRespVO> list = sourceMapper.listUser(sourceReqQuery);
        List<GoodsDetailVO> goodsDetailVOList = new ArrayList<>();

        String goodsNamePrefix;
        if (sourceType == 1) {
            goodsNamePrefix = "录像";
        } else if (sourceType == 2) {
            goodsNamePrefix = "图片";
        } else {
            goodsNamePrefix = "其他类型";
        }
        //图片编号
        int i=1;
        for (SourceRespVO sourceRespVO : list) {
            GoodsDetailVO goodsDetailVO = new GoodsDetailVO();
            goodsDetailVO.setGoodsId(sourceRespVO.getId());
            String shootingTime = DateUtil.format(sourceRespVO.getCreateTime(), "yyyy.MM.dd HH:mm:ss");
            if (i < 10) {
                goodsDetailVO.setGoodsName(goodsNamePrefix + "0" + i + " " + shootingTime);
            } else {
                goodsDetailVO.setGoodsName(goodsNamePrefix + i + " " + shootingTime);
            }
            goodsDetailVO.setScenicId(sourceRespVO.getScenicId());
            goodsDetailVO.setScenicName(sourceRespVO.getScenicName());
            goodsDetailVO.setGoodsType(sourceType);
            goodsDetailVO.setGoodsId(sourceRespVO.getId());
            goodsDetailVO.setIsFree(sourceRespVO.getIsFree());
            goodsDetailVO.setIsBuy(sourceRespVO.getIsBuy());
            if (sourceRespVO.getVideoUrl() != null) {
                try {
                    URI url = URI.create(sourceRespVO.getVideoUrl());
                    if (StringUtils.startsWith(url.getHost(), "100.64.")) {
                        // 内网地址，需要代理
                        goodsDetailVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
                    } else {
                        goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
                    }
                } catch (IllegalArgumentException e) {
                    log.warn("url地址解析异常：{}", sourceRespVO.getVideoUrl(), e);
                    goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
                }
            }
            goodsDetailVO.setUrl(sourceRespVO.getUrl());
            goodsDetailVO.setCreateTime(sourceRespVO.getCreateTime());
            goodsDetailVO.setIsFree(sourceRespVO.getIsFree());
            goodsDetailVOList.add(goodsDetailVO);
            i++;
        }

        return goodsDetailVOList;
    }

    @Override
    public ApiResponse<VideoGoodsDetailVO> videoGoodsDetail(Long userId, Long videoId) {
        VideoGoodsDetailVO goodsDetailVO = new VideoGoodsDetailVO();
        VideoRespVO videoRespVO = videoMapper.getById(videoId);
        if (videoRespVO == null) {
            return ApiResponse.fail("该vlog不存在或已失效");
        }
        goodsDetailVO.setGoodsName(videoRespVO.getTemplateName());
        goodsDetailVO.setScenicId(videoRespVO.getScenicId());
        goodsDetailVO.setScenicName(videoRespVO.getScenicName());
        goodsDetailVO.setGoodsType(0);
        goodsDetailVO.setGoodsId(videoRespVO.getId());
        goodsDetailVO.setVideoUrl(videoRespVO.getVideoUrl());
        goodsDetailVO.setTemplateCoverUrl(videoRespVO.getTemplateCoverUrl());
        goodsDetailVO.setCreateTime(videoRespVO.getCreateTime());
        goodsDetailVO.setHeight(videoRespVO.getHeight());
        goodsDetailVO.setWidth(videoRespVO.getWidth());
        goodsDetailVO.setDuration(videoRespVO.getDuration());
        if (userId == null) {
            goodsDetailVO.setIsBuy(0);
            goodsDetailVO.setShare(true);
            goodsDetailVO.setPrice("未登录");
        } else {
            MemberVideoEntity entity = videoMapper.queryUserVideo(userId, videoId);
            if (entity == null) {
                goodsDetailVO.setIsBuy(0);
                goodsDetailVO.setShare(true);
                goodsDetailVO.setPrice("未登录");
            } else {
                goodsDetailVO.setShare(false);
                goodsDetailVO.setFaceId(entity.getFaceId());
                goodsDetailVO.setIsBuy(entity.getIsBuy());
                if (Integer.valueOf(0).equals(entity.getIsBuy())) {
                    PriceObj priceObj = orderBiz.queryPrice(videoRespVO.getScenicId(), 0, videoId);
                    if (priceObj.isFree()) {
                        goodsDetailVO.setIsBuy(1);
                    } else {
                        goodsDetailVO.setIsBuy(0);
                        goodsDetailVO.setPrice(priceObj.getPrice().toString());
                        goodsDetailVO.setSlashPrice(priceObj.getSlashPrice().toString());
                    }
                }
            }
        }
        TaskEntity task = videoTaskRepository.getTaskById(videoRespVO.getTaskId());
        JSONObject paramJson = JSON.parseObject(task.getTaskParams());
        AtomicInteger deviceCount = new AtomicInteger();
        goodsDetailVO.setShotTime(taskTaskService.getTaskShotDate(task.getId()));
        if (paramJson == null) {
            deviceCount.set(1);
        } else {
            List<String> templatePlaceholder = templateRepository.getTemplatePlaceholder(task.getTemplateId());
            paramJson.entrySet().stream()
                    .filter(entry -> StringUtils.isNumeric(entry.getKey()))
                    .forEach(entry -> {
                        JSONArray jsonArray = paramJson.getJSONArray(entry.getKey());
                        if (jsonArray != null && !jsonArray.isEmpty()) {
                            for (Object ignored : jsonArray) {
                                if (templatePlaceholder.contains(entry.getKey())) {
                                    deviceCount.getAndIncrement();
                                    templatePlaceholder.remove(entry.getKey());
                                }
                            }
                        }
                    });
        }
        goodsDetailVO.setLensNum(deviceCount.get());
        return ApiResponse.success(goodsDetailVO);
    }

    /**
     * 查询用户当前景区的视频合成任务状态
     *
     * @param faceId 景区id
     * @return 0没有任务 1 合成中 2 合成成功
     */
    @Override
    public VideoTaskStatusVO getTaskStatusByFaceId(Long faceId) {
        VideoTaskStatusVO response = new VideoTaskStatusVO();
        FaceEntity face = faceRepository.getFace(faceId);
        if (face == null) {
            response.setStatus(-1);
            return response;
        }
        Long userId = face.getMemberId();
        response.setFaceId(faceId);
        response.setScenicId(face.getScenicId());
        int faceCutStatus = taskStatusBiz.getFaceCutStatus(faceId);
        response.setCutStatus(faceCutStatus);
        if (faceCutStatus == 0) {
            // 切视频中，也显示正在处理
            response.setStatus(2);
            return response;
        }
        List<MemberVideoEntity> taskList = videoMapper.listRelationByFace(userId, faceId);
        if (faceCutStatus != 1 && taskList.isEmpty()) {
            // 视频切成了能够获取视频的状态，但是没有任务，还是显示正在处理
            response.setStatus(0);
            return response;
        }
        if (taskList.isEmpty()) {
            response.setStatus(0);
            return response;
        }
        List<TemplateRespVO> templateList = templateRepository.getTemplateListByScenicId(response.getScenicId());
        List<Long> templateIds = templateList.stream().map(TemplateRespVO::getId).collect(Collectors.toList());
        response.setMaxCount(templateList.size());
        List<MemberVideoEntity> notFinishedTasks = taskList.stream()
                .filter(task -> templateIds.contains(task.getTemplateId()))
                .filter(task -> {
                    TaskEntity taskById = videoTaskRepository.getTaskById(task.getTaskId());
                    if (taskById == null) {
                        return true;
                    }
                    return taskById.getStatus() == 0 || taskById.getStatus() == 2;
                })
                .collect(Collectors.toList());
        long finishedTask = taskList.stream()
                .filter(task -> {
                    TaskEntity taskById = videoTaskRepository.getTaskById(task.getTaskId());
                    if (taskById == null) {
                        return false;
                    }
                    return taskById.getStatus() == 1;
                })
                .map(MemberVideoEntity::getTemplateId)
                .distinct()
                .count();
        response.setCount(finishedTask);
        if (!notFinishedTasks.isEmpty()) {
            response.setTemplateId(notFinishedTasks.getFirst().getTemplateId());
            response.setTaskId(notFinishedTasks.getFirst().getTaskId());
            response.setStatus(2);
            return response;
        }
        // 重查一下
        taskList = videoMapper.listRelationByFace(userId, faceId);
        MemberVideoEntity lastVideo = taskList.getLast();
        if (null == lastVideo.getVideoId()) {
            response.setTemplateId(lastVideo.getTemplateId());
            response.setTaskId(lastVideo.getTaskId());
            response.setStatus(2);
            return response;
        }
        response.setTaskId(lastVideo.getTaskId());
        response.setTemplateId(lastVideo.getTemplateId());
        response.setVideoId(lastVideo.getVideoId());
        response.setStatus(1);
        return response;
    }

    @Override
    public VideoTaskStatusVO getAllTaskStatus(Long userId) {
        FaceRespVO lastFaceByUserId = faceMapper.findLastFaceByUserId(String.valueOf(userId));
        return getTaskStatusByFaceId(lastFaceByUserId.getId());
    }

    @Override
    public VideoTaskStatusVO getTaskStatusByTemplateId(Long faceId, Long templateId) {
        List<MemberVideoEntity> taskList = videoMapper.listRelationByFaceAndTemplate(faceId, templateId);
        VideoTaskStatusVO response = new VideoTaskStatusVO();
        response.setFaceId(faceId);
        response.setTemplateId(templateId);
        if (taskList.isEmpty()) {
            response.setStatus(0);
            return response;
        }
        response.setScenicId(taskList.getFirst().getScenicId());
        response.setMaxCount(templateRepository.getTemplateListByScenicId(response.getScenicId()).size());
        List<MemberVideoEntity> notFinishedTasks = taskList.stream()
                .filter(task -> {
                    TaskEntity taskById = videoTaskRepository.getTaskById(task.getTaskId());
                    if (taskById == null) {
                        return true;
                    }
                    return taskById.getStatus() == 0 || taskById.getStatus() == 2;
                }).collect(Collectors.toList());
        long finishedTask = taskList.stream()
                .filter(task -> {
                    TaskEntity taskById = videoTaskRepository.getTaskById(task.getTaskId());
                    if (taskById == null) {
                        return false;
                    }
                    return taskById.getStatus() == 1;
                }).count();
        response.setCount(finishedTask);
        int faceCutStatus = taskStatusBiz.getFaceCutStatus(faceId);
        if (Integer.valueOf(0).equals(faceCutStatus)) {
            if (!notFinishedTasks.isEmpty()) {
                response.setTemplateId(notFinishedTasks.getFirst().getTemplateId());
            }
            response.setStatus(2);
            return response;
        }
        if (!notFinishedTasks.isEmpty()) {
            response.setTemplateId(notFinishedTasks.getFirst().getTemplateId());
            response.setTaskId(notFinishedTasks.getFirst().getTaskId());
            response.setStatus(2);
            return response;
        }
        MemberVideoEntity lastVideo = taskList.getLast();
        response.setTaskId(lastVideo.getTaskId());
        response.setTemplateId(lastVideo.getTemplateId());
        response.setVideoId(lastVideo.getVideoId());
        if (null != lastVideo.getVideoId()) {
            response.setStatus(1);
            response.setVideoId(lastVideo.getVideoId());
        } else {
            TaskEntity taskById = videoTaskRepository.getTaskById(lastVideo.getTaskId());
            if (taskById == null) {
                response.setStatus(1);
            } else {
                if (taskById.getStatus() == 1) {
                    response.setStatus(1);
                    response.setVideoId(lastVideo.getVideoId());
                } else if (taskById.getStatus() == 0 || taskById.getStatus() == 2) {
                    response.setStatus(2);
                } else {
                    response.setStatus(1);
                }
            }
        }
        return response;
    }

    @Override
    public VideoTaskStatusVO getTaskStatusByScenicId(Long userId, Long scenicId) {
        FaceRespVO faceVO = faceMapper.getLatestByMemberId(userId, scenicId);
        VideoTaskStatusVO response = new VideoTaskStatusVO();
        response.setScenicId(scenicId);
        if (faceVO == null) {
            // 从来没露脸
            response.setStatus(-2);
            return response;
        }
        return getTaskStatusByFaceId(faceVO.getId());
    }

    @Override
    public ApiResponse<GoodsDetailVO> sourceGoodsInfo(Long sourceId) {
        SourceRespVO sourceRespVO = sourceMapper.getById(sourceId);
        if (sourceRespVO == null) {
            return ApiResponse.fail("该视频不存在");
        }
        GoodsDetailVO goodsDetailVO = new GoodsDetailVO();
        goodsDetailVO.setGoodsName("原片");
        goodsDetailVO.setScenicId(sourceRespVO.getScenicId());
        goodsDetailVO.setScenicName(sourceRespVO.getScenicName());
        goodsDetailVO.setGoodsType(sourceRespVO.getType());
        goodsDetailVO.setGoodsId(sourceRespVO.getId());
        if (sourceRespVO.getVideoUrl() != null) {
            try {
                URI url = URI.create(sourceRespVO.getVideoUrl());
                if (StringUtils.startsWith(url.getHost(), "100.64.")) {
                    // 内网地址，需要代理
                    goodsDetailVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
                } else {
                    goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
                }
            } catch (IllegalArgumentException e) {
                log.warn("url地址解析异常：{}", sourceRespVO.getVideoUrl(), e);
                goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
            }
        }
        goodsDetailVO.setTemplateCoverUrl(sourceRespVO.getUrl());
        goodsDetailVO.setCreateTime(sourceRespVO.getCreateTime());
        return ApiResponse.success(goodsDetailVO);
    }

    @Override
    public List<GoodsUrlVO> sourceGoodsListPreview(GoodsReqQuery query) {
        List<File> tmpFile = new ArrayList<>();
        FaceEntity face = faceRepository.getFace(query.getFaceId());
        if (face == null) {
            return Collections.emptyList();
        }
        Integer sourceType = query.getSourceType();
        SourceReqQuery sourceReqQuery = new SourceReqQuery();
        sourceReqQuery.setScenicId(query.getScenicId());
        sourceReqQuery.setIsBuy(query.getIsBuy());
        sourceReqQuery.setMemberId(face.getMemberId());
        sourceReqQuery.setType(sourceType);
        sourceReqQuery.setFaceId(query.getFaceId());
        List<SourceRespVO> list = sourceMapper.listUser(sourceReqQuery);
        if (!Integer.valueOf(2).equals(query.getSourceType())) {
            return list.stream().map(source -> {
                GoodsUrlVO goodsUrlVO = new GoodsUrlVO();
                goodsUrlVO.setGoodsType(source.getType());
                goodsUrlVO.setGoodsId(source.getId());
                goodsUrlVO.setUrl(source.getVideoUrl());
                goodsUrlVO.setCreateTime(source.getCreateTime());
                return goodsUrlVO;
            }).collect(Collectors.toList());
        }
        List<GoodsUrlVO> defaultUrlList = list.stream().map(source -> {
            GoodsUrlVO goodsUrlVO = new GoodsUrlVO();
            goodsUrlVO.setGoodsType(source.getType());
            goodsUrlVO.setGoodsId(source.getId());
            goodsUrlVO.setUrl(source.getUrl());
            goodsUrlVO.setCreateTime(source.getCreateTime());
            return goodsUrlVO;
        }).collect(Collectors.toList());
        IsBuyRespVO isBuy = orderBiz.isBuy(face.getMemberId(), query.getScenicId(), query.getSourceType(), query.getFaceId());
        if (!isBuy.isBuy()) {
            ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(face.getScenicId());
            if (scenicConfig != null && ((scenicConfig.getAntiScreenRecordType() & 2) == 0)) {
                // 未启用水印
                return defaultUrlList;
            }
            IStorageAdapter adapter;
            if (scenicConfig != null && scenicConfig.getStoreType() != null) {
                adapter = StorageFactory.get(scenicConfig.getStoreType());
                adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
            } else {
                adapter = StorageFactory.use("assets-ext");
            }
            IOperator operator = ImageWatermarkFactory.get(ImageWatermarkOperatorEnum.WATERMARK);
            List<SourceWatermarkEntity> watermarkEntityList = sourceMapper.listSourceWatermark(defaultUrlList.stream().map(GoodsUrlVO::getGoodsId).collect(Collectors.toList()), null, ImageWatermarkOperatorEnum.WATERMARK.getType());
            List<GoodsUrlVO> collect = defaultUrlList.stream().parallel().peek(item -> {
                Optional<SourceWatermarkEntity> any = watermarkEntityList.stream()
                        .filter(watermark -> watermark.getSourceId().equals(item.getGoodsId()))
                        .findAny();
                if (any.isPresent()) {
                    item.setUrl(any.get().getWatermarkUrl());
                } else {
                    // 生成
                    File dstFile = new File(item.getGoodsId() + ".jpg");
                    File watermarkedFile = new File(item.getGoodsId() + "_" + ImageWatermarkOperatorEnum.WATERMARK.getType() + "." + ImageWatermarkOperatorEnum.WATERMARK.getPreferFileType());
                    try {
                        HttpUtil.downloadFile(item.getUrl().replace("oss.zhentuai.com", "frametour-assets.oss-cn-shanghai-internal.aliyuncs.com"), dstFile);
                    } catch (Exception e) {
                        log.error("downloadFile error", e);
                        return;
                    }
                    tmpFile.add(dstFile);
                    WatermarkInfo info = new WatermarkInfo();
                    info.setOriginalFile(dstFile);
                    info.setWatermarkedFile(watermarkedFile);
                    try {
                        operator.process(info);
                    } catch (ImageWatermarkException e) {
                        log.error("process error", e);
                        return;
                    }
                    String url = adapter.uploadFile(null, watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
                    adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
                    sourceMapper.addSourceWatermark(item.getGoodsId(), null, ImageWatermarkOperatorEnum.WATERMARK.getType(), url);
                    tmpFile.add(watermarkedFile);
                    item.setUrl(url);
                }
            }).collect(Collectors.toList());
            for (File file : tmpFile) {
                file.delete();
            }
            return collect;
        }
        return defaultUrlList;
    }

    @Override
    public List<GoodsUrlVO> sourceGoodsListDownload(GoodsReqQuery query) {
        List<File> tmpFile = new ArrayList<>();
        FaceEntity face = faceRepository.getFace(query.getFaceId());
        if (face == null) {
            return Collections.emptyList();
        }
        Integer sourceType = query.getSourceType();
        SourceReqQuery sourceReqQuery = new SourceReqQuery();
        sourceReqQuery.setScenicId(face.getScenicId());
        sourceReqQuery.setMemberId(face.getMemberId());
        sourceReqQuery.setType(sourceType);
        sourceReqQuery.setFaceId(query.getFaceId());
        List<SourceRespVO> list = sourceMapper.listUser(sourceReqQuery);
        if (query.getGoodsId() != null) {
            list = list.stream().filter(source -> source.getId().equals(query.getGoodsId())).collect(Collectors.toList());
        }
        if (!Integer.valueOf(2).equals(query.getSourceType())) {
            return list.stream().map(source -> {
                GoodsUrlVO goodsUrlVO = new GoodsUrlVO();
                goodsUrlVO.setGoodsType(source.getType());
                goodsUrlVO.setGoodsId(source.getId());
                goodsUrlVO.setUrl(source.getVideoUrl());
                goodsUrlVO.setCreateTime(source.getCreateTime());
                return goodsUrlVO;
            }).collect(Collectors.toList());
        }
        long count = list.stream().filter((item) -> {
            if (item.getIsFree() > 0) {
                return false;
            }
            if (item.getIsBuy() > 0) {
                return false;
            }
            return true;
        }).count();
        if (count > 0) {
            IsBuyRespVO isBuy = orderBiz.isBuy(face.getMemberId(), query.getScenicId(), query.getSourceType(), query.getFaceId());
            if (!isBuy.isBuy()) {
                return Collections.emptyList();
            }
        }
        List<GoodsUrlVO> defaultUrlList = list.stream().map(source -> {
            GoodsUrlVO goodsUrlVO = new GoodsUrlVO();
            goodsUrlVO.setGoodsType(source.getType());
            goodsUrlVO.setGoodsId(source.getId());
            goodsUrlVO.setUrl(source.getUrl());
            goodsUrlVO.setCreateTime(source.getCreateTime());
            return goodsUrlVO;
        }).collect(Collectors.toList());
        ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(face.getScenicId());
        MpConfigEntity scenicMpConfig = scenicRepository.getScenicMpConfig(face.getScenicId());
        if (scenicMpConfig == null) {
            log.warn("未配置小程序参数，无法生成二维码");
            return defaultUrlList;
        }
        if (scenicConfig != null && scenicConfig.getWatermarkType() != null) {
            ImageWatermarkOperatorEnum type = ImageWatermarkOperatorEnum.getByCode(scenicConfig.getWatermarkType());
            if (type != null) {
                IStorageAdapter adapter;
                if (scenicConfig.getStoreType() != null) {
                    adapter = StorageFactory.get(scenicConfig.getStoreType());
                    adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
                } else {
                    adapter = StorageFactory.use("assets-ext");
                }
                IOperator operator = ImageWatermarkFactory.get(type);
                List<SourceWatermarkEntity> watermarkEntityList = sourceMapper.listSourceWatermark(list.stream().map(SourceRespVO::getId).collect(Collectors.toList()), face.getId(), type.getType());
                File qrcode = new File("qrcode_"+face.getId()+".jpg");
                try {
                    String urlLink = WxMpUtil.generateUrlLink(scenicMpConfig.getAppId(), scenicMpConfig.getAppSecret(), "pages/videoSynthesis/index", "scenicId=" + face.getScenicId() + "&faceId=" + face.getId());
                    QrCodeUtil.generate(urlLink + "?cq=", 300, 300, qrcode);
                } catch (Exception e) {
                    log.error("generateWXQRCode error", e);
                    return defaultUrlList;
                }
                tmpFile.add(qrcode);
                List<GoodsUrlVO> collect = defaultUrlList.stream().peek(item -> {
                    Optional<SourceWatermarkEntity> any = watermarkEntityList.stream()
                            .filter(watermark -> watermark.getSourceId().equals(item.getGoodsId()))
                            .findAny();
                    if (any.isPresent()) {
                        item.setUrl(any.get().getWatermarkUrl());
                    } else {
                        // 生成
                        String text = scenicConfig.getWatermarkScenicText();
                        if (StringUtils.isBlank(text)) {
                            SourceEntity entity = sourceMapper.getEntity(item.getGoodsId());
                            if (entity != null) {
                                DeviceEntity device = deviceRepository.getDevice(entity.getDeviceId());
                                if (device != null) {
                                    text = device.getName();
                                }
                            }
                        }
                        File dstFile = new File(item.getGoodsId() + ".jpg");
                        File watermarkedFile = new File(item.getGoodsId() + "_" + type.getType() + "." + type.getPreferFileType());
                        try {
                            HttpUtil.downloadFile(item.getUrl().replace("oss.zhentuai.com", "frametour-assets.oss-cn-shanghai-internal.aliyuncs.com"), dstFile);
                        } catch (Exception e) {
                            log.error("downloadFile error", e);
                            return;
                        }
                        tmpFile.add(dstFile);
                        WatermarkInfo info = new WatermarkInfo();
                        info.setOriginalFile(dstFile);
                        info.setQrcodeFile(qrcode);
                        info.setScenicLine(text);
                        info.setDatetime(item.getCreateTime());
                        info.setDtFormat(scenicConfig.getWatermarkDtFormat());
                        info.setWatermarkedFile(watermarkedFile);
                        try {
                            operator.process(info);
                        } catch (ImageWatermarkException e) {
                            log.error("process error", e);
                            return;
                        }
                        String url = adapter.uploadFile(null, watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
                        adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
                        sourceMapper.addSourceWatermark(item.getGoodsId(), face.getId(), type.getType(), url);
                        tmpFile.add(watermarkedFile);
                        item.setUrl(url);
                    }
                }).collect(Collectors.toList());
                for (File file : tmpFile) {
                    file.delete();
                }
                return collect;
            }
        }
        return defaultUrlList;
    }

    @Override
    public Integer sourceGoodsCount(GoodsReqQuery query) {
        FaceEntity face = faceRepository.getFace(query.getFaceId());
        if (face == null) {
            return 0;
        }
        Integer sourceType = query.getSourceType();
        SourceReqQuery sourceReqQuery = new SourceReqQuery();
        sourceReqQuery.setScenicId(query.getScenicId());
        sourceReqQuery.setIsBuy(query.getIsBuy());
        sourceReqQuery.setMemberId(face.getMemberId());
        sourceReqQuery.setType(sourceType);
        sourceReqQuery.setFaceId(query.getFaceId());
        return sourceMapper.countUser(sourceReqQuery);
    }
}
