package shop.alien.second.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import shop.alien.entity.second.SecondGoods;
import shop.alien.entity.second.SecondGoodsRecord;
import shop.alien.entity.second.vo.SecondGoodsRecordDetailVo;
import shop.alien.entity.second.vo.SecondGoodsVo;
import shop.alien.entity.store.LifeUser;
import shop.alien.entity.store.StoreImg;
import shop.alien.mapper.LifeUserMapper;
import shop.alien.mapper.StoreImgMapper;
import shop.alien.mapper.second.SecondGoodsMapper;
import shop.alien.mapper.second.SecondGoodsRecordMapper;
import shop.alien.second.service.RiskControlGoodsService;
import shop.alien.util.common.Constants;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 风控商品服务实现类
 * 提供风控相关的商品信息查询服务，包括通过记录ID和商品ID批量查询商品详细信息
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RiskControlGoodsServiceImpl implements RiskControlGoodsService {

    /**
     * 注入商品记录Mapper
      */
    private final SecondGoodsRecordMapper secondGoodsRecordMapper;

    /**
     * 注入商品Mapper
     */
    private final SecondGoodsMapper secondGoodsMapper;

    /**
     * 注入图片Mapper
      */
    private final StoreImgMapper storeImgMapper;

    /**
     * 注入用户Mapper
     */
    private final LifeUserMapper lifeUserMapper;

    /**
     * 通过商品记录表ID批量查询商品信息（包含图片）
     * @param recordIds 商品记录表ID列表
     * @return 商品信息列表
     */
    @Override
    public List<SecondGoodsRecordDetailVo> getGoodsInfoByRecordIds(List<Integer> recordIds) {
        // 检查传入ID列表是否为空，如果为空则直接返回空列表
        if (CollectionUtils.isEmpty(recordIds)) {
            return new ArrayList<>();
        }

        // 构建查询条件，根据记录ID列表查询商品记录信息
        QueryWrapper<SecondGoodsRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("sg.id", recordIds);
        // 执行查询获取商品记录列表
        List<SecondGoodsRecord> records = secondGoodsRecordMapper.selectdminGoodsList(queryWrapper);
        
        // 检查查询结果是否为空，如果为空则直接返回空列表
        if (CollectionUtils.isEmpty(records)) {
            return new ArrayList<>();
        }

        // 批量获取用户和图片信息
        BatchQueryResult<SecondGoodsRecord> batchResult = batchQueryUserInfoAndImageInfo(records, 
            SecondGoodsRecord::getUserId, SecondGoodsRecord::getId);

        // 创建结果列表，用于存储最终的商品记录详情VO对象
        List<SecondGoodsRecordDetailVo> result = new ArrayList<>();
        // 遍历所有商品记录，构建对应的VO对象
        for (SecondGoodsRecord record : records) {
            // 根据商品记录创建VO对象
            SecondGoodsRecordDetailVo detailVo = SecondGoodsRecordDetailVo.fromRecord(record);

            // 如果记录中有用户ID且在用户映射表中存在该用户，则设置用户信息
            if (record.getUserId() != null && batchResult.userMap.containsKey(record.getUserId())) {
                // 从用户映射表中获取用户信息
                LifeUser user = batchResult.userMap.get(record.getUserId());
                // 设置用户名和用户手机号
                detailVo.setUserName(user.getUserName());
                detailVo.setUserPhone(user.getUserPhone());
            }

            // 如果图片映射表中包含该记录的ID，则设置图片信息
            if (batchResult.imageMap.containsKey(record.getId())) {
                // 从图片映射表中获取该记录的图片列表
                List<StoreImg> recordImages = batchResult.imageMap.get(record.getId());
                // 提取图片URL列表
                List<String> imageUrls = recordImages.stream()
                        .map(StoreImg::getImgUrl)
                        .collect(Collectors.toList());
                // 处理图片列表（区分图片和视频）
                List<Map<String, Object>> imgList = processReportImages(recordImages, 2);
                // 设置图片列表和图片URL列表
                detailVo.setImgList(imgList);
                detailVo.setImageUrls(imageUrls);
            }

            // 将构建好的VO对象添加到结果列表中
            result.add(detailVo);
        }

        // 返回最终的结果列表
        return result;
    }

    /**
     * 通过商品表ID批量查询商品信息（包含图片）
     * @param goodsIds 商品表ID列表
     * @return 商品信息列表
     */
    @Override
    public List<SecondGoodsVo> getGoodsInfoByGoodsIds(List<Integer> goodsIds) {
        // 检查传入ID列表是否为空，如果为空则直接返回空列表
        if (CollectionUtils.isEmpty(goodsIds)) {
            return new ArrayList<>();
        }

        // 构建查询条件，根据商品ID列表查询商品信息
        QueryWrapper<SecondGoodsVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("sg.id", goodsIds);
        // 执行查询获取商品列表
        List<SecondGoodsVo> secondGoodsList = secondGoodsMapper.selectGoodsList(queryWrapper);

        // 检查查询结果是否为空，如果为空则直接返回空列表
        if (CollectionUtils.isEmpty(secondGoodsList)) {
            return new ArrayList<>();
        }

        // 批量获取用户和图片信息
        BatchQueryResult<SecondGoodsVo> batchResult = batchQueryUserInfoAndImageInfo(secondGoodsList,
            SecondGoods::getUserId, SecondGoods::getId);

        // 创建结果列表，用于存储最终的商品VO对象
        List<SecondGoodsVo> result = new ArrayList<>();
        // 遍历所有商品，构建对应的VO对象
        for (SecondGoods secondGoods : secondGoodsList) {
            // 创建新的商品VO对象
            SecondGoodsVo secondGoodsVo = new SecondGoodsVo();
            // 将商品属性复制到VO对象中
            BeanUtils.copyProperties(secondGoods, secondGoodsVo);

            // 如果VO对象中有用户ID且在用户映射表中存在该用户，则设置用户信息
            if (secondGoodsVo.getUserId() != null && batchResult.userMap.containsKey(secondGoodsVo.getUserId())) {
                // 从用户映射表中获取用户信息
                LifeUser user = batchResult.userMap.get(secondGoodsVo.getUserId());
                // 设置用户名和用户手机号
                secondGoodsVo.setUserName(user.getUserName());
                secondGoodsVo.setUserPhone(user.getUserPhone());
            }

            // 如果图片映射表中包含该商品的ID，则设置图片信息
            if (batchResult.imageMap.containsKey(secondGoodsVo.getId())) {
                // 从图片映射表中获取该商品的图片列表
                List<StoreImg> recordImages = batchResult.imageMap.get(secondGoodsVo.getId());
                // 提取图片URL列表
                List<String> imageUrls = recordImages.stream()
                        .map(StoreImg::getImgUrl)
                        .collect(Collectors.toList());
                // 处理图片列表（区分图片和视频）
                List<Map<String, Object>> imgList = processReportImages(recordImages, 2);
                // 设置图片列表和图片URL列表
                secondGoodsVo.setImgList(imgList);
                secondGoodsVo.setImageUrls(imageUrls);
            }

            // 将构建好的VO对象添加到结果列表中
            result.add(secondGoodsVo);
        }

        // 返回最终的结果列表
        return result;
    }

    /**
     * 批量查询用户信息和图片信息的通用方法
     * @param records 商品记录列表
     * @param userIdGetter 获取用户ID的函数
     * @param entityIdGetter 获取实体ID的函数（可能是记录ID或商品ID）
     * @param <T> 记录类型
     * @return 批量查询结果
     */
    private <T> BatchQueryResult<T> batchQueryUserInfoAndImageInfo(List<T> records, 
            Function<T, Integer> userIdGetter, Function<T, Integer> entityIdGetter) {
        
        // 从商品记录中提取所有非空的用户ID并去重，用于后续批量查询用户信息
        List<Integer> userIds = records.stream()
                .map(userIdGetter)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        // 创建用户映射表，用于存储用户ID到用户信息的映射关系
        Map<Integer, LifeUser> userMap = new HashMap<>();
        // 如果存在用户ID，则批量查询用户信息
        if (!CollectionUtils.isEmpty(userIds)) {
            // 构建用户查询条件，根据用户ID列表和未删除标识查询用户信息
            QueryWrapper<LifeUser> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.lambda()
                    .in(LifeUser::getId, userIds)
                    .eq(LifeUser::getDeleteFlag, Constants.DeleteFlag.NOT_DELETED);
            // 执行查询获取用户列表
            List<LifeUser> users = lifeUserMapper.selectList(userQueryWrapper);
            // 将用户列表转换为以用户ID为键的映射表，使用合并函数处理可能的重复键
            userMap = users.stream().collect(Collectors.toMap(
                LifeUser::getId,
                user -> user,
                (existing, replacement) -> existing // 处理键冲突，保留第一个值
            ));
        }

        // 从商品记录中提取所有实体ID，用于后续查询图片信息
        List<Integer> entityIdList = records.stream()
                .map(entityIdGetter)
                .collect(Collectors.toList());

        // 构建图片查询条件，根据实体ID列表、图片类型和未删除标识查询图片信息
        QueryWrapper<StoreImg> imageQueryWrapper = new QueryWrapper<>();
        imageQueryWrapper.lambda()
                .in(StoreImg::getStoreId, entityIdList)
                .eq(StoreImg::getDeleteFlag, Constants.DeleteFlag.NOT_DELETED)
                .orderByAsc(StoreImg::getImgSort);
        
        // 根据记录类型设置不同的图片类型
        if (!records.isEmpty()) {
            T firstRecord = records.get(0);
            if (firstRecord instanceof SecondGoodsRecord) {
                // 如果是商品记录类型，使用SECOND_HAND_RECORD类型
                imageQueryWrapper.lambda()
                        .eq(StoreImg::getImgType, Constants.ImageType.SECOND_HAND_RECORD);
            } else if (firstRecord instanceof SecondGoodsVo) {
                // 如果是商品类型，使用SECOND_HAND类型
                imageQueryWrapper.lambda()
                        .eq(StoreImg::getImgType, Constants.ImageType.SECOND_HAND_GOODS);
            }
        }
        
        // 执行查询获取图片列表
        List<StoreImg> imageList = storeImgMapper.selectList(imageQueryWrapper);

        // 将图片列表按照实体ID进行分组，方便后续关联到对应记录
        Map<Integer, List<StoreImg>> imageMap = imageList.stream()
                .collect(Collectors.groupingBy(StoreImg::getStoreId));
        
        // 返回批量查询结果
        return new BatchQueryResult<>(userMap, imageMap);
    }

    /**
     * 批量查询结果类
     * @param <T> 记录类型
     */
    private static class BatchQueryResult<T> {
        final Map<Integer, LifeUser> userMap;
        final Map<Integer, List<StoreImg>> imageMap;

        public BatchQueryResult(Map<Integer, LifeUser> userMap, Map<Integer, List<StoreImg>> imageMap) {
            this.userMap = userMap;
            this.imageMap = imageMap;
        }
    }

    /**
     * 处理图片列表，区分图片和视频类型
     * @param imageList 图片URL集合
     * @param type  类型 1-举报 2-商品
     * @return 图片列表，每个元素包含类型和URL信息
     */
    private List<Map<String, Object>> processReportImages(List<StoreImg> imageList, Integer type) {
        // 创建结果列表
        List<Map<String, Object>> list = new ArrayList<>();
        // 定义视频文件类型扩展名列表
        List<String> videoFileType = Arrays.asList("mp4", "avi", "flv", "mkv", "rmvb", "wmv", "3gp", "mov");

        // 遍历所有图片对象
        for (StoreImg img : imageList) {
            // 创建映射对象存储图片信息
            Map<String, Object> map = new HashMap<>();
            // 从图片URL中提取文件扩展名
            String fileType = img.getImgUrl().substring(img.getImgUrl().lastIndexOf(".") + 1);
            // 判断文件类型是否为视频
            if (videoFileType.contains(fileType.toLowerCase())) {
                // 如果是视频，设置类型为video
                map.put("type", "video");
            } else {
                // 如果不是视频，设置类型为image
                map.put("type", "image");
            }
            // 设置图片URL
            map.put("imgUrl", img.getImgUrl());
            // 如果类型为1（举报类型），则设置视频URL
            if (type == 1) {
                map.put("videoUrl", img.getImgUrl());
            }
            // 将映射对象添加到结果列表中
            list.add(map);
        }

        // 返回处理后的图片列表
        return list;
    }

}