package com.xxl.job.executor.report.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xxl.job.executor.common.entity.CtopOauthToken;
import com.xxl.job.executor.material.entity.ByteDanceAdvertisePlan;
import com.xxl.job.executor.material.entity.ByteDanceCampaign;
import com.xxl.job.executor.material.entity.ByteDanceCreative;
import com.xxl.job.executor.material.service.IByteDanceAdvertisePlanService;
import com.xxl.job.executor.material.service.IByteDanceCampaignService;
import com.xxl.job.executor.material.service.IByteDanceCreativeService;
import com.xxl.job.executor.report.entity.ByteDanceOperationRecord;
import com.xxl.job.executor.report.entity.BytedanceReportPlayableDaily;
import com.xxl.job.executor.report.entity.BytedanceReportPlayableRetry;
import com.xxl.job.executor.report.mapper.BytedanceOperationRecordMapper;
import com.xxl.job.executor.report.mapper.BytedanceReportPlayableDailyMapper;
import com.xxl.job.executor.report.service.IBytedanceInterfaceService;
import com.xxl.job.executor.utils.Check;
import com.xxl.job.executor.utils.DateUtils;
import com.xxl.job.executor.utils.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

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

@Service
@Slf4j
@Primary
public class BytedanceInterfaceServiceImpl implements IBytedanceInterfaceService {
    @Autowired
    private IByteDanceCampaignService byteDanceCampaignService;
    @Autowired
    private IByteDanceAdvertisePlanService byteDanceAdvertisePlanService;
    @Autowired
    private BytedanceOperationRecordMapper bytedanceOperationRecordMapper;
    @Autowired
    private IByteDanceCreativeService byteDanceCreativeService;
    @Autowired
    private BytedanceReportPlayableDailyMapper bytedanceReportPlayableDailyMapper;

    @Override
    public void searchLog(Long accountId, CtopOauthToken token, Integer operationTarget, String startDate, String endDate){
        int pageNum = 1;
        int pageSize = 20;
        String startTime = startDate + " 00:00:00";
        String endTime = endDate + " 23:59:59";

        try {
            if(operationTarget == 2){
                QueryWrapper<ByteDanceCampaign> parameterQueryWrapper = new QueryWrapper<>();
                parameterQueryWrapper.eq("account_id", accountId);
                parameterQueryWrapper.select("id");
                List<ByteDanceCampaign> list = byteDanceCampaignService.list(parameterQueryWrapper);
                for (ByteDanceCampaign campaign:list){
                    int code = logSearchByPage(pageNum, pageSize, token, accountId, campaign.getId(), 2, startTime, endTime);  //组
                }
            }else if(operationTarget == 3){
                QueryWrapper<ByteDanceAdvertisePlan> parameterQueryWrapper = new QueryWrapper<>();
                parameterQueryWrapper.eq("account_id", accountId);
                parameterQueryWrapper.select("id");
                List<ByteDanceAdvertisePlan> list = byteDanceAdvertisePlanService.list(parameterQueryWrapper);
                for (ByteDanceAdvertisePlan plan:list){
                    int code = logSearchByPage(pageNum, pageSize, token, accountId, plan.getId(), 3, startTime, endTime);  //计划
                }
            }else if(operationTarget == 4){
                QueryWrapper<ByteDanceCreative> parameterQueryWrapper = new QueryWrapper<>();
                parameterQueryWrapper.eq("account_id", accountId);
                parameterQueryWrapper.select("id");
                List<ByteDanceCreative> list = byteDanceCreativeService.list(parameterQueryWrapper);
                for(ByteDanceCreative creative:list){
                    int code = logSearchByPage(pageNum, pageSize, token, accountId, creative.getId(), 4, startTime, endTime);  //创意
                }
            }
        }catch (Exception e){
            log.error("获取头条操作记录失败:accountId:{},startDate:{},endDate:{}", token.getAccountId(), startDate, endDate);
            log.error(e.getMessage());
        }
    }

