package org.jeecg.modules.bytedance.advertise.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Joiner;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.bytedance.advertise.dockapi.MarketingService;
import org.jeecg.modules.bytedance.advertise.entity.*;
import org.jeecg.modules.bytedance.advertise.enums.BytedanceCreativeMatTypeEnum;
import org.jeecg.modules.bytedance.advertise.mapper.*;
import org.jeecg.modules.bytedance.advertise.service.*;
import org.jeecg.modules.bytedance.advertise.vo.AdConvertQueryVo;
import org.jeecg.modules.bytedance.advertise.vo.AdGroupSearchVo;
import org.jeecg.modules.bytedance.advertise.vo.IndustryVo;
import org.jeecg.modules.bytedance.advertise.vo.PlanSearchVo;
import org.jeecg.modules.bytedance.common.constant.BytedanceConstant;
import org.jeecg.modules.bytedance.common.entity.CtopOauthToken;
import org.jeecg.modules.bytedance.common.entity.MaterialImageInfo;
import org.jeecg.modules.bytedance.common.entity.MaterialInfo;
import org.jeecg.modules.bytedance.common.entity.UserAllocation;
import org.jeecg.modules.bytedance.common.service.*;
import org.jeecg.modules.bytedance.common.utils.Check;
import org.jeecg.modules.bytedance.common.utils.GetCampaignNum;
import org.jeecg.modules.bytedance.common.utils.StringUtils;
import org.jeecg.modules.bytedance.report.utils.TimeStartAndEndUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 头条智能投放账户配置信息表
 * @author jeecg-boot
 * 2021-04-20
 * @version V1.0
 */
@Service
@Slf4j
public class AiBytedanceAdvertiserStrategyServiceImpl extends ServiceImpl<AiBytedanceAdvertiserStrategyMapper, AiBytedanceAdvertiserStrategy> implements IAiBytedanceAdvertiserStrategyService {
    @Autowired
    private IBytedanceVideoSlogenInfoService slogenInfoService;
    @Autowired
    private IFileInfoService fileInfoService;
    @Resource
    private AiBytedanceAdvertiserStrategyMapper aiBytedanceAdvertiserStrategyMapper;
    @Autowired
    private ICtopOauthTokenService tokenService;
    @Autowired
    private IMaterialImageInfoService materialImageInfoService;
    @Autowired
    private IUserAllocationService userAllocationService;
    @Autowired
    private IBytedanceImageInfoService bytedanceImageInfoService;
    @Autowired
    private IBytedanceAiVideoCreativeLogService videoCreativeLogService;
    @Autowired
    private IMaterialInfoService materialInfoService;
    @Autowired
    private IByteDanceCampaignService campaignService;
    @Autowired
    private IAiBytedanceAdDplinkInfoService adDplinkInfoService;
    @Autowired
    private IByteDanceVideoInfoService videoInfoService;
    @Autowired
    private MarketingService marketingService;
    @Resource
    ByteDanceGeneralCopywriterMapper byteDanceGeneralCopywriterMapper;
    @Resource
    BytedanceMaterialRejectReasonMapper bytedanceMaterialRejectReasonMapper;
    @Autowired
    IAiBytedanceAutocreateLogService iBytedanceAutocreateLogService;

