package cn.reghao.tnb.content.app.data.service;

import cn.reghao.file.api.iface.OssService;
import cn.reghao.jutil.jdk.db.Page;
import cn.reghao.jutil.jdk.db.PageList;
import cn.reghao.jutil.jdk.result.Result;
import cn.reghao.jutil.web.WebResult;
import cn.reghao.jutil.tool.id.SnowFlake;
import cn.reghao.oss.sdk.model.dto.media.ImageInfo;
import cn.reghao.tnb.account.api.iface.AccountQuery;
import cn.reghao.tnb.common.auth.UserContext;
import cn.reghao.tnb.content.api.constant.PostScope;
import cn.reghao.tnb.content.api.dto.ImagePublishSbt;
import cn.reghao.tnb.content.app.data.db.repository.ImageRepository;
import cn.reghao.tnb.content.app.data.model.dto.AlbumImageData;
import cn.reghao.tnb.content.app.data.model.po.ImagePost;
import cn.reghao.tnb.content.app.data.model.po.ImageFile;
import cn.reghao.tnb.content.app.data.model.vo.AlbumCard;
import cn.reghao.tnb.content.app.data.model.vo.ImageAlbumCard;
import cn.reghao.tnb.content.app.data.model.vo.ImageAlbumQuery;
import cn.reghao.tnb.content.app.data.model.vo.ImageData;
import cn.reghao.tnb.content.app.vod.db.repository.AlbumRepository;
import cn.reghao.tnb.content.app.vod.service.ContentPermission;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2023-08-21 10:49:28
 */
@Slf4j
@Service
public class ImagePostService {
    @DubboReference(check = false, retries = 0, timeout = 60_000)
    private AccountQuery accountQuery;
    @DubboReference(check = false, timeout = 60_000)
    private OssService ossService;

    private final int pageSize = 12;
    private final SnowFlake idGenerator;
    private final ImageRepository imageRepository;
    private final AlbumRepository albumRepository;
    private final ContentPermission contentPermission;

    public ImagePostService(ImageRepository imageRepository, AlbumRepository albumRepository,
                            ContentPermission contentPermission) {
        this.idGenerator = new SnowFlake(1L, 1L);
        this.imageRepository = imageRepository;
        this.albumRepository = albumRepository;
        this.contentPermission = contentPermission;
    }

    public Result create(ImagePublishSbt imagePublishSbt) {
        String albumName = imagePublishSbt.getAlbumName();
        int scope = imagePublishSbt.getScope();
        long albumId = idGenerator.nextId();
        ImagePost imagePost = new ImagePost(albumId, albumName, scope);
        imageRepository.saveImageAlbum(imagePost);
        return Result.success();
    }

