package io.renren.modules.demo.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.renren.common.advert.AdvertPlatformAuthStatusEnum;
import io.renren.common.advert.AdvertPlatform;
import io.renren.common.advert.AdvertPlatformOauth;
import io.renren.common.advert.AdvertService;
import io.renren.common.exception.RenException;
import io.renren.common.utils.DateUtils;
import io.renren.modules.demo.service.RemoteAdvertPort;
import io.renren.modules.demo.service.SaveOrUpdateAdvertAccount;
import io.renren.modules.sys.dao.AdvertOauthDao;
import io.renren.modules.sys.dto.*;
import io.renren.modules.sys.entity.AdvertOauthEntity;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

@Component
@Slf4j
@AdvertPlatformOauth(AdvertService.SERVICE_OAUTH + AdvertPlatform.OCEANENGINE)
public class OceanengineAdapter implements RemoteAdvertPort {
    @Value("${advert_platform.oceanengine.domain_url}")
    private String domain_url;
    @Value("${advert_platform.oceanengine.oauth.auth_code_url}")
    private String authCodeUrl;
    @Value("${advert_platform.oceanengine.oauth.get_token_url}")
    private String getTokenUrl;
    @Value("${advert_platform.oceanengine.oauth.refresh_token_url}")
    private String refreshTokenUrl;
    @Value("${advert_platform.oceanengine.oauth.get_advertiser_path}")
    private String getAdvertiserPath;
    @Value("${advert_platform.oceanengine.account.get_advertiser_info}")
    private String getAdvertiserInfoPath;
    @Value("${advert_platform.oceanengine.account.get_advertiser_by_agent_path}")
    private String getAdvertiserByAgentPath;
    @Value("${advert_platform.oceanengine.account.get_advertiser_by_child_agent_path}")
    private String getAdvertiserByChildAgentPath;
    @Value("${advert_platform.oceanengine.account.get_advertiser_by_majordomo_path}")
    private String getAdvertiserByMajordomoPath;
    @Value("${advert_platform.oceanengine.account.get_advertiser_fund_path}")
    private String getAdvertiserFundPath;
    @Value("${advert_platform.oceanengine.account.get_advertiser_fund_daily_stat_path}")
    private String getAdvertiserFundDailyStatPath;
    @Value("${advert_platform.oceanengine.account.get_advertiser_fund_transaction_path}")
    private String getAdvertiserFundTransactionPath;
    @Value("${advert_platform.oceanengine.account.get_advertiser_report_audience_city_path}")
    private String getAdvertiseReportAudienceCityPath;
    @Value("${advert_platform.oceanengine.app_id}")
    private String appId;
    @Value("${advert_platform.oceanengine.secret}")
    private String secret;
    @Autowired
    private AdvertOauthDao advertOauthDao;
    @Autowired
    private SaveOrUpdateAdvertAccount saveOrUpdateAdvertAccount;
    @Autowired
    private OkHttpClient client;

    private static MediaType MT_JSON = MediaType.parse("application/json");
    @Override
    public String grantOauth(Long id) {
        String url = authCodeUrl + "&state="+id;
        return url;
    }

