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

import cn.com.ctop.common.module.entity.CtopOauthToken;
import cn.com.ctop.common.module.entity.Product;
import cn.com.ctop.common.module.entity.UserAllocation;
import cn.com.ctop.common.module.mapper.ProductMapper;
import cn.com.ctop.common.module.mapper.ProjectMapper;
import cn.com.ctop.common.module.service.ICtopOauthTokenService;
import cn.com.ctop.common.module.service.IUserAllocationService;
import cn.com.ctop.common.module.utils.Check;
import cn.com.ctop.common.module.utils.ExportExcelUtils;
import cn.com.ctop.common.module.utils.KuaishouInterfaceConstant;
import cn.com.ctop.common.module.utils.PropertiesUtils;
import cn.com.ctop.kuaishou.modules.ai.service.IAiKuaiShouAppInfoService;
import cn.com.ctop.kuaishou.modules.ai.service.IKuaishouAppPackageService;
import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouAppList;
import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouAppListService;
import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouCreativeService;
import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouMaterialUploadService;
import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouInterfaceService;
import cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannel;
import cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannelAppInfo;
import cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannelCreateStrategy;
import cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannelItems;
import cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannelItemsRel;
import cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannelRel;
import cn.com.ctop.kuaishou.modules.channel.entity.KuaishouChannelUpdateRecord;
import cn.com.ctop.kuaishou.modules.channel.mapper.KuaishouChannelMapper;
import cn.com.ctop.kuaishou.modules.channel.service.IKuaishouChannelAppInfoService;
import cn.com.ctop.kuaishou.modules.channel.service.IKuaishouChannelCreateStrategyService;
import cn.com.ctop.kuaishou.modules.channel.service.IKuaishouChannelItemsRelService;
import cn.com.ctop.kuaishou.modules.channel.service.IKuaishouChannelItemsService;
import cn.com.ctop.kuaishou.modules.channel.service.IKuaishouChannelRelService;
import cn.com.ctop.kuaishou.modules.channel.service.IKuaishouChannelService;
import cn.com.ctop.kuaishou.modules.channel.service.IKuaishouChannelUpdateRecordService;
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.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 渠道号信息表
 *
 * @author jeecg-boot
 * 2021-08-30
 * @version V1.0
 */
@Service
public class KuaishouChannelServiceImpl extends ServiceImpl<KuaishouChannelMapper, KuaishouChannel> implements IKuaishouChannelService {
    @Autowired
    private IKuaiShouMaterialUploadService materialUploadService;

    @Autowired
    private KuaishouChannelMapper channelMapper;
    @Autowired
    private IKuaishouChannelRelService channelRelService;

    @Autowired
    private IKuaishouAppPackageService kuaishouAppPackageService;

    @Autowired
    private IKuaishouChannelCreateStrategyService channelCreateStrategyService;

    @Autowired
    private IKuaishouChannelItemsService channelItemsService;

    @Autowired
    private IKuaishouChannelItemsRelService channelItemsRelService;

    @Autowired
    private IKuaishouChannelAppInfoService channelAppInfoService;

    @Autowired
    private IKuaiShouCreativeService kuaiShouCreativeService;

    @Autowired
    private IKuaiShouAppListService kuaiShouAppListService;

    @Autowired
    private IKuaishouInterfaceService kuaishouInterfaceService;

    @Autowired
    private IAiKuaiShouAppInfoService appInfoService;

    @Autowired
    private IUserAllocationService userAllocationService;

    @Autowired
    private IKuaishouChannelUpdateRecordService channelUpdateRecordService;

    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private ICtopOauthTokenService tokenService;
    private static final String CHANNEL_STR = "-{{渠道号}}-";
    private static final String NUMBER_STR = "-{{编号}}-";


    @Override
    public Result<Object> channelManagementHome(KuaishouChannel kuaishouChannel) {
        List<JSONObject> list = channelMapper.channelManagementHome(kuaishouChannel);
        return Result.ok(new PageInfo<>(list));
    }

    @Override
    public Result<Object> channelNumberDetails(KuaishouChannel kuaishouChannel, Integer pageNo, Integer pageSize) {
        Long total = channelMapper.channelNumberDetailsTotal(kuaishouChannel);
        PageHelper.startPage(pageNo, pageSize, false);
        List<KuaishouChannel> kuaishouChannels = channelMapper.channelNumberDetails(kuaishouChannel);
        for (KuaishouChannel channel : kuaishouChannels) {
            List<KuaishouChannelItems> list = channelItemsRelService.queryItems(channel.getId());
            channel.setItems(list);
        }
        PageInfo pageInfo = new PageInfo(kuaishouChannels);
        pageInfo.setTotal(total);
        return Result.ok(pageInfo);
    }

    @Override
    public Result<Object> channelNumberUsageDetailsList(KuaishouChannel kuaishouChannel, Integer pageNo, Integer pageSize) {
        Long total = channelMapper.channelNumberUsageDetailsListTotal(kuaishouChannel);
        PageHelper.startPage(pageNo, pageSize, false);
        List<KuaishouChannel> list = channelMapper.channelNumberUsageDetailsList(kuaishouChannel);
        PageInfo pageInfo = new PageInfo(list);
        pageInfo.setTotal(total);
        return Result.ok(pageInfo);
    }

    @Override
    public Result<Object> channelNumberBindingItemInfo(JSONArray request) {
        List<JSONObject> list = channelMapper.channelNumberBindingItemInfo(request);
        return Result.ok(list);
    }


