# InternalTrendSourceController.java

    package cloud.wconnect.rateshop.controller.internal.rateshop;

    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.FunctionIdConstant;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.ForbiddenException;
    import cloud.wconnect.commonlib.pojo.dto.ListPagedDTO;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.query.OpenFunctionPropertyQuery;
    import cloud.wconnect.commonlib.service.PropertyInternalService;
    import cloud.wconnect.commonlib.util.SignUtils;
    import cloud.wconnect.rateshop.cons.rateshop.RateShopCons;
    import cloud.wconnect.rateshop.cons.rateshop.TrendSourceDatasourceEnum;
    import cloud.wconnect.rateshop.entity.rateshop.TrendSourceSetting;
    import cloud.wconnect.rateshop.entity.rateshop.TrendSourceUrl;
    import cloud.wconnect.rateshop.pojo.dto.rateshop.internal.InternalTrendSourceDTO;
    import cloud.wconnect.rateshop.service.rateshop.ITrendSourceSettingService;
    import cloud.wconnect.rateshop.service.rateshop.ITrendSourceUrlService;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.google.common.collect.Lists;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.*;

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

    /**
     * 市场趋势数据源 控制层
     *
     * @author lichen
     * @date 2023/6/19
     */
    @RestController
    @RequestMapping("/internal/trend-sources")
    public class InternalTrendSourceController {

        @Value("${internal.service.auth-key.basic}")
        private String authKey;
        @Autowired
        private ITrendSourceSettingService trendSourceSettingService;
        @Autowired
        private ITrendSourceUrlService trendSourceUrlService;
        @Autowired
        private PropertyInternalService propertyInternalService;

        /**
         * 查询市场需求趋势源信息
         *
         * @param sign 签名
         * @param page 页码
         * @param size 每页大小
         * @return cloud.wconnect.commonlib.pojo.dto.ListPagedDTO<cloud.wconnect.rateshop.pojo.dto.internal.InternalTrendSourceDTO>
         * @author lichen
         * @date 2023/6/19
         */
        @GetMapping
        public ListPagedDTO<InternalTrendSourceDTO> list(@RequestHeader String sign,
                                                         @RequestParam Integer type,
                                                         @RequestParam Integer datasourceId,
                                                         @RequestParam(required = false) Integer page,
                                                         @RequestParam(required = false) Integer size) {
            //计算签名
            String actualSign;
            boolean isPage = Objects.nonNull(page) && Objects.nonNull(size);
            if (isPage) {
                actualSign = SignUtils.signWithKey(authKey, type, datasourceId, page, size);
            } else {
                actualSign = SignUtils.signWithKey(authKey, type, datasourceId, "", "");
            }

            //校验签名
            if (!actualSign.equals(sign)) {
                String logMsg = MessageFormat.format("The parameters may be modified illegally; expectedSign:{0}, "
                        + "actualSign:{1}, authKey:{2}", sign, actualSign, authKey);
                throw new ForbiddenException(BaseErrorCodeEnum.DATA_FORBIDDEN.getI18nCode(),
                        BaseErrorCodeEnum.DATA_FORBIDDEN.getCode(), logMsg);
            }

            //校验type是否合法
            if(!Lists.newArrayList(RateShopCons.TYPE_OPEN_HOTEL_NUM,
                    RateShopCons.TYPE_TOTAL_HOTEL_NUM).contains(type)){
                throw new BadRequestException(BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getI18nCode(),
                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(), "The type must between in [1:Total Hotel Num 2:Open Hotel Num]");
            }
            //校验datasourceId是否合法
            TrendSourceDatasourceEnum.checkDatasourceId(datasourceId);

            //查询资产使用的需求趋势
            List<TrendSourceSetting> trendSourceSettings;
            long total;
            if(isPage){
                Page<TrendSourceSetting> resultPage = trendSourceSettingService.page(new Page<>(page, size),
                        new LambdaQueryWrapper<TrendSourceSetting>().orderByAsc(TrendSourceSetting::getId));
                total = resultPage.getTotal();
                trendSourceSettings = resultPage.getRecords();
            }else{
                trendSourceSettings = trendSourceSettingService.list();
                total = trendSourceSettings.size();
            }
            if (total == 0) return new ListPagedDTO<>();

            //资产ID集合
            List<Integer> propertyIds = trendSourceSettings.stream().map(TrendSourceSetting::getPropertyId).toList();
            //开通模块的的资产ID
            OpenFunctionPropertyQuery openFunctionPropertyQuery = new OpenFunctionPropertyQuery();
            openFunctionPropertyQuery.setIds(propertyIds);
            openFunctionPropertyQuery.setOpenFunctionIds(Lists.newArrayList(FunctionIdConstant.RATE_SHOP));
            List<Integer> openPropertyIds = propertyInternalService.getOpenFunctionProperty(openFunctionPropertyQuery)
                    .stream().filter(PropertyDTO::getStatus).map(PropertyDTO::getId).toList();
            if (CollectionUtils.isEmpty(openPropertyIds)) return new ListPagedDTO<>();

            //过滤出开通的资产配置的地区id
            List<Integer> locationIds = trendSourceSettings.stream()
                    .filter(setting -> openPropertyIds.contains(setting.getPropertyId()))
                    .map(TrendSourceSetting::getLocationId).toList();

            //地区对应的url
            List<TrendSourceUrl> urls = trendSourceUrlService.list(new LambdaQueryWrapper<TrendSourceUrl>()
                    .in(TrendSourceUrl::getLocationId, locationIds)
                    .eq(TrendSourceUrl::getType, type)
                    .eq(TrendSourceUrl::getDatasourceId, datasourceId));
            Map<Integer, String> locationId2Url = urls.stream().collect(Collectors.toMap(TrendSourceUrl::getLocationId, TrendSourceUrl::getUrl));

            List<Integer> locationIdsByDistinct = locationIds.stream().distinct().toList();
            ArrayList<InternalTrendSourceDTO> internalTrendSourceDTOList = Lists.newArrayListWithCapacity(locationIdsByDistinct.size());
            for (Integer locationId : locationIdsByDistinct) {
                String url = locationId2Url.get(locationId);
                if(StringUtils.isNotBlank(url)){
                    InternalTrendSourceDTO internalTrendSourceDTO = new InternalTrendSourceDTO();
                    internalTrendSourceDTO.setLocationId(locationId);
                    internalTrendSourceDTO.setUrl(url);
                    internalTrendSourceDTOList.add(internalTrendSourceDTO);
                }
            }
            return new ListPagedDTO<>(total, internalTrendSourceDTOList);
        }

    }