package cn.com.ctop.kuaishou.modules.ai.service.impl;

import cn.com.ctop.common.module.entity.CtopOauthToken;
import cn.com.ctop.common.module.entity.MaterialCutFrame;
import cn.com.ctop.common.module.entity.MaterialImageInfo;
import cn.com.ctop.common.module.service.ICtopOauthTokenService;
import cn.com.ctop.common.module.service.IMaterialCutFrameService;
import cn.com.ctop.common.module.service.IMaterialImageInfoService;
import cn.com.ctop.kuaishou.modules.ai.entity.*;
import cn.com.ctop.kuaishou.modules.ai.service.*;
import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouImageGet;
import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouVideoGet;
import cn.com.ctop.kuaishou.modules.batch.entity.KuaishouStrategy;
import cn.com.ctop.kuaishou.modules.batch.mapper.KuaiShouVideoGetMapper;
import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouImageGetService;
import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouMaterialUploadService;
import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouVideoGetService;
import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouInterfaceService;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.util.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AiStrategyServiceImpl implements IAiStrategyService {

    private static final Logger log = LoggerFactory.getLogger(AiStrategyServiceImpl.class);

    @Autowired
    private IKuaiShouVideoGetService videoGetService;
    @Autowired
    private IAiKuaishouStrategyTargetBaseService targetBaseService;
    @Autowired
    private IAiKuaishouStrategyTemplateService templateService;
    @Autowired
    private IAiKuaishouStrategyMiddleService middleService;
    @Autowired
    private IAiKuaishouStrategyTargetUnionService targetUnionService;
    @Autowired
    private IKuaishouInterfaceService kuaishouInterfaceService;
    @Autowired
    private ICtopOauthTokenService tokenService;
    @Autowired
    private IAiKuaishouStrategyMapCreativeService mapCreativeService;
    @Autowired
    private IMaterialCutFrameService materialCutFrameService;
    @Autowired
    private IMaterialImageInfoService materialImageInfoService;
    @Autowired
    private IKuaiShouImageGetService imageGetService;
    @Autowired
    private IKuaiShouMaterialUploadService materialUploadService;
    @Resource
    private KuaiShouVideoGetMapper videoGetMapper;

    /**
     *
     * @param strategy
     */
    @Override
    public void createCreativeByStrategy(KuaishouStrategy strategy){
        //获取账户id
        Long accountId = strategy.getAccountId();
        CtopOauthToken token = tokenService.getOauthTokenByAccountId(accountId.toString());
        if(null == token){
            log.info("token获取失败=>accountId:{}",strategy.getAccountId());
            return;
        }

        //策略类型
        String scenes = strategy.getScenes();
        //根据策略类型获取策略模板信息
        AiKuaishouStrategyTemplate strategyTemplate = templateService.getOneByParams(scenes, 1);
        if(null == strategyTemplate){
            log.info("策略模板信息获取失败=>testDirection:{}",scenes);
            return;
        }

        // 1: 根据模板信息表里的 material_select_method (素材选择方式)，得到"跑量视频"和"上新视频"获取方式
        // {'highQualityMaterial':{'days':7, 'num':5},'newMaterialNum':5}
        // TODO 更新该账户下的 ctop_kuaishou_video_get 数据

        // 获取当天零点到现在的非素造的视频
        kuaishouInterfaceService.getVideoList(token,DateUtils.date2Str(),DateUtils.date2Str());

        /*// 获取当天零点到现在的素造视频
        String startDate = DateUtils.formatDate(new Date(),"yyyy-MM-dd HH:mm:ss");
        // 时间差，单位为分钟
        int dimeDiff = 5;
        Date now = new Date();
        String endDate = DateUtils.formatDate(new Date(now.getTime() - dimeDiff*60*1000),"yyyy-MM-dd HH:mm:ss");
        kuaishouInterfaceService.getSuZaoList(token.getAccessToken(), token.getAccountId(), 1, startDate, endDate)));*/

        JSONObject materialSelectMethod = JSONObject.parseObject(strategyTemplate.getMaterialSelectMethod());
        List<KuaiShouVideoGet> newVideos = new ArrayList<KuaiShouVideoGet>();
        List<KuaiShouVideoGet> highQualityVideos = new ArrayList<KuaiShouVideoGet>();

        if (materialSelectMethod.containsKey("newMaterialNum")){
            int newVideoCnt = (int) materialSelectMethod.get("newMaterialNum");
            newVideos = videoGetService.getNewVideoDescDate(accountId,newVideoCnt);
        }
        if(materialSelectMethod.containsKey("highQualityMaterial")){
            int days = materialSelectMethod.getJSONObject("highQualityMaterial").getInteger("days");
            int highQualityVideoCnt = materialSelectMethod.getJSONObject("highQualityMaterial").getInteger("num");
            highQualityVideos = videoGetMapper.getHighQualityVideo(accountId,days,highQualityVideoCnt);
        }

        // 跑量视频 + 上新视频 合并到一个list, 为单素材搭配组做准备 TODO
        List<KuaiShouVideoGet> fullVideos = new ArrayList<KuaiShouVideoGet>();
        fullVideos.addAll(highQualityVideos);
        fullVideos.addAll(newVideos);
        if(fullVideos.isEmpty()){
            log.info("素材获取失败=>accountId:{}",accountId);
            return;
        }

        String materialFixType = strategyTemplate.getMaterialFixType();
        Date campaignDate = new Date();
        String timestamp = DateUtils.formatDate(campaignDate,"yyyyMMddHHmmss");
        if(scenes.equals("1")){
            //素材+出价
            List<Long>getCapbids = splitCapBidByDomain(strategy.getCpaBidMin(),strategy.getCpaBidMax(),strategy.getStepSize());
            if(null == getCapbids||getCapbids.isEmpty()){
                log.info("出价范围异常=>start:{};end:{}",strategy.getCpaBidMin().toString(),strategy.getCpaBidMax().toString());
                return;
            }
            //7、一个计划，拼装创建计划的入参json
            JSONObject campaignParams = new JSONObject();
            campaignParams.put("advertiser_id",token.getAccountId());
            String campaignName = "户14-上下滑&信息流" + "-自定义001-"+ "剪辑-低价-低价包邮-活动-年龄18岁以上-单出价-"+ timestamp;
            campaignParams.put("campaign_name",campaignName);
            campaignParams.put("type",Integer.parseInt(strategy.getMarketingGoal()));
            campaignParams.put("day_budget",0L);
            Map<String, Object> campaignCreateResult = kuaishouInterfaceService.campaignCreate(token.getAccessToken(), token.getAccountId(), campaignParams);
            Integer code = (Integer) campaignCreateResult.get("code");
            String message = (String) campaignCreateResult.get("message");
            if(code != 0 ){
                log.info("计划创建失败=>message:{}",message);
                return;
            }
            Long campaignId = (Long) campaignCreateResult.get("campaignId");
            int unitCnt = 1;
            // 8、根据素材和出价，两层循环 创建组和创意
            for (Long item:getCapbids) {
                //判定素材搭配方式
                if(null!=materialFixType&&materialFixType.trim().equals("single")){
                    // 选择素材，创建创意
                    for(KuaiShouVideoGet videoItem: fullVideos){
                        //拼装广告组参数
                        unitCnt ++;
                        String unitName = campaignName + "-" + unitCnt;
                        JSONObject unitParams = createUnitParams(token, campaignId, strategy, item, unitName);
                        Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams,1);
                        Integer unitCode = (Integer) unitCreateResult.get("code");
                        String unitMessage = (String) unitCreateResult.get("message");
                        if(unitCode != 0 ){
                            log.info("组创建失败=>accountId:{};message:{}",accountId,unitMessage);
                            continue;
                        }
                        Long unitId = (Long) unitCreateResult.get("unitId");
                        JSONObject creativeParams = creativeParams(token,unitId,videoItem,unitCnt,strategy);
                        JSONArray sceneIdJsonArray = JSONArray.parseArray(strategy.getSceneId());
                        // 如果广告位只包含 上下滑大屏广告（6），则一个素材搭配1张封面，生成1个创意
                        if (sceneIdJsonArray.contains(6) && sceneIdJsonArray.size() == 1){
                            //直接创建创意
                            createCreative(token,creativeParams,campaignId,unitId,strategy,null,1,videoItem);
                        } else {
                            // 素材自带的封面 ctop_material_image_info 内部素材的自带封面，素造的没有
                            // 素材的智能抽帧封面 ctop_material_cut_frame 其中素造的为8张封面，内部的为15张封面
                            List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoItem.getSignature());
                            List<MaterialImageInfo> orgFrameList = materialImageInfoService.getListByVideoSignature(videoItem.getSignature());
                            // 其他情况下，一个素材搭配15张封面，生成15个创意
                            if ((null == cutFrameList||cutFrameList.isEmpty())&&(null == orgFrameList|| orgFrameList.isEmpty())){
                                log.info("未获取到视频封面=>videoSignature:{}",videoItem.getSignature());
                                continue;
                            }
                            createCreativeByImage(cutFrameList,orgFrameList,token,creativeParams,campaignId,unitId,strategy,videoItem,3,null);
                        }
                    }
                }
                else{
                    //混搭素材逻辑
                    //跑量素材
                    if(highQualityVideos.size() > 0){
                        // 取模和余数:
                        int mod = highQualityVideos.size() / 15;
                        int rem = highQualityVideos.size() % 15;
                        int innerUnitCnt = 0;
                        if(mod!=0){
                            for(int i=0;i<mod;i++){
                                String unitName = campaignName + "-跑量-" + item + "-" + innerUnitCnt;
                                JSONObject unitParams = createUnitParams(token, campaignId, strategy, item, unitName);
                                Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams,1);
                                Integer unitCode = (Integer) unitCreateResult.get("code");
                                String unitMessage = (String) unitCreateResult.get("message");
                                if(unitCode != 0 ){
                                    log.info("组创建失败=>accountId:{};message:{}",accountId,unitMessage);
                                    continue;
                                }
                                Long unitId = (Long) unitCreateResult.get("unitId");
                                for(int j=0;j<15;j++){
                                    JSONObject creativeParams = creativeParams(token,unitId,highQualityVideos.get(i*15+j),unitCnt,strategy);
                                    createCreative(token,creativeParams,campaignId,unitId,strategy,null,j+1,highQualityVideos.get(i*15+j));
                                }
                                innerUnitCnt++;
                            }

                        }
                        if(rem!=0){
                            String unitName = campaignName + "-跑量-" + item + "-" + innerUnitCnt;
                            JSONObject unitParams = createUnitParams(token, campaignId, strategy, item, unitName);
                            Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams,1);
                            Integer unitCode = (Integer) unitCreateResult.get("code");
                            String unitMessage = (String) unitCreateResult.get("message");
                            if(unitCode != 0 ){
                                log.info("组创建失败=>accountId:{};message:{}",accountId,unitMessage);
                                continue;
                            }
                            Long unitId = (Long) unitCreateResult.get("unitId");

                            for(int j=0;j<rem;j++){
                                JSONObject creativeParams = creativeParams(token,unitId,highQualityVideos.get(mod*15+j),unitCnt,strategy);
                                createCreative(token,creativeParams,campaignId,unitId,strategy,null,j+1,highQualityVideos.get(mod*15+j));
                            }
                        }
                    }
                    // 新上素材混搭
                    if(newVideos.size() > 0){
                        // 取模和余数:
                        int mod = newVideos.size() / 15;
                        int rem = newVideos.size() % 15;
                        int innerUnitCnt = 0;
                        if(mod!=0){
                            for(int i=0;i<mod;i++){
                                String unitName = campaignName + "-上新-" + item + "-" + innerUnitCnt;
                                JSONObject unitParams = createUnitParams(token, campaignId, strategy, item, unitName);
                                Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams,1);
                                Integer unitCode = (Integer) unitCreateResult.get("code");
                                String unitMessage = (String) unitCreateResult.get("message");
                                if(unitCode != 0 ){
                                    log.info("组创建失败=>accountId:{};message:{}",accountId,unitMessage);
                                    continue;
                                }
                                Long unitId = (Long) unitCreateResult.get("unitId");
                                for(int j=0;j<15;j++){
                                    JSONObject creativeParams = creativeParams(token,unitId,newVideos.get(i*15+j),unitCnt,strategy);
                                    createCreative(token,creativeParams,campaignId,unitId,strategy,null,j+1,newVideos.get(i*15+j));
                                }
                                innerUnitCnt++;
                            }

                        }
                        if(rem!=0){
                            String unitName = campaignName + "-上新-" + item + "-" + innerUnitCnt;
                            JSONObject unitParams = createUnitParams(token, campaignId, strategy, item, unitName);
                            Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams,1);
                            Integer unitCode = (Integer) unitCreateResult.get("code");
                            String unitMessage = (String) unitCreateResult.get("message");
                            if(unitCode != 0 ){
                                log.info("组创建失败=>accountId:{};message:{}",accountId,unitMessage);
                                continue;
                            }
                            Long unitId = (Long) unitCreateResult.get("unitId");

                            for(int j=0;j<rem;j++){
                                JSONObject creativeParams = creativeParams(token,unitId,newVideos.get(mod*15+j),unitCnt,strategy);
                                createCreative(token,creativeParams,campaignId,unitId,strategy,null,j+1,newVideos.get(mod*15+j));
                            }
                        }
                    }
                }
            }
        }else if(scenes.equals(2)){
            //素材+定向
            //2:根据测试方向获取相应的定向拆分数据类型
            List<AiKuaishouStrategyTargetBase>targetBases = targetBaseService.listByType(strategyTemplate.getTestDirection());
            if(null == targetBases){
                log.info("定向拆分信息获取失败=>testDirection:{}",strategyTemplate.getTestDirection());
                return;
            }
            //3:获取相应字段相应的用户定义域
            String definitionDomain = getStragyDefDomain(strategyTemplate,strategy);
            //4:计算定向拆分逻辑
            List<AiKuaishouStrategyTargetBase>getBases = splitBasesByDomain(definitionDomain,targetBases);
            if(null == getBases||getBases.isEmpty()){
                log.info("定向拆分失败=>definitionDomain:{}",definitionDomain);
                return;
            }
            //5、策略--策略模板 关联表，写入数据库
            AiKuaishouStrategyMiddle strategyMiddle = new AiKuaishouStrategyMiddle(strategyTemplate.getId(),strategy.getId());
            middleService.save(strategyMiddle);
            //7、一个计划，拼装创建计划的入参json
            JSONObject campaignParams = new JSONObject();
            campaignParams.put("advertiser_id",token.getAccountId());
            String campaignName = "户14-上下滑&信息流" + "-通投001"+ "剪辑-低价-低价包邮-活动-年龄18岁以上-单出价-"+ timestamp;
            campaignParams.put("campaign_name",campaignName);
            campaignParams.put("type",Integer.parseInt(strategy.getMarketingGoal()));
            campaignParams.put("day_budget",0L);
            Map<String, Object> campaignCreateResult = kuaishouInterfaceService.campaignCreate(token.getAccessToken(), token.getAccountId(), campaignParams);
            Integer code = (Integer) campaignCreateResult.get("code");
            String message = (String) campaignCreateResult.get("message");
            if(code != 0 ){
                log.info("计划创建失败=>message:{}",message);
                return;
            }
            Long campaignId = (Long) campaignCreateResult.get("campaignId");
            int unitCnt = 0;
            // 8、根据定向和素材，两层循环 创建组和创意
            for (AiKuaishouStrategyTargetBase item:getBases) {
                if(null!=materialFixType&&materialFixType.trim().equals("single")){
                    // 策略定向拆分数据，写入数据库
                    AiKuaishouStrategyTargetUnion targetUnion = new AiKuaishouStrategyTargetUnion(strategyMiddle.getId(),item.getId(),item.getTargetContent());
                    targetUnionService.save(targetUnion);
                    // 选择素材，创建创意
                    for(KuaiShouVideoGet videoItem: fullVideos){
                        //拼装广告组参数
                        unitCnt++;
                        String unitName = campaignName + "-" + unitCnt;
                        JSONObject unitParams = createUnitParams(token,campaignId,strategy,strategyTemplate, item,timestamp,unitName);
                        Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams,1);
                        Integer unitCode = (Integer) unitCreateResult.get("code");
                        String unitMessage = (String) unitCreateResult.get("message");
                        if(unitCode != 0 ){
                            log.info("组创建失败=>accountId:{};message:{}",accountId,unitMessage);
                            continue;
                        }
                        Long unitId = (Long) unitCreateResult.get("unitId");
                        JSONObject creativeParams = creativeParams(token,unitId,videoItem,unitCnt,strategy);
                        JSONArray sceneIdJsonArray = JSONArray.parseArray(strategy.getSceneId());
                        // 如果广告位只包含 上下滑大屏广告（6），则一个素材搭配1张封面，生成1个创意
                        if (sceneIdJsonArray.contains(6) && sceneIdJsonArray.size() == 1){
                            //直接创建创意
                            createCreative(token,creativeParams,campaignId,unitId,strategy,targetUnion,1,videoItem);
                        } else {
                            // 素材自带的封面 ctop_material_image_info 内部素材的自带封面，素造的没有
                            // 素材的智能抽帧封面 ctop_material_cut_frame 其中素造的为8张封面，内部的为15张封面
                            List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoItem.getSignature());
                            List<MaterialImageInfo> orgFrameList = materialImageInfoService.getListByVideoSignature(videoItem.getSignature());
                            // 其他情况下，一个素材搭配15张封面，生成15个创意
                            if ((null == cutFrameList||cutFrameList.isEmpty())&&(null == orgFrameList|| orgFrameList.isEmpty())){
                                log.info("未获取到视频封面=>videoSignature:{}",videoItem.getSignature());
                                continue;
                            }
                            createCreativeByImage(cutFrameList,orgFrameList,token,creativeParams,campaignId,unitId,strategy,videoItem,15,targetUnion);
                        }
                    }
                }else{
                    // 策略定向拆分数据，写入数据库
                    AiKuaishouStrategyTargetUnion targetUnion = new AiKuaishouStrategyTargetUnion(strategyMiddle.getId(),item.getId(),item.getTargetContent());
                    targetUnionService.save(targetUnion);
                    // 选择素材，创建创意
                    for(KuaiShouVideoGet videoItem: fullVideos){
                        unitCnt++;
                        String unitName = campaignName + "-" + unitCnt;
                        JSONObject unitParams = createUnitParams(token,campaignId,strategy,strategyTemplate, item,timestamp,unitName);
                        Map<String, Object> unitCreateResult = kuaishouInterfaceService.adUnitCreate(token.getAccessToken(), token.getAccountId(), unitParams,1);
                        Integer unitCode = (Integer) unitCreateResult.get("code");
                        String unitMessage = (String) unitCreateResult.get("message");
                        if(unitCode != 0 ){
                            log.info("组创建失败=>accountId:{};message:{}",accountId,unitMessage);
                            continue;
                        }
                        Long unitId = (Long) unitCreateResult.get("unitId");
                        JSONObject creativeParams = creativeParams(token,unitId,videoItem,unitCnt,strategy);
                        JSONArray sceneIdJsonArray = JSONArray.parseArray(strategy.getSceneId());
                        // 如果广告位只包含 上下滑大屏广告（6），则一个素材搭配1张封面，生成1个创意
                        if (sceneIdJsonArray.contains(6) && sceneIdJsonArray.size() == 1){
                            //直接创建创意
                            createCreative(token,creativeParams,campaignId,unitId,strategy,targetUnion,1,videoItem);
                        } else {
                            // 素材自带的封面 ctop_material_image_info 内部素材的自带封面，素造的没有
                            // 素材的智能抽帧封面 ctop_material_cut_frame 其中素造的为8张封面，内部的为15张封面
                            List<MaterialCutFrame> cutFrameList = materialCutFrameService.getListByVideoSignature(videoItem.getSignature());
                            List<MaterialImageInfo> orgFrameList = materialImageInfoService.getListByVideoSignature(videoItem.getSignature());
                            // 其他情况下，一个素材搭配15张封面，生成15个创意
                            if ((null == cutFrameList||cutFrameList.isEmpty())&&(null == orgFrameList|| orgFrameList.isEmpty())){
                                log.info("未获取到视频封面=>videoSignature:{}",videoItem.getSignature());
                                continue;
                            }
                            createCreativeByImage(cutFrameList,orgFrameList,token,creativeParams,campaignId,unitId,strategy,videoItem,1,targetUnion);
                        }
                    }
                }
            }
        }

    }

    private void createCreativeByImage(List<MaterialCutFrame> cutFrameList,List<MaterialImageInfo> orgFrameList,
                                       CtopOauthToken token,JSONObject creativeParams,
                                       Long campaignId,Long unitId,KuaishouStrategy strategy,KuaiShouVideoGet videoItem,
                                       int imageNumber,AiKuaishouStrategyTargetUnion targetUnion){
        int creativeCnt  = 1;
        if (null!=orgFrameList&&!orgFrameList.isEmpty()) {
            for (int i = 0; i < orgFrameList.size(); i++) {
                String imageCode = orgFrameList.get(i).getCode();
                String imageUrl = orgFrameList.get(i).getUrl();
                String imageToken = getImageToken(imageUrl,imageCode,token.getAccountId(),token.getAccessToken());
                creativeParams.put("image_token",imageToken);
                createCreative(token,creativeParams,campaignId,unitId,strategy,null,creativeCnt,videoItem);
                creativeCnt++;
                if (creativeCnt > imageNumber) {
                    break;
                }
            }
        }

        if ((null!=cutFrameList&&!cutFrameList.isEmpty()) && (creativeCnt<=15)){
            for (int i = 0; i < cutFrameList.size(); i++) {
                String imageCode = cutFrameList.get(i).getSignature();
                String imageUrl = cutFrameList.get(i).getUrl();
                String imageToken = getImageToken(imageUrl,imageCode,token.getAccountId(),token.getAccessToken());
                creativeParams.put("image_token",imageToken);
                createCreative(token,creativeParams,campaignId,unitId,strategy,null,creativeCnt,videoItem);
                creativeCnt ++;
                if (creativeCnt > imageNumber) {
                    break;
                }
            }
        }
    }

    private JSONObject createUnitParams(CtopOauthToken token, Long campaignId, KuaishouStrategy strategy, Long item,
                                        String unitName) {
        // 拼装创建组的入参 json
        JSONObject unitParams = new JSONObject();
        unitParams.put("advertiser_id",token.getAccountId());
        unitParams.put("campaign_id",campaignId);
        unitParams.put("unit_name", unitName);
        unitParams.put("bid_type",10);
        unitParams.put("ocpx_action_type",180);

        if(null!=strategy.getUseAppMarket()&&!"".equals(strategy.getUseAppMarket())){
            unitParams.put("use_app_market",Integer.parseInt(strategy.getUseAppMarket()));
        }
        if(null!=strategy.getAppStore()&&!"".equals(strategy.getAppStore())){
            unitParams.put("app_store",JSONArray.parseArray(strategy.getAppStore()));
        }

        // 在本策略中，都是 OCPM 的出价方式
        unitParams.put("cpa_bid",item);
        unitParams.put("ocpx_action_type",strategy.getOcpxActionType());
        unitParams.put("deep_conversion_type",strategy.getDeepConversionType());
        unitParams.put("deep_conversion_bid",strategy.getDeepConversionBid());
        unitParams.put("scene_id",JSONArray.parseArray(strategy.getSceneId()));
        unitParams.put("unit_type",4);

        // 格式为yyyy-MM-dd，需大于等于当前时间
        unitParams.put("begin_time",DateUtils.formatDate(new Date()));
        if(null!=strategy.getConvertId()){
            unitParams.put("convert_id",strategy.getConvertId());
        }
        // 当计划类型是3/4/5时必填
        if(null!=strategy.getUrl()&&!"".equals(strategy.getUrl())){
            unitParams.put("url",strategy.getUrl());
        }
        JSONArray appIds = JSONArray.parseArray(strategy.getAppIds());
        //TODO 先只做单appId的逻辑
        if(null!=appIds&&!appIds.isEmpty()){
            unitParams.put("app_id",appIds.getLong(0));
        }
        unitParams.put("show_mode",2);
        unitParams.put("speed",1);
        // 设置定向内容
        JSONObject targetJsonObject = new JSONObject();
        targetJsonObject.put("region",JSONArray.parseArray(strategy.getRegion()));
        targetJsonObject.put("ages_range",JSONArray.parseArray(strategy.getAgesRange()));
        targetJsonObject.put("gender",strategy.getGender());
        targetJsonObject.put("platform_os",strategy.getPlatformOs());
        JSONArray population = JSONArray.parseArray(strategy.getPopulation());
        if(null!=population&&!population.isEmpty()){
            targetJsonObject.put("population",population);
        }
        JSONArray excludePopulation = JSONArray.parseArray(strategy.getExcludePopulation());
        if(null!=excludePopulation&&!excludePopulation.isEmpty()){
            targetJsonObject.put("exclude_population",excludePopulation);
        }

        unitParams.put("target",targetJsonObject);
        return unitParams;
    }

    private static List<Long> splitCapBidByDomain(Long cpaBidMin, Long cpaBidMax, Long stepSize) {
        List<Long>result = new ArrayList<>();
        if(cpaBidMin>cpaBidMax){
            return result;
        }
        if(cpaBidMin.equals(cpaBidMax)){
            result.add(cpaBidMin);
            return result;
        }
        if(cpaBidMin<cpaBidMax){
            result.add(cpaBidMin);
            result.add(cpaBidMax);
            while (cpaBidMin<cpaBidMax){
                cpaBidMin+=stepSize;
                if(cpaBidMin>= cpaBidMax){
                    return result;
                }
                result.add(cpaBidMin);
            }
        }
        return result;
    }

    private JSONObject creativeParams(CtopOauthToken token,Long unitId,KuaiShouVideoGet videoItem,int unitCnt,KuaishouStrategy strategy){
        JSONObject creativeParams = new JSONObject();
        creativeParams.put("advertiser_id",token.getAccountId());
        creativeParams.put("unit_id",unitId);
        creativeParams.put("photo_id",videoItem.getPhotoId());
        creativeParams.put("creative_material_type",videoItem.getMaterialType());
        creativeParams.put("action_bar_text","下载抢购");
        creativeParams.put("description","不买亏大了！众多商品低至一元！看看你多花了多少冤枉钱！");
        // 安卓下载中间页ID
        JSONArray siteIdArray = JSONArray.parseArray(strategy.getSiteId());
        if(null == siteIdArray||!siteIdArray.isEmpty()){
            JSONObject siteObject = siteIdArray.getJSONObject(0);
            Long appId = siteObject.getLong("appId");
            Long siteId = siteObject.getLong("siteId");
            if(null!=siteId){
                creativeParams.put("site_id",siteId);
            }
        }
        if(null != strategy.getClickTrackUrl()&&!"".equals(strategy.getClickTrackUrl())){
            creativeParams.put("click_track_url",strategy.getClickTrackUrl());
        }
        if(null != strategy.getImpressionUrl()&&!"".equals(strategy.getImpressionUrl())){
            creativeParams.put("impression_url",strategy.getImpressionUrl());
        }
        if(null != strategy.getActionbarClickUrl()&&!"".equals(strategy.getActionbarClickUrl())){
            creativeParams.put("actionbar_click_url",strategy.getActionbarClickUrl());
        }
        if(null!=strategy.getCreativeCategory()){
            creativeParams.put("creative_category",strategy.getCreativeCategory());
            creativeParams.put("creative_tag",JSONArray.parseArray(strategy.getCreativeTag()));
        }
        return creativeParams;
    }

    private String getStragyDefDomain(AiKuaishouStrategyTemplate strategyTemplate,KuaishouStrategy strategy){
        String definitionDomain = null;
        if (strategyTemplate.getTestDirection().equals("age")){
            definitionDomain = strategy.getAgesRange();
        }
        if (strategyTemplate.getTestDirection().equals("gender")){
            definitionDomain = strategy.getGender().toString();
        }
        if (strategyTemplate.getTestDirection().equals("region")){
            definitionDomain = strategy.getRegion();
        }
        if (strategyTemplate.getTestDirection().equals("operation_system")){
            definitionDomain = strategy.getPlatformOs().toString();
        }
        return definitionDomain;
    }

    private JSONObject createUnitParams(CtopOauthToken token,Long campaignId,KuaishouStrategy strategy,AiKuaishouStrategyTemplate strategyTemplate,
                                        AiKuaishouStrategyTargetBase item,String timestamp,String unitName){
        // 拼装创建组的入参 json
        JSONObject unitParams = new JSONObject();
        unitParams.put("advertiser_id",token.getAccountId());
        unitParams.put("campaign_id",campaignId);
        String uuid = UUID.randomUUID().toString();
        unitParams.put("unit_name", unitName);
        unitParams.put("bid_type",10);
        unitParams.put("ocpx_action_type",180);

        if(null!=strategy.getUseAppMarket()&&!"".equals(strategy.getUseAppMarket())){
            unitParams.put("use_app_market",Integer.parseInt(strategy.getUseAppMarket()));
        }
        if(null!=strategy.getAppStore()&&!"".equals(strategy.getAppStore())){
            unitParams.put("app_store",JSONArray.parseArray(strategy.getAppStore()));
        }

        // 在本策略中，都是 OCPM 的出价方式
        unitParams.put("cpa_bid",strategy.getCpaBid());
        unitParams.put("ocpx_action_type",strategy.getOcpxActionType());
        unitParams.put("deep_conversion_type",strategy.getDeepConversionType());
        unitParams.put("deep_conversion_bid",strategy.getDeepConversionBid());
        unitParams.put("scene_id",JSONArray.parseArray(strategy.getSceneId()));
        unitParams.put("unit_type",4);

        // 格式为yyyy-MM-dd，需大于等于当前时间
        unitParams.put("begin_time",DateUtils.formatDate(new Date()));
        if(null!=strategy.getConvertId()){
            unitParams.put("convert_id",strategy.getConvertId());
        }
        // 当计划类型是3/4/5时必填
        if(null!=strategy.getUrl()&&!"".equals(strategy.getUrl())){
            unitParams.put("url",strategy.getUrl());
        }
        JSONArray appIds = JSONArray.parseArray(strategy.getAppIds());
        //TODO 先只做单appId的逻辑
        if(null!=appIds&&!appIds.isEmpty()){
            unitParams.put("app_id",appIds.getLong(0));
        }
        unitParams.put("show_mode",2);
        unitParams.put("speed",1);
        // 设置定向内容
        JSONObject targetJsonObject = new JSONObject();
        //TODO 34
        if (strategyTemplate.getTestDirection().equals("region")){
            targetJsonObject.put("region",JSONArray.parseArray(item.getTargetContent()));
        } else {
            targetJsonObject.put("region",JSONArray.parseArray(strategy.getRegion()));
        }

        //TODO 5
        if (strategyTemplate.getTestDirection().equals("age")){
            targetJsonObject.put("ages_range",JSONArray.parseArray(item.getTargetContent()));
        } else{
            targetJsonObject.put("ages_range",JSONArray.parseArray(strategy.getAgesRange()));
        }

        //TODO 3
        if (strategyTemplate.getTestDirection().equals("gender")){
            targetJsonObject.put("gender",item.getTargetContent());
        } else {
            targetJsonObject.put("gender",strategy.getGender());
        }

        //TODO
        if (strategyTemplate.getTestDirection().equals("operation_system")){
            targetJsonObject.put("platform_os",item.getTargetContent());
        } else {
            targetJsonObject.put("platform_os",strategy.getPlatformOs());
        }
        JSONArray population = JSONArray.parseArray(strategy.getPopulation());
        if(null!=population&&!population.isEmpty()){
            targetJsonObject.put("population",population);
        }
        JSONArray excludePopulation = JSONArray.parseArray(strategy.getExcludePopulation());
        if(null!=excludePopulation&&!excludePopulation.isEmpty()){
            targetJsonObject.put("paid_audience",excludePopulation);
        }

        unitParams.put("target",targetJsonObject);
        return unitParams;
    }
    private void createCreative(CtopOauthToken token,JSONObject creativeParams,Long campaignId,Long unitId,
                                KuaishouStrategy strategy,AiKuaishouStrategyTargetUnion targetUnion,int creativeCnt,KuaiShouVideoGet videoGet){
        creativeParams.put("creative_name","自定义创意_竖版视频_"+creativeCnt);
        Map<String, Object> creativeCreateResult = kuaishouInterfaceService.creativeCreate
                (token.getAccessToken(), token.getAccountId(), creativeParams,1);
        Integer creativeCode = (Integer) creativeCreateResult.get("code");
        String creativeMessage = (String) creativeCreateResult.get("message");
        if(creativeCode != 0 ){
            log.info("创意创建失败=>message:{}",creativeMessage);
            return;
        }
        Long creativeId = (Long) creativeCreateResult.get("creativeId");
        AiKuaishouStrategyMapCreative mapCreative = new AiKuaishouStrategyMapCreative();
        mapCreative.setAccountId(token.getAccountId());
        mapCreative.setCampaignId(campaignId);
        mapCreative.setUnitId(unitId);
        //TODO 添加
        mapCreative.setVideoSignature(videoGet.getSignature());
        mapCreative.setCreativeId(creativeId);
        mapCreative.setStrategyId(strategy.getId());
        if(null!=targetUnion){
            mapCreative.setStrategyTargetUnionId(targetUnion.getId());
        }
        mapCreativeService.save(mapCreative);
    }

    private String getImageToken(String imageUrl, String imageCode, Long accountId,String token){
        // 根据imageUrl 和 imageCode，获取 imageToken （创建创意用）
        KuaiShouImageGet imageGet = imageGetService.getOneByParams(null,imageCode);
        if ((null == imageGet) || ("".equals(imageGet.getImageToken()))){
            // 如果取不到image_token
            // 则调用上传url的方法 kuauiShouImageUpload(url, signature, accountId, oauthToken.getAccessToken());
            return materialUploadService.kuauiShouImageUpload(imageUrl,imageCode,accountId,token);
        }

        return imageGet.getImageToken();
    }

    private List<AiKuaishouStrategyTargetBase> splitBasesByDomain(String definitionDomain,
                                                                  List<AiKuaishouStrategyTargetBase> targetBases) {
        if(null==definitionDomain){
            return targetBases;
        }
        if(null == targetBases||targetBases.isEmpty()){
            return null;
        }
        String type =  targetBases.get(0).getType();
        List<AiKuaishouStrategyTargetBase> resultBase = null;
        //数字
        if("number".equals(type)){
            resultBase = targetBases.stream().filter(target -> definitionDomain.equals(target.getTargetContent())).
                    collect(Collectors.toList());
        }
        //数组
        if("array".equals(type)){
            resultBase = targetBases.stream().filter(target -> checkContainsEveryOne(definitionDomain,target.getTargetContent())).map(target->{
                target.setTargetContent(getContainsElement(definitionDomain,target.getTargetContent()));
                return target;
            }).collect(Collectors.toList());
        }
        return resultBase;
    }

    /**
     * 后期需要优化
     * 判定是否存在交集
     * @param definitionDomain
     * @param targetContent
     * @return
     */
    private boolean checkContainsEveryOne(String definitionDomain, String targetContent) {
        JSONArray definitionDomainArray = JSONArray.parseArray(definitionDomain);
        JSONArray targetContentArray = JSONArray.parseArray(targetContent);
        if(definitionDomainArray.size()>=targetContentArray.size()){
            return checkContains(targetContentArray,definitionDomainArray);
        }
        return checkContains(definitionDomainArray,targetContentArray);
    }

    /**
     *
     * @param shortArray
     * @param longArray
     * @return
     */
    private boolean checkContains(JSONArray shortArray, JSONArray longArray) {
        for (int i = 0; i < shortArray.size(); i++) {
            Long s = shortArray.getLong(i);
            for(int j=0;j<longArray.size();j++){
                Long l = longArray.getLong(j);
                if(s.equals(l)){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 获取交集元素
     * @param definitionDomain
     * @param targetContent
     * @return
     */
    private String getContainsElement(String definitionDomain, String targetContent){
        JSONArray definitionDomainArray = JSONArray.parseArray(definitionDomain);
        JSONArray targetContentArray = JSONArray.parseArray(targetContent);
        return getContainsArray(definitionDomainArray,targetContentArray);
    }

    private String getContainsArray(JSONArray definitionDomainArray, JSONArray targetContentArray) {
        log.info("definitionDomainArray:"+definitionDomainArray.toJSONString());
        log.info("targetContentArray:"+targetContentArray.toJSONString());
        JSONArray resultArray = new JSONArray();
        for (int i = 0; i < definitionDomainArray.size(); i++) {
            Long s = definitionDomainArray.getLong(i);
            for(int j=0;j<targetContentArray.size();j++){
                Long l = targetContentArray.getLong(j);
                if(l.equals(s)){
                    resultArray.add(l);
                }
            }
        }
        log.info("result:"+resultArray.toJSONString());
        return resultArray.toJSONString();
    }
}