    public Result add(AlbumImageData albumImageData) {
        long albumId = albumImageData.getAlbumId();
        ImagePost imagePost = imageRepository.getImageAlbum(albumId);
        if (imagePost == null) {
            String errMsg = String.format("相册 %s 不存在", albumId);
            return Result.fail(errMsg);
        }

        int total = imageRepository.countImageFiles(albumId);
        int imageCount = total + 1;
        if (imageCount > 1000) {
            String errMsg = "一个相册最多可包含 1000 张图片";
            return Result.fail(errMsg);
        }

        String imageFileId = albumImageData.getImageFileId();
        int channelId = imagePost.getChannelId();
        try {
            ImageInfo imageInfo = ossService.getImageInfo(channelId, imageFileId);
            /*Map<String, ConvertedImageInfo> map = imageFileIds.stream()
                    .map(imageFileId -> ossService.getWebpInfo(channelId, imageFileId))
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(ConvertedImageInfo::getImageFileId, convertedImageInfo -> convertedImageInfo));
            if (map.isEmpty()) {
                String errMsg = String.format("相册 %s 中的图片转换为 webp 失败", albumId);
                return Result.fail(errMsg);
            }*/

            ImageFile imageFile = new ImageFile(albumId, channelId, imageInfo);
            Integer channelScope = ossService.getChannelScope(channelId);
            if (channelScope == null ) {
                String errMsg = String.format("channelId %s 的 scope 在 oss 中不存在", channelId);
                return Result.fail(errMsg);
            }

            int scope = imagePost.getScope();
            if (channelScope != scope) {
                ossService.setObjectScope(channelId, imageFileId, scope);
            }
            imageRepository.addAlbumImage(albumId, imageCount, imageFile);
            return Result.success();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.fail("");
    }

    private boolean isCollected(String imageFileId) {
        long loginUser = UserContext.getUser();
        return albumRepository.getByImagePost(imageFileId, loginUser) != null;
    }

    public PageList<AlbumCard> getUserAlbums(long userId, int page) {
        List<Integer> scopes = contentPermission.getUserScopes();
        long loginUser = UserContext.getUser();
        if (loginUser == userId) {
            scopes.add(PostScope.PRIVATE.getCode());
        }

        ImageAlbumQuery imageAlbumQuery = new ImageAlbumQuery.Builder().userId(userId).build();
        int total = imageRepository.countByCriteria(imageAlbumQuery);
        Page page1 = new Page(page, pageSize);
        List<ImagePost> list = imageRepository.findImageAlbumByPage(page1, imageAlbumQuery);
        List<AlbumCard> albumCards = list.stream().map(imagePost -> {
            try {
                int scope = imagePost.getScope();
                if (scope != PostScope.PUBLIC.getCode()) {
                    int channelId = imagePost.getChannelId();
                    String coverUrl = imagePost.getCoverUrl();
                    if (!coverUrl.isBlank()) {
                        ImageFile imageFile = imageRepository.getByUrl(coverUrl);
                        String objectId = imageFile.getObjectId();
                        imagePost.setCoverUrl(ossService.getSignedUrl(channelId, objectId));
                    }
                }
                String userIdStr = accountQuery.getUserIdStr(imagePost.getUserId());
                return new AlbumCard(imagePost, userIdStr);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }).filter(Objects::nonNull).collect(Collectors.toList());

        return PageList.pageList(page, pageSize, total, albumCards);
    }

    public String getImageAlbum(long albumId, int pageNumber) {
        ImagePost imagePost = imageRepository.getImageAlbum(albumId);
        if (imagePost == null) {
            return WebResult.notFound();
        }

        long owner = imagePost.getUserId();
        int scope = imagePost.getScope();
        long loginUser = UserContext.getUser();
        if (scope == PostScope.PRIVATE.getCode() && owner != loginUser) {
            return WebResult.notFound();
        }

        boolean hasPermission = contentPermission.hasPermission(owner, scope, loginUser);
        if (!hasPermission) {
            return WebResult.failWithMsg("permission denied");
        }

        int total = imageRepository.countImageFiles(albumId);
        Page page1 = new Page(pageNumber, pageSize);
        List<String> imageFileIds = imageRepository.getImageFileIds(albumId, page1);
        List<ImageFile> imageFiles = imageRepository.getImageFiles(imageFileIds);
        Map<String, List<ImageFile>> map = imageFiles.stream()
                .collect(Collectors.groupingBy(ImageFile::getImageFileId));

        List<ImageData> list = new ArrayList<>();
        map.forEach((imageFileId, list1) -> {
            ImageData imageData = new ImageData(imageFileId);
            list1.forEach(imageFile -> {
                String url = imageFile.getUrl();
                String format = imageFile.getFormat();
                if (format.equals("webp")) {
                    imageData.setThumbnailUrl(url);
                } else {
                    imageData.setOriginalUrl(url);
                }
            });

            if (imageData.getThumbnailUrl() == null) {
                imageData.setThumbnailUrl(imageData.getOriginalUrl());
            }
            boolean collected = isCollected(imageFileId);
            imageData.setCollected(collected);
            list.add(imageData);
        });

        PageList<ImageData> pageList = PageList.pageList(pageNumber, pageSize, total, list);
        String userIdStr = accountQuery.getUserIdStr(imagePost.getUserId());
        ImageAlbumCard imageAlbumCard = new ImageAlbumCard(imagePost, userIdStr);
        imageAlbumCard.setImages(pageList);
        if (scope != PostScope.PUBLIC.getCode()) {
            imageAlbumCard.getImages().getList().forEach(imageData -> {
                String imageFileId = imageData.getImageFileId();
                try {
                    int channelId = imagePost.getChannelId();
                    String signedUrl = ossService.getSignedUrl(channelId, imageFileId);
                    imageData.setThumbnailUrl(signedUrl);
                    imageData.setOriginalUrl(signedUrl);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }

        return WebResult.success(imageAlbumCard);
    }
}