    @Override
    public void getToken(Map<String,Object> paramMap) {
        if(paramMap==null || paramMap.get("state")==null || paramMap.get("auth_code")==null){
            throw new RenException("缺少必要参数");
        }
        Long state = Long.parseLong(paramMap.get("state").toString());
        String authorization_code = paramMap.get("auth_code").toString();
        AdvertOauthEntity advertOauthEntity = advertOauthDao.selectById(state);
        try {
            JSONObject jsonObjectParam = new JSONObject();
            jsonObjectParam.put("app_id",appId);
            jsonObjectParam.put("secret",secret);
            jsonObjectParam.put("grant_type","auth_code");
            jsonObjectParam.put("auth_code",authorization_code);
            byte[] bodyAsBytes = new ObjectMapper().writeValueAsBytes(jsonObjectParam);
            String json = new String(bodyAsBytes);
            RequestBody requestBody = RequestBody.create(MT_JSON, json.getBytes());
            Request request = new Request.Builder()
                    .url(getTokenUrl)
                    .addHeader("Accept-Encoding", "identity") // TODO: 如果是这些类型 "gzip, deflate, br"，会出错
                    .addHeader("Content-Encoding", "identity")
                    .addHeader("Content-Type", "application/json")
                    .post(requestBody)
                    .build();

            Call call = client.newCall(request);
            Response response = call.execute();

//            if (!response.isSuccessful()) {
//                throw new RemoteClientException("response not successful");
//            }
            String respDataStr = response.body().string();
            log.info("通过 Authorization Code={} 获取 Access Token调用结果={}",authorization_code,respDataStr);

            JSONObject jsonObject = JSONObject.parseObject(respDataStr);
            Integer code = jsonObject.getInteger("code");
            if(code==0) {
                JSONObject data = jsonObject.getJSONObject("data");
                String accessToken = data.getString("access_token");
                String refreshToken = data.getString("refresh_token");
                Integer accessTokenExpiresIn = data.getInteger("expires_in");
                Integer refreshTokenExpiresIn = data.getInteger("refresh_token_expires_in");
                JSONArray advertiserIdArr = data.getJSONArray("advertiser_ids");

                //更新
                if(advertOauthEntity!=null){
                    advertOauthEntity.setAccessToken(accessToken);
                    advertOauthEntity.setAccessTokenExpiresIn(accessTokenExpiresIn.longValue());
                    advertOauthEntity.setAccessTokenExpireTime(DateUtils.addDateSeconds(new Date(),accessTokenExpiresIn));
                    advertOauthEntity.setRefreshToken(refreshToken);
                    advertOauthEntity.setRefreshTokenExpiresIn(refreshTokenExpiresIn.longValue());
                    advertOauthEntity.setRefreshTokenExpireTime(DateUtils.addDateSeconds(new Date(),refreshTokenExpiresIn));
                    advertOauthEntity.setUpdateTime(new Date());
                    advertOauthEntity.setStatus(AdvertPlatformAuthStatusEnum.SUCCESS.name());
                    advertOauthEntity.setAuthorizerInfo(JSON.toJSONString(advertiserIdArr));
                }
                //获取账户和类型
                Map<String,String> accountTypeMap = getAccountType(advertOauthEntity.getAccessToken(),advertOauthEntity.getAuthorizerInfo());
                //维护授权账号
                saveOrUpdateAdvertAccount.saveAdvertAccountByGrantOath(advertOauthEntity,accountTypeMap);
            }else{
                log.info("通过 Authorization Code={} 获取 Access Token调用结果异常code={}",authorization_code,code);
                throw new RenException("获取token异常，code="+code);
            }

        }catch (Exception e){
            e.printStackTrace();
            log.error("通过 Authorization Code={} 获取 Access Token  error={}",e);
            advertOauthEntity.setStatus(AdvertPlatformAuthStatusEnum.FAILED.name());
            advertOauthEntity.setUpdateTime(new Date());
        } finally {
            advertOauthDao.updateById(advertOauthEntity);
        }
    }