    @Override
    public Long createCreative(CtopOauthToken token, AiBytedanceAdvertiserStrategy strategy, Integer createType, Long videoCnt, String openUrl) throws ParseException {
        UserAllocation userAllocation = userAllocationService.getByAccountId(strategy.getAccountId());
        if(null == userAllocation||userAllocation.getAccountStatus()!=0){
            log.info("此账户不存在或者已经被关闭=>accountId:{}", token.getAccountId());
            return videoCnt;
        }
        //获取全量广告组数据
        campaignService.getAdvertiserCampaign(token, null, null);
        //查询相应的素材信息
        Long timeStart = BytedanceCreativeMatTypeEnum.getStartTimeByType(createType.toString());
        Long timeEnd = BytedanceCreativeMatTypeEnum.getEndTimeByType(createType.toString());
        String startTime = DateUtils.formatDate()+" 00:00:00";
        String endTime = DateUtils.formatDate()+" 23:59:59";
        Long endTimestamp = DateUtils.parseDate(endTime,"yyyy-MM-dd hh:mm:ss").getTime();
        if(timeStart != 0){
            startTime = DateUtils.formatDateTime(endTimestamp + timeStart * 60 * 1000L);
        }
        if(timeEnd != 0){
            endTime = DateUtils.formatDateTime(endTimestamp + timeEnd * 60 * 1000L);
        }
        //获取素材 账户所在的项目id 为空
        List<ByteDanceVideoInfo> videoInfos = getvideoOrImageInfoByCreateType(null,strategy,startTime,endTime,createType,videoCnt);
        if(null == videoInfos||videoInfos.isEmpty()){
            log.info("获取{}素材为空=>accountId:{}",BytedanceCreativeMatTypeEnum.getNameByType(createType+""),token.getAccountId());
            return videoCnt;
        }
        log.info("获取{}素材个数:{}=>accountId:{}",BytedanceCreativeMatTypeEnum.getNameByType(createType+""),videoInfos.size(),token.getAccountId());
        for (ByteDanceVideoInfo video:videoInfos) {
            //判断此素材为视频
            if ("video".equalsIgnoreCase(video.getMaterialType())){
                //视频是否是低质视频，为1跳过
                Integer isLowQuality = bytedanceMaterialRejectReasonMapper.getIsLowQualityByVideoId(video.getVid());
                if(!Check.isNull(isLowQuality) && 1 == isLowQuality){
                    continue;
                }
            }

            Integer useDplinkIndex = strategy.getDpLinkIndexUsed();
            if(null==useDplinkIndex||useDplinkIndex.equals(0)){
                //查看已使用的dp链接
                AiBytedanceAdDplinkInfo adDplinkInfo = adDplinkInfoService.getlatestDpLinkInfo(strategy.getId(),strategy.getAccountId(),strategy.getCreativeImageMode(),1);
                if(null == adDplinkInfo){
                    adDplinkInfo = new AiBytedanceAdDplinkInfo();
                    if("FIX".equalsIgnoreCase(strategy.getAdBidCreateType())){
                        adDplinkInfo.setAdBid(strategy.getAdCpaBid());
                    }else{
                        adDplinkInfo.setAdBid(strategy.getAdMinBid());
                    }
                    adDplinkInfo.setDpLinkIndex(strategy.getDpLinkStartIndex());
                }else{
                    adDplinkInfo.setId(null);
                    adDplinkInfo.setCreateTime(new Date());
                    adDplinkInfo.setDpLinkIndex(adDplinkInfo.getDpLinkIndex()+1);
                }

                //不使用dp链接
                String date = DateUtils.formatDate();
                //组名称
                String campaignName = getCampaignName(strategy,null,date);
                //创建组 并返回 组id
                Long campaignId = getCampaignId(strategy,campaignName,token);
                if(null == campaignId){
                    return videoCnt;
                }
                //计划名称
                String adName = getAdName(strategy,null,video,userAllocation.getProjectId());
                //截取 计划名称
                adName = StringUtils.adNameSubMaterial(adName);
                //计算本次出价
                BigDecimal currentCpaBid = StringUtils.getRandomAdCpaBid(strategy.getAdBidCreateType(),strategy.getAdMaxBid(),strategy.getAdMinBid(),strategy.getAdStepBid(),adDplinkInfo.getAdBid(),strategy.getAdCpaBid());
                JSONObject adParams = getAdParams(strategy,adName,campaignId,currentCpaBid);
                Long adId = createAdInfo(token,strategy,adParams);
                if(null == adId){
                    continue;
                }

                //3:创建创意
                JSONObject creativeParams = getCreativeParams(strategy,adId,video,token);
                log.info("账户id:{},不使用dp链接;创意创建参数:{}",strategy.getAccountId(),creativeParams);
                JSONObject creativeObject =  marketingService.creativeCreate(token,adId,creativeParams);
                log.info("账户id:{},不使用dp链接;创建返回数据=====》》》》》》{}",token.getAccountId(),creativeObject);
                if(null!=creativeObject.getInteger("code")&&creativeObject.getInteger("code")!=0){
                    List<Long> adIds = new ArrayList<>();
                    adIds.add(adId);
                    marketingService.updPlanStatus(token,adIds,"delete");
                    String message = creativeObject.getString("message");
                    Integer code = creativeObject.getInteger("code");
                    //创建创意失败
                    log.info("账户id:{};创意创建失败:code==>{};message==>{}",strategy.getAccountId(),code,message);
                    AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
                            strategy.getAccountId(),
                            "创意创建失败",
                            code,
                            message,
                            "marketingService.creativeCreate => token:"+ token.toString()+",adIds:"+adIds.toString()+"strategy:"+strategy.getAccountId()+",creativeParams:"+creativeParams.toJSONString());
                    iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
                    continue;
                }

                adDplinkInfo.setAdId(adId);
                adDplinkInfo.setAccountId(strategy.getAccountId());
                adDplinkInfo.setStatus(1);
                adDplinkInfo.setStrategyId(strategy.getId());
                adDplinkInfo.setImageMode(strategy.getCreativeImageMode());
                adDplinkInfoService.save(adDplinkInfo);

                BytedanceAiVideoCreativeLog creativeLog = new BytedanceAiVideoCreativeLog(strategy,adId,campaignId,video);
                videoCreativeLogService.saveOrUpdate(creativeLog);
                videoCnt --;
                if(videoCnt<=0){
                    return 0L;
                }
            }else{
                Long dpIndex ;
                AiBytedanceAdDplinkInfo adDplinkInfo = adDplinkInfoService.getlatestDpLinkInfo(strategy.getId(),strategy.getAccountId(),strategy.getCreativeImageMode(),1);
                if(null == adDplinkInfo){
                    adDplinkInfo = new AiBytedanceAdDplinkInfo();
                    if("FIX".equalsIgnoreCase(strategy.getAdBidCreateType())){
                        adDplinkInfo.setAdBid(strategy.getAdCpaBid());
                    }else{
                        adDplinkInfo.setAdBid(strategy.getAdMinBid());
                    }
                    adDplinkInfo.setDpLinkIndex(strategy.getDpLinkStartIndex());
                }else{
                    adDplinkInfo.setId(null);
                    adDplinkInfo.setCreateTime(new Date());
                    adDplinkInfo.setDpLinkIndex(adDplinkInfo.getDpLinkIndex()+1);
                }
                dpIndex = adDplinkInfo.getDpLinkIndex();
                // 超出下标范围
                // 已使用dp链接 < 账户配置结束下标 || 已使用dp链接 > 结束下标
                if( dpIndex < strategy.getDpLinkStartIndex() || dpIndex > strategy.getDpLinkEndIndex()){
                    log.info("策略创建结束===dp链接超过了限制===>账户id:{};策略id:{}", token.getAccountId(),strategy.getId());
                    return 0L;
                }
                //组名称
                String campaignName = getCampaignName(strategy,dpIndex,null);
                //创建组 并返回 组id
                Long campaignId = getCampaignId(strategy,campaignName,token);
                if(null == campaignId){
                    return videoCnt;
                }
                strategy.setAdOpenUrl(openUrl.replace("{{dp链接下标}}",dpIndex.toString()));
                String dplinkCode = StringUtils.getParamFromUrl(strategy.getAdOpenUrl(),"bc_fl_src");
                //计划名称
                String adName = getAdName(strategy,dplinkCode,video,userAllocation.getProjectId());
                //截取 计划名称
                adName = StringUtils.adNameSubMaterial(adName);
                //计算本次出价
                BigDecimal currentCpaBid = StringUtils.getRandomAdCpaBid(strategy.getAdBidCreateType(),strategy.getAdMaxBid(),strategy.getAdMinBid(),strategy.getAdStepBid(),adDplinkInfo.getAdBid(),strategy.getAdCpaBid());
                adDplinkInfo.setAdBid(currentCpaBid);
                JSONObject adParams = getAdParams(strategy,adName,campaignId,currentCpaBid);
                Long adId = createAdInfo(token,strategy,adParams);
                if(null == adId){
                    continue;
                }
                //3:创建创意
                JSONObject creativeParams = getCreativeParams(strategy,adId,video,token);
                log.info("账户id:{},使用dp链接;创意创建参数:{}",strategy.getAccountId(),creativeParams);

                JSONObject creativeObject =  marketingService.creativeCreate(token,adId,creativeParams);
                log.info("账户id:{},使用dp链接;创建返回数据=====》》》》》》{}",token.getAccountId(),creativeObject);

                if(null!=creativeObject.getInteger("code")&&creativeObject.getInteger("code")!=0){
                    List<Long> adIds = new ArrayList<>();
                    adIds.add(adId);
                    marketingService.updPlanStatus(token,adIds,"delete");
                    String message = creativeObject.getString("message");
                    Integer code = creativeObject.getInteger("code");
                    //创建创意失败
                    log.info("账户id:{};创意创建失败:code==>{};message==>{}",strategy.getAccountId(),code,message);
                    AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
                            strategy.getAccountId(),
                            "创意创建失败",
                            code,
                            message,
                            "marketingService.creativeCreate => token:"+ token.toString()+",adIds:"+adIds.toString()+"strategy:"+strategy.getAccountId()+",creativeParams:"+creativeParams.toJSONString());
                    iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
                    continue;
                }

                adDplinkInfo.setAdId(adId);
                adDplinkInfo.setAccountId(strategy.getAccountId());
                adDplinkInfo.setStatus(1);
                adDplinkInfo.setStrategyId(strategy.getId());
                adDplinkInfo.setImageMode(strategy.getCreativeImageMode());
                adDplinkInfoService.save(adDplinkInfo);
                BytedanceAiVideoCreativeLog creativeLog = new BytedanceAiVideoCreativeLog(strategy,adId,campaignId,video);
                videoCreativeLogService.saveOrUpdate(creativeLog);
                videoCnt --;
                if(videoCnt<=0){
                    return 0L;
                }
            }
        }
        return videoCnt;
    }

    // 创建创意  拼接创意参数 master
    private JSONObject getCreativeParams(AiBytedanceAdvertiserStrategy strategy, Long adId,ByteDanceVideoInfo videoInfo,CtopOauthToken token) {
        JSONObject params = new JSONObject();
        params.put("advertiser_id", token.getAccountId());
        params.put("ad_id", adId);

        /*基础创意*/
        JSONObject ad_data = new JSONObject();
        //行业类别
        String thirdIndustryId = strategy.getCreativeThirdIndustryId();
        if(!Check.isNull(thirdIndustryId)){
            ad_data.put("third_industry_id",thirdIndustryId);
        }

        //关键词 添加随机关键词逻辑
        String adKeywords = strategy.getCreativeAdKeywords();
        if(!Check.isNull(adKeywords)){
            String [] keywords = adKeywords.split(",");
            if(keywords.length>0){
                if(keywords.length<=20){
                    ad_data.put("ad_keywords",keywords);
                }else {
                    List<String>keywordList = Arrays.asList(keywords);
                    Collections.shuffle(keywordList);
                    List<String> getKeyWords = keywordList.subList(0,20);
                    ad_data.put("ad_keywords",getKeyWords);
                }
            }
        }
        //广告来源
        String source = strategy.getCreativeSource();
        if(!Check.isNull(source)){
            ad_data.put("source",source);
        }
        //推广抖音号
        String iesCoreUserId = strategy.getCreativeIesCoreUserId();
        if(!Check.isNull(iesCoreUserId)){
            ad_data.put("ies_core_user_id",iesCoreUserId);
        }
        //主页作品列表隐藏广告内容
        Integer isFeedAndFavSee = strategy.getCreativeIsFeedAndFavSee();
        if(null!=isFeedAndFavSee&&isFeedAndFavSee!=0){
            ad_data.put("is_feed_and_fav_see",isFeedAndFavSee);
        }
        //是否开启自动生成素材
        Integer creativeAutoGenerateSwitch = strategy.getCreativeAutoGenerateSwitch();
        if(null!=creativeAutoGenerateSwitch&&creativeAutoGenerateSwitch!=1){
            ad_data.put("creative_auto_generate_switch",creativeAutoGenerateSwitch);
        }
        //是否自动生成视频素材
        Integer isPresentedVideo = strategy.getCreativeIsPresentedVideo();
        if(null!=isPresentedVideo&&isPresentedVideo!=0){
            ad_data.put("is_presented_video",isPresentedVideo);
        }
        //是否开启衍生计划 该字段已下线
      /*  Integer generateDerivedAd = strategy.getCreativeGenerateDerivedAd();
        if(null!=generateDerivedAd&&generateDerivedAd!=0){
            ad_data.put("generate_derived_ad",generateDerivedAd);
        }*/
        //搭配试玩素材url
        String playableUrl = strategy.getCreativePlayableUrl();
        if(!Check.isNull(playableUrl)){
            ad_data.put("playable_url",playableUrl);
        }
        //应用名
        String appName = strategy.getCreativeAppName();
        if(!Check.isNull(appName)){
            ad_data.put("app_name",appName);
        }
        //Android应用下载详情页
        String webUrl = strategy.getCreativeWebUrl();
        if(!Check.isNull(webUrl)){
            ad_data.put("web_url",webUrl);
        }
        //落地页链接
        if(!Check.isNull(strategy.getAdExternalUrl())){
            ad_data.put("external_url",strategy.getAdExternalUrl());
        }

        //是否关闭评论，0为开启，1为关闭，默认值：0
        Integer isCommentDisable = strategy.getCreativeIsCommentDisable();
        if(!Check.isNull(isCommentDisable)&&isCommentDisable!=0){
            ad_data.put("is_comment_disable",isCommentDisable);
        }
        //允许客户端下载视频功能
        Integer adDownloadStatus = strategy.getCreativeDownloadStatus();
        if(!Check.isNull(adDownloadStatus)&&adDownloadStatus!=0){
            ad_data.put("ad_download_status",adDownloadStatus);
        }
        //创意展现方式
        String creativeDisplayMode = strategy.getCreativeDisplayMode();
        if(!Check.isNull(creativeDisplayMode)){
            ad_data.put("creative_display_mode",creativeDisplayMode);
        }
        params.put("ad_data",ad_data);

        JSONObject creObj = new JSONObject();

        JSONArray titleArray = new JSONArray();

        //文案数量 默认10-master
        int copyNum = (Check.isNull(strategy.getCopywritingNumber()) || strategy.getCopywritingNumber() == 0) ? 10 : strategy.getCopywritingNumber();
        //根据账户 和 文案数量 查询 指定文案
        List<BytedanceVideoSlogenInfo> slogenInfos = slogenInfoService.listByParams(videoInfo.getSignature(),1,copyNum);
        //使用指定文案
        if(!Check.isNull(slogenInfos)){
            for (BytedanceVideoSlogenInfo slogenInfo:slogenInfos) {
                if(titleArray.size() >= copyNum){    //接口中是要求一个视频最多10个标题
                    break;
                }
                JSONObject titleObject = new JSONObject();
                titleObject.put("title",slogenInfo.getSlogan());
                String creativeWordsIds = slogenInfo.getCreativeWordIds();
                JSONArray wordsArr = new JSONArray();
                if(null!=creativeWordsIds&&!creativeWordsIds.trim().equals("")){
                    JSONArray creativeWordsArray = JSON.parseArray(creativeWordsIds);
                        for (Object creative : creativeWordsArray) {
                            JSONObject creativeObject = new JSONObject();
                            creativeObject.put("word_id",creative);
                            wordsArr.add(creativeObject);
                        }
                        titleObject.put("word_list",wordsArr);

                }
                titleArray.add(titleObject);
            }
        }

        // 视频 指定文案不够的时候 使用通用文案 最多3条
        if ("video".equalsIgnoreCase(videoInfo.getMaterialType())){
            List<ByteDanceGeneralCopywriter> byteDanceGeneralCopywriter = byteDanceGeneralCopywriterMapper.getRandThree(strategy.getAccountId());
            if(!Check.isNull(byteDanceGeneralCopywriter)){
                for(int i = 0; i < byteDanceGeneralCopywriter.size(); i++){
                    if(titleArray.size() >= copyNum){
                        break;
                    }
                    JSONObject titleObject = new JSONObject();
                    titleObject.put("title",byteDanceGeneralCopywriter.get(i).getTextCopywriter());
                    String creativeWordsIds = byteDanceGeneralCopywriter.get(i).getCreativeWordIds();
                    JSONArray wordsArr = new JSONArray();
                    if(null != creativeWordsIds && !creativeWordsIds.trim().equals("")){
                        JSONArray creativeWordsArray = JSON.parseArray(creativeWordsIds);
                            for (Object creative : creativeWordsArray) {
                                JSONObject creativeObject = new JSONObject();
                                creativeObject.put("word_id",creative);
                                wordsArr.add(creativeObject);
                            }
                            titleObject.put("word_list",wordsArr);
                    }
                    titleArray.add(titleObject);
                }

            }
            // 图片 使用通用文案 最多10条
        }else if ("image".equalsIgnoreCase(videoInfo.getMaterialType())){
            List<ByteDanceGeneralCopywriter> byteDanceGeneralCopywriterList = byteDanceGeneralCopywriterMapper.getRandTen(strategy.getAccountId(),copyNum);
            if(!Check.isNull(byteDanceGeneralCopywriterList)){
                for (ByteDanceGeneralCopywriter byteDanceGeneralCopywriter : byteDanceGeneralCopywriterList){
                    JSONObject titleObject = new JSONObject();
                    titleObject.put("title",byteDanceGeneralCopywriter.getTextCopywriter());
                    String creativeWordsIds = byteDanceGeneralCopywriter.getCreativeWordIds();
                    if(null!=creativeWordsIds&&!creativeWordsIds.trim().equals("")){
                        JSONArray creativeWordsArray = JSON.parseArray(creativeWordsIds);
                        JSONArray wordsArr = new JSONArray();
                        if(null!=creativeWordsArray&&!creativeWordsArray.isEmpty()){
                            for (Object creative : creativeWordsArray) {
                                JSONObject creativeObject = new JSONObject();
                                creativeObject.put("word_id",creative);
                                wordsArr.add(creativeObject);
                            }
                            titleObject.put("word_list",wordsArr);
                        }
                    }
                    titleArray.add(titleObject);
                }
            }
        }
        if (Check.isNull(titleArray)){
            log.info("账户-----{}-------暂无文案，请补充文案信息",strategy.getAccountId());
            AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
                    strategy.getAccountId(),
                    "创意获取文案为空",
                    40000,
                    strategy.getAccountId()+"暂无文案，请补充文案信息",
                    "创建创意=====> ,id:"+strategy.getId()+"strategy:"+strategy.getAccountId());
            iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
        }
        creObj.put("title_materials",titleArray);
        JSONArray imageMaterials = new JSONArray();
        JSONObject object = new JSONObject();
        //类型
        if ("image".equalsIgnoreCase(videoInfo.getMaterialType())){
            //图片素材
            object.put("image_mode",strategy.getCreativeImageMode());
            String[] imageIds = new String[]{videoInfo.getId()};
            JSONArray image_info = new JSONArray();
            for (String imgId : imageIds) {
                JSONObject imageObject = new JSONObject();
                imageObject.put("image_id",imgId);
                image_info.add(imageObject);
            }
            object.put("image_info",image_info);
            imageMaterials.add(object);
            creObj.put("image_materials",imageMaterials);
        }

        if ("video".equalsIgnoreCase(videoInfo.getMaterialType())){
            //视频
            object.put("image_mode",strategy.getCreativeImageMode());
            JSONObject videoObj = new JSONObject();
            videoObj.put("video_id",videoInfo.getVid());
            //视频封面
            JSONObject imgObj = new JSONObject();
            //获取视频封面id
            String imageId = getSuggestImageId(token,videoInfo.getVid());
            if(!Check.isNull(imageId)){
                imgObj.put("image_id",imageId);
            }
            object.put("image_info",imgObj);
            object.put("video_info",videoObj);
            imageMaterials.add(object);
            creObj.put("video_materials",imageMaterials);
        }

        //通投智选 竖版视频 横版视频 横图大图
        if (!Check.isNull(strategy.getAdDeliveryRange()) && "UNIVERSAL".equalsIgnoreCase(strategy.getAdDeliveryRange())){
            List<ByteDanceVideoInfo> resultList = new ArrayList<>();
            //获取 最近14天的时间 开始 和截至时间点
            Map<String,String> map = TimeStartAndEndUtil.getNowFourTeenTime();
            //横板视频
            if (strategy.getCreativeImageMode().contains("CREATIVE_IMAGE_MODE_VIDEO")){
                List<ByteDanceVideoInfo>  listMode = byteDanceVideoInfoMapper.getModeVideo(strategy.getAccountId(),map.get("startTime"),map.get("endTime"),1L);
                if (!Check.isNull(listMode)){
                    for (ByteDanceVideoInfo info : listMode) {
                        //横板视频
                        object.put("image_mode","CREATIVE_IMAGE_MODE_VIDEO");
                        JSONObject videoObj = new JSONObject();
                        videoObj.put("video_id",info.getVid());
                        //视频封面
                        JSONObject imgObj = new JSONObject();
                        //获取视频封面id
                        String imageId = getSuggestImageId(token,info.getVid());
                        if(!Check.isNull(imageId)){
                            imgObj.put("image_id",imageId);
                        }
                        object.put("image_info",imgObj);
                        object.put("video_info",videoObj);
                        imageMaterials.add(object);
                        creObj.put("video_materials",imageMaterials);
                    }
                }
            }
            //横图大图
            if (strategy.getCreativeImageMode().contains("CREATIVE_IMAGE_MODE_LARGE")){
                List<ByteDanceVideoInfo>  listImage = byteDanceVideoInfoMapper.getModeImageLarge(strategy.getAccountId(),map.get("startTime"),map.get("endTime"),1L);
                if (!Check.isNull(listImage)){
                    for (ByteDanceVideoInfo info : listImage) {
                        //图片素材
                        object.put("image_mode","CREATIVE_IMAGE_MODE_LARGE");
                        String[] imageIds = new String[]{info.getId()};
                        JSONArray image_info = new JSONArray();
                        for (String imgId : imageIds) {
                            JSONObject imageObject = new JSONObject();
                            imageObject.put("image_id",imgId);
                            image_info.add(imageObject);
                        }
                        object.put("image_info",image_info);
                        imageMaterials.add(object);
                        creObj.put("image_materials",imageMaterials);
                    }
                }
            }
        }

        //副标题
        String subTitle = strategy.getCreativeSubTitle();
        if(!Check.isNull(subTitle)){
            JSONObject titleObj = new JSONObject();
            titleObj.put("sub_title",subTitle);
            creObj.put("sub_title_material",titleObj);
        }
        //组件id
       JSONArray component = new JSONArray();
       String componentIdStr = strategy.getComponentId();
       if (!Check.isNull(componentIdStr)){
           String[] componentId = componentIdStr.split(",");
           for (String strId : componentId) {
               JSONObject obj = new JSONObject();
               obj.put("component_id",new Long(strId));
               component.add(obj);
           }
           creObj.put("component_materials",component);
       }
        params.put("creative",creObj);
        return params;

    }


    private String getBytedanceImageIdByCode(String imageCode, CtopOauthToken token) {
        //1：根据code获取图片信息
        BytedanceImageInfo bytedanceImageInfo = bytedanceImageInfoService.getByParams(imageCode);
        if(null!=bytedanceImageInfo){
            return bytedanceImageInfo.getId();
        }
        //2:根据code查询图片素材信息
        MaterialImageInfo imageInfo = materialImageInfoService.getByCode(imageCode);
        if(null ==  imageInfo){
            return null;
        }
        Map<String, Object> result = fileInfoService.uploadImageToBytedance(token.getAccountId().toString(),imageInfo.getUrl());
        Integer code = (Integer) result.get("code");
        if(null == code||code!=0){
            return null;
        }
        BytedanceImageInfo info  = (BytedanceImageInfo)result.get("data");
        if(null != info&&null!=info.getId()){
            return info.getId();
        }
        return null;
    }

    private String getSuggestImageId(CtopOauthToken token, String vid) {
        return fileInfoService.getSuggestImageId(token,vid);
    }

    private Long createAdInfo(CtopOauthToken token, AiBytedanceAdvertiserStrategy strategy, JSONObject adParams) {
        Result result = marketingService.createAdvertiserPlan(token,adParams,strategy);
        log.info("账户id{}=====创建计划{}===",token.getAccountId(),result);
        if(result.getCode()!=0){
            AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
                    strategy.getAccountId(),
                    "计划创建异常",
                    result.getCode(),
                    result.getMessage(),
                    adParams.toJSONString());
            iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
            return null;
        }
        return (Long)result.getResult();
    }

    private JSONObject getAdParams(AiBytedanceAdvertiserStrategy strategy, String adName, Long campaignId,BigDecimal currentCpaBid) {
        JSONObject params = new JSONObject();
        //公共参数
        params.put("advertiser_id",strategy.getAccountId());
        params.put("campaign_id",campaignId);
        params.put("name",adName);
        //竞价策略 默认优先跑量
        params.put("flow_control_mode","FLOW_CONTROL_MODE_FAST");

        // 搜索快投
        /*if(!"UNION".equals(strategy.getAdDeliveryRange())){
            params.put("feed_delivery_search","DISABLED");
        }
*/
        //params.put("feed_delivery_search","DISABLED");
        //投放范围
        if(null!=strategy.getAdDeliveryRange() && !"".equals(strategy.getAdDeliveryRange().trim())){
            params.put("delivery_range",strategy.getAdDeliveryRange());
            //搜索快投
           if(!"UNION".equals(strategy.getAdDeliveryRange())){
                params.put("feed_delivery_search","DISABLED");
            }
        }

        //点击监测链接
        String actionTrackUrl = strategy.getCreativeActionTrackUrl();
        if(!Check.isNull(actionTrackUrl)){
            params.put("action_track_url",new String[]{actionTrackUrl});
        }


        //广告位大类
         if (!Check.isNull(strategy.getInventoryCatalog())){
            params.put("inventory_catalog",strategy.getInventoryCatalog());
        }else{
             params.put("inventory_catalog","MANUAL");
         }

        //广告投放位置
        String inventoryType = strategy.getCreativeInventoryType();
        if ("CREATIVE_IMAGE_MODE_UNION_SPLASH".equalsIgnoreCase(strategy.getCreativeImageMode())) {
            params.put("inventory_type", new String[]{"INVENTORY_UNION_SPLASH_SLOT"});
        } else {
            if (null != inventoryType && !"".equals(inventoryType)) {
                String[] inventoryTypeString = inventoryType.split(",");
                if (inventoryTypeString.length > 0) {
                    params.put("inventory_type", inventoryTypeString);
                }
            }
        }
        //优选广告位
        if (!Check.isNull(strategy.getCreativeSmartInventory())){
            params.put("smart_inventory",strategy.getCreativeSmartInventory());
        }else{
            params.put("smart_inventory","NORMAL");
        }

        // 投放形式
        if(!Check.isNull(strategy.getAdUnionVideoType())){
            params.put("union_video_type",strategy.getAdUnionVideoType());
        }

        //下载方式
        params.put("download_type",strategy.getAdDownloadType());


        if(!Check.isNull(strategy.getAdDownloadUrl())){
            params.put("download_url",strategy.getAdDownloadUrl());
        }
        if(!Check.isNull(strategy.getAdPackage())&&!strategy.getAdPackage().equals("NONE")){
            params.put("package",strategy.getAdPackage());
        }
        //params.put("download_url","https://apps.bytesfield.com/download/basic/cur/1c728178004c8d4d6c83444a05c414c1a1cfae48");
       // params.put("package","com.taobao.litetao");
        if(!Check.isNull(strategy.getAdQuickAppUrl())){
            params.put("quick_app_url",strategy.getAdQuickAppUrl());
        }

        if(!Check.isNull(strategy.getAdAppType())){
            params.put("app_type",strategy.getAdAppType());
        }
        if(!Check.isNull(strategy.getAdDownloadMode())){
            params.put("download_mode",strategy.getAdDownloadMode());
        }
        if(!Check.isNull(strategy.getAdConvertId())){
            params.put("convert_id",strategy.getAdConvertId());
        }

        if(!Check.isNull(strategy.getAdOpenUrl())){
            params.put("open_url",strategy.getAdOpenUrl());
        }
        if(!Check.isNull(strategy.getAdAdvancedCreativeType())){
            params.put("advanced_creative_type",strategy.getAdAdvancedCreativeType());
        }
        if(!Check.isNull(strategy.getAdGamePackageDesc())){
            params.put("game_package_desc",strategy.getAdGamePackageDesc());
        }
        if(!Check.isNull(strategy.getAdGamePackageBatchId())){
            params.put("game_package_batch_id",strategy.getAdGamePackageBatchId());
        }
        if(!Check.isNull(strategy.getAdGamePackageThumbnailId())){
            JSONArray ids = JSON.parseArray(strategy.getAdGamePackageThumbnailId());
            if(null != ids&&!ids.isEmpty()){
                params.put("game_package_thumbnail_ids",ids);
            }
        }
        //用户定向    定向类型 add-新建定向；choice-选择定向
        if(!Check.isNull(strategy.getAdAudiencePackageId()) && "choice".equalsIgnoreCase(strategy.getAdDirectionalFlag())){
            params.put("audience_package_id",strategy.getAdAudiencePackageId());
        }
        if(!Check.isNull(strategy.getAdDistrict())){
            params.put("district",strategy.getAdDistrict());
        }
        if(!Check.isNull(strategy.getAdCity())){
            String[] city = strategy.getAdCity().split(",");
            if(city.length>0){
                params.put("city",city);
            }
        }
        if(!Check.isNull(strategy.getAdLocationType())){
            params.put("location_type",strategy.getAdLocationType());
        }
        if(!Check.isNull(strategy.getAdGender())){
            params.put("gender",strategy.getAdGender());
        }
        if(!Check.isNull(strategy.getAdAge())){
            String[] age = strategy.getAdAge().split(",");
            if(age.length>0){
                JSONArray ageArray = new JSONArray();
                for(int i=0;i<age.length;i++){
                    if(null!=age[i]&&!"NONE".equals(age[i])){
                        ageArray.add(age[i]);
                    }
                }
                if(!ageArray.isEmpty()){
                    params.put("age",ageArray);
                }
            }
        }
        if(!Check.isNull(strategy.getAdRetargetingTagsInclude())){
            String[] retargetingTagsInclude = strategy.getAdRetargetingTagsInclude().split(",");
            if(retargetingTagsInclude.length>0){
                JSONArray retargetingTagsIncludeArray = new JSONArray();
                for(int i=0;i<retargetingTagsInclude.length;i++){
                    if(null!=retargetingTagsInclude[i]&&!"NONE".equals(retargetingTagsInclude[i])){
                        retargetingTagsIncludeArray.add(Long.parseLong(retargetingTagsInclude[i]));
                    }
                }
                if(!retargetingTagsIncludeArray.isEmpty()){
                    params.put("retargeting_tags_include",retargetingTagsIncludeArray);
                }
            }
        }
        if(!Check.isNull(strategy.getAdRetargetingTagsExclude())){
            String[] getAdRetargetingTagsExclude = strategy.getAdRetargetingTagsExclude().split(",");
            if(getAdRetargetingTagsExclude.length>0){
                JSONArray getAdRetargetingTagsExcludeArray = new JSONArray();
                for(int i=0;i<getAdRetargetingTagsExclude.length;i++){
                    if(null!=getAdRetargetingTagsExclude[i]&&!"NONE".equals(getAdRetargetingTagsExclude[i])){
                        getAdRetargetingTagsExcludeArray.add(getAdRetargetingTagsExclude[i]);
                    }
                }
                if(!getAdRetargetingTagsExcludeArray.isEmpty()){
                    params.put("retargeting_tags_exclude",getAdRetargetingTagsExcludeArray);
                }
            }
        }
        if(!Check.isNull(strategy.getAdInterestActionMode())){
            params.put("interest_action_mode",strategy.getAdInterestActionMode());
        }
        if(!Check.isNull(strategy.getAdActionScene())){
            String[] actionScene = strategy.getAdActionScene().split(",");
            if(actionScene.length>0){
                JSONArray actionSceneArray = new JSONArray();
                for(int i=0;i<actionScene.length;i++){
                    actionSceneArray.add(actionScene[i]);
                }
                params.put("action_scene",actionSceneArray);
            }
        }
        if(!Check.isNull(strategy.getAdActionDays())){
            params.put("action_days",strategy.getAdActionDays());
        }
        if(!Check.isNull(strategy.getAdActionCategories())){
            String[] actionCategories = strategy.getAdActionCategories().split(",");
            if(actionCategories.length>0){
                JSONArray actionCategoriesArray = new JSONArray();
                for(int i=0;i<actionCategories.length;i++){
                    actionCategoriesArray.add(actionCategories[i]);
                }
                params.put("action_categories",actionCategoriesArray);
            }
        }
        if(!Check.isNull(strategy.getAdActionWords())){
            String[] actionWords = strategy.getAdActionWords().split(",");
            if(actionWords.length>0){
                JSONArray actionWordsArray = new JSONArray();
                for(int i=0;i<actionWords.length;i++){
                    actionWordsArray.add(actionWords[i]);
                }
                params.put("action_words",actionWordsArray);
            }
        }
        if(!Check.isNull(strategy.getAdInterestCategories())){
            String[] interestCategories = strategy.getAdInterestCategories().split(",");
            if(interestCategories.length>0){
                JSONArray interestCategoriesArray = new JSONArray();
                for(int i=0;i<interestCategories.length;i++){
                    interestCategoriesArray.add(interestCategories[i]);
                }
                params.put("interest_categories",interestCategoriesArray);
            }
        }
        if(!Check.isNull(strategy.getAdInterestWords())){
            String[] interestWords = strategy.getAdInterestWords().split(",");
            if(interestWords.length>0){
                params.put("interest_words",interestWords);
            }
        }
        if(!Check.isNull(strategy.getAdAwemeFanBehaviors())){
            String[] awemeFanBehaviors = strategy.getAdAwemeFanBehaviors().split(",");
            if(awemeFanBehaviors.length>0){
                params.put("aweme_fan_behaviors",awemeFanBehaviors);
            }
        }
        if(!Check.isNull(strategy.getAdAwemeFanCategories())){
            String[] awemeFanCategories = strategy.getAdAwemeFanCategories().split(",");
            if(awemeFanCategories.length>0){
                params.put("aweme_fan_categories",awemeFanCategories);
            }
        }
        if(!Check.isNull(strategy.getAdAwemeFanAccounts())){
            String[] awemeFanAccount = strategy.getAdAwemeFanAccounts().split(",");
            if(awemeFanAccount.length>0){
                params.put("aweme_fan_accounts",awemeFanAccount);
            }
        }
        if(!Check.isNull(strategy.getAdAwemeFansNumbers())){
            String[] awemeFansNumbers = strategy.getAdAwemeFansNumbers().split(",");
            if(awemeFansNumbers.length>0){
                params.put("aweme_fans_numbers",awemeFansNumbers);
            }
        }
        if(!Check.isNull(strategy.getAdFilterAwemeAbnormalActive())){
            params.put("filter_aweme_abnormal_active",strategy.getAdFilterAwemeAbnormalActive());
        }
        if(!Check.isNull(strategy.getAdFilterAwemeFansCount())){
            params.put("filter_aweme_fans_count",strategy.getAdFilterAwemeFansCount());
        }
        if(!Check.isNull(strategy.getAdFilterOwnAwemeFans())){
            params.put("filter_own_aweme_fans",strategy.getAdFilterOwnAwemeFans());
        }
        if(!Check.isNull(strategy.getAdSuperiorPopularityType())){
            params.put("superior_popularity_type",strategy.getAdSuperiorPopularityType());
        }
        if(!Check.isNull(strategy.getAdFlowPackage())){
            String[] flowPackage = strategy.getAdFlowPackage().split(",");
            if(flowPackage.length>0){
                params.put("flow_package",flowPackage);
            }
        }
        if(!Check.isNull(strategy.getAdExcludeFlowPackage())){
            String[] excludeFlowPackage = strategy.getAdExcludeFlowPackage().split(",");
            if(excludeFlowPackage.length>0){
                params.put("exclude_flow_package",excludeFlowPackage);
            }
        }

        if(!Check.isNull(strategy.getAdPlatform())){
            String[] platform = strategy.getAdPlatform().split(",");
            if(platform.length>0){
                params.put("platform",platform);
            }
        }

        if(!Check.isNull(strategy.getAdAndroidOsv())){
            params.put("android_osv",strategy.getAdAndroidOsv());
        }

        if(!Check.isNull(strategy.getAdAdIosOsv())){
            params.put("ios_osv",strategy.getAdAdIosOsv());
        }
        if(!Check.isNull(strategy.getAdAc())){
            String[] ac = strategy.getAdAc().split(",");
            if(ac.length>0){
                JSONArray acArray = new JSONArray();
                for(int i=0;i<ac.length;i++){
                    if(null!=ac[i]&&!"NONE".equals(ac[i])){
                        acArray.add(ac[i]);
                    }
                }
                if(!acArray.isEmpty()){
                    params.put("ac",acArray);
                }
            }
        }
        if(!Check.isNull(strategy.getAdCarrier())){
            String[] carrier = strategy.getAdCarrier().split(",");
            if(carrier.length>0){
                JSONArray carrierArray = new JSONArray();
                for(int i=0;i<carrier.length;i++){
                    if(null!=carrier[i]&&!"NONE".equals(carrier[i])) {
                        carrierArray.add(carrier[i]);
                    }
                }
                if(!carrierArray.isEmpty()){
                    params.put("carrier",carrierArray);
                }
            }
        }
        if(!Check.isNull(strategy.getAdDeviceType())&&!strategy.getAdDeviceType().trim().equals("NONE")){
            String[] deviceType = strategy.getAdDeviceType().split(",");
            if(deviceType.length>0){
                params.put("device_type",deviceType);
            }
        }

        if(!Check.isNull(strategy.getAdHideIfExists())){
            params.put("hide_if_exists",strategy.getAdHideIfExists());
        }


        if(!Check.isNull(strategy.getAdHideIfConverted())){
            String hideIfConverted = strategy.getAdHideIfConverted();
            params.put("hide_if_converted",hideIfConverted);
            if(hideIfConverted.equals("APP")||hideIfConverted.equals("CUSTOMER")){
                if(!Check.isNull(strategy.getAdConvertedTimeDuration())){
                    params.put("converted_time_duration",strategy.getAdConvertedTimeDuration());
                }
            }
        }

        if(!Check.isNull(strategy.getAdActivateType())){
            String[] activateType = strategy.getAdActivateType().split(",");
            if(activateType.length>0){
                JSONArray activateTypeArray = new JSONArray();
                for(int i=0;i<activateType.length;i++){
                    activateTypeArray.add(activateType[i]);
                }
                params.put("activate_type",activateTypeArray);
            }
        }
        if(!Check.isNull(strategy.getAdArticleCategory())){
            String[] articleCategory = strategy.getAdArticleCategory().split(",");
            if(articleCategory.length>0){
                JSONArray articleCategoryArray = new JSONArray();
                for(int i=0;i<articleCategory.length;i++){
                    articleCategoryArray.add(articleCategory[i]);
                }
                params.put("article_category",articleCategoryArray);
            }
        }
        if(!Check.isNull(strategy.getAdDeviceBrand())){
            String[] deviceBrand = strategy.getAdDeviceBrand().split(",");
            if(deviceBrand.length>0){
                JSONArray deviceBrandArray = new JSONArray();
                for(int i=0;i<deviceBrand.length;i++){
                    deviceBrandArray.add(deviceBrand[i]);
                }
                params.put("device_brand",deviceBrandArray);
            }
        }
        if(!Check.isNull(strategy.getAdLaunchPrice())){
            String[] launchPrice = strategy.getAdLaunchPrice().split(",");
            if(launchPrice.length>0){
                JSONArray launchPriceArray = new JSONArray();
                for(int i=0;i<launchPrice.length;i++){
                    launchPriceArray.add(launchPrice[i]);
                }
                params.put("launch_price",launchPriceArray);
            }
        }
        if(!Check.isNull(strategy.getAdAutoExtendEnabled())){
            params.put("auto_extend_enabled",strategy.getAdAutoExtendEnabled());
        }
        //可放开定向
        if(!Check.isNull(strategy.getAdAutoExtendTargets())){
            String[] autoExtendTargets = strategy.getAdAutoExtendTargets().split(",");
            if(autoExtendTargets.length>0){
                JSONArray autoExtendTargetsArray = new JSONArray();
                for(int i=0;i<autoExtendTargets.length;i++){
                    autoExtendTargetsArray.add(autoExtendTargets[i]);
                }
                params.put("auto_extend_targets",autoExtendTargetsArray);
            }
        }
        //预算与出价
        if(!Check.isNull(strategy.getAdSmartBidType())){
            params.put("smart_bid_type",strategy.getAdSmartBidType());
        }
        if(!Check.isNull(strategy.getAdAdjustCpa())){
            params.put("adjust_cpa",strategy.getAdAdjustCpa());
        }
        if(!Check.isNull(strategy.getAdFlowControlMode())){
            params.put("flow_control_mode",strategy.getAdFlowControlMode());
        }
        if(!Check.isNull(strategy.getAdBudgetMode())){
            params.put("budget_mode",strategy.getAdBudgetMode());
        }
        if(!Check.isNull(strategy.getAdBudget())){
            params.put("budget",strategy.getAdBudget());
        }
        if(!Check.isNull(strategy.getAdScheduleType())){
            params.put("schedule_type",strategy.getAdScheduleType());
        }

        //总预算 必须设置 起始时间
        if ("BUDGET_MODE_TOTAL".equalsIgnoreCase(strategy.getAdBudgetMode())){
            params.put("start_time",strategy.getAdStartTime()+" 00:00");
            params.put("end_time",strategy.getAdEndTime()+" 00:00");
        }


        if(!Check.isNull(strategy.getAdScheduleTime())){
            params.put("schedule_time",strategy.getAdScheduleTime());
        }
        if(!Check.isNull(strategy.getAdPricing())){
            params.put("pricing",strategy.getAdPricing());
        }
        if(!Check.isNull(strategy.getAdBid())){
            params.put("bid",strategy.getAdBid());
        }
        params.put("cpa_bid",currentCpaBid);
        if(!Check.isNull(strategy.getAdDeepBidType())){
            params.put("deep_bid_type",strategy.getAdDeepBidType());
            params.put("deep_cpabid",strategy.getAdDeepCpabid());

        }

        if(!Check.isNull(strategy.getAdLubanRoiGoal())){
            params.put("luban_roi_goal",strategy.getAdLubanRoiGoal());
        }
        if(!Check.isNull(strategy.getAdRoiGoal())){
            params.put("roi_goal",strategy.getAdRoiGoal());
        }
        return params;
    }

    private String getAdName(AiBytedanceAdvertiserStrategy strategy, String dplinkCode, ByteDanceVideoInfo videoInfo,Long projectId) {
        String adName = strategy.getAdName();
        if(null == adName|| "".equals(adName.trim())){
            return null;
        }
        if(adName.contains("{{日期}}")){
            String date = DateUtils.formatDate(new Date(),"yyyyMMdd");
            adName = adName.replace("{{日期}}",date);
        }
        if(adName.contains("{{创意方式}}")){
            adName = adName.replace("{{创意方式}}","程序化");
        }
        if(adName.contains("{{dp链接标识}}")&&null!=dplinkCode){
            adName = adName.replace("{{dp链接标识}}",dplinkCode);
        }
        if(adName.contains("{{出价方式}}")){
            String pricing = strategy.getAdPricing().replace("PRICING_","").toLowerCase(Locale.ROOT);
            adName = adName.replace("{{出价方式}}",pricing);
        }

        if(adName.contains("{{素材名称}}")){
            if ("video".equals(videoInfo.getMaterialType())){
                MaterialInfo info = materialInfoService.getParams(videoInfo.getSignature(),null,null);
                if(null!=info&&null!=info.getMaterialName()){
                    adName = adName.replace("{{素材名称}}","["+info.getMaterialName()+"]");
                }
            }else {
                adName = adName.replace("{{素材名称}}","["+videoInfo.getFilename()+"]");
            }
        }

        if(adName.contains("{{序号}}")){
            int i = adDplinkInfoService.getDpLinkInfoCount(strategy.getAccountId(),strategy.getCreativeImageMode());
            adName = adName.replace("{{序号}}",String.valueOf(i+1));
        }

        adName = adName.replace("--","-");
        if(adName.startsWith("-")){
            adName = adName.substring(1);
        }
        if(adName.endsWith("-")){
            adName = adName.substring(0,adName.length()-1);
        }
        adName = adName.replace("--","-");
        return adName;
    }


    /**
     * 创建 组
     * 如果已有组信息 则 返回组id
     * 没有则 新建
     * @param strategy
     * @param campaignName
     * @param token
     * @return
     */
    private Long getCampaignId(AiBytedanceAdvertiserStrategy strategy, String campaignName,CtopOauthToken token) {
        ByteDanceCampaign campaign = campaignService.getOneByParams(strategy.getAccountId(),campaignName);
        if(null != campaign){
            return campaign.getId();
        }
        //创建组信息
        JSONObject campaignParam = new JSONObject();
        campaignParam.put("advertiser_id",strategy.getAccountId());
        campaignParam.put("campaign_name",campaignName);
        campaignParam.put("landing_type",strategy.getCampaignLandingType());
        if(null==strategy.getCampaignBudgetMode()|| "".equals(strategy.getCampaignBudgetMode())){
            campaignParam.put("budget_mode","BUDGET_MODE_INFINITE");
        }else{
            campaignParam.put("budget_mode",strategy.getCampaignBudgetMode());
        }
        //日预算必须设定预算金额
        if(null!=strategy.getCampaignBudgetMode()&& "BUDGET_MODE_DAY".equals(strategy.getCampaignBudgetMode())){
            campaignParam.put("budget",strategy.getCampaignBudget());
        }
        if(null != strategy.getCampaignDeliveryRelatedNum()&&!"".equals(strategy.getCampaignDeliveryRelatedNum().trim())){
            campaignParam.put("delivery_related_num",strategy.getCampaignDeliveryRelatedNum());
        }
        //营销目的 --行动转化
        //营销目的，允许值CONVERSION行动转化、INTENTION用户意向、ACKNOWLEDGE品牌认知
        campaignParam.put("marketing_purpose",strategy.getMarketingPurpose());
        //广告类型 允许值FEED信息流、SEARCH搜索广告
        campaignParam.put("campaign_type",strategy.getCampaignType());
        //创建组
        Result campaignData = marketingService.createCampaign(token, campaignParam);
        log.info("账户id{}===创建组==={}",token.getAccountId(),campaignData);
        if(campaignData.getCode()!=0){
            AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
                    strategy.getAccountId(),
                    "组创建异常",
                    campaignData.getCode(),
                    campaignData.getMessage(),
                    campaignParam.toJSONString());
            iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
            return null;
        }
        return (Long)campaignData.getResult();
    }

    private String getCampaignName(AiBytedanceAdvertiserStrategy strategy,Long dplinkIndex,String date) {
        String result = strategy.getCampaignName();
        if(null != dplinkIndex && dplinkIndex !=0){
            String campaignSufix = getRangeIndex(strategy.getDpLinkStartIndex(),strategy.getDpLinkEndIndex(),strategy.getCampaignAdCnt(),dplinkIndex);
            result = result + campaignSufix;
        }
        if(null!=date&&!date.trim().equals("")) {
            result = result + "-" + date;
        }

        if(result.contains("{{序号}}")){
            //查询同素材类型当天已有计划数量
            int i = adDplinkInfoService.getDpLinkInfoCount(strategy.getAccountId(),strategy.getCreativeImageMode());
            Long num = GetCampaignNum.getCampaignNameNum(strategy.getCampaignCnt(),strategy.getCampaignAdCnt(), i+1);
            result = result.replace("{{序号}}",String.valueOf(num));
        }

        if(result.contains("{{日期}}")){
            String time = DateUtils.formatDate(new Date(),"yyyyMMdd");
            result = result.replace("{{日期}}",time);
        }

        result = result.replace("--","-");
        if(result.startsWith("-")){
            result = result.substring(1);
        }
        if(result.endsWith("-")){
            result = result.substring(0,result.length()-1);
        }
        result = result.replace("--","-");
        return result;
    }

    private String getRangeIndex(Long dpLinkStartIndex,Long dpLinkEndIndex, Long campaignAdCnt, Long dpIndex) {
       /* if(dpIndex<dpLinkStartIndex||dpIndex>dpLinkEndIndex){
            //超出下标范围
            return null;
        }*/
        Long startIndex ;
        Long endIndex ;
        //计算当前下标值和范围区段的余数
        Long yzIndex = (dpIndex-dpLinkStartIndex+1)%campaignAdCnt;
        if(yzIndex == 0){
            startIndex = dpIndex-campaignAdCnt+1;
            endIndex = dpIndex;
        }else{
            startIndex = dpIndex-yzIndex+1;
            endIndex = dpIndex-yzIndex+campaignAdCnt;
        }
        //dp 链接 超出可用范围
        if (endIndex > dpLinkEndIndex){
            endIndex = dpLinkEndIndex;
        }
        return "-("+startIndex+"/"+endIndex+")";
    }

    private List<ByteDanceVideoInfo> getVideoInfoByCreateType(Long projectId,AiBytedanceAdvertiserStrategy strategy, String startTime, String endTime, Integer createType, Long videoCnt) {
        //根据 imageMode 获取素材类型
        //2-竖版视频 1-横板视频
        String imageMode = BytedanceCreativeMatTypeEnum.getNameByType(strategy.getCreativeImageMode());
        //1：上新素材 2：跑量素材 3：遗漏素材 4：打捞素材
        if(createType == 1||createType == 3){
            return videoInfoService.listByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt,0);
        }else if(createType == 2){
            startTime = startTime.substring(0,10);
            endTime = endTime.substring(0,10);
            return videoInfoService.topMatByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt);
        }else if(createType == 4){
            return videoInfoService.historyMatByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt);
        }
        return null;
    }

    /**
     * 图片素材
     */
    private List<ByteDanceVideoInfo> getImageInfoByCreateType(Long projectId,AiBytedanceAdvertiserStrategy strategy, String startTime, String endTime, Integer createType, Long videoCnt) {
        //根据 imageMode 获取素材类型
        //1-大图横图; 2-大图竖图 3-开屏
        String imageMode = BytedanceCreativeMatTypeEnum.getNameByType(strategy.getCreativeImageMode());
        //1：上新素材 2：跑量素材 3：遗漏素材 4：打捞素材
        if(createType == 1||createType == 3){
            return videoInfoService.imageListByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt,0);
        }else if(createType == 2){
            return videoInfoService.imageTopMatByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt);
        }else if(createType == 4){
            return videoInfoService.imageHistoryMatByParams(projectId,strategy.getAccountId(),imageMode,startTime,endTime,videoCnt);
        }
        return null;
    }

    @Resource
    private ByteDanceVideoInfoMapper byteDanceVideoInfoMapper;

    private List<ByteDanceVideoInfo> getvideoOrImageInfoByCreateType(Long projectId,AiBytedanceAdvertiserStrategy strategy, String startTime, String endTime, Integer createType, Long videoCnt) {
        //通投智选 (以 竖版视频 类型为主)
        if (!Check.isNull(strategy.getAdDeliveryRange()) && "UNIVERSAL".equalsIgnoreCase(strategy.getAdDeliveryRange())){
            AiBytedanceAdvertiserStrategy universal =  new AiBytedanceAdvertiserStrategy();
            universal.setAccountId(strategy.getAccountId());
            universal.setCreativeImageMode("CREATIVE_IMAGE_MODE_VIDEO_VERTICAL");
            return getVideoInfoByCreateType(projectId,universal,startTime,endTime,createType,videoCnt);
        }
        //横板视频 || 竖版视频
        if (strategy.getCreativeImageMode().equalsIgnoreCase("CREATIVE_IMAGE_MODE_VIDEO")
                || strategy.getCreativeImageMode().equalsIgnoreCase("CREATIVE_IMAGE_MODE_VIDEO_VERTICAL")){
            //获取 视频 素材
            return getVideoInfoByCreateType(projectId,strategy,startTime,endTime,createType,videoCnt);
        }
        //获取 图片 素材
        return getImageInfoByCreateType(projectId,strategy,startTime,endTime,createType,videoCnt);
    }











    /**
     *  修改状态 (0开-1关)
     *  同一账户下只能有一条数据信息为开启，可以全部关闭
     * @param
     * @return
     */
    @Override
    @Transactional
    public Result updStaById(String id,String state,String accountId,String creativeImageMode) {
        //开启
        if (org.apache.commons.lang3.StringUtils.equals(state,"0")){
            //修改状态为开启
            aiBytedanceAdvertiserStrategyMapper.updStaById(id,state);
            //关闭 账户下 其他数据信息（不包含本条id信息） 状态为 关闭
            aiBytedanceAdvertiserStrategyMapper.updStaByAccountId(accountId,creativeImageMode,"1",id);
        }
        //关闭
        if (org.apache.commons.lang3.StringUtils.equals(state,"1")){
            // 修改 账户下 状态 为关闭
            aiBytedanceAdvertiserStrategyMapper.updStaById(id,state);
        }

        return Result.successMsg("状态修改成功---》"+("0".equals(state) ? "开" : "关"), null);
    }


    /**
     * 头条 - 配置信息 修改 出价; 预算;
     * @param updAdStaOrCpaOrBudget
     * @return
     */
    @Override
    public Result updStaOrCpaOrBudgetById(UpdAdStaOrCpaOrBudget updAdStaOrCpaOrBudget) {
        CtopOauthToken token = tokenService.getOauthTokenByAccountId(String.valueOf(updAdStaOrCpaOrBudget.getAccountId()));
        //1-修改出价
        if (BytedanceConstant.UPDTYPE_BID.equals(updAdStaOrCpaOrBudget.getType())) {
            //查询计划预算
            QueryWrapper<AiBytedanceAdvertiserStrategy> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id",updAdStaOrCpaOrBudget.getId());
            queryWrapper.last("limit 1");
            AiBytedanceAdvertiserStrategy strategyVo = aiBytedanceAdvertiserStrategyMapper.selectOne(queryWrapper);
            //出价不能大于计划预算test
            int a = 0;
            // 出价不为空 则 固定出价
            if (!Check.isNull(updAdStaOrCpaOrBudget.getAdCpaBid())){
                // 出价 > 计划预算
                a = updAdStaOrCpaOrBudget.getAdCpaBid().compareTo(strategyVo.getAdBudget());
            //出价为空 则 随机出价 或者 阶梯出价
            // 最高出价 不能大于 计划预算
            }else {
                // 最高出价 > 计划预算
                a = updAdStaOrCpaOrBudget.getAdMaxBid().compareTo(strategyVo.getAdBudget());
            }
            if (a == 1){
                return Result.errorMsg("最高出价不能大于计划预算。");
            }
            aiBytedanceAdvertiserStrategyMapper.updCpaById(updAdStaOrCpaOrBudget);
        }
        //2-修改预算（给西安提供 修改 预算）
        if (BytedanceConstant.UPDTYPE_BUDGET.equals(updAdStaOrCpaOrBudget.getType())) {

            //指定预算
            if (updAdStaOrCpaOrBudget.getBudgetType().equals("2")){
                if (!Check.isNull(updAdStaOrCpaOrBudget.getCost())){
                    //  前者 < 后者
                    int a = new BigDecimal(updAdStaOrCpaOrBudget.getBudget()).compareTo(updAdStaOrCpaOrBudget.getCost().multiply(new BigDecimal(1.05)));
                    if (a == -1){
                        return Result.errorMsg("修改后预算金额不能低于当前已消费金额的105%");
                    }
                }
            }
            aiBytedanceAdvertiserStrategyMapper.updBudgetById(updAdStaOrCpaOrBudget.getId(), updAdStaOrCpaOrBudget.getBudget(),updAdStaOrCpaOrBudget.getBudgetType());

            //账户预算 同步 头条
            //BUDGET_MODE_DAY-日预算
            // BUDGET_MODE_INFINITE-不限
            String accountBudgetMode = updAdStaOrCpaOrBudget.getBudgetType().equals("1") ? "BUDGET_MODE_INFINITE" : "BUDGET_MODE_DAY";
            Result resultBudget = marketingService.updateBudget(token,accountBudgetMode,new BigDecimal(updAdStaOrCpaOrBudget.getBudget()));
            if (!resultBudget.isSuccess()){
                return Result.error(resultBudget.getMessage());
            }

        }
        return Result.successMsg("修改"+(BytedanceConstant.UPDTYPE_BID.equals(updAdStaOrCpaOrBudget.getType()) ? "出价" : "预算")+"成功。",null);
    }



    /**
     *
     * 获取行业类别
     * @param accountId 广告主id
     * @param type 行业类别
     * @return org.jeecg.common.api.vo.Result
     * @author zianY
     */
    @Override
    public Result getIndustryList(String accountId, String type) throws Exception {
        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId);
        if (null == token) {
            log.info("token获取失败=>accountId:{}", accountId);
            return Result.error("token获取失败====>>>>accountId:"+accountId);
        }
        // api 获取行业列表
        Result listResult = marketingService.getToolIndustryList(token,type);
        if (!listResult.isSuccess()){
            return Result.errorMsg(listResult.getMessage());
        }
        List<Map<String,Object>> industryListMap = (List<Map<String,Object>>) listResult.getResult();
        // list map 数据格式 转 list entity 数据格式
        List<IndustryVo> industryList = Check.convertListMap2ListBean(industryListMap,IndustryVo.class);
        //所有行业分类 设置 父id
        industryList.forEach(industryVo -> {
            if ("1".equals(industryVo.getLevel())){
                industryVo.setPId("0");
            }
            if ("2".equals(industryVo.getLevel())){
                industryVo.setPId(industryVo.getFirst_industry_id());
            }
            if ("3".equals(industryVo.getLevel())){
                industryVo.setPId(industryVo.getSecond_industry_id());
            }
        });

        //行业分类 层级展示
        List<Map<String,Object>> classificationVos = treeCategoryData(industryList,"0");
        return Result.successMsg("获取行业列表成功。",classificationVos);

    }

    /**
     * 递归 行业分类 tree 层级展示
     * @param allList
     * @param parentId
     * @return
     */
    public List<Map<String,Object>> treeCategoryData(List<IndustryVo> allList, String parentId) {
        List<Map<String,Object>> mapList = new ArrayList<>();
        for (IndustryVo vo : allList) {
            if (parentId.equals(vo.getPId())){
                Map<String,Object> map = new HashMap<>();
                map.put("industryId", vo.getIndustry_id());
                map.put("industryName", vo.getIndustry_name());
                map.put("level", vo.getLevel());
                map.put("pId", vo.getPId());
                map.put("children", treeCategoryData(allList,vo.getIndustry_id()));
                mapList.add(map);
            }
        }
        return mapList;

    }



    /**
     *
     * 获取广告组
     *
     * @param accountId 广告主id
     * @param adGroupSearchVoList
     * @param pageNo
     * @param pageSize
     * @return org.jeecg.common.api.vo.Result
     * @author zianY
     */
    @Override
    public Result getCampaignGroup(String accountId, List<AdGroupSearchVo> adGroupSearchVoList, Integer pageNo, Integer pageSize) {

        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId);
        if (null == token) {
            log.info("token获取失败=>accountId:{}", accountId);
            return Result.error("token获取失败====>>>>accountId:"+accountId);
        }
        // 获取广告组
        Result industryList = marketingService.getCampaignGroupList(token,accountId,null,pageNo,pageSize);
        log.error("获取广告组=======>>>>>>>>>>>{}", industryList.getResult());
        return Result.successMsg("获取广告组成功。", industryList.getResult());
    }



    /**
     *
     * 获取广告计划
     *
     * @param accountId 广告主id
     * @param adGroupSearchVoList 计划参数
     * @param pageNo 页数
     * @param pageSize 每页条数
     * @return org.jeecg.common.api.vo.Result
     * @author zianY
     */
    @Override
    public Result getCampaignPlan(String accountId, PlanSearchVo adGroupSearchVoList, Integer pageNo, Integer pageSize) {

        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId);
        if (null == token) {
            log.info("token获取失败=>accountId:{}", accountId);
            return Result.error("token获取失败====>>>>accountId:"+accountId );
        }
        // 获取计划
        Result industryList = marketingService.getPlanList(token,adGroupSearchVoList,pageNo,pageSize);
        log.error("获取广告计划=======>>>>>>>>>>>{}", industryList.getResult());
        return Result.successMsg("获取广告计划成功。", industryList.getResult());
    }

    /**
     *
     * 获取创意详细信息
     *
     * @param accountId 广告主id
     * @param adId 计划id
     * @return org.jeecg.common.api.vo.Result
     * @author zianY
     */
    @Override
    public Result creativeReadInfo(String accountId, String adId) {
        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId);
        if (null == token) {
            log.info("token获取失败=>accountId:{}", accountId);
            return Result.error("token获取失败====>>>>accountId:"+accountId);
        }
        // 获取 创意详细信息
        Result industryList = marketingService.creativeRead(token,accountId,adId);
        log.error("获取创意详细信息=======>>>>>>>>>>>{}", industryList.getResult());
        return Result.successMsg("获取创意详细信息成功。", industryList.getResult());
    }
    /**
     *
     * 修改 广告 组-计划-创意
     *
     * @param strategy
     * @return: org.jeecg.common.api.vo.Result
     * @author: zianY
     */
    @Override
    public Result updateADCreative(AiBytedanceAdvertiserStrategy strategy, String groupModifyTime, String planModifyTime) {

        CtopOauthToken token = tokenService.getOauthTokenByAccountId(strategy.getAccountId()+"");
        if (null == token) {
            log.info("token获取失败=>accountId:{}", strategy.getAccountId());
            return Result.error("token获取失败====>>>>accountId:"+strategy.getAccountId());
        }
        // 1:修改广告组
        Result resultCampaign = marketingService.updateCampaign(token,
                "广告组id",groupModifyTime,
                strategy.getCampaignName(),strategy.getCampaignBudgetMode(),strategy.getCampaignLandingType());
        //广告组id
        Long campaignId = (Long) resultCampaign.getResult();
        // 2:修改广告计划
        Result resultPlan = marketingService.updateAdvertiserPlan(token,"计划id",planModifyTime,strategy);
        //计划id
        Object planId = resultPlan.getResult();
        //3:修改创意 TODO 拼接创意参数
        Result creativeInfo = marketingService.creativeUpdate(token, "计划id","创意时间戳",null);
        //数据修改
        aiBytedanceAdvertiserStrategyMapper.updateById(strategy);
        return Result.successMsg("修改成功", strategy);
    }


    /**
     *
     * @description: 查询广告计划可用转化目标
     *
     * @param adConvertQueryVo
     * @return: org.jeecg.common.api.vo.Result
     * @author: zianY
     */
    @Override
    public Result getToolConvert(AdConvertQueryVo adConvertQueryVo) {
        CtopOauthToken token = tokenService.getOauthTokenByAccountId(adConvertQueryVo.getAdvertiserId());
        if (null == token) {
            log.info("token获取失败=>accountId:{}", token.getAccountId());
            return Result.error("token获取失败====>>>>accountId:"+token.getAccountId());
        }
        return marketingService.getToolConvertQuery(token,adConvertQueryVo);
    }

    /**
     * 查询转化目标详细信息
     * @param accountId
     * @param convertId
     * @return
     */
    @Override
    public Result readToolConvertInfo(String accountId,String convertId) {
        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId);
        if (null == token) {
            log.info("token获取失败=>accountId:{}", token.getAccountId());
            return Result.error("token获取失败====>>>>accountId:"+token.getAccountId());
        }
        return marketingService.readToolConvertInfo(token,accountId,convertId);
    }

    @Resource
    private RuleDataAccountMapper ruleDataAccountMapper;
    /**
     *
     * @description: 添加配置 信息
     *
     * @param aiBytedanceAdvertiserStrategy
     * @return org.jeecg.common.api.vo.Result
     * @author zianY
     */
    @Override
    @Transactional
    public Result addBytedanceStrategy(AiBytedanceAdvertiserStrategy aiBytedanceAdvertiserStrategy) {
        CtopOauthToken token = tokenService.getOauthTokenByAccountId(String.valueOf(aiBytedanceAdvertiserStrategy.getAccountId()));
        //预算金额不能低于当前已消费金额的105%
        QueryWrapper<RuleDataAccount> ruleDataAccountQueryWrapper = new QueryWrapper<>();
        ruleDataAccountQueryWrapper.eq("account_id",aiBytedanceAdvertiserStrategy.getAccountId());
        //获取消耗 余额
        RuleDataAccount ruleDataAccountVo = ruleDataAccountMapper.selectOne(ruleDataAccountQueryWrapper);
        // 值 为0 不限预算
        // ！0 指定预算
        if (!aiBytedanceAdvertiserStrategy.getAccountBudget().equals(new BigDecimal("0"))){
            if (!Check.isNull(ruleDataAccountVo)){
                //  前者 < 后者
                int a = aiBytedanceAdvertiserStrategy.getAccountBudget().compareTo(ruleDataAccountVo.getCost().multiply(new BigDecimal(1.05)));
                if (a == -1){
                    return Result.errorMsg("预算金额不能低于当前已消费金额的105%");
                }
            }
        }

        // 数据入库 string[] 转 string
        //商品卖点
        aiBytedanceAdvertiserStrategy.setCreativeProductSellingPoints(org.apache.commons.lang3.StringUtils.join(aiBytedanceAdvertiserStrategy.getProductSellingPoints(), ","));
        //广告位置
        aiBytedanceAdvertiserStrategy.setCreativeInventoryType(org.apache.commons.lang3.StringUtils.join(aiBytedanceAdvertiserStrategy.getCreativeInventoryTypes(), ","));
        //创意标签
        aiBytedanceAdvertiserStrategy.setCreativeAdKeywords(org.apache.commons.lang3.StringUtils.join(aiBytedanceAdvertiserStrategy.getAdKeywords(), ","));
        aiBytedanceAdvertiserStrategy.setCreateTime(new Date());
        //默认组数量为 1 -前端已修改完成
        //aiBytedanceAdvertiserStrategy.setCampaignAdCnt(aiBytedanceAdvertiserStrategy.getCampaignAdCnt() == 0L ? 1 : aiBytedanceAdvertiserStrategy.getCampaignAdCnt());

        //同一账户下 同素材类型 只能有一条信息为开启
        //关闭 账户下 其他数据信息（不包含本条id信息） 状态为 关闭
        aiBytedanceAdvertiserStrategyMapper.updStaByAccountId(String.valueOf(aiBytedanceAdvertiserStrategy.getAccountId()),aiBytedanceAdvertiserStrategy.getCreativeImageMode(),"1",null);
        //状态（0开 1关）
        aiBytedanceAdvertiserStrategy.setStatus(0);

        //添加素材信息
       /* MaterialImageInfo imageInfo = new MaterialImageInfo();
        imageInfo.setUrl(aiBytedanceAdvertiserStrategy.getImageUrl());
        imageInfo.setUserId(aiBytedanceAdvertiserStrategy.getUserId());
        materialImageInfoService.initImageCode(imageInfo);
*/


        aiBytedanceAdvertiserStrategyMapper.insert(aiBytedanceAdvertiserStrategy);


        //账户预算 同步 头条
        //BUDGET_MODE_DAY-日预算
        // BUDGET_MODE_INFINITE-不限
        String accountBudgetMode = aiBytedanceAdvertiserStrategy.getAccountBudgetMode().equals("1") ? "BUDGET_MODE_INFINITE" : "BUDGET_MODE_DAY";
        Result resultBudget = marketingService.updateBudget(token,accountBudgetMode,aiBytedanceAdvertiserStrategy.getAccountBudget());
       /* if (!resultBudget.isSuccess()){
            return Result.error(resultBudget.getMessage());
        }*/
        return Result.successMsg("新增成功。",aiBytedanceAdvertiserStrategy);
    }

    @Override
    public List<AiBytedanceAdvertiserStrategy> getByAccountId(Long accountId,Integer status) {
        QueryWrapper<AiBytedanceAdvertiserStrategy> queryWrapper = new QueryWrapper<>();
        if(null!=accountId){
            queryWrapper.eq("account_id",accountId);
        }
        if(null!=status){
            queryWrapper.eq("status",status);
        }
        queryWrapper.orderByDesc("id");
        return this.list(queryWrapper);
    }

    @Autowired
    private IByteDanceAdvertisePlanService planService;
    @Autowired
    private IByteDanceAdvertiserDataService advertiserDataService;

    @Override
    public void customCreativeSupplement(AiBytedanceAdvertiserStrategy strategy, Integer hour,String openUrl) {
        try{
            CtopOauthToken token = tokenService.getOauthTokenByAccountId(strategy.getAccountId()+"");
            if (null == token) {
                log.info("token获取失败=>accountId:{}", strategy.getAccountId());
                return;
            }
            Long customUnitCnt = strategy.getCampaignAdCnt()*strategy.getCampaignCnt();
            Long unitNum = customUnitCnt * hour / 19;
            log.info("{}当前时间内需要创建计划总数：{}", strategy.getAccountId(), unitNum);
            //查询当前账户创建自定义类型计划数量
            int unitCreateCnt = planService.queryToDayBuiltCount(strategy.getAccountId());
            log.info("{}截止目前创建计划总数：{}", strategy.getAccountId(), unitCreateCnt);
            long remindCnt = unitNum - unitCreateCnt;
            if (remindCnt >= 1) {
                log.info("{}计划创建不足，剩余需要创建个数{},使用上新素材创建", strategy.getAccountId(), remindCnt);
                //优先创建历史遗漏素材
                remindCnt = this.createCreative(token, strategy, 1, remindCnt,openUrl);
            }
            if (remindCnt >= 1) {
                log.info("{}计划创建不足，剩余需要创建个数{},使用历史遗漏素材创建", strategy.getAccountId(), remindCnt);
                //优先创建历史遗漏素材
                remindCnt = this.createCreative(token, strategy, 3, remindCnt,openUrl);
            }
            if (remindCnt >= 1) {
                log.info("{}计划创建不足，剩余需要创建个数{},使用高质量素材创建", strategy.getAccountId(), remindCnt);
                //高质量素材
                remindCnt = this.createCreative(token, strategy, 2, remindCnt,openUrl);
            }
            if (remindCnt >= 1) {
                //历史打捞素材
                log.info("{}计划创建不足，剩余需要创建个数{},使用历史打捞素材创建", strategy.getAccountId(), remindCnt);
                this.createCreative(token, strategy, 4, remindCnt,openUrl);
            }
            //获取最新的plan计划更新到表格
            String nowDate = DateUtils.formatDate();
            advertiserDataService.getAdvertiserPlan(token, "", nowDate, nowDate);

            int newUnitCreateCnt = planService.queryToDayBuiltCount(strategy.getAccountId());
            AiBytedanceAutocreateLog iBytedanceAutocreateLog = new AiBytedanceAutocreateLog(
                    strategy.getAccountId(),
                    "创建广告计划",
                    200,
                    "当前账户需要创建计划总数为"+unitNum+"个，截止目前有"+unitCreateCnt+"个，此次创建成功"+(newUnitCreateCnt - unitCreateCnt)+"个。",
                    "aiBytedanceAdvertiserStrategyService.customCreativeSupplement => strategy:"+ strategy.toString()+",hour:"+hour);
            iBytedanceAutocreateLogService.save(iBytedanceAutocreateLog);
        }catch (Exception e){
            log.info(e.getMessage());
        }
    }



    /**
     *
     * 获取行动号召
     *
     * @param accountId
     * @param landingType
     * @param advancedCreativeType
     * @return org.jeecg.common.api.vo.Result
     * @author zianY
     */
    @Override
    public Result getAdActionText(String accountId, String landingType, String advancedCreativeType) throws Exception{
        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId);
      // return marketingService.getActionText(token,landingType,advancedCreativeType);
        //行动号召 不使用 api接口获取 使用自定义
        String actionText[] = {"购买同款","专属优惠","抢抢看","去看看","立即下单",
                                "获取优惠","查看详情","更多精彩","查看惊喜","领取好礼",
                                "去逛逛","领取福利","来拼一拼","立即抢购","更多秒杀",
                                "更多优惠","了解更多","了解详情","点击抢购"};
       return Result.successMsg("返回行动号召成功。", actionText);
    }


    @Resource
    private BytedanceAreaInfoMapper bytedanceAreaInfoMapper;

    /**
     *
     * 获取定向包
     *
     * @param accountId 广告主id
     * @param landingType 投放目标
     * @param deliveryRange
     * @return org.jeecg.common.api.vo.Result
     * @author zianY
     */
    @Override
    public Result getAdAudiencePackage(String accountId, String landingType, String deliveryRange){
       CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId);
        //查询定向包信息
       Result list = marketingService.getAudiencePackage(token,landingType,deliveryRange);
       if (!list.isSuccess()){
           return Result.errorMsg(list.getMessage());
       }
       //处理返回结果
       JSONObject jsonObject = (JSONObject)list.getResult();
       JSONArray array = jsonObject.getJSONArray("audience_packages");
        List<Map<String,JSONObject>> dataList = JSONArray.parseObject(array.toJSONString(),List.class);
        dataList.forEach(map -> {
            JSONObject audience = map.get("audience");
            //性别
            String gender = audience.getString("gender");
            if (Check.isNull(gender)){
                audience.put("gender", "NONE");
            }
            //返回结果中的city 查询 城市名称
            JSONArray citys = audience.getJSONArray("city");
            if (citys != null){
                QueryWrapper<BytedanceAreaInfo> queryWrapper = new QueryWrapper<>();
                queryWrapper.in("code", citys);
                List<BytedanceAreaInfo> cityList = bytedanceAreaInfoMapper.selectList(queryWrapper);
                List<String> cityStr = cityList.stream().map(BytedanceAreaInfo::getName).collect(Collectors.toList());
                audience.put("cityNames",cityStr);
            }
            //平台
            JSONArray platform = audience.getJSONArray("platform");
            if (!Check.isNull(platform)){
                String platformStr = org.apache.commons.lang3.StringUtils.join(platform,",");
                String str = platformStr.replace("ANDROID","Android");
                audience.put("platform",Arrays.asList(str));
            }
        });
        return Result.successMsg("成功。",dataList);
    }

    /**
     *
     * 获取人群包列表信息
     *
     * @param accountId
     * @return org.jeecg.common.api.vo.Result
     * @author zianY
     */
    @Override
    public Result getDMPCustomAudience(String accountId){

        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId);
        // 获取人群包列表
       Result list = marketingService.selectCustomAudience(token);
       if (!list.isSuccess()){
           return Result.errorMsg(list.getMessage());
       }
        //List<Map<String,Object>> listMap = (List<Map<String, Object>>) list.getResult();
        JSONArray array =(JSONArray)list.getResult();
        List<Map<String,Object>> dataList = JSONArray.parseObject(array.toJSONString(),List.class);
        //获取人群包id  List
        List<Object> packageList = dataList.stream().map(map -> map.get("custom_audience_id")).collect(Collectors.toList());
        String idStr = Joiner.on(",").join(packageList);
        List<Integer> idsIntList = Arrays.asList(idStr.split(",")).stream().map(id -> Integer.valueOf(id.trim())).collect(Collectors.toList());
        //获取人群包详细信息
        Result packageInfoList = marketingService.getAudiencePackageRead(token,accountId,idsIntList);
        List<Map<String,Object>> listInfoMap = (List<Map<String, Object>>) packageInfoList.getResult();
        //人群包是否被删除 "1"：已删除，"0"：未删除
        //人群包可投放状态，只有当状态为CUSTOM_AUDIENCE_DELIVERY_STATUS_AVAILABLE时才可进行投放使用
        List<Map<String,Object>> filterList = listInfoMap.stream()
                .filter(info -> Integer.valueOf(info.get("isdel")+"") == 0)
                .filter(info -> "CUSTOM_AUDIENCE_DELIVERY_STATUS_AVAILABLE".equalsIgnoreCase(info.get("delivery_status")+""))
                .collect(Collectors.toList());
        return Result.successMsg("人群包获取成功。",filterList);
    }


    @Override
    public Result createAudiencePackage(String accountId){
        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId);
       Result list = marketingService.createAudiencePackage(token);
        return Result.successMsg("定向包创建成功。",list);
    }

    /**
     *
     * 获取橙子建站站点列表
     * https://www.chengzijianzhan.com/tetris/page/XXXXXXXXXXXXX/（其中XX是建站ID，拼装后就可获得投放的URL/预览URL）
     * Android应用下载详情页 当广告计划app_type为"APP_ANDROID"时, 必填
     * @param accountId
     * @return org.jeecg.common.api.vo.Result
     * @author zianY
     */
    @Override
    public Result getChengZiSite(String accountId) {
        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId);
        Result list = marketingService.getSite(token);
        if (!list.isSuccess()){
            return Result.errorMsg(list.getMessage());
        }
        JSONArray array =(JSONArray)list.getResult();
        List<Map<String,Object>> dataList = JSONArray.parseObject(array.toJSONString(),List.class);
        dataList.forEach(map -> {
            map.put("creativeWebUrl","https://www.chengzijianzhan.com/tetris/page/"+map.get("siteId"));
        });
        return Result.successMsg("获取橙子建站站点列表成功。",dataList);
    }

    /**
     *查询 组名称 计划名称
     */
    @Override
    public Result getStrategyInfoByName(AiBytedanceAdvertiserStrategy aiBytedanceAdvertiserStrategy) {
        //查询 组名称
        QueryWrapper<AiBytedanceAdvertiserStrategy> queryWrapperCampaign = new QueryWrapper<>();
        //查询计划名称
        QueryWrapper<AiBytedanceAdvertiserStrategy> queryWrapperAdName = new QueryWrapper<>();
        List<AiBytedanceAdvertiserStrategy> strategyInfoCampain = new ArrayList<>();
        List<AiBytedanceAdvertiserStrategy> strategyInfoAdName = new ArrayList<>();
        //新增
        if (Check.isNull(aiBytedanceAdvertiserStrategy.getId())){
            queryWrapperCampaign.eq("campaign_name",aiBytedanceAdvertiserStrategy.getCampaignName());
            strategyInfoCampain = aiBytedanceAdvertiserStrategyMapper.selectList(queryWrapperCampaign);
            if (!Check.isNull(strategyInfoCampain)){
                return Result.error("新创建的账户配置已存在相同的组名称【"+aiBytedanceAdvertiserStrategy.getCampaignName()+"】请修改后重新保存。");
            }
            queryWrapperAdName.eq("ad_name",aiBytedanceAdvertiserStrategy.getAdName());
            strategyInfoAdName = aiBytedanceAdvertiserStrategyMapper.selectList(queryWrapperAdName);
            if (!Check.isNull(strategyInfoAdName)){
                return Result.error("新创建的账户配置已存在相同的计划名称【"+aiBytedanceAdvertiserStrategy.getAdName()+"】请修改后重新保存。");
            }
        // 编辑
        }else {
            queryWrapperCampaign.eq("campaign_name",aiBytedanceAdvertiserStrategy.getCampaignName());
            strategyInfoCampain = aiBytedanceAdvertiserStrategyMapper.selectList(queryWrapperCampaign);
            strategyInfoCampain.stream().map(AiBytedanceAdvertiserStrategy::getId).collect(Collectors.toList());
            if (!Check.isNull(strategyInfoCampain) &&
                    !strategyInfoCampain.stream().map(AiBytedanceAdvertiserStrategy::getId).collect(Collectors.toList()).contains(aiBytedanceAdvertiserStrategy.getId())){
                return Result.error("新创建的账户配置已存在相同的组名称【"+aiBytedanceAdvertiserStrategy.getCampaignName()+"】请修改后重新保存。");
            }
            queryWrapperAdName.eq("ad_name",aiBytedanceAdvertiserStrategy.getAdName());
            strategyInfoAdName = aiBytedanceAdvertiserStrategyMapper.selectList(queryWrapperAdName);
            if (!Check.isNull(strategyInfoAdName) &&
                    !strategyInfoAdName.stream().map(AiBytedanceAdvertiserStrategy::getId).collect(Collectors.toList()).contains(aiBytedanceAdvertiserStrategy.getId())){
                return Result.error("新创建的账户配置已存在相同的计划名称【"+aiBytedanceAdvertiserStrategy.getAdName()+"】请修改后重新保存。");
            }
        }



        return Result.successMsg("成功。",null);
    }





}