    private int logSearchByPage(Integer pageNum, Integer pageSize, CtopOauthToken token, Long accountId, Long objectId, Integer operationType, String startTime, String endTime) {
        log.info("当前页数：" + pageNum);
        String access_token = token.getAccessToken();

        // 请求地址
        String open_api_domain = "https://ad.oceanengine.com";
        String path = "/open_api/2/tools/log_search/";

        // 请求参数
        Map data = new HashMap();
        data.put("advertiser_id", accountId);
        data.put("start_time", startTime);
        data.put("end_time", endTime);
        data.put("page", pageNum);
        data.put("page_size", pageSize);

        List<Long> list = new ArrayList<>();
        list.add(objectId);
        data.put("object_id", list);

        JSONObject json = HttpUtils.bytedanceGetRequest(access_token, open_api_domain + path, JSONObject.parseObject(JSONObject.toJSONString(data)));
        if (json == null) {
            log.error("头条日志查询返回为空，请求有误:" + JSONObject.toJSONString(data) + ";;;返回值为："+ json);
            return -2;
        }

        Integer returnCode = 200;
        try {
            int code = json.getInteger("code");
            if (code == 0) {
                List<ByteDanceOperationRecord> records = new ArrayList<>();
                JSONObject dataResultJson = json.getJSONObject("data");
                JSONArray logsArray = dataResultJson.getJSONArray("logs");
                JSONObject pageInfoJson = dataResultJson.getJSONObject("page_info");

                if (Check.isNull(logsArray) || Check.isNull(pageInfoJson)) {
                    log.error("获取任务列表返回信息data内容为空,头条accountId:" + accountId + ";返回json为：" + json + "请求为：" + JSONObject.toJSONString(data));
                    return -1;
                }

                int totalPage = pageInfoJson.getInteger("total_number");
                int page = pageInfoJson.getInteger("page");

                if (totalPage == 0) {
                    log.info("头条日志查询返回页数为0，请求:" + JSONObject.toJSONString(data) + ";;;返回值为："+ json);
                    return 1;
                }

                int logsSize = logsArray.size();
                for (int i = 0; i < logsSize; i++) {
                    JSONObject logJson = logsArray.getJSONObject(i);
                    ByteDanceOperationRecord record = new ByteDanceOperationRecord();
                    record.setAccountId(accountId);
                    record.setContentTitle(logJson.getString("content_title"));
                    record.setContentLog(logJson.getString("content_log"));
                    record.setObjectId(logJson.getLong("object_id"));
                    record.setObjectName(logJson.getString("object_name"));
                    record.setObjectType(logJson.getString("object_type"));
                    record.setOperationCreateTime(logJson.getDate("create_time"));
                    record.setStatDate(DateUtils.formatDate(logJson.getDate("create_time")));
                    record.setOperator(logJson.getString("operator"));
                    record.setOptIp(logJson.getString("opt_ip"));
                    record.setOperationTarget(operationType);

                    records.add(record);
                }

                //按类型入库
                if (records != null && records.size() != 0) {
                    insertLog(operationType, records);
                }

                if (page < totalPage) {
                    logSearchByPage(page + 1, pageSize, token, accountId, objectId, operationType, startTime, endTime);
                }else{
                    return 1;
                }
            } else {
                log.error("头条日志查询返回为空，请求有误:" + JSONObject.toJSONString(data) + ";;;返回值为：" + json);
                return -1;
            }
        }catch(Exception e){
            e.printStackTrace();
            log.error("头条视频素材报表其他错误，accountId:" + accountId + "，json：" + json + "请求为：" + JSONObject.toJSONString(data));
            returnCode = -3;
        }
        return returnCode;
    }

    private void insertLog(Integer operationTarget, List<ByteDanceOperationRecord> records){
        if(operationTarget == 2){
            bytedanceOperationRecordMapper.insertOperationRecordCampaign(records);
        }else if(operationTarget == 3){
            bytedanceOperationRecordMapper.insertOperationRecordPlan(records);
        }else if(operationTarget == 4){
            bytedanceOperationRecordMapper.insertOperationRecordCreative(records);
        }
    }

    //////////////////////////////////////////////////

    @Override
    public List<BytedanceReportPlayableRetry> getRetryList() {
        return bytedanceReportPlayableDailyMapper.getRetryList();
    }

    @Override
    public int bytedancePlayableReportRetry(Integer type, CtopOauthToken token, String startDate, String endDate) {
        Long accountId = token.getAccountId();
        log.info("头条试玩报表重试开始 当前accountId：{}  {}~{},type:{}" , accountId, startDate,endDate,type);
        Integer page = 1;
        Integer pageSize = 100;
        Integer code = null;
        code = bytedancePlayableReportByPage(page, pageSize, token, accountId, startDate, endDate);


        BytedanceReportPlayableRetry retry = new BytedanceReportPlayableRetry();
        retry.setAccountId(accountId);
        retry.setStartDate(startDate);
        retry.setEndDate(endDate);
        retry.setStatusCode(code);
        retry.setType(type);
        if (code != 200 && code != 1) {
            retry.setStatus(0);
            bytedanceReportPlayableDailyMapper.replaceMaterialRetry(retry);
        } else {
            retry.setStatus(1);
            bytedanceReportPlayableDailyMapper.replaceMaterialRetry(retry);
        }
        log.info("头条试玩报表重试结束 当前accountId：{}  {}~{},type:{},code:{}" , accountId, startDate,endDate,type,code);
        return code;
    }