    @Override
    public void refreshToken(Long state,String refreshToken) {
        AdvertOauthEntity advertOauthEntity = advertOauthDao.selectById(state);
        try {
            JSONObject jsonObjectParam = new JSONObject();
            jsonObjectParam.put("app_id",appId);
            jsonObjectParam.put("secret",secret);
            jsonObjectParam.put("grant_type","refresh_token");
            jsonObjectParam.put("refresh_token",advertOauthEntity.getRefreshToken());
            byte[] bodyAsBytes = new ObjectMapper().writeValueAsBytes(jsonObjectParam);
            String json = new String(bodyAsBytes);
            RequestBody requestBody = RequestBody.create(MT_JSON, json.getBytes());
            Request request = new Request.Builder()
                    .url(refreshTokenUrl)
                    .addHeader("Accept-Encoding", "identity") // TODO: 如果是这些类型 "gzip, deflate, br"，会出错
                    .addHeader("Content-Encoding", "identity")
                    .addHeader("Content-Type", "application/json")
                    .post(requestBody)
                    .build();

            Call call = client.newCall(request);
            Response response = call.execute();

//            if (!response.isSuccessful()) {
//                throw new RemoteClientException("response not successful");
//            }
            String respDataStr = response.body().string();
            log.info("通过 refreshToken={} 刷新 Access Token调用结果={}",advertOauthEntity.getRefreshToken(),respDataStr);

            JSONObject jsonObject = JSONObject.parseObject(respDataStr);
            Integer code = jsonObject.getInteger("code");
            if(code==0) {
                JSONObject data = jsonObject.getJSONObject("data");
                String accessToken = data.getString("access_token");
                String newRefreshToken = data.getString("refresh_token");
                Integer accessTokenExpiresIn = data.getInteger("expires_in");
                Integer refreshTokenExpiresIn = data.getInteger("refresh_token_expires_in");

                //更新
                if(advertOauthEntity!=null){
                    advertOauthEntity.setAccessToken(accessToken);
                    advertOauthEntity.setAccessTokenExpiresIn(accessTokenExpiresIn.longValue());
                    advertOauthEntity.setAccessTokenExpireTime(DateUtils.addDateSeconds(new Date(),accessTokenExpiresIn));
                    advertOauthEntity.setRefreshToken(newRefreshToken);
                    advertOauthEntity.setRefreshTokenExpireTime(DateUtils.addDateSeconds(new Date(),refreshTokenExpiresIn));
                    advertOauthEntity.setUpdateTime(new Date());
                    advertOauthEntity.setStatus(AdvertPlatformAuthStatusEnum.SUCCESS.name());
                }
                //获取账户和类型
                Map<String,String> accountTypeMap = getAccountType(advertOauthEntity.getAccessToken(),advertOauthEntity.getAuthorizerInfo());
                //维护授权账号（刷新授权token）
                saveOrUpdateAdvertAccount.saveAdvertAccountByRefreshOathToken(advertOauthEntity,accountTypeMap);
            }else{
                log.info("通过 refreshToken={} 刷新 Access Token调用结果异常code={}",advertOauthEntity.getRefreshToken(),code);
                throw new RenException("刷新token异常，code="+code);
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("通过 refreshToken={} 刷新 Access Token  error={}",advertOauthEntity.getRefreshToken(),e);
//            advertOauthEntity.setStatus(AdvertPlatformAuthStatusEnum.FAILED.name());
//            advertOauthEntity.setUpdateTime(new Date());
        } finally {
            advertOauthDao.updateById(advertOauthEntity);
        }
    }

    /**
     * 授权账户以及类型
     * @param accessToken
     * @param authInfo
     * @return
     */
    @Override
    public Map<String, String> getAccountType(String accessToken,String authInfo) {
        if (StringUtils.hasLength(authInfo)){
            JSONArray authArray = JSONArray.parseArray(authInfo);
            if (!authArray.isEmpty()){
                return queryAdvertiserMap(accessToken);
            }
        }
        return null;
    }

    private Map<String,String> queryAdvertiserMap(String accessToken){
        try {
            String url = domain_url+getAdvertiserPath+"?access_token="+accessToken+"&app_id="+appId+"&secret="+secret;
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Accept-Encoding", "identity") // TODO: 如果是这些类型 "gzip, deflate, br"，会出错
                    .addHeader("Content-Encoding", "identity")
                    .addHeader("Content-Type", "application/json")
                    .get()
                    .build();

            Call call = client.newCall(request);
            Response response = call.execute();

            String respDataStr = response.body().string();
            log.info("获取已授权账户,accessToken={}，调用结果={}",accessToken,respDataStr);

            JSONObject jsonObject = JSONObject.parseObject(respDataStr);
            Integer code = jsonObject.getInteger("code");
            if(code==0) {
                JSONObject data = jsonObject.getJSONObject("data");
                if(data!=null){
                    if(data!=null && data.containsKey("list") && !CollectionUtils.isEmpty(data.getJSONArray("list"))){
                        JSONArray dataList = data.getJSONArray("list");
                        Map<String,String> advertiserMap = new HashMap<>();
                        for (int i=0;i<dataList.size();i++){
                            advertiserMap.put(dataList.getJSONObject(i).getString("account_role"),dataList.getJSONObject(i).getString("advertiser_id"));
                        }
                        return advertiserMap;
                    }else{
                        throw new RenException("获取已授权账户为空");
                    }

                }
            }else{
                throw new RenException("获取已授权账户异常:{"+jsonObject.getString("message")+"}");
            }

        }catch (RenException e){
            log.error("获取已授权账户异常 自定义 error={}",e);
        }catch (Exception e){
            log.error("获取已授权账户异常  error={}",e);
        }
        return null;
    }

    @Override
    public List<RdAdvertiserDTO> getAdvertiserIdList(String accountType, String accountId, String accessToken) {
        if ("ADVERTISER".equalsIgnoreCase(accountType)){
            //广告主
            return queryAdvertiserInfo(accountId,accessToken,null);
        }else if ("CUSTOMER_ADMIN".equalsIgnoreCase(accountType)){
            //管理员授权的纵横组织
            return queryAdvertiserByMajordomo(accountId,accessToken);
        }else if ("CUSTOMER_OPERATOR".equalsIgnoreCase(accountType)){
            //协作者授权的纵横组织
            return queryAdvertiserByMajordomo(accountId,accessToken);
        }else if ("AGENT".equalsIgnoreCase(accountType) || "CHILD_AGENT".equalsIgnoreCase(accountType)){
            //代理商
            AdvertiserPageDTO advertiserDTO = new AdvertiserPageDTO(accountType,accountId,accessToken);
            advertiserDTO = queryAdvertiserByAgent(advertiserDTO);
            List<String> advertiserIdList = advertiserDTO.getAdvertiserIdList();
            if (!CollectionUtils.isEmpty(advertiserIdList)){
                List<RdAdvertiserDTO> advertiserDTOList = new ArrayList<>();
                for (int i=0;i<advertiserIdList.size();i++){
                    List<RdAdvertiserDTO> list = queryAdvertiserInfo(advertiserIdList.get(i),accessToken,accountId);
                    if (!CollectionUtils.isEmpty(list)){
                        advertiserDTOList.addAll(list);
                    }
                }
                return advertiserDTOList;
            }
        }
        return null;
    }

    private List<RdAdvertiserDTO> queryAdvertiserInfo(String accountId,String accessToken,String newAccountId){
        try {
            String url = domain_url+getAdvertiserInfoPath+"?advertiser_ids=[\""+accountId+"\"]";
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Accept-Encoding", "identity") // TODO: 如果是这些类型 "gzip, deflate, br"，会出错
                    .addHeader("Content-Encoding", "identity")
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Access-Token", accessToken)
                    .get()
                    .build();

            Call call = client.newCall(request);
            Response response = call.execute();

            String respDataStr = response.body().string();
            log.info("查询广告主={}下的广告主账户,accessToken={}，url={}，调用结果={}",accountId,accessToken,url,respDataStr);

            JSONObject jsonObject = JSONObject.parseObject(respDataStr);
            Integer code = jsonObject.getInteger("code");
            if(code==0) {
                JSONArray dataArray = jsonObject.getJSONArray("data");
                if(!CollectionUtils.isEmpty(dataArray)){
                    List<RdAdvertiserDTO> advertiserDTOList = new ArrayList<>();
                    RdAdvertiserDTO rdAdvertiserDTO;
                    for (int i=0;i<dataArray.size();i++){
                        rdAdvertiserDTO = new RdAdvertiserDTO();
                        JSONObject advertiserObject = dataArray.getJSONObject(i);
                        rdAdvertiserDTO.setAccountId(StringUtils.hasLength(newAccountId)?newAccountId:accountId);
                        rdAdvertiserDTO.setAdvertiserId(advertiserObject.getString("id"));
                        rdAdvertiserDTO.setAdvertiserName(advertiserObject.getString("name"));
                        rdAdvertiserDTO.setRole(advertiserObject.getString("role"));
                        rdAdvertiserDTO.setAdvertiserStatus(advertiserObject.getString("status"));
                        rdAdvertiserDTO.setAddress(advertiserObject.getString("address"));
                        rdAdvertiserDTO.setLicenseUrl(advertiserObject.getString("license_url"));
                        rdAdvertiserDTO.setLicenseNo(advertiserObject.getString("license_no"));
                        rdAdvertiserDTO.setLicenseProvince(advertiserObject.getString("license_province"));
                        rdAdvertiserDTO.setLicenseCity(advertiserObject.getString("license_city"));
                        rdAdvertiserDTO.setCompany(advertiserObject.getString("company"));
                        rdAdvertiserDTO.setBrand(advertiserObject.getString("brand"));
                        rdAdvertiserDTO.setPromotionArea(advertiserObject.getString("promotion_area"));
                        rdAdvertiserDTO.setPromotionCenterProvince(advertiserObject.getString("promotion_center_province"));
                        rdAdvertiserDTO.setPromotionCenterCity(advertiserObject.getString("promotion_center_city"));
                        rdAdvertiserDTO.setFirstIndustryName(advertiserObject.getString("first_industry_name"));
                        rdAdvertiserDTO.setSecondIndustryName(advertiserObject.getString("second_industry_name"));
                        rdAdvertiserDTO.setReason(advertiserObject.getString("reason"));
                        rdAdvertiserDTO.setAdvertiserCreateTime(advertiserObject.getString("create_time"));
                        advertiserDTOList.add(rdAdvertiserDTO);
                    }
                    return advertiserDTOList;
                }
            }else{
                throw new RenException("查询广告主账户异常:{"+jsonObject.getString("message")+"}");
            }

        }catch (RenException e){
            log.error("查询广告主={}下的广告主账户异常 自定义 error={}",accountId,e);
        }catch (Exception e){
            log.error("查询广告主={}下的广告主账户异常  error={}",accountId,e);
        }
        return null;
    }

    private List<RdAdvertiserDTO> queryAdvertiserByMajordomo(String accountId,String accessToken){
        try {
            String url = domain_url+getAdvertiserByMajordomoPath+"?advertiser_id="+accountId;
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Accept-Encoding", "identity") // TODO: 如果是这些类型 "gzip, deflate, br"，会出错
                    .addHeader("Content-Encoding", "identity")
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Access-Token", accessToken)
                    .get()
                    .build();

            Call call = client.newCall(request);
            Response response = call.execute();

            String respDataStr = response.body().string();
            log.info("查询纵横账户={}下的广告主账户,accessToken={}，url={}，调用结果={}",accountId,accessToken,url,respDataStr);

            JSONObject jsonObject = JSONObject.parseObject(respDataStr);
            Integer code = jsonObject.getInteger("code");
            if(code==0) {
                JSONObject dataObject = jsonObject.getJSONObject("data");
                JSONArray advertiserArray = dataObject.getJSONArray("list");
                if(!CollectionUtils.isEmpty(advertiserArray)){
                    List<RdAdvertiserDTO> advertiserDTOList = new ArrayList<>();
                    for (int i=0;i<advertiserArray.size();i++){
                        JSONObject advertiserObject = advertiserArray.getJSONObject(i);
                        List<RdAdvertiserDTO> list = queryAdvertiserInfo(advertiserObject.getString("advertiser_id"),accessToken,accountId);
                        if (!CollectionUtils.isEmpty(list)){
                            advertiserDTOList.addAll(list);
                        }
                    }
                    return advertiserDTOList;
                }
            }else{
                throw new RenException("查询纵横账户下的广告主账户异常:{"+jsonObject.getString("message")+"}");
            }

        }catch (RenException e){
            log.error("查询纵横账户={}下的广告主账户异常 自定义 error={}",accountId,e);
        }catch (Exception e){
            log.error("查询纵横账户={}下的广告主账户异常  error={}",accountId,e);
        }
        return null;
    }

    private AdvertiserPageDTO queryAdvertiserByAgent(AdvertiserPageDTO advertiserDTO){
        try {
            String url = domain_url+getAdvertiserByAgentPath+"?advertiser_id="+advertiserDTO.getAccountId()+"&page="+(advertiserDTO.getPage()+1)+"&page_size="+advertiserDTO.getPageSize();
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Accept-Encoding", "identity") // TODO: 如果是这些类型 "gzip, deflate, br"，会出错
                    .addHeader("Content-Encoding", "identity")
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Access-Token", advertiserDTO.getAccessToken())
                    .get()
                    .build();

            Call call = client.newCall(request);
            Response response = call.execute();

            String respDataStr = response.body().string();
            log.info("查询代理商账户={}下的广告主账户,accessToken={}，url={}，调用结果={}",advertiserDTO.getAccountId(),advertiserDTO.getAccessToken(),url,respDataStr);

            JSONObject jsonObject = JSONObject.parseObject(respDataStr);
            Integer code = jsonObject.getInteger("code");
            if(code==0) {
                JSONObject dataObject = jsonObject.getJSONObject("data");
                if(dataObject!=null){
                    JSONArray dataArray = dataObject.getJSONArray("list");
                    JSONObject pageInfoObject = dataObject.getJSONObject("page_info");
                    if (pageInfoObject!=null){
                        advertiserDTO.setPage(pageInfoObject.getIntValue("page"));
                        advertiserDTO.setPageSize(pageInfoObject.getIntValue("page_size"));
                        advertiserDTO.setTotalNumber(pageInfoObject.getIntValue("total_number"));
                        advertiserDTO.setTotalPage(pageInfoObject.getIntValue("total_page"));
                    }
                    //当前页==总页数（已经查询结束）
                    if (!dataArray.isEmpty()){
                        List<String> advertiserIdList = advertiserDTO.getAdvertiserIdList();
                        for (int i=0;i<dataArray.size();i++){
                            String advertiser = dataArray.getString(i);
                            advertiserIdList.add(advertiser);
                        }
                        advertiserDTO.setAdvertiserIdList(advertiserIdList);
                    }
                    if (pageInfoObject.getIntValue("page")>=pageInfoObject.getIntValue("total_page")){
                        return advertiserDTO;
                    }else{
                        return queryAdvertiserByAgent(advertiserDTO);
                    }
                }else{
                    return advertiserDTO;
                }
            }else{
                throw new RenException("查询代理商账户下的广告主账户异常:{"+jsonObject.getString("message")+"}");
            }

        }catch (RenException e){
            log.error("查询代理商账户={}下的广告主账户异常 自定义 error={}",advertiserDTO.getAccountId(),e);
        }catch (Exception e){
            log.error("查询代理商账户={}下的广告主账户异常  error={}",advertiserDTO.getAccountId(),e);
        }
        return null;
    }

    @Override
    public RdAccountDTO getAdvertiserFund(String advertiserId, String accessToken) {
        try {
            String url = domain_url+getAdvertiserFundPath+"?advertiser_id="+advertiserId;
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Accept-Encoding", "identity") // TODO: 如果是这些类型 "gzip, deflate, br"，会出错
                    .addHeader("Content-Encoding", "identity")
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Access-Token", accessToken)
                    .get()
                    .build();

            Call call = client.newCall(request);
            Response response = call.execute();

            String respDataStr = response.body().string();
            log.info("查询广告主={}账户资金信息,accessToken={}，url={}，调用结果={}",advertiserId,accessToken,url,respDataStr);

            JSONObject jsonObject = JSONObject.parseObject(respDataStr);
            Integer code = jsonObject.getInteger("code");
            if(code==0) {
                JSONObject dataObject = jsonObject.getJSONObject("data");
                if(dataObject!=null && !dataObject.isEmpty()){
                    RdAccountDTO rdAccountDTO = new RdAccountDTO();
                    rdAccountDTO.setAdvertiserId(dataObject.getString("advertiser_id"));
                    rdAccountDTO.setAdvertiserName(dataObject.getString("name"));
                    rdAccountDTO.setEmail(dataObject.getString("email"));
                    rdAccountDTO.setBalance(dataObject.getBigDecimal("balance"));
                    rdAccountDTO.setValidBalance(dataObject.getBigDecimal("valid_balance"));
                    rdAccountDTO.setCash(dataObject.getBigDecimal("cash"));
                    rdAccountDTO.setValidCash(dataObject.getBigDecimal("valid_cash"));
                    rdAccountDTO.setGrantss(dataObject.getBigDecimal("grant"));
                    rdAccountDTO.setDefaultGrant(dataObject.getBigDecimal("default_grant"));
                    rdAccountDTO.setCommonGrant(dataObject.getBigDecimal("common_grant"));
                    rdAccountDTO.setSearchGrant(dataObject.getBigDecimal("search_grant"));
                    rdAccountDTO.setUnionGrant(dataObject.getBigDecimal("union_grant"));
                    rdAccountDTO.setValidGrant(dataObject.getBigDecimal("valid_grant"));
                    rdAccountDTO.setReturnGoodsAbs(dataObject.getBigDecimal("return_goods_abs"));
                    rdAccountDTO.setValidReturnGoodsAbs(dataObject.getBigDecimal("valid_return_goods_abs"));
                    rdAccountDTO.setReturnGoodsCost(dataObject.getBigDecimal("return_goods_cost"));
                    return rdAccountDTO;
                }
            }else{
                throw new RenException("查询广告主账户资金信息异常:{"+jsonObject.getString("message")+"}");
            }

        }catch (RenException e){
            log.error("查询广告主={}账户资金信息异常 自定义 error={}",advertiserId,e);
        }catch (Exception e){
            log.error("查询广告主={}账户资金信息异常  error={}",advertiserId,e);
        }
        return null;
    }

    @Override
    public RdAccountDailyStatDTO getAdvertiserFundDailyStat(String advertiserId, String accessToken, String date) {
        try {
            String url = domain_url+getAdvertiserFundDailyStatPath+"?advertiser_id="+advertiserId+"&start_date="+date+"&end_date="+date;
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Accept-Encoding", "identity") // TODO: 如果是这些类型 "gzip, deflate, br"，会出错
                    .addHeader("Content-Encoding", "identity")
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Access-Token", accessToken)
                    .get()
                    .build();

            Call call = client.newCall(request);
            Response response = call.execute();

            String respDataStr = response.body().string();
            log.info("查询广告主={}日流水信息,accessToken={}，url={}，调用结果={}",advertiserId,accessToken,url,respDataStr);

            JSONObject jsonObject = JSONObject.parseObject(respDataStr);
            Integer code = jsonObject.getInteger("code");
            if(code==0) {
                JSONObject dataObject = jsonObject.getJSONObject("data");
                if(dataObject!=null && !dataObject.isEmpty()){
                    JSONArray listArray = dataObject.getJSONArray("list");
                    if (!CollectionUtils.isEmpty(listArray)){
                        JSONObject data = listArray.getJSONObject(0);
                        if(data!=null && !data.isEmpty()){
                            RdAccountDailyStatDTO rdAccountDailyStatDTO = new RdAccountDailyStatDTO();
                            rdAccountDailyStatDTO.setAdvertiserId(data.getString("advertiser_id"));
                            rdAccountDailyStatDTO.setDate(data.getString("date"));
                            rdAccountDailyStatDTO.setBalance(data.getBigDecimal("balance"));
                            rdAccountDailyStatDTO.setCashCost(data.getBigDecimal("cash_cost"));
                            rdAccountDailyStatDTO.setCost(data.getBigDecimal("cost"));
                            rdAccountDailyStatDTO.setFrozen(data.getBigDecimal("frozen"));
                            rdAccountDailyStatDTO.setIncome(data.getBigDecimal("income"));
                            rdAccountDailyStatDTO.setRewardCost(data.getBigDecimal("reward_cost"));
                            rdAccountDailyStatDTO.setSharedWalletCost(data.getBigDecimal("shared_wallet_cost"));
                            rdAccountDailyStatDTO.setTransferIn(data.getBigDecimal("transfer_in"));
                            rdAccountDailyStatDTO.setTransferOut(data.getBigDecimal("transfer_out"));
                            return rdAccountDailyStatDTO;
                        }
                    }
                }
            }else{
                throw new RenException("查询广告主账户日流水异常:{"+jsonObject.getString("message")+"}");
            }

        }catch (RenException e){
            log.error("查询广告主={}账户日流水异常 自定义 error={}",advertiserId,e);
        }catch (Exception e){
            log.error("查询广告主={}账户日流水异常  error={}",advertiserId,e);
        }
        return null;
    }

    @Override
    public AdvertiserFundTransactionPageDTO getAdvertiserFundTransaction(AdvertiserFundTransactionPageDTO advertiserPageDTO,String transactionType) {
        try {
            String url = domain_url+getAdvertiserFundTransactionPath+"?advertiser_id="+advertiserPageDTO.getAdvertiserId()+"&start_date="+advertiserPageDTO.getDate()+"&end_date="+advertiserPageDTO.getDate()+"&transaction_type="+transactionType+"&page="+(advertiserPageDTO.getPage()+1)+"&page_size="+advertiserPageDTO.getPageSize();
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Accept-Encoding", "identity") // TODO: 如果是这些类型 "gzip, deflate, br"，会出错
                    .addHeader("Content-Encoding", "identity")
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Access-Token", advertiserPageDTO.getAccessToken())
                    .get()
                    .build();

            Call call = client.newCall(request);
            Response response = call.execute();

            String respDataStr = response.body().string();
            log.info("查询广告主={}账户流水明细,accessToken={}，url={}，调用结果={}",advertiserPageDTO.getAdvertiserId(),advertiserPageDTO.getAccessToken(),url,respDataStr);

            JSONObject jsonObject = JSONObject.parseObject(respDataStr);
            Integer code = jsonObject.getInteger("code");
            if(code==0) {
                JSONObject dataObject = jsonObject.getJSONObject("data");
                if(dataObject!=null){
                    JSONArray dataArray = dataObject.getJSONArray("list");
                    JSONObject pageInfoObject = dataObject.getJSONObject("page_info");
                    if (pageInfoObject!=null){
                        advertiserPageDTO.setPage(pageInfoObject.getIntValue("page"));
                        advertiserPageDTO.setPageSize(pageInfoObject.getIntValue("page_size"));
                        advertiserPageDTO.setTotalNumber(pageInfoObject.getIntValue("total_number"));
                        advertiserPageDTO.setTotalPage(pageInfoObject.getIntValue("total_page"));
                    }
                    //当前页==总页数（已经查询结束）
                    if (!CollectionUtils.isEmpty(dataArray)){
                        List<RdAccountLogDTO> rdAccountLogDTOList = advertiserPageDTO.getRdAccountLogDTOList();
                        for (int i=0;i<dataArray.size();i++){
                            JSONObject data = dataArray.getJSONObject(i);
                            if(dataObject!=null && !dataObject.isEmpty()){
                                RdAccountLogDTO rdAccountLogDTO = new RdAccountLogDTO();
                                rdAccountLogDTO.setDate(advertiserPageDTO.getDate());
                                rdAccountLogDTO.setAdvertiserId(data.getString("advertiser_id"));
                                rdAccountLogDTO.setTransactionType(data.getString("transaction_type"));
                                rdAccountLogDTO.setAccountCreateTime(data.getString("create_time"));
                                rdAccountLogDTO.setAmount(data.getBigDecimal("amount"));
                                rdAccountLogDTO.setFrozen(data.getBigDecimal("frozen"));
                                rdAccountLogDTO.setCash(data.getBigDecimal("cash"));
                                rdAccountLogDTO.setGrantss(data.getBigDecimal("grant"));
                                rdAccountLogDTO.setReturnGoods(data.getBigDecimal("return_goods"));
                                rdAccountLogDTO.setTransactionSeq(data.getString("transaction_seq"));
                                rdAccountLogDTO.setRemitter(data.getString("remitter"));
                                rdAccountLogDTO.setPayee(data.getString("payee"));
                                rdAccountLogDTO.setDealbase(data.getInteger("dealbase"));
                                rdAccountLogDTOList.add(rdAccountLogDTO);
                            }
                        }
                        advertiserPageDTO.setRdAccountLogDTOList(rdAccountLogDTOList);
                    }
                    if (pageInfoObject.getIntValue("page")>=pageInfoObject.getIntValue("total_page")){
                        return advertiserPageDTO;
                    }else{
                        return getAdvertiserFundTransaction(advertiserPageDTO,transactionType);
                    }
                }else{
                    return advertiserPageDTO;
                }
            }else{
                throw new RenException("查询广告主账户流水明细异常:{"+jsonObject.getString("message")+"}");
            }

        }catch (RenException e){
            log.error("查询广告主={}账户流水明细异常 自定义 error={}",advertiserPageDTO.getAdvertiserId(),e);
        }catch (Exception e){
            log.error("查询广告主={}账户流水明细异常  error={}",advertiserPageDTO.getAdvertiserId(),e);
        }
        return null;
    }

    @Override
    public List<RdAudienceCityDTO> getAdvertiserAudienceCity(String advertiserId, String accessToken, String date) {
        try {
            String url = domain_url+getAdvertiseReportAudienceCityPath+"?advertiser_id="+advertiserId+"&start_date="+date+"&end_date="+date+"&id_type=AUDIENCE_STAT_ID_TYPE_ADVERTISER"+"&metrics=[\"cost\",\"show\",\"click\",\"convert\"]";;
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Accept-Encoding", "identity") // TODO: 如果是这些类型 "gzip, deflate, br"，会出错
                    .addHeader("Content-Encoding", "identity")
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Access-Token", accessToken)
                    .get()
                    .build();

            Call call = client.newCall(request);
            Response response = call.execute();

            String respDataStr = response.body().string();
            log.info("查询广告主={}受众分析市级数据,accessToken={}，url={}，调用结果={}",advertiserId,accessToken,url,respDataStr);

            JSONObject jsonObject = JSONObject.parseObject(respDataStr);
            Integer code = jsonObject.getInteger("code");
            if(code==0) {
                JSONArray dataArray = jsonObject.getJSONArray("data");
                if (!CollectionUtils.isEmpty(dataArray)) {
                    List<RdAudienceCityDTO> rdAudienceCityDTOList = new ArrayList<>();
                    RdAudienceCityDTO rdAudienceCityDTO;
                    for (int i=0;i<dataArray.size();i++) {
                        JSONObject dataObject = dataArray.getJSONObject(i);
                        if (dataObject != null && !dataObject.isEmpty()) {
                            rdAudienceCityDTO = new RdAudienceCityDTO();
                            rdAudienceCityDTO.setDate(dataObject.getString("date"));
                            rdAudienceCityDTO.setProvinceName(dataObject.getString("province_name"));
                            rdAudienceCityDTO.setCityName(dataObject.getString("city_name"));
                            JSONObject metricsDictObject = dataObject.getJSONObject("metrics_dict");
                            if (metricsDictObject != null && !metricsDictObject.isEmpty()) {
                                rdAudienceCityDTO.setCost(metricsDictObject.getBigDecimal("cost"));
                                rdAudienceCityDTO.setShows(metricsDictObject.getInteger("show"));
                                rdAudienceCityDTO.setClick(metricsDictObject.getInteger("click"));
                                rdAudienceCityDTO.setConverts(metricsDictObject.getInteger("convert"));

                            }
                            rdAudienceCityDTOList.add(rdAudienceCityDTO);
                        }
                    }
                    return rdAudienceCityDTOList;
                }
            }else{
                throw new RenException("查询广告主受众分析市级数据异常:{"+jsonObject.getString("message")+"}");
            }

        }catch (RenException e){
            log.error("查询广告主={}受众分析市级数据异常 自定义 error={}",advertiserId,e);
        }catch (Exception e){
            log.error("查询广告主={}受众分析市级数据异常  error={}",advertiserId,e);
        }
        return null;
    }
}
