package cn.com.ctop.kuaishou.modules.batch.controller;

import cn.com.ctop.common.module.entity.CtopOauthToken;
import cn.com.ctop.common.module.entity.UserAllocation;
import cn.com.ctop.common.module.material.entity.MaterialVideoAuthor;
import cn.com.ctop.common.module.service.ICtopOauthTokenService;
import cn.com.ctop.common.module.utils.Check;
import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouInterfaceService;
import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouRealTimeDataService;
import cn.com.ctop.kuaishou.modules.report.entity.KuaishouReportHourlyGroup;
import cn.com.ctop.kuaishou.modules.report.service.IKuaishouReportHourlyGroupService;
import cn.com.ctop.kuaishou.modules.utils.LinkUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.gson.JsonObject;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Description: 广告组-app信息
 * @Author: jeecg-boot
 * @Date: 2019-07-23
 * @Version: V1.0
 */
@Slf4j
@RestController
@RequestMapping("/kuaishou/realTime")
public class KuaiShouRealTimeController {
    @Autowired
    private IKuaishouRealTimeDataService realTimeDataService;
    @Autowired
    private ICtopOauthTokenService oauthTokenService;

    @Autowired
    private ICtopOauthTokenService tokenService;

    @Autowired
    IKuaishouReportHourlyGroupService kuaishouReportHourlyGroupService;


    @Autowired
    IKuaishouInterfaceService kuaishouInterfaceService;




    /**
     *  快手- 获取实时数据 计划
     * @param requestJson
     * @return
     */
    @PostMapping(value = "/getCampaignDate")
    public Result<JSONArray> getCampaignDate(@RequestBody JSONObject requestJson) {
        Result<JSONArray> result = new Result<>();
        try {
            Long accountId = requestJson.getLong("accountId");
            if (Check.isNull(accountId)) {
                throw new Exception("请传入账户id");
            }
            CtopOauthToken oauthToken = oauthTokenService.getTokenByAccountId(accountId);
            if (Check.isNull(oauthToken)) {
                throw new Exception("未获取到账户信息");
            }
            Long campaignId = requestJson.getLong("campaignId");
            if (Check.isNull(campaignId)) {
                throw new Exception("请传入计划id");
            }
            String startDate = requestJson.getString("startDate");
            String endDate = requestJson.getString("endDate");
            if (Check.isNull(startDate) || Check.isNull(endDate)) {
                throw new Exception("请选择开始、结束查询时间");
            }
            JSONArray campaignDate = realTimeDataService.getCampaignDate(accountId, oauthToken.getAccessToken(), campaignId, startDate, endDate);
            result.setSuccess(true);
            result.setResult(campaignDate);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setMessage(e.getMessage());
        }

        return result;
    }




    /**
     *  快手- 获取实时数据 组
     * @param requestJson
     * @return
     */
    @PostMapping(value = "/getUnitDate")
    public Result<JSONArray> getUnitDate(@RequestBody JSONObject requestJson) {
        Result<JSONArray> result = new Result<>();
        try {
            Long accountId = requestJson.getLong("accountId");
            if (Check.isNull(accountId)) {
                throw new Exception("请传入账户id");
            }
            CtopOauthToken oauthToken = oauthTokenService.getTokenByAccountId(accountId);
            if (Check.isNull(oauthToken)) {
                throw new Exception("未获取到账户信息");
            }
            Long unitId = requestJson.getLong("unitId");
            /*if (Check.isNull(unitId)) {
                throw new Exception("请传入组id");
            }*/
            String startDate = requestJson.getString("startDate");
            String endDate = requestJson.getString("endDate");
            if (Check.isNull(startDate) || Check.isNull(endDate)) {
                throw new Exception("请选择开始、结束查询时间");
            }
            JSONArray unitData = realTimeDataService.getUnitDate(accountId, oauthToken.getAccessToken(), unitId, startDate, endDate);
            result.setSuccess(true);
            result.setResult(unitData);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setMessage(e.getMessage());
        }

        return result;
    }