    /**
     * 头条视频素材报表
     * @param token
     * @param startDate
     * @param endDate
     * @return
     */
    @Override
    public int bytedancePlayableReport(CtopOauthToken token, String startDate, String endDate) {
        Long accountId = token.getAccountId();
        log.info("头条试玩报表当前accountId为：{}  {}~{},开始" , accountId, startDate,endDate);
        Integer page = 1;
        Integer pageSize = 100;
        int code = bytedancePlayableReportByPage(page, pageSize, token, accountId, startDate, endDate);
        if (code != 200 && code != 1) {
            BytedanceReportPlayableRetry retry = new BytedanceReportPlayableRetry();
            retry.setAccountId(accountId);
            retry.setStatus(0);
            retry.setStartDate(startDate);
            retry.setEndDate(endDate);
            retry.setStatusCode(code);
            retry.setType(1);  //1试玩报表
            bytedanceReportPlayableDailyMapper.replaceMaterialRetry(retry);
        }
        log.info("头条试玩报表当前accountId为：{}  {}~{}，结束" , accountId, startDate,endDate);
        return code;
    }

    private int bytedancePlayableReportByPage(Integer page, Integer pageSize, CtopOauthToken token, Long accountId, String startDate, String endDate) {
        log.info("当前页数："+ page);
        String access_token = token.getAccessToken();

        // 请求地址
        String open_api_domain = "https://ad.oceanengine.com";
        String path = "/open_api/2/report/integrated/get/";

        // 请求参数
        Map data = new HashMap();
        data.put("advertiser_id", accountId);
        data.put("start_date", startDate);
        data.put("end_date", endDate);
        data.put("page", page);
        data.put("page_size", pageSize);
        data.put("group_by", new String[]{"STAT_GROUP_BY_PLAYABLE_ID", "STAT_GROUP_BY_TIME_DAY"});  //, "STAT_GROUP_BY_TIME_DAY"

        JSONObject json = HttpUtils.bytedanceGetRequest(access_token, open_api_domain + path, JSONObject.parseObject(JSONObject.toJSONString(data)));
        if (json == null) {
            log.error("返回为空，请求有误:" + JSONObject.toJSONString(data));
            return -2;
        }

        int returnCode = 200;
        try {
            if (!Check.isNull(json)) {
                Integer code = json.getInteger("code");
                if (code != 0) {
                    log.error("获取任务列表返回信息错误，错误码为：" + code + ",头条accountId:" + accountId + ";返回json为：" + json + "请求为：" + JSONObject.toJSONString(data));
                    return -1;
                }

                JSONObject jsonData = json.getJSONObject("data");
                if (Check.isNull(jsonData)) {
                    log.error("获取任务列表返回信息data内容为空,头条accountId:" + accountId + ";返回json为：" + json + "请求为：" + JSONObject.toJSONString(data));
                    return -1;
                }
                JSONObject pageInfo = jsonData.getJSONObject("page_info");
                Integer totalPage = pageInfo.getInteger("total_page");
                Integer currentPage = pageInfo.getInteger("page");

                JSONArray jsonArrayay = jsonData.getJSONArray("list");
                if (jsonArrayay.size() == 0) {
                    log.info("accountId:" + accountId + "；没有数据。总页数为：" + totalPage + "当前页数为：" + currentPage);
                    return 1;
                }

                List<BytedanceReportPlayableDaily> bytedanceReportPlayableDailyList = new ArrayList<>();
                for (int i = 0; i < jsonArrayay.size(); i++) {
                    JSONObject detailJson = jsonArrayay.getJSONObject(i);
                    if (!Check.isNull(detailJson)) {
                        BytedanceReportPlayableDaily daily = new BytedanceReportPlayableDaily(detailJson, accountId);
                        bytedanceReportPlayableDailyList.add(daily);
                    }
                }
                bytedanceReportPlayableDailyMapper.replaceIntoBatch(bytedanceReportPlayableDailyList);
                if (currentPage >= totalPage) {
                    log.info("头条视频素材报表当前accountId为：{}  {}~{}，接口数据拉取成功" , accountId, startDate,endDate);
                    return 1;
                } else {
                    return bytedancePlayableReportByPage(page + 1, pageSize, token, accountId, startDate, endDate);
                }
            } else {
                log.error("头条视频素材报表服务器返回为空，accountId:" + accountId + "，json：" + json + "请求为：" + JSONObject.toJSONString(data));
                return -1;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("头条视频素材报表其他错误，accountId:" + accountId + "，json：" + json + "请求为：" + JSONObject.toJSONString(data));
            returnCode = -3;
        }
        return returnCode;
    }
}