    /**
     * 校验渠道号是否重复
     */
    private boolean checkChannelCode(KuaishouChannelCreateStrategy strategy) {
        String numberValue = strategy.getNumberValue().trim();
        Integer min = strategy.getNumberMin();
        Integer max = strategy.getNumberMax();

        QueryWrapper<KuaishouChannelCreateStrategy> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id", strategy.getProductId());
        if (!Check.isNull(strategy.getAccountId())) {
            queryWrapper.eq("account_id", strategy.getAccountId());
        }
        queryWrapper.eq("project_id", strategy.getProjectId());
        queryWrapper.eq("channel_code", strategy.getChannelCode());
        if (!Check.isNull(strategy.getNumberLength())) {
            queryWrapper.eq("number_length", strategy.getNumberLength());
        }

        //查询是否有长度和渠道号命名一致的数据
        List<KuaishouChannelCreateStrategy> list = channelCreateStrategyService.list(queryWrapper);
        //若不存在，则可以直接创建
        if (Check.isNull(list) || list.isEmpty()) {
            return true;
        }
        //存在已有的渠道则需要判断是否重复
        if (numberValue.contains("-")) {
            for (KuaishouChannelCreateStrategy sy : list) {
                if (sy.getNumberMin() >= min && sy.getNumberMin() <= max) {
                    return false;
                }
                if (sy.getNumberMax() >= min && sy.getNumberMax() <= max) {
                    return false;
                }
                if (min >= sy.getNumberMin() && min <= sy.getNumberMax()) {
                    return false;
                }
                if (max >= sy.getNumberMin() && max <= sy.getNumberMax()) {
                    return false;
                }
                if (min == sy.getNumberMin() || min == sy.getNumberMax() || max == sy.getNumberMin() || max == sy.getNumberMax()) {
                    return false;
                }
            }
        } else {
            for (KuaishouChannelCreateStrategy sy : list) {
                if (numberValue.equals(sy.getNumberValue())) {
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public Result<Object> systemBatchCreation(JSONObject request) {
        KuaishouChannelCreateStrategy strategy = JSONObject.parseObject(request.toJSONString(), KuaishouChannelCreateStrategy.class);
        if (strategy.getUsageRange() == 1 && Check.isNull(strategy.getAccountId())) {
            return Result.error("选择使用账户范围时，账户ID必填");
        }
        if (Check.isNull(strategy)) {
            return Result.error("数据转换异常");
        }
        JSONObject obj = projectMapper.getProduct(strategy.getAccountId(), strategy.getProjectId());
        strategy.setProjectId(obj.getLong("projectId"));
        strategy.setProductId(obj.getLong("productId"));
        QueryWrapper<KuaishouChannelCreateStrategy> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id", strategy.getProductId());
        if (!Check.isNull(strategy.getAccountId())) {
            queryWrapper.eq("account_id", strategy.getAccountId());
        }
        queryWrapper.eq("project_id", strategy.getProjectId());
        Integer numberMin = 0;
        Integer numberMax = 0;
        if (strategy.getNumberValue().contains("-")) {
            String[] split = strategy.getNumberValue().split("-");
            numberMin = Integer.valueOf(split[0]);
            numberMax = Integer.valueOf(split[1]);
            strategy.setNumberMin(numberMin);
            strategy.setNumberMax(numberMax);
        }
        //查询是否已经创建过策略，若已创建则某些字段必须一致，比如是否循环、使用层级
        KuaishouChannelCreateStrategy one = channelCreateStrategyService.getOne(queryWrapper.last("limit 1"));
        if (!Check.isNull(one)) {
            if (!one.getUsageLevel().equals(strategy.getUsageLevel())) {
                return Result.error("创建失败，使用层级字段与原有策略不一致！");
            }
            //验证渠道号命名唯一
            if (!checkChannelCode(strategy)) {
                return Result.error("创建失败，渠道号命名重复");
            }
        }
        if (Check.isNull(strategy.getUserId())) {
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            if (!Check.isNull(sysUser)) {
                strategy.setUserId(sysUser.getId());
            }
        }
        try {
            strategy.setStateDate(DateUtils.getDate(DateUtils.WEB_FORMAT));
            boolean save = channelCreateStrategyService.save(strategy);
            //项目名称
            strategy.setProjectName(projectMapper.getNameByProjectId(strategy.getProjectId()));
            //产品名
            Product product = productMapper.selectById(strategy.getProductId());
            if (!Check.isNull(product)) {
                strategy.setProductName(product.getProductName());
            }
            //下载链接
            String appIconUrl = strategy.getAppIconUrl();
            if (!Check.isNull(appIconUrl) && !appIconUrl.contains("http")) {
                strategy.setAppIconUrl("https:" + appIconUrl);
            }
            //创建单个渠道号
            if (!strategy.getNumberValue().contains("-")) {
                return customizedCreate(strategy);
            }
            Integer usageRange = strategy.getUsageRange();
            if (usageRange == 2) {
                /*==========================范围是 项目==========================*/
                String usageLevel = strategy.getUsageLevel();
                //获取项目下账户集
                List<Long> accountList = userAllocationService.getAccountListByProjectId(strategy.getProjectId());
                if (Check.isNull(accountList) || accountList.isEmpty()) {
                    return Result.error("未获取有效账户");
                }
                if ("account".equals(usageLevel)) {
                    /*-----------------项目维度：使用层级是账户-----------------*/
                    int length = accountList.size();
                    //待循环的数组长度
                    int size = numberMax - numberMin + 1;
                    //项目下有账户
                    if (length > 0) {
                        //循环数大于账户数
                        if (size >= length) {
                            /*-----------------项目维度：渠道号编码长度 大于 项目下账户总数-----------------*/
                            for (int i = numberMin; i <= numberMax; i++) {
                                length = --length;
                                if (length >= 0) {
                                    Long accountId = accountList.get(length);
                                    if (!Check.isNull(accountId)) {
                                        strategy.setAccountId(accountId);
                                        createProjectLevelChannel(strategy, i);
                                    }
                                }
                            }
                        } else {
                            /*-----------------项目维度：渠道号编码长度 小于 项目下账户总数，不循环使用渠道号逻辑-----------------*/
                            //判断是否循环 0:否，1:是
                            if (strategy.getIsCycle() == 0) {
                                for (int i = numberMin; i <= numberMax; i++) {
                                    length = --length;
                                    if (length >= 0) {
                                        Long accountId = accountList.get(length);
                                        if (!Check.isNull(accountId)) {
                                            strategy.setAccountId(accountId);
                                            createProjectLevelChannel(strategy, i);
                                        }
                                    }
                                }
                            } else {
                                /*-----------------项目维度：渠道号编码长度 小于 项目下账户总数，循环使用渠道号逻辑-----------------*/
                                //可循环的次数,向上取整，除开取本身
                                List<List<Long>> accountSubLists = Lists.partition(accountList, size);
                                for (int i = 0; i < accountSubLists.size(); i++) {
                                    List<Long> accountSubList = accountSubLists.get(i);
                                    //k获取账户子集的数据
                                    int i1 = accountSubList.size();
                                    for (int j = numberMin; j <= numberMax; j++) {
                                        i1--;
                                        if (i1 >= 0) {
                                            Long accountId = accountSubList.get(i1);
                                            if (!Check.isNull(accountId)) {
                                                strategy.setAccountId(accountId);
                                                createProjectLevelChannel(strategy, j);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else {
                    /*-----------------项目维度：使用层级是计划、组-----------------*/
                    for (Long accountId : accountList) {
                        strategy.setAccountId(accountId);
                        addMoreChannel(strategy, numberMin, numberMax);
                    }
                }
            } else {
                /*==========================范围是 账户==========================*/
                addMoreChannel(strategy, numberMin, numberMax);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成渠道号异常");
        }

        return Result.ok("创建成功");
    }


    private void createProjectLevelChannel(KuaishouChannelCreateStrategy strategy, Integer i) {
        try {
            CtopOauthToken token = tokenService.getTokenByAccountId(strategy.getAccountId());
            KuaishouChannelCreateStrategy replaceData = replaceWildcard(strategy, i);
            createApp(replaceData, token, null);
            createChannel(replaceData, i);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成渠道号异常");
        }
    }

    /**
     * 账户级批量创建渠道号
     */
    private void addMoreChannel(KuaishouChannelCreateStrategy strategy, Integer numberMin, Integer numberMax) {
        try {
            //获取token
            CtopOauthToken token = tokenService.getTokenByAccountId(strategy.getAccountId());
            List<KuaiShouAppList> oldAppList = null;
            if (Check.isNull(strategy.getAppId())) {
                //使用范围是账户时，查询旧app来做匹配
                kuaishouInterfaceService.getAppList(token.getAccountId(), token.getAccessToken());
                oldAppList = kuaiShouAppListService.getAppListByAccountId(token.getAccountId());
            }
            if (!Check.isNull(strategy.getUrl()) && strategy.getUrl().contains(CHANNEL_STR)) {
                for (int i = numberMin; i <= numberMax; i++) {
                    KuaishouChannelCreateStrategy replaceData = replaceWildcard(strategy, i);
                    createApp(replaceData, token, oldAppList);
                    createChannel(replaceData, i);
                }
            } else {
                createApp(strategy, token, oldAppList);
                for (int i = numberMin; i <= numberMax; i++) {
                    KuaishouChannelCreateStrategy replaceData = replaceWildcard(strategy, i);
                    createChannel(replaceData, i);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 执行创建单一渠道号
     */
    private Result<Object> customizedCreate(KuaishouChannelCreateStrategy strategy) {
        try {/*==========================范围是 项目==========================*/
            if (strategy.getUsageRange() == 2) {
                //获取项目下账户集
                List<Long> accountList = userAllocationService.getAccountListByProjectId(strategy.getProjectId());
                if (Check.isNull(accountList) || accountList.isEmpty()) {
                    return Result.error("未获取有效账户");
                }
                for (Long accountId : accountList) {
                    strategy.setAccountId(accountId);
                    addSingleChannel(strategy);
                }
            } else {
                /*==========================范围是 账户==========================*/
                addSingleChannel(strategy);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("创建单个渠道号异常");
        }
        return Result.ok("创建成功");
    }

    /**
     * 创建单个渠道号
     */
    private void addSingleChannel(KuaishouChannelCreateStrategy strategy) {
        try {
            Integer i = Integer.valueOf(strategy.getNumberValue());
            List<KuaiShouAppList> oldAppList = null;
            CtopOauthToken token = tokenService.getTokenByAccountId(strategy.getAccountId());
            if (Check.isNull(strategy.getAppId())) {
                //使用范围是账户时，查询旧app来做匹配
                kuaishouInterfaceService.getAppList(token.getAccountId(), token.getAccessToken());
                oldAppList = kuaiShouAppListService.getAppListByAccountId(token.getAccountId());
            }
            KuaishouChannelCreateStrategy replaceData = replaceWildcard(strategy, i);
            createApp(replaceData, token, oldAppList);
            createChannel(replaceData, i);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取应用AppId
     */
    private void createApp(KuaishouChannelCreateStrategy strategy, CtopOauthToken
            token, List<KuaiShouAppList> oldAppList) throws Exception {
        //创建应用,若已存在appId，则说明渠道号不在下载链接中，应用已创建
        if (Check.isNull(strategy.getAppId())) {
            KuaiShouAppList app = null;
            //判断 旧应用是否有相同的下载链接
            if (!Check.isNull(oldAppList) && oldAppList.size() > 0) {
                for (KuaiShouAppList appList : oldAppList) {
                    //符合则记录，并跳出循环
                    if (strategy.getUrl().equals(appList.getUrl())) {
                        app = appList;
                        break;
                    }
                }
            }
            //获取应用图片token
            JSONObject tokenJson = appInfoService.uploadAppIconImage(strategy.getAppIconUrl(), token.getAccountId(), token.getAccessToken());
            if (!Check.isNull(tokenJson) && tokenJson.getInteger("code") != 0) {
                log.error("通过账户ID（" + token.getAccountId() + "）获取图片Token失败，返回信息：" + tokenJson.getString("message"));
            }
            strategy.setImageToken(tokenJson.getString("imageToken"));

            //判断是否有应用，没有则创建
            if (Check.isNull(app)) {
                //------------------------------新建应用---------------------------------------
                addApp(strategy, token);
            } else {
                //有应用则继续判断应用标记是否一致，不一致则修改，一致就获取appId
                if (strategy.getAppVersion().equals(app.getAppVersion())) {
                    QueryWrapper<KuaishouChannelAppInfo> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("account_id", strategy.getProjectId());
                    queryWrapper.eq("app_version", app.getAppVersion());
                    queryWrapper.eq("url", app.getUrl()).last("limit 1");
                    KuaishouChannelAppInfo one = channelAppInfoService.getOne(queryWrapper);
                    if (Check.isNull(one)) {
                        KuaishouChannelAppInfo channelAppInfo = new KuaishouChannelAppInfo();
                        BeanUtils.copyProperties(app, channelAppInfo);
                        channelAppInfo.setState(1);
                        channelAppInfo.setUrl((String) app.getUrl());
                        channelAppInfo.setUseSdk(0);
                        channelAppInfo.setAppIconUrl((String) app.getAppIconUrl());
                        channelAppInfo.setId(null);
                        channelAppInfo.setType("copy");
                        channelAppInfo.setRemark("copy原有App");
                        channelAppInfoService.save(channelAppInfo);
                    }
                    strategy.setAppId(app.getAppId());
                } else {
                    //------------------------------修改应用---------------------------------------
                    updateApp(strategy, app, token);
                }
            }
        }else{
            KuaiShouAppList appInfo = kuaiShouAppListService.getAppInfo(strategy.getAccountId(), strategy.getAppId());
            KuaishouChannelAppInfo channelAppInfo = new KuaishouChannelAppInfo();
            BeanUtils.copyProperties(appInfo, channelAppInfo);
            channelAppInfo.setState(1);
            channelAppInfo.setUrl((String) appInfo.getUrl());
            channelAppInfo.setUseSdk(0);
            channelAppInfo.setAppIconUrl((String) appInfo.getAppIconUrl());
            channelAppInfo.setId(null);
            channelAppInfo.setType("check");
            channelAppInfo.setRemark("选择原有App");
            channelAppInfoService.save(channelAppInfo);
        }
    }

    /**
     * 创建渠道号
     */
    private void createChannel(KuaishouChannelCreateStrategy strategy, Integer number) throws Exception {
        KuaishouChannel kuaishouChannel = new KuaishouChannel();
        BeanUtils.copyProperties(strategy, kuaishouChannel);
        kuaishouChannel.setChannelNumber(Long.valueOf(number));
        kuaishouChannel.setId(null);
        kuaishouChannel.setStrategyId(strategy.getId());
        this.save(kuaishouChannel);

        KuaishouChannelRel channelRel = new KuaishouChannelRel();
        BeanUtils.copyProperties(strategy, channelRel);
        channelRel.setId(null);
        channelRelService.save(channelRel);
        if (!Check.isNull(strategy.getIsHaveItem()) && strategy.getIsHaveItem() == 1 && !Check.isNull(strategy.getItemName())) {
            QueryWrapper<KuaishouChannelItems> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("project_id", strategy.getProjectId());
            queryWrapper.eq("state", 1);
            queryWrapper.eq("item_name", strategy.getItemName()).last("limit 1");
            KuaishouChannelItems one = channelItemsService.getOne(queryWrapper);
            if (!Check.isNull(one)) {
                KuaishouChannelItemsRel rel = new KuaishouChannelItemsRel();
                rel.setItemId(one.getId());
                rel.setChannelId(kuaishouChannel.getId());
                channelItemsRelService.save(rel);
            }
        }
    }

    private void updateApp(KuaishouChannelCreateStrategy strategy, KuaiShouAppList app, CtopOauthToken token) throws
            Exception {
        KuaishouChannelAppInfo channelAppInfo = new KuaishouChannelAppInfo();
        BeanUtils.copyProperties(app, channelAppInfo);
        channelAppInfo.setType("update");
        channelAppInfo.setAppVersion(strategy.getAppVersion());
        channelAppInfo.setAppPrivacyUrl(strategy.getAppPrivacyUrl());
        channelAppInfo.setUrl(String.valueOf(app.getUrl()));
        channelAppInfo.setUseSdk(0);
        channelAppInfo.setAppIconUrl(String.valueOf(app.getAppIconUrl()));
        channelAppInfo.setImageToken(String.valueOf(app.getImageToken()));
        JSONObject requestJson = new JSONObject();
        requestJson.put("app_id", app.getAppId());
        requestJson.put("advertiser_id", token.getAccountId());
        requestJson.put("app_version", strategy.getAppVersion());
        requestJson.put("app_privacy_url", strategy.getAppPrivacyUrl());
        String url = PropertiesUtils.getConfig("kuaishou_api_url") + KuaishouInterfaceConstant.APP_UPDATE;
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "multipart/form-data");
        headerMap.put("Access-Token", token.getAccessToken());
        String result = materialUploadService.exceptInfoForRestTemplate(url, requestJson, headerMap);
        JSONObject resultJson = JSONObject.parseObject(result);
        if (!Check.isNull(resultJson)) {
            Integer code = resultJson.getInteger("code");
            if (code == 0) {
                JSONObject data = resultJson.getJSONObject("data");
                Long appId = data.getLong("app_id");
                channelAppInfo.setState(1);//成功
                channelAppInfo.setRemark("修改成功");
                strategy.setAppId(appId);
            } else {
                channelAppInfo.setState(0);
                channelAppInfo.setRemark(resultJson.getString("message"));
                channelAppInfo.setAppId(null);
            }
        } else {
            channelAppInfo.setState(0);
            channelAppInfo.setRemark("上传应用返回结果为空");
            channelAppInfo.setAppId(null);
        }
        channelAppInfoService.save(channelAppInfo);
    }

    /**
     * 添加app
     */
    private void addApp(KuaishouChannelCreateStrategy strategy, CtopOauthToken token) throws Exception {
        KuaishouChannelAppInfo channelAppInfo = new KuaishouChannelAppInfo();
        BeanUtils.copyProperties(strategy, channelAppInfo);
        String request = null;
        if (!Check.isNull(token)) {
            String accessToken = token.getAccessToken();
            JSONObject requestJson = new JSONObject();
            requestJson.put("advertiser_id", token.getAccountId());
            requestJson.put("app_version", strategy.getAppVersion());
            requestJson.put("app_name", strategy.getAppName());
            requestJson.put("image_token", strategy.getImageToken());
            requestJson.put("package_name", strategy.getPackageName());
            requestJson.put("platform", 1);//Android应用下载
            requestJson.put("url", strategy.getUrl());
            requestJson.put("use_sdk", 0);
            requestJson.put("app_privacy_url", strategy.getAppPrivacyUrl());
            String url = PropertiesUtils.getConfig("kuaishou_api_url") + KuaishouInterfaceConstant.APP_CREATE;
            Thread.sleep(500);
            Map<String, String> headerMap = new HashMap<>();
            headerMap.put("Content-Type", "multipart/form-data");
            headerMap.put("Access-Token", accessToken);
            request = materialUploadService.exceptInfoForRestTemplate(url, requestJson, headerMap);
        }
        JSONObject resultJson = JSONObject.parseObject(request);
        if (!Check.isNull(resultJson)) {
            Integer code = resultJson.getInteger("code");
            if (code == 0) {
                JSONObject data = resultJson.getJSONObject("data");
                Long appId = data.getLong("app_id");
                channelAppInfo.setState(1);//成功
                channelAppInfo.setRemark("应用创建成功");
                channelAppInfo.setAppId(appId);
                strategy.setAppId(appId);
            } else {
                channelAppInfo.setState(0);
                channelAppInfo.setRemark(resultJson.getString("message"));
            }
        } else {
            channelAppInfo.setState(0);
            channelAppInfo.setRemark("fail");
        }
        channelAppInfo.setUseSdk(0);
        channelAppInfo.setPlatform(1);//1：Android应用下载
        channelAppInfo.setType("add");
        channelAppInfo.setId(null);
        channelAppInfoService.save(channelAppInfo);
        strategy.setChannelAppInfoId(channelAppInfo.getId());
    }

    /**
     * 获取编号
     */
    private String getNumberStr(Integer numberLength, Integer number) {
        String numberStr = "";
        if (numberLength == 0) {
            numberStr = String.valueOf(number);
        } else {
            //编号
            numberStr = String.format("%0" + numberLength + "d", number);
        }
        return numberStr;
    }

    /**
     * 获取渠道号
     */
    private String getChannelCode(String ochannelCode, String numberStr) {
        String channelCode = ochannelCode.replace(NUMBER_STR, numberStr).trim();
        channelCode = channelCode.replace("--", "-");
        if (channelCode.startsWith("-")) {
            channelCode = channelCode.substring(1, channelCode.length());
        }
        if (channelCode.endsWith("-")) {
            channelCode = channelCode.substring(0, channelCode.length() - 1);
        }
        return channelCode;
    }

    /**
     * 替换通配符
     */
    private KuaishouChannelCreateStrategy replaceWildcard(KuaishouChannelCreateStrategy strategy, Integer number) {
        KuaishouChannelCreateStrategy channelStrategy = new KuaishouChannelCreateStrategy();
        BeanUtils.copyProperties(strategy, channelStrategy);
        String numberStr = "";
        if (strategy.getCreateType() == 1) {
            Integer numberLength = strategy.getNumberLength();
            //编号
            numberStr = getNumberStr(numberLength, number);
        }
        //渠道号
        String channelCode = getChannelCode(strategy.getChannelCode(), numberStr);

        channelStrategy.setChannelCode(channelCode);
        String channelName = strategy.getChannelName();
        if (channelName.contains(CHANNEL_STR) || channelName.contains(NUMBER_STR)) {
            channelName = channelName.replace(CHANNEL_STR, channelCode).replace(NUMBER_STR, numberStr).trim();
            channelName = channelName.replace("--", "-");
            channelName = channelName.replace("--", "-");
            if (channelName.startsWith("-")) {
                channelName = channelName.substring(1, channelName.length());
            }
            if (channelName.endsWith("-")) {
                channelName = channelName.substring(0, channelName.length() - 1);
            }
            channelStrategy.setChannelName(channelName);
        }
        String schemaUri = strategy.getSchemaUri();
        if (!Check.isNull(schemaUri) && (schemaUri.contains(CHANNEL_STR) || schemaUri.contains(NUMBER_STR))) {
            channelStrategy.setSchemaUri(schemaUri.replace(CHANNEL_STR, channelCode).replace(NUMBER_STR, numberStr).trim());
        }
        if (!Check.isNull(strategy.getUrl()) && (strategy.getUrl().contains(CHANNEL_STR) || strategy.getUrl().contains(NUMBER_STR))) {
            channelStrategy.setUrl(strategy.getUrl().replace(CHANNEL_STR, channelCode).replace(NUMBER_STR, numberStr).trim());
        }
        if (!Check.isNull(strategy.getActionbarClickUrl()) && (strategy.getActionbarClickUrl().contains(CHANNEL_STR) || strategy.getActionbarClickUrl().contains(NUMBER_STR))) {
            channelStrategy.setActionbarClickUrl(strategy.getActionbarClickUrl().replace(CHANNEL_STR, channelCode).replace(NUMBER_STR, numberStr).trim());
        }
        if (!Check.isNull(strategy.getClickTrackUrl()) && (strategy.getClickTrackUrl().contains(CHANNEL_STR) || strategy.getClickTrackUrl().contains(NUMBER_STR))) {
            channelStrategy.setClickTrackUrl(strategy.getClickTrackUrl().replace(CHANNEL_STR, channelCode).replace(NUMBER_STR, numberStr).trim());
        }
        String appVersion = strategy.getAppVersion();
        if (appVersion.contains(CHANNEL_STR)) {
            appVersion = appVersion.replace(CHANNEL_STR, channelCode).trim();
            if (appVersion.endsWith("-")) {
                appVersion = appVersion.substring(0, appVersion.length() - 1);
            }
            channelStrategy.setAppVersion(appVersion);
        }
        return channelStrategy;
    }

    @Override
    public Result<Object> importChannelExcel(MultipartFile file, String imageUrl) throws Exception {
        JSONObject returnJson = new JSONObject();
        Workbook workbook = null;
        String fileName = file.getOriginalFilename();
        String substring = fileName.substring(fileName.lastIndexOf(".") + 1).toUpperCase();
        if ("XLS".equals(substring)) {
            workbook = new HSSFWorkbook(file.getInputStream());
        } else if ("XLSX".equals(substring)) {
            workbook = new XSSFWorkbook(file.getInputStream());
        } else {
            throw new Exception("文件不是Excel文件");
        }
        Sheet sheet = workbook.getSheet("Sheet1");
        if (Check.isNull(sheet)) {
            throw new Exception("Sheet标题不是默认的Sheet1");
        }
        int rows = sheet.getLastRowNum();// 指的行数，一共有多少行+
        if (rows == 0) {
            throw new Exception("请填写数据");
        }
        List<JSONObject> list = new ArrayList<>();
        ExportExcelUtils eeu = new ExportExcelUtils();
        for (int i = 1; i <= rows + 1; i++) {
            Row row = sheet.getRow(i);
            if (row != null) {
                String productId = eeu.getCellValue(row.getCell(0));
                if (Check.isNull(productId)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，产品列缺失数据");
                }
                String projectId = eeu.getCellValue(row.getCell(1));
                if (Check.isNull(projectId)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，项目列缺失数据");
                }
                String userId = eeu.getCellValue(row.getCell(2));
                if (Check.isNull(userId)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，渠道号创建人列缺失数据");
                }
                String usageRange = eeu.getCellValue(row.getCell(3));
                if (Check.isNull(usageRange)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，使用范围列缺失数据");
                }
                String accountId = eeu.getCellValue(row.getCell(4));
                String imageToken = null;
                String md5 = null;
                if ("1".equals(usageRange)) {
                    if (Check.isNull(accountId)) {
                        return Result.error("解析数据失败，文档中第" + (i + 1) + "行，账户ID列缺失数据");
                    } else {
                        CtopOauthToken token = tokenService.getTokenByAccountId(Long.valueOf(accountId));
                        if (!imageUrl.contains("http")) {
                            imageUrl = "https:" + imageUrl;
                        }
                        JSONObject tokenJson = appInfoService.uploadAppIconImage(imageUrl, token.getAccountId(), token.getAccessToken());
                        if (!Check.isNull(tokenJson) && tokenJson.getInteger("code") != 0) {
                            log.error("通过账户ID（" + token.getAccountId() + "）获取图片Token失败，返回信息：" + tokenJson.getString("message"));
                        }
                        imageToken = tokenJson.getString("imageToken");
                        md5 = tokenJson.getString("signature");
                        if (Check.isNull(imageToken)) {
                            return Result.error(tokenJson.getString("message"));
                        }
                    }
                }
                String channelCode = eeu.getCellValue(row.getCell(5));
                if (Check.isNull(channelCode)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，渠道号列缺失数据");
                }
                String channelName = eeu.getCellValue(row.getCell(6));
                if (Check.isNull(channelName)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，渠道号名称列缺失数据");
                }
                String url = eeu.getCellValue(row.getCell(7));
                if (Check.isNull(url)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，下载链接列缺失数据");
                } else if (!url.contains("http")) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，下载链接格式不正确");
                }
                String packageName = eeu.getCellValue(row.getCell(8));
                if (Check.isNull(packageName)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，应用包名列缺失数据");
                }
                String appName = eeu.getCellValue(row.getCell(9));
                if (Check.isNull(appName)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，应用名称列缺失数据");
                }
                String appVersion = eeu.getCellValue(row.getCell(10));
                if (Check.isNull(appVersion)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，应用标记列缺失数据");
                }
                String appPrivacyUrl = eeu.getCellValue(row.getCell(11));
                if (Check.isNull(appPrivacyUrl)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，隐私政策链接列缺失数据");
                } else if (!appPrivacyUrl.contains("http")) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，隐私政策链接格式不正确");
                }
                String clickTrackUrl = eeu.getCellValue(row.getCell(12));
                if (Check.isNull(clickTrackUrl)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，第三方点击监测链接列缺失数据");
                } else if (!clickTrackUrl.contains("http")) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，第三方点击监测链接格式不正确");
                }
                String isHaveItem = eeu.getCellValue(row.getCell(13));
                if (Check.isNull(isHaveItem)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，是否关联单品列缺失数据");
                }
                String itemName = eeu.getCellValue(row.getCell(14));
                if ("1".equals(isHaveItem) && Check.isNull(itemName)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，关联单品名称列缺失数据");
                }
                String usageLevel = eeu.getCellValue(row.getCell(15));
                if (Check.isNull(usageLevel)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，使用层级列缺失数据");
                }
                String isCycleTimes = eeu.getCellValue(row.getCell(16));
                if (Check.isNull(isCycleTimes)) {
                    return Result.error("解析数据失败，文档中第" + (i + 1) + "行，是否循环列缺失数据");
                }
                //调起链接
                String schemaUri = eeu.getCellValue(row.getCell(18));
                //第三方actionBar监测链接
                String actionbarClickUrl = eeu.getCellValue(row.getCell(19));
                JSONObject obj = new JSONObject();
                obj.put("productId", productId);
                obj.put("projectId", projectId);
                obj.put("usageRange", usageRange);
                obj.put("accountId", accountId);
                obj.put("userId", userId);
                obj.put("channelCode", channelCode);
                obj.put("channelName", channelName);
                obj.put("url", url);
                obj.put("packageName", packageName);
                obj.put("appName", appName);
                obj.put("appVersion", appVersion);
                obj.put("appPrivacyUrl", appPrivacyUrl);
                obj.put("clickTrackUrl", clickTrackUrl);
                obj.put("isHaveItem", isHaveItem);
                obj.put("itemName", itemName);
                obj.put("usageLevel", usageLevel.toLowerCase());
                obj.put("isCycle", isCycleTimes);
                obj.put("schemaUri", schemaUri);
                obj.put("actionbarClickUrl", actionbarClickUrl);
                obj.put("md5", md5);
                obj.put("imageToken", imageToken);
                obj.put("appIconUrl", imageUrl);
                obj.put("numberValue", 0);
                obj.put("createType", 2);
                list.add(obj);
            }
        }
        String msg = "";
        if (!list.isEmpty()) {
            for (int i = 0; i < list.size(); i++) {
                JSONObject jsonObject = list.get(i);
                Result<Object> result = customizedCreate(jsonObject, 2);
                if (result.getCode() != CommonConstant.SC_OK_200) {
                    msg += "第" + (i + 1) + "行（" + result.getMessage() + "），";
                }
            }
            if (!Check.isNull(msg)) {
                msg = "，其中" + msg.substring(0, msg.length() - 1) + "导入失败！";
            }
        }
        return Result.ok("文件导入完成" + msg);
    }


    private Result<Object> customizedCreate(JSONObject request, Integer createType) throws Exception {
        try {
            KuaishouChannelCreateStrategy strategy = JSONObject.parseObject(request.toJSONString(), KuaishouChannelCreateStrategy.class);
            if (!Check.isNull(strategy)) {
                QueryWrapper<UserAllocation> usqueryWrapper = new QueryWrapper<>();
                usqueryWrapper.eq("account_id", strategy.getAccountId());
                usqueryWrapper.eq("project_id", strategy.getProjectId());
                UserAllocation userAllocation = userAllocationService.getOne(usqueryWrapper);
                if (Check.isNull(userAllocation)) {
                    return Result.error("账户和项目不匹配");
                }
                JSONObject obj = projectMapper.getProduct(strategy.getAccountId(), strategy.getProjectId());
                if (!Check.isNull(obj)) {
                    strategy.setProjectId(obj.getLong("projectId"));
                    strategy.setProductId(obj.getLong("productId"));
                }
                strategy.setCreateType(createType);

                if (strategy.getNumberValue().contains("-")) {
                    String[] split = strategy.getNumberValue().split("-");
                    Integer numberMin = Integer.valueOf(split[0]);
                    Integer numberMax = Integer.valueOf(split[1]);
                    strategy.setNumberMin(numberMin);
                    strategy.setNumberMax(numberMax);
                }

                QueryWrapper<KuaishouChannelCreateStrategy> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("product_id", strategy.getProductId());
                if (!Check.isNull(strategy.getAccountId())) {
                    queryWrapper.eq("account_id", strategy.getAccountId());
                }
                queryWrapper.eq("project_id", strategy.getProjectId()).last("limit 1");
                //查询是否已经创建过策略，若已创建,则某些字段必须一致，比如是否循环、使用层级
                KuaishouChannelCreateStrategy one = channelCreateStrategyService.getOne(queryWrapper);
                if (!Check.isNull(one)) {
                    if (!one.getUsageLevel().equals(strategy.getUsageLevel())) {
                        return Result.error("创建失败，使用层级字段与原有策略不一致");
                    }
                    //验证渠道号命名唯一
                    if (!checkChannelCode(strategy)) {
                        return Result.error("创建失败，渠道号命名重复");
                    }
                }
                strategy.setStateDate(DateUtils.getDate(DateUtils.WEB_FORMAT));
                boolean save = channelCreateStrategyService.save(strategy);
                //项目名称
                strategy.setProjectName(projectMapper.getNameByProjectId(strategy.getProjectId()));
                //产品名
                Product product = productMapper.selectById(strategy.getProductId());
                if (!Check.isNull(product)) {
                    strategy.setProductName(product.getProductName());
                }
                //下载链接
                String appIconUrl = strategy.getAppIconUrl();
                if (!Check.isNull(appIconUrl) && !appIconUrl.contains("http")) {
                    strategy.setAppIconUrl("https:" + appIconUrl);
                }
                channelCreateStrategyService.save(strategy);
                return customizedCreate(strategy);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成渠道号异常");
        }
        return Result.ok("添加成功");
    }

    @Override
    public Result<Object> queryChannel(Long accountId, String level, String appName, String photoName) throws Exception {
        KuaishouChannel one = channelMapper.getChannelEntity(accountId);
        if (Check.isNull(one)) {
            return Result.error("未查询到渠道号");
        }
        //是否循环重复使用 0:否，1:是
        Integer isCycle = one.getIsCycle();
        if (isCycle == 0) {
            if ("account".equals(level)) {
                //账户层级   不可循环使用渠道号
                List<KuaishouChannel> list = channelMapper.getAccountLevelNoRepeatChannel(accountId, appName);
                KuaishouChannel channel = getValidChannel(list);
                if (!Check.isNull(channel)) {
                    return Result.ok(channel);
                }
            } else {
                //获取可用渠道号，筛查出一个返回给前端
                List<KuaishouChannel> list = channelMapper.queryNoAccountLevelNoRepeatChannel(level, accountId, appName);
                KuaishouChannel channel = getValidChannel(list);
                if (!Check.isNull(channel)) {
                    return Result.ok(channel);
                }
            }
        } else {
            //循环使用逻辑
            if ("account".equals(level)) {
                //账户层级可循环使用渠道号
                List<KuaishouChannel> list = channelMapper.getAccountLevelRepeatChannel(accountId,appName);
                KuaishouChannel channel = getValidChannel(list);
                if (!Check.isNull(channel)) {
                    return Result.ok(channel);
                }
            } else {
                //查询账户所有策略
                List<Long> strategyIds = channelCreateStrategyService.queryAllIdByAccountId(accountId);
                if (Check.isNull(strategyIds) || strategyIds.isEmpty()) {
                    return Result.error("渠道号获取失败，该账户没有创建过渠道号");
                }
                List<Integer> usageTimesTypes = channelMapper.queryUsedLevel(strategyIds);
                if (Check.isNull(usageTimesTypes)) {
                    return Result.error("渠道号已无效");
                }
                for (Integer usageTimes : usageTimesTypes) {
                    //获取可用渠道号，筛查出一个返回给前端
                    List<KuaishouChannel> list = channelMapper.queryChannelByUsageTimes(usageTimes, level, strategyIds, appName);
                    KuaishouChannel channel = getValidChannel(list);
                    if (!Check.isNull(channel)) {
                        return Result.ok(channel);
                    }
                }
            }
        }
        return Result.error("查询失败");
    }

    /**
     * 筛选渠道号，给渠道号添加单品
     */
    private KuaishouChannel getValidChannel(List<KuaishouChannel> list) {
        if (Check.isNull(list) || list.isEmpty()) {
            return null;
        }
        for (KuaishouChannel channel : list) {
            //1 关联单品，无单品则跳过
            if (channel.getIsHaveItem() == 1) {
                List<KuaishouChannelItems> items = channelItemsRelService.queryItems(channel.getId());
                if (Check.isNull(items) || items.isEmpty()) {
                    continue;
                }
                channel.setItems(items);
            }
            return channel;
        }
        return null;
    }

    @Override
    public Result<Object> queryChannelLevel(JSONObject data) {
        Long accountId = data.getLong("accountId");
        JSONArray appNameArray = data.getJSONArray("appNameArray");
        String appName = appNameArray.getString(0);
        KuaishouChannel channel = channelMapper.queryByAccountId(accountId, 1);
        JSONObject request = new JSONObject();
        if (!Check.isNull(channel)) {
            request.put("list", channelMapper.queryItemsListByAccountId(accountId, appName));
        } else {
            channel = channelMapper.queryByAccountId(accountId, null);
            if (Check.isNull(channel)) {
                return Result.error("该账户没有配置渠道号");
            }
        }
        request.put("channel", channel);
        return Result.ok(request);
    }

    @Override
    public void callBackUpdateChannelRel(String level, String channelCode, Long accountId, Long planId, Long groupId) {
        try {
            QueryWrapper<KuaishouChannel> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("account_id", accountId);
            queryWrapper.eq("channel_code", channelCode).last("limit 1");
            KuaishouChannel one = this.getOne(queryWrapper);
            if (!Check.isNull(one)) {
                one.setUpdateTime(new Date());
                QueryWrapper<KuaishouChannelRel> relqueryWrapper = new QueryWrapper<>();
                relqueryWrapper.eq("account_id", accountId);
                relqueryWrapper.eq("channel_code", channelCode).orderByAsc("create_time").last("limit 1");
                KuaishouChannelRel rel = channelRelService.getOne(relqueryWrapper);
                if (!Check.isNull(rel)) {
                    if (!Check.isNull(rel.getCampaignId())) {
                        rel.setId(null);
                    }
                    rel.setCampaignId(planId);
                    rel.setUnitId(groupId);
                    rel.setUpdateTime(new Date());
                    channelRelService.save(rel);
//                    if ("plan".equals(level)) {
//                        Integer usageTimes = channelRelService.queryUsePlanCount(accountId, channelCode);
//                        one.setUsageTimes(usageTimes);
//                        this.saveOrUpdate(one);
//                    } else if ("group".equals(level)) {
                    Integer usageTimes = channelRelService.queryUseGroupCount(accountId, channelCode);
                    one.setUsageTimes(usageTimes);
                    this.saveOrUpdate(one);
//                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("渠道号回调异常", e);
        }
    }

    @Override
    public KuaishouChannel queryUsedChannel(Long accountId, Long newCampaignId, String level) {
        KuaishouChannel channel = channelMapper.queryUsedChannel(accountId, newCampaignId, level);
        if (!Check.isNull(channel) && channel.getIsHaveItem() == 1) {
            List<KuaishouChannelItems> list = channelItemsRelService.queryItems(channel.getId());
            if (Check.isNull(list) || list.isEmpty()) {
                return null;
            }
            channel.setItems(list);
        }
        return channel;
    }

    @Override
    public Result<Object> queryChannelList(Long accountId, String appName) {
        List<JSONObject> kuaishouChannels = channelMapper.queryChannelList(accountId, appName);
        PageInfo pageInfo = new PageInfo(kuaishouChannels);
        return Result.ok(pageInfo);
    }

    @Override
    public Result<Object> updateChannels(KuaishouChannel channel) {
        try {
            Long accountId = channel.getAccountId();
            String schemaUri = channel.getSchemaUri();
            String clickTrackUrl = channel.getClickTrackUrl();
            String actionbarClickUrl = channel.getActionbarClickUrl();
            Integer isHaveItem = channel.getIsHaveItem();
            Integer isCycle = channel.getIsCycle();
            List<KuaishouChannel> list = new ArrayList<>();
            List<KuaishouChannel> oldList = channelMapper.queryChannelListByAccount(accountId);
            if (!Check.isNull(schemaUri) && schemaUri.contains(CHANNEL_STR)) {
                for (KuaishouChannel kuaishouChannel : oldList) {
                    kuaishouChannel.setSchemaUri(schemaUri.replace(CHANNEL_STR, kuaishouChannel.getChannelCode()));
                    list.add(kuaishouChannel);
                }
            }
            if (!Check.isNull(clickTrackUrl) && clickTrackUrl.contains(CHANNEL_STR)) {
                boolean flag = list.size() > 0;
                for (int i = 0; i < oldList.size(); i++) {
                    String channelCode = oldList.get(i).getChannelCode();
                    if (flag) {
                        list.get(i).setClickTrackUrl(clickTrackUrl.replace(CHANNEL_STR, channelCode));
                    } else {
                        KuaishouChannel kuaishouChannel = oldList.get(i);
                        kuaishouChannel.setClickTrackUrl(clickTrackUrl.replace(CHANNEL_STR, channelCode));
                        list.add(kuaishouChannel);
                    }
                }
            }
            if (!Check.isNull(actionbarClickUrl) && actionbarClickUrl.contains(CHANNEL_STR)) {
                boolean flag = list.size() > 0;
                for (int i = 0; i < oldList.size(); i++) {
                    String channelCode = oldList.get(i).getChannelCode();
                    if (flag) {
                        list.get(i).setActionbarClickUrl(actionbarClickUrl.replace(CHANNEL_STR, channelCode));
                    } else {
                        KuaishouChannel kuaishouChannel = oldList.get(i);
                        kuaishouChannel.setActionbarClickUrl(actionbarClickUrl.replace(CHANNEL_STR, channelCode));
                        list.add(kuaishouChannel);
                    }
                }
            }
            if (list.size() > 0) {
                for (KuaishouChannel kuaishouChannel : list) {
                    if (!Check.isNull(isHaveItem)) {
                        kuaishouChannel.setIsHaveItem(isHaveItem);
                    }
                    if (!Check.isNull(isCycle)) {
                        kuaishouChannel.setIsCycle(isCycle);
                    }
                    if (!Check.isNull(schemaUri) && !schemaUri.contains(CHANNEL_STR)) {
                        kuaishouChannel.setSchemaUri(schemaUri);
                    }
                    if (!Check.isNull(clickTrackUrl) && !clickTrackUrl.contains(CHANNEL_STR)) {
                        kuaishouChannel.setClickTrackUrl(clickTrackUrl);
                    }
                    if (!Check.isNull(actionbarClickUrl) && !actionbarClickUrl.contains(CHANNEL_STR)) {
                        kuaishouChannel.setActionbarClickUrl(actionbarClickUrl);
                    }
                    this.updateById(kuaishouChannel);
                }
            } else {
                QueryWrapper<KuaishouChannel> wrapper = new QueryWrapper<>();
                wrapper.eq("account_id", accountId);
                wrapper.eq("state", 1);
                wrapper.eq("channel_state", 1);
                KuaishouChannel channelEntity = new KuaishouChannel();
                if (!Check.isNull(schemaUri)) {
                    channelEntity.setSchemaUri(schemaUri);
                }
                if (!Check.isNull(clickTrackUrl)) {
                    channelEntity.setClickTrackUrl(clickTrackUrl);
                }
                if (!Check.isNull(actionbarClickUrl)) {
                    channelEntity.setActionbarClickUrl(actionbarClickUrl);
                }
                if (!Check.isNull(isCycle)) {
                    channelEntity.setIsCycle(isCycle);
                }
                if (!Check.isNull(isHaveItem)) {
                    channelEntity.setIsHaveItem(isHaveItem);
                }
                channelMapper.update(channelEntity, wrapper);
            }
            //添加修改记录
            KuaishouChannelUpdateRecord record = new KuaishouChannelUpdateRecord();
            BeanUtils.copyProperties(channel, record);
            record.setOperationTime(DateUtils.getDate(DateUtils.WEB_FORMAT));
            channelUpdateRecordService.save(record);
            return Result.ok("修改成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("修改渠道号异常");
        }
    }

    private Result<Object> getRealAccountChannel(Long accountId, List<KuaishouChannelCreateStrategy> strategys, String appName) throws Exception {
        List<KuaishouChannel> channelList = channelMapper.queryByAccountIdLevel(accountId, "account");
        if (!Check.isNull(channelList)) {
            for (KuaishouChannel channel : channelList) {
                if (channel.getIsHaveItem() == 1) {
                    List<KuaishouChannelItems> list = channelItemsRelService.queryItems(channel.getId());
                    if (Check.isNull(list) || list.isEmpty()) {
                        continue;
                    }
                    channel.setItems(list);
                }
                KuaishouChannelRel channelRel = channelRelService.queryByAccountChannelCode(channel.getChannelCode(), accountId, appName);
                if (Check.isNull(channelRel)) {
                    continue;
                }
                if (Check.isNull(channelRel.getAppId())) {
                    createNewApp(channel, accountId, 1);
                    if (Check.isNull(channel.getAppId())) {
                        continue;
                    } else {
                        channelRel.setAppId(channel.getAppId());
                        channelRelService.saveOrUpdate(channelRel);
                        return Result.ok(channel);
                    }
                } else {
                    channel.setAppId(channelRel.getAppId());
                    return Result.ok(channel);
                }
            }
        }
        return Result.error("未查询到渠道号");
    }

    private void createNewApp(KuaishouChannel channel, Long accountId, int count) throws Exception {
        CtopOauthToken token = tokenService.getTokenByAccountId(accountId);
        String accessToken = null;
        if (!Check.isNull(token)) {
            accessToken = token.getAccessToken();
        }
        if (Check.isNull(channel.getChannelAppInfoId())) {
            return;
        }
        KuaishouChannelAppInfo one = channelAppInfoService.getById(channel.getChannelAppInfoId());
        String appIconUrl = one.getAppIconUrl();
        if (!Check.isNull(appIconUrl) && !appIconUrl.contains("http")) {
            one.setAppIconUrl("https:" + appIconUrl);
        }
        JSONObject tokenJson = appInfoService.uploadAppIconImage(one.getAppIconUrl(), token.getAccountId(), token.getAccessToken());
        if (!Check.isNull(tokenJson) && tokenJson.getInteger("code") != 0) {
            log.error("通过账户ID（" + token.getAccountId() + "）获取图片Token失败，返回信息：" + tokenJson.getString("message"));
        }
        String imageToken = tokenJson.getString("imageToken");
        JSONObject requestJson = new JSONObject();
        requestJson.put("advertiser_id", accountId);
        requestJson.put("app_version", one.getAppVersion());
        requestJson.put("app_name", one.getAppName());
        requestJson.put("image_token", imageToken);
        requestJson.put("package_name", one.getPackageName());
        requestJson.put("platform", 1);//Android应用下载
        requestJson.put("url", one.getUrl());
        requestJson.put("use_sdk", 0);
        requestJson.put("app_privacy_url", one.getAppPrivacyUrl());
        String url = PropertiesUtils.getConfig("kuaishou_api_url") + KuaishouInterfaceConstant.APP_CREATE;
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "multipart/form-data");
        headerMap.put("Access-Token", accessToken);
        String request = materialUploadService.exceptInfoForRestTemplate(url, requestJson, headerMap);
        JSONObject resultJson = JSONObject.parseObject(request);
        if (!Check.isNull(resultJson)) {
            Integer code = resultJson.getInteger("code");
            if (code == 0) {
                JSONObject data = resultJson.getJSONObject("data");
                Long appId = data.getLong("app_id");
                one.setState(1);//成功
                one.setRemark("创建" + count + "次，succsee");
                one.setAppId(appId);
                channelAppInfoService.saveOrUpdate(one);
                channel.setAppId(appId);
            } else {
                String message = resultJson.getString("message");
                one.setRemark("创建" + count + "次，" + message);
                channelAppInfoService.saveOrUpdate(one);
                if (message.contains("token")) {
                    //token失效直接跳过
                    return;
                }
                if (count == 3) {
                    //渠道号关联的应用创建3次未成功，该渠道号状态置为无效
                    channel.setState(0);
                    this.saveOrUpdate(channel);
                }
            }
        }
        if (Check.isNull(one.getAppId()) && count < 4) {
            createNewApp(channel, accountId, count + 1);
        }
    }
}