    /**
     * 盯盘-快手 组实时数据信息
     * @param accountId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping(value = "/getUnitDateInfo")
    public Result getUnitDate(@RequestParam("accountId") Long accountId,
                                         @RequestParam(value = "pageNum",defaultValue = "1") Integer pageNum,
                                         @RequestParam(value = "pageSize",defaultValue = "10") Integer pageSize) {

        DecimalFormat df = new DecimalFormat("#.000");

        String nowDate = DateUtils.getNowDate("yyyy-MM-dd");
        CtopOauthToken token = tokenService.getTokenByAccountId(accountId);


        List<KuaishouReportHourlyGroup> unitList = new ArrayList<>();


        //优化目标
        Integer conver = 0;
        //获取广告组的出价
        Map unitPrice = kuaishouInterfaceService.getKuaishouUnitList(token, null,new Date(), new Date() , 1,pageNum,pageSize);

        JSONArray array = JSONArray.parseArray(unitPrice.get("details").toString());

        for (Object obj : array) {

            KuaishouReportHourlyGroup unitInfo = new KuaishouReportHourlyGroup();
            //获取组id
            List<Long> unitIdList = new ArrayList<>();
            JSONObject vo = JSONObject.parseObject(obj.toString());
            unitIdList.add(vo.getLong("unit_id"));

            //广告主 当天 实时 组 数据信息
            JSONArray unitData = realTimeDataService.getUnitDatePage(accountId, unitIdList, token.getAccessToken(), nowDate, nowDate, pageNum, pageSize);
            List<KuaishouReportHourlyGroup> k = JSONArray.parseArray(unitData.toString(),KuaishouReportHourlyGroup.class);
            if (!Check.isNull(k)){
                unitInfo  = k.get(0);
            }

            unitInfo.setTotalCount(Integer.valueOf(unitPrice.get("totalCount").toString()));



            unitInfo.setUnitName(vo.getString("unit_name"));

            //出价
            unitInfo.setBid(vo.getLong("bid"));
            unitInfo.setCpaBid(vo.getLong("cpa_bid"));
            unitInfo.setBidType(vo.getInteger("bid_type"));
            //优化目标
            conver = vo.getInteger("ocpx_action_type");
            unitInfo.setConverType(conver);
            //计划id
            unitInfo.setCampaignId(vo.getLong("campaign_id"));
            //组id
            unitInfo.setUnitId(vo.getLong("unit_id"));
            unitInfo.setUnitName(vo.getString("unit_name"));

            //投放状态 1：投放中；2：暂停 3：删除
            unitInfo.setPutStatus(vo.getInteger("put_status"));

            //激活成本 = 花费  / 激活数
            String activationCost = "0";

            if (!Check.isNull(k)){
                if (unitInfo.getCharge().doubleValue() != new Double(0) && unitInfo.getActivation() != 0l) {
                    Double activation_cost = unitInfo.getCharge().doubleValue() / unitInfo.getActivation();
                    activationCost = df.format(activation_cost);
                }

            unitInfo.setActivationCost(activationCost);


                //优化目标： 激活，  付费，  行为，  表单提交，  注册，  唤起应用，  关键行为
                //对应转化数 激活数，付费数，行为数，表单提交数，注册数，唤起应用次数，关键行为数
                //优化目标id 来源---ctop_kuaishou_ocpx_action_type_config
                //激活
                if (conver == 180) {
                    unitInfo.setConverNum(unitInfo.getActivation().intValue());
                }
                //付费
                if (conver == 190) {
                    unitInfo.setConverNum(unitInfo.getEventPay().intValue());
                }
                //行为
                if (conver == 2) {
                    unitInfo.setConverNum(unitInfo.getBclick().intValue());
                }
                //表单提交
                if (conver == 53) {
                    unitInfo.setConverNum(unitInfo.getFormCount().intValue());
                }
                //注册
                if (conver == 396) {
                    unitInfo.setConverNum(unitInfo.getEventRegister().intValue());
                }
                //唤起应用
                if (conver == 324) {
                    unitInfo.setConverNum(unitInfo.getEventAppInvoked().intValue());
                }
                //关键行为
                if (conver == 773) {
                    unitInfo.setConverNum(unitInfo.getKeyAction().intValue());
                }
                //转化成本 = 花费 / 转化数
                unitInfo.setConverCost(Check.isNull(unitInfo.getCharge()) || Check.isNull(unitInfo.getConverNum()) ? 0 : unitInfo.getCharge().doubleValue() / unitInfo.getConverNum().doubleValue());
                if (unitInfo.getConverCost().isNaN() || unitInfo.getConverCost().isInfinite()) {
                    unitInfo.setConverCost(new Double(0));
                }

                //操作建议
                //消耗
                Double charge = unitInfo.getCharge().doubleValue();
                //出价 单位:厘
                long bid = new Long("1000");
                //2：CPC
                if (unitInfo.getBidType() == 2){
                    bid = unitInfo.getBid();
                //10：OCPM
                }else if(unitInfo.getBidType() == 10){
                    bid = unitInfo.getCpaBid();
                }
                Double price = new Double(bid/1000).doubleValue();

                //转化数量
                Integer converNum = unitInfo.getConverNum();
                //转化成本
                Double converCost = unitInfo.getConverCost();

                //1. 转化成本大于出价×120%，消耗大于500元：
                if ((converCost > price * 1.2) && (charge > 500)) {
                    unitInfo.setOperationAgree("高成本 | 有消耗");
                    unitInfo.setOperationAgreeContent("建议限制预算");
                    unitInfo.setOperationAgreeInfo("当前广告组转化成本偏高且消耗大于500，建议限制预算;");
                }
                //2.  转化成本大于出价×120%，转化数大于10小于等于50：
                if (converCost > price * 1.2 && LinkUtils.isInTheInterval(String.valueOf(converNum), "(10,50)")) {
                    unitInfo.setOperationAgree("高成本 | 有转化");
                    unitInfo.setOperationAgreeContent("建议限制预算");
                    unitInfo.setOperationAgreeInfo("当前广告组成本大于出价×120%且转化数介于10-50之间;");
                }
                //3. 转化成本大于出价×120%，转化数大于50
                if (converCost > price * 1.2 && LinkUtils.isInTheInterval(String.valueOf(converNum), "(50,∞)")) {
                    unitInfo.setOperationAgree("高成本 | 有转化");
                    unitInfo.setOperationAgreeContent("建议降低出价;");
                    unitInfo.setOperationAgreeInfo("当前转化成本大于出价×120%，转化数大于50，建议降低出价;");
                }
                //4.  转化成本小于等于出价×120%，转化数大于10小于等于50
                if (converCost <= price * 1.2 && LinkUtils.isInTheInterval(String.valueOf(converNum), "(10,50]")) {
                    unitInfo.setOperationAgree("成本合理 | 有转化");
                    unitInfo.setOperationAgreeContent("建议复制推广组或放开预算");
                    unitInfo.setOperationAgreeInfo("当前转化成本小于等于出价×120%，转化数大于10小于等于50，建议复制推广组或放开预算;");
                }
                //5.  消耗大于0小于等于100，转化数大于0小于等于10：
                if (LinkUtils.isInTheInterval(String.valueOf(charge), "(0,100]") && LinkUtils.isInTheInterval(String.valueOf(converNum), "(0,10]")) {
                    unitInfo.setOperationAgree("消耗少 | 转化少");
                    unitInfo.setOperationAgreeContent("建议启用加速探索");
                    unitInfo.setOperationAgreeInfo("当前广告组消耗大于0小于等于100，转化数大于0小于等于10，建议加速探索;");
                }
                //6.  消耗大于等于500，转化数等于0：
                if (charge >= 500 && converNum == 0) {
                    unitInfo.setOperationAgree("有消耗 | 无转化");
                    unitInfo.setOperationAgreeContent("建议暂停广告组");
                    unitInfo.setOperationAgreeInfo("当前广告组消耗大于等于500且转化数等于0，建议暂停推广组;");
                }
                //7.   消耗大于100小于等于500
                if (LinkUtils.isInTheInterval(String.valueOf(charge), "(100,500]")) {
                    unitInfo.setOperationAgree("有一定消耗");
                    unitInfo.setOperationAgreeContent("建议继续观察");
                    unitInfo.setOperationAgreeInfo("当前广告组消耗大于100小于等于500，建议继续观察;");
                }


            }
            unitInfo.setOperationAgree("暂无");
            unitInfo.setOperationAgreeContent("暂无");
            unitInfo.setOperationAgreeInfo("暂无");


            setFeidValueNotNull(unitInfo);

            unitList.add(unitInfo);

        }
        return Result.ok(unitList);
    }









    private void setFeidValueNotNull (Object obj){
        try {
            for (Field field: obj.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            if (field.get(obj) == null){
                if (field.getGenericType().toString().equals("class java.lang.String")) {
                    field.set(obj, "0");
                }else if (field.getGenericType().toString().equals("class java.lang.Integer")) {
                    field.set(obj, 0);
                }else if (field.getGenericType().toString().equals("class java.lang.Double")) {
                    field.set(obj, 0.0);
                }else if (field.getGenericType().toString().equals("class java.lang.Long")) {
                    field.set(obj, 0L);
                }else if(field.getGenericType().toString().equals("class java.math.BigDecimal")){
                    field.set(obj, new BigDecimal(0));
                }
            }
        }

        }catch (Exception e){
            e.printStackTrace();
        }


    }




}
