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

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.xxl.job.executor.common.entity.CtopOauthToken;
import com.xxl.job.executor.material.entity.ByteDanceAdvertisePlan;
import com.xxl.job.executor.material.mapper.ByteDanceAdvertisePlanMapper;
import com.xxl.job.executor.material.service.IByteDanceAdvertisePlanService;
import com.xxl.job.executor.utils.HttpUtils;
import com.xxl.job.executor.utils.PropertiesUtils;
import com.xxl.job.executor.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Slf4j
@Service
public class ByteDanceAdvertisePlanServiceImpl extends ServiceImpl<ByteDanceAdvertisePlanMapper, ByteDanceAdvertisePlan> implements IByteDanceAdvertisePlanService {
    @Autowired
    private ByteDanceAdvertisePlanMapper byteDanceAdvertisePlanMapper;
    @Override
    public Map<String, Object> getAdvertiserPlan(CtopOauthToken token, String ids, String date, String updateDate) {
        getAd(token, 1, ids, date, updateDate);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("code", 0);
        resultMap.put("message", "获取广告计划信息成功");
        return resultMap;
    }

    @Override
    public Map<String, Object> createAdvertiserPlan(CtopOauthToken token, String landingType, ByteDanceAdvertisePlan byteDanceAdvertisePlan) {

        Map<String, Object> resultMap = new HashMap<>();
        //拼接访问参数
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("Access-Token", token.getAccessToken());

        JSONObject params = new JSONObject();
        params.put("advertiser_id", byteDanceAdvertisePlan.getAccountId());
        params.put("campaign_id", byteDanceAdvertisePlan.getCampaignId());
        params.put("name", byteDanceAdvertisePlan.getName());
        params.put("operation", byteDanceAdvertisePlan.getOperation() == null ? "enable" : byteDanceAdvertisePlan.getOperation());
        params.put("delivery_range", byteDanceAdvertisePlan.getDeliveryRange() == null ? "DEFAULT" : byteDanceAdvertisePlan.getDeliveryRange());
        params.put("union_video_type", byteDanceAdvertisePlan.getUnionVideoType() == null ? "ORIGINAL_VIDEO" : byteDanceAdvertisePlan.getUnionVideoType());
        params.put("budget_mode", byteDanceAdvertisePlan.getBudgetMode());
        params.put("budget", byteDanceAdvertisePlan.getBudget());
        params.put("schedule_type", byteDanceAdvertisePlan.getScheduleType());
        params.put("start_time", byteDanceAdvertisePlan.getStartTime());
        params.put("end_time", byteDanceAdvertisePlan.getEndTime());
        //广告投放时段
        if(!"".equals(byteDanceAdvertisePlan.getScheduleTime())){
            params.put("schedule_time",byteDanceAdvertisePlan.getScheduleTime());
        }
        params.put("pricing", byteDanceAdvertisePlan.getPricing());
        params.put("bid", byteDanceAdvertisePlan.getBid());
        params.put("cpa_bid", byteDanceAdvertisePlan.getCpaBid());
        params.put("flow_control_mode", byteDanceAdvertisePlan.getFlowControlMode());
        if ("PRICING_OCPM".equals(byteDanceAdvertisePlan.getPricing())) {
            if(byteDanceAdvertisePlan.getConvertId()!=null){
                //查询必填参数convert_id
                params.put("convert_id", byteDanceAdvertisePlan.getConvertId());
            }else{
                int convertId=getConvertIdByExternalAction(byteDanceAdvertisePlan.getExternalAction());
                params.put("convert_id",convertId);
                byteDanceAdvertisePlan.setConvertId((long) convertId);
            }
        }
        params.put("deep_bid_type", byteDanceAdvertisePlan.getDeepBidType());
        params.put("deep_cpabid", byteDanceAdvertisePlan.getDeepCpaBid());
        params.put("hide_if_converted", byteDanceAdvertisePlan.getHideIfConverted());
        params.put("hide_if_exists", byteDanceAdvertisePlan.getHideIfExists() == null ? 0 : byteDanceAdvertisePlan.getHideIfExists());
        params.put("converted_time_duration", byteDanceAdvertisePlan.getConvertedTimeDuration());
        params.put("luban_roi_goal",byteDanceAdvertisePlan.getLubanRoiGoal());
        params.put("roi_goal",byteDanceAdvertisePlan.getRoiGoal());
        //params.put("unique_fk",byteDanceAdvertisePlan.getUniqueFk")==null?"":byteDanceAdvertisePlan.getString("uniqueFk"));
        //params.put("smart_bid_type",byteDanceAdvertisePlan.getSmartBidType")==null?"":byteDanceAdvertisePlan.getString("smartBidType"));
        params.put("adjust_cpa", 0);
        //暂时不需要定向包id
        //params.put("audience_package_id",byteDanceAdvertisePlan.getLong("audiencePackageId"));
        if("YES".equals(byteDanceAdvertisePlan.getUseOpenUrl())){
            params.put("open_url", byteDanceAdvertisePlan.getOpenUrl());
        }
        //判断推广目的
        if ("LINK".equals(landingType)) {
            params.put("external_url", byteDanceAdvertisePlan.getExternalUrl());
        }
        if ("APP".equals(landingType)) {
            params.put("download_type", byteDanceAdvertisePlan.getDownloadType());
            params.put("download_url", byteDanceAdvertisePlan.getDownloadUrl());
            params.put("package", byteDanceAdvertisePlan.getToutiaoPackage());
            params.put("app_type",byteDanceAdvertisePlan.getAppType());
        }

        //公共参数--受众相关
        params.put("retargeting_tags_include", byteDanceAdvertisePlan.getRetargetingTags());
        params.put("retargeting_tags_exclude", byteDanceAdvertisePlan.getRetargetingTagsExclude());
        params.put("gender", byteDanceAdvertisePlan.getGender());
        params.put("age", byteDanceAdvertisePlan.getAge());
        params.put("carrier", byteDanceAdvertisePlan.getCarrier());
        params.put("ac", byteDanceAdvertisePlan.getAc());
        params.put("device_brand", byteDanceAdvertisePlan.getDeviceBrand());
        params.put("article_category", byteDanceAdvertisePlan.getArticleCategory());
        params.put("activate_type", byteDanceAdvertisePlan.getActivateType());
        params.put("city", byteDanceAdvertisePlan.getCity());
        params.put("business_ids", byteDanceAdvertisePlan.getBusinessIds());
        params.put("location_type", byteDanceAdvertisePlan.getLocationType());
        params.put("superior_popularity_type", byteDanceAdvertisePlan.getSuperiorPopularityType());
        params.put("flow_package", byteDanceAdvertisePlan.getFlowPackage());
        params.put("exclude_flow_package", byteDanceAdvertisePlan.getExcludeFlowPackage());
        params.put("device_type", byteDanceAdvertisePlan.getDeviceType());
        params.put("auto_extend_enabled", byteDanceAdvertisePlan.getAutoExtendEnabled());
        params.put("launch_price", byteDanceAdvertisePlan.getLaunchPrice());
        params.put("interest_action_mode", byteDanceAdvertisePlan.getInterestActionMode());
        params.put("action_scene", byteDanceAdvertisePlan.getActionScene());
        params.put("action_days", byteDanceAdvertisePlan.getActionDays());
        params.put("action_categories", byteDanceAdvertisePlan.getActionCategories());
        params.put("action_words", byteDanceAdvertisePlan.getActionWords());
        params.put("interest_categories", byteDanceAdvertisePlan.getInterestWords());
        params.put("interest_words", byteDanceAdvertisePlan.getGeolocation());

        JSONObject jsonObject = JSONObject.parseObject(HttpUtils.httpPostRequest(PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_ad_create"), params, headers));
        if (jsonObject.getInteger("code") == 0) {
            resultMap.put("code", 0);
            byteDanceAdvertisePlan.setId(jsonObject.getJSONObject("data").getLong("ad_id"));
            resultMap.put("data",byteDanceAdvertisePlan);
        } else {
            log.error("广告计划创建失败==》accountId:{},message:{}", token.getAccountId(), jsonObject.getString("message"));
            resultMap.put("code",-200);
            resultMap.put("message", jsonObject.getString("message"));
        }
        return resultMap;
    }

    @Override
    public Map<String, Object> updateAdvertiserPlan(CtopOauthToken token, String landingType, ByteDanceAdvertisePlan byteDanceAdvertisePlan) {

        Map<String, Object> resultMap = new HashMap<>();

        //查询记录，获取修改时间等字段
        List adId=new ArrayList();
        adId.add(byteDanceAdvertisePlan.getId());
        Map<String, Object> map = queryAdByAdId(token, Long.valueOf(byteDanceAdvertisePlan.getAccountId()), adId);
        if(!map.get("code").equals(0)){
            log.error("获取修改时间接口错误");
        }else {
            Object modifyTime = ((Map) ((JSONObject) map.get("data")).getJSONArray("list").get(0)).get("modify_time");
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type", "application/json");
            headers.put("Access-Token", token.getAccessToken());

            JSONObject params = new JSONObject();
            params.put("advertiser_id", byteDanceAdvertisePlan.getAccountId());
            params.put("ad_id", byteDanceAdvertisePlan.getId());
            params.put("name", byteDanceAdvertisePlan.getName());
            params.put("modify_time", modifyTime);
            params.put("budget", byteDanceAdvertisePlan.getBudget());
            params.put("schedule_type", byteDanceAdvertisePlan.getScheduleType());
            params.put("start_time", byteDanceAdvertisePlan.getStartTime());
            params.put("end_time", byteDanceAdvertisePlan.getEndTime());
            //广告投放时段
            if(!"".equals(byteDanceAdvertisePlan.getScheduleTime())){
                params.put("schedule_time",byteDanceAdvertisePlan.getScheduleTime());
            }
            params.put("bid", byteDanceAdvertisePlan.getBid());
            params.put("cpa_bid", byteDanceAdvertisePlan.getCpaBid());
            params.put("flow_control_mode", byteDanceAdvertisePlan.getFlowControlMode());
            params.put("convert_id", byteDanceAdvertisePlan.getConvertId());
            params.put("deep_bid_type", byteDanceAdvertisePlan.getDeepBidType());
            params.put("deep_cpabid", byteDanceAdvertisePlan.getDeepCpaBid());
            params.put("hide_if_converted", byteDanceAdvertisePlan.getHideIfConverted());
            params.put("hide_if_exists", byteDanceAdvertisePlan.getHideIfExists() == null ? 0 : byteDanceAdvertisePlan.getHideIfExists());
            //params.put("converted_time_duration", byteDanceAdvertisePlan.getConvertedTimeDuration());
            //params.put("luban_roi_goal",byteDanceAdvertisePlan.getLubanRoiGoal()==null?0.00:byteDanceAdvertisePlan.getFloat("lubanRoiGoal"));
            //params.put("roi_goal",byteDanceAdvertisePlan.getFroiGoal")==null?0.00:byteDanceAdvertisePlan.getFloat("roiGoal"));
            //params.put("audience_package_id",byteDanceAdvertisePlan.getLong("audiencePackageId"));
            params.put("adjust_cpa", 0);
            //暂时不需要定向包id
            //params.put("audience_package_id",byteDanceAdvertisePlan.getLong("audiencePackageId"));
        /*if(byteDanceAdvertisePlan.getUseOpenUrl().equals("YES")){
            params.put("open_url", byteDanceAdvertisePlan.getOpenUrl());
        }*/
            //判断推广目的
        /*if (landingType.equals("LINK")) {
            params.put("external_url", byteDanceAdvertisePlan.getExternalUrl());
        }
        if (landingType.equals("APP")) {
            params.put("download_type", byteDanceAdvertisePlan.getDownloadType());
            params.put("download_url", byteDanceAdvertisePlan.getDownloadUrl());
            params.put("package", byteDanceAdvertisePlan.getToutiaoPackage());
            params.put("app_type",byteDanceAdvertisePlan.getAppType());
        }*/
            JSONObject jsonObject = JSONObject.parseObject(HttpUtils.httpPostRequest(PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_ad_update"), params, headers));
            if (jsonObject.getInteger("code") != 0) {
                log.error("广告计划修改失败==》accountId:{},message:{}", token.getAccountId(), jsonObject.getString("message"));
                resultMap.put("code", -1);
                resultMap.put("message", jsonObject.getString("message"));
                return resultMap;
            }
            resultMap.put("code", 0);
            resultMap.put("message", "广告组状态修改成功");
        }

        return resultMap;
    }

    @Override
    public Map<String, Object> updateAdvertiserPlanStatus(CtopOauthToken token, JSONArray adIds, String optStatus) {

        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("Access-Token", token.getAccessToken());
        switch (optStatus) {
            case "AD_STATUS_DISABLE":
                optStatus = "disable";
                break;
            case "AD_STATUS_ENABLE":
                optStatus = "enable";
                break;
            case "AD_STATUS_DELETE":
                optStatus = "delete";
                break;
        }
        JSONObject params = new JSONObject();
        params.put("advertiser_id", token.getAccountId());
        params.put("ad_ids", adIds.toJSONString());
        params.put("opt_status", optStatus);
        String result = HttpUtils.httpPostRequest(PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_ad_update_status"), params, headers);
        JSONObject jsonObject = JSONObject.parseObject(result);
        int code = jsonObject.getInteger("code");
        Map<String, Object> resultMap = new HashMap<>();
        if (code != 0) {
            log.error("广告计划更新状态接口异常==》accountId:{},message:{}", token.getAccountId(), jsonObject.getString("message"));
            resultMap.put("code", -1);
            resultMap.put("message", jsonObject.getString("message"));
            return resultMap;
        }
        resultMap.put("code", 0);
        resultMap.put("message", "广告组状态修改成功");
        return resultMap;
    }

    @Override
    public Map<String, Object> updateAdvertiserPlanBudget(CtopOauthToken token, JSONArray adIds, JSONArray budgets) {
        JSONArray data = new JSONArray();
        if (adIds.size() > 0) {
            for (int i = 0; i < adIds.size(); i++) {
                JSONObject object = new JSONObject();
                Long adId = Long.valueOf(adIds.get(i).toString());
                Long budget = Long.valueOf(budgets.get(i).toString());
                object.put("ad_id", adId);
                object.put("budget", budget);
                data.add(object);
            }
        }
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("Access-Token", token.getAccessToken());

        JSONObject params = new JSONObject();
        params.put("advertiser_id", token.getAccountId());
        params.put("data", data.toJSONString());
        String result = HttpUtils.httpPostRequest(PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_ad_update_budget"), params, headers);
        JSONObject jsonObject = JSONObject.parseObject(result);
        Map<String, Object> resultMap = new HashMap<>();
        int code = jsonObject.getInteger("code");
        if (code!=0) {
            log.info("修改计划预算接口异常==》accountId:{},message:{}", token.getAccountId(), jsonObject.getString("message"));
            resultMap.put("code", -1);
            resultMap.put("message", jsonObject.getString("message"));
            return resultMap;
        }
        resultMap.put("code", 0);
        resultMap.put("message", "修改计划预算成功");
        return resultMap;
    }

    @Override
    public Map<String, Object> updateAdvertiserPlanBid(CtopOauthToken token, JSONArray adIds, JSONArray bids) {
        JSONArray data = new JSONArray();
        if (adIds.size() > 0) {
            for (int i = 0; i < adIds.size(); i++) {
                JSONObject object = new JSONObject();
                Long adId = Long.valueOf(adIds.get(i).toString());
                Long bid = Long.valueOf(bids.get(i).toString());
                object.put("ad_id", adId);
                object.put("bid", bid);
                data.add(object);
            }
        }
        //2: 根据token以及用户id获取用户信息数据
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("Access-Token", token.getAccessToken());

        JSONObject params = new JSONObject();
        params.put("advertiser_id", token.getAccountId());
        params.put("data", data.toJSONString());
        JSONObject jsonObject = JSONObject.parseObject(HttpUtils.httpPostRequest(PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_ad_update_bid"), params, headers));
        int code = jsonObject.getInteger("code");
        Map<String, Object> resultMap = new HashMap<>();
        if (code != 0) {
            log.info("修改计划出价接口异常==》accountId:{},message:{}", token.getAccountId(), jsonObject.getString("message"));
            resultMap.put("code", -1);
            resultMap.put("message", jsonObject.getString("message"));
            return resultMap;
        }
        resultMap.put("code", 0);
        resultMap.put("message", "修改计划出价成功");
        return resultMap;
    }

    @Override
    public Map<String, Object> getAdvertiserPlanRejectReason(CtopOauthToken token, Long advertiserId, List<Long> adIds) {

        Map<String, Object> resultMap = new HashMap<>();

        String url = PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_ad_update_reject_reason");
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("Access-Token", token.getAccessToken());

        JSONObject params = new JSONObject();
        params.put("advertiser_id", advertiserId);
        params.put("ad_ids", adIds);
        String result = HttpUtils.httpPostRequest(url, params, headers);
        JSONObject jsonObject = JSONObject.parseObject(result);
        int code = jsonObject.getInteger("code");
        if (code != 0) {
            log.info("获取计划审核建议接口异常==》accountId:{},message:{}", token.getAccountId(), jsonObject.getString("message"));
            resultMap.put("code", -1);
            resultMap.put("message", jsonObject.getString("message"));
            return resultMap;
        }
        resultMap.put("code", 0);
        resultMap.put("message", "获取计划审核建议成功");
        return resultMap;
    }


    public void getAd(CtopOauthToken token, int pageNum, String ids, String date, String updateDate) {
        JSONArray getIds = new JSONArray();
        if (null != ids && !"".equals(ids)) {
            String[] idString = ids.split(StringUtils.COMMA);
            if (idString.length > 0) {
                for (String s : idString) {
                    Long getId = Long.parseLong(s);
                    getIds.add(getId);
                }
            }
        }
        // 请求地址
        String url = PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_ad_get");
        // 请求参数
        Map<String, Object> filtering = new HashMap<>();
        if (getIds.size() > 0) {
            filtering.put("ids", getIds);
        }
        if (null != date && !"".equals(date)) {
            filtering.put("ad_create_time", date);
        }
        if (null != updateDate && !"".equals(updateDate)) {
            filtering.put("ad_modify_time", updateDate);
        }

        JSONObject param = new JSONObject();
        param.put("advertiser_id", token.getAccountId());
        param.put("page", pageNum);
        param.put("page_size", 100);
        param.put("filtering", filtering);
        JSONObject resultObject = HttpUtils.bytedanceGetRequest(token.getAccessToken(), url, param);
        int code = resultObject.getInteger("code");
        if (code != 0) {
            log.error("获取广告计划信息接口异常==》accountId:{},message:{}", token.getAccountId(), resultObject.getString("message"));
            return;
        }
        JSONArray data = resultObject.getJSONObject("data").getJSONArray("list");
        if (null == data || data.isEmpty()) {
            return;
        }
        for (int i = 0; i < data.size(); i++) {
            JSONObject dataObject = data.getJSONObject(i);
            ByteDanceAdvertisePlan advertisePlan = new ByteDanceAdvertisePlan(dataObject, String.valueOf(token.getAccountId()));
            BigDecimal deepCpaBid = dataObject.getBigDecimal("deep_cpabid");
            if (null != deepCpaBid) {
                advertisePlan.setDeepCpaBid(deepCpaBid);
            }
            this.saveOrUpdate(advertisePlan);
        }
        getAd(token, pageNum + 1, ids, date, updateDate);
    }

    @Override
    public List<String> selectWarningGroup(Long accountId, BigDecimal maxBid) {
        return byteDanceAdvertisePlanMapper.selectWarningGroup(accountId, maxBid);

    }

    @Override
    public List<String> selectWarningCpaBid(Long accountId, BigDecimal maxCapBid) {
        return byteDanceAdvertisePlanMapper.selectWarningCpaBid(accountId, maxCapBid);
    }

    @Override
    public List<ByteDanceAdvertisePlan> getAllPlans(Long accountId,String createDate) {
        QueryWrapper<ByteDanceAdvertisePlan>queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account_id",accountId+"");
        if(null!=createDate&&!"".equals(createDate.trim())){
            queryWrapper.ge("ad_create_time",createDate+" 00:00:00");
        }
        queryWrapper.ne("opt_status","AD_STATUS_DELETE");
        queryWrapper.orderByDesc("ad_create_time");
        return this.list(queryWrapper);
    }

    private Map<String, Object> queryAdByAdId(CtopOauthToken token, Long accountId, List adId){

        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("Access-Token", token.getAccessToken());

        JSONObject params = new JSONObject();
        params.put("advertiser_id", accountId);
        Map<String, Object> filtering = new HashMap<>();
        filtering.put("ids",adId);
        params.put("filtering", filtering);
        JSONObject jsonObject = JSONObject.parseObject(HttpUtils.httpGetRequest(PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + PropertiesUtils.getValue("bytedance_config", "bytedance_v2_ad_get"), headers, params));
        Map<String, Object> resultMap = new HashMap<>();
        if (jsonObject.getInteger("code") == 0) {
            resultMap.put("code", 0);
            resultMap.put("data",jsonObject.getJSONObject("data"));
        } else {
            log.error("广告计划查询失败==》accountId:{},message:{}", token.getAccountId(), jsonObject.getString("message"));
            resultMap.put("code",-200);
            resultMap.put("message", jsonObject.getString("message"));
        }
        return resultMap;
    }

    private int getConvertIdByExternalAction(String externalAction){
        int result=0;
        switch (externalAction) {
            case "AD_CONVERT_TYPE_DOWNLOAD_FINISH":
                result = 4;
                break;
            case "AD_CONVERT_TYPE_BUTTON":
                result = 5;
                break;
            case "AD_CONVERT_TYPE_DOWNLOAD_START":
                result = 9;
                break;
            case "AD_CONVERT_TYPE_INSTALL_FINISH":
                result = 15;
                break;
            case "AD_CONVERT_TYPE_REDIRECT":
                result = 95;
                break;
        }
        return result;
    }

}
