package cn.com.ctop.toutiao.modules.agent.service.impl;

import cn.com.ctop.common.module.entity.CtopOauthToken;
import cn.com.ctop.common.module.utils.Check;
import cn.com.ctop.toutiao.modules.agent.entity.TransactionDay;
import cn.com.ctop.toutiao.modules.agent.entity.TransactionDetails;
import cn.com.ctop.toutiao.modules.agent.mapper.CtopAccountTransactionDayMapper;
import cn.com.ctop.toutiao.modules.agent.mapper.CtopAccountTransactionDetailsMapper;
import cn.com.ctop.toutiao.modules.agent.mapper.CtopAgentAccountMapper;
import cn.com.ctop.toutiao.modules.agent.service.AgentManagementService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.jeecg.common.api.vo.Result;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static java.util.stream.Collectors.toList;

/**
 * 代理商管理
 *
 * @author zzy
 * @create: 2021-07-14
 */
@Service
@Slf4j
public class AgentManagementServiceImpl implements AgentManagementService {

    private final String OPEN_API_URL_PREFIX = "https://ad.oceanengine.com/open_api/2/";
    private final String ACCOUNT_LIST_URL = "agent/advertiser/select/";
    private final String ACCOUNT_TRANSACTION_DETAILS_URL = "advertiser/fund/transaction/get/";
    private final String ACCOUNT_TRANSACTION_DAY_URL = "advertiser/fund/daily_stat/";
    private final String ADVERTISER_ID = "73970348172";
    private final String RECHARGE = "RECHARGE";
    private final String TRANSFER = "TRANSFER";

    static ExecutorService executorService = Executors.newFixedThreadPool(3);


    @Resource
    CtopAgentAccountMapper ctopAgentAccountMapper;
    @Resource
    CtopAccountTransactionDetailsMapper ctopAccountTransactionDetailsMapper;

    @Resource
    CtopAccountTransactionDayMapper ctopAccountTransactionDayMapper;

    private String accountList = "1651537304110087;1640370875427848;73970348172";

    /**
     * 同步代理商下账号
     *
     * @author zzy
     * @create: 2021-07-14
     */

    @Override
    public Result synchronousAccount() {
        log.info("开始同步账号信息");
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        List<String> dataList = new ArrayList();
        Result result = new Result();
        try {
            if (accountList != null) {
                String[] split = accountList.split(";");
                for (String account : split) {
                    //分页查询第一页数据
                    JSONObject agentAccountList = selectAgentAdvertiser(1, 2000, account);
                    if (!Integer.valueOf(agentAccountList.get("code").toString()).equals(0)) {
                        log.info("代理商:{}拉取账户异常--{}", account, agentAccountList);
                    }
                    ;

                    JSONObject data = (JSONObject) agentAccountList.get("data");
                    //dataList.addAll((List) data.get("list"));
                    if (data.size() > 0) {
                        JSONObject page_info = (JSONObject) data.get("page_info");
                        int total_page = (int) page_info.get("total_page");
                        //查询其他页数据
                        for (int i = 0; i < total_page; i++) {
                            JSONObject agenttList = selectAgentAdvertiser(i + 1, 2000, account);
                            JSONObject agentData = (JSONObject) agenttList.get("data");
                            List<Long> list = (List<Long>) agentData.get("list");
                            list.stream().forEach(str -> {
                                dataList.add(str.toString());
                            });

                        }
                        log.info("拉取" + account + "下账户数量:{}", dataList.size());
                        //查询数据库已存在id
                        List<String> accountIdList = ctopAgentAccountMapper.getAllAccountId();
                        if (!accountIdList.isEmpty()) {
                            //筛选巨量引擎剔除的用户
                            List<String> removeList = accountIdList.stream().filter(item -> !dataList.contains(item)).collect(toList());
                            //筛选巨量引擎新增的用户
                            List<String> addList = dataList.stream().filter(item -> !accountIdList.contains(item)).collect(toList());
                            //修改剔除的用户状态
                            if (!removeList.isEmpty()) {
                                ctopAgentAccountMapper.updateAccountState(removeList, 1);
                            }
                            //保存新增的用户
                            if (!addList.isEmpty()) {
                                ctopAgentAccountMapper.insertAccountData(addList, ADVERTISER_ID, df.format(new Date()));
                            }
                        } else {
                            ctopAgentAccountMapper.insertAccountData(dataList, ADVERTISER_ID, df.format(new Date()));
                        }

                    }
                }
            }

            result.setSuccess(true);
            result.setMessage("success");
            return result;
        } catch (Exception e) {
            log.info("同步失败:{}", e.toString());
            result.error500("同步失败");
            return result;
        }
    }

    /**
     * 同步账户交易流水
     *
     * @author zzy
     * @create: 2021-07-15
     */
    @Override
    public Result synchronousAccountTransactionDetails(String startDate, String endDate) {
        log.info("开始同步账号交易流水");
        Result result = new Result();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        List<TransactionDetails> transactionDetailsList = new ArrayList<>();
        try {
            List<String> accountIdList = ctopAgentAccountMapper.getAllAccountId();
            if (!accountIdList.isEmpty()) {
                List<String> transactionSeqList = ctopAccountTransactionDetailsMapper.getTransactionSeq(df.format(new Date()));
                accountIdList.stream().forEach(str -> {
                    if (!str.isEmpty()) {
                        //查询账号下充值的交易流水
                        JSONObject jsonObject = queryAccountTransactionDetails(str, RECHARGE, 1, 1000, startDate, endDate);
                        int code = (int) jsonObject.get("code");
                        if (code != 0) {
                            result.setMessage((String) jsonObject.get("message"));
                            log.info((String) jsonObject.get("message"));
                            return;
                        }
                        JSONObject data = (JSONObject) jsonObject.get("data");
                        if (data != null) {
                            List<Object> dataList = (List<Object>) data.get("list");
                            if (dataList != null && !dataList.isEmpty()) {
                                //充值类存在记录
                                //保存第一页数据
                                dataList.stream().forEach(ob -> {
                                    TransactionDetails transactionDetails = JSONObject.toJavaObject((JSON) ob, TransactionDetails.class);
                                    //订单号不存在
                                    if (transactionSeqList.isEmpty() || !transactionSeqList.contains(transactionDetails.getTransaction_seq())) {
                                        transactionDetailsList.add(transactionDetails);
                                    }

                                });
                                JSONObject page_info = (JSONObject) data.get("page_info");
                                int total_page = (int) page_info.get("total_page");
                                //查询其他页数据
                                if (total_page > 1) {
                                    for (int i = 2; i <= total_page; i++) {
                                        JSONObject jo = queryAccountTransactionDetails(str, RECHARGE, i, 1000, startDate, endDate);
                                        JSONObject accountData = (JSONObject) jo.get("data");
                                        List<Object> rechargeList = (List<Object>) accountData.get("list");
                                        rechargeList.stream().forEach(transactionDetails -> {
                                            TransactionDetails transactionDetailsOther = JSONObject.toJavaObject((JSON) transactionDetails, TransactionDetails.class);
                                            //订单号不存在
                                            if (transactionSeqList.isEmpty() || !transactionSeqList.contains(transactionDetailsOther.getTransaction_seq())) {
                                                transactionDetailsList.add(transactionDetailsOther);
                                            }
                                        });
                                    }
                                }
                            }
                        }

                        //查询账号下转账的交易流水
                        JSONObject transferJsonObject = queryAccountTransactionDetails(str, TRANSFER, 1, 1000, startDate, endDate);
                        JSONObject transferData = (JSONObject) transferJsonObject.get("data");
                        int code1 = (int) jsonObject.get("code");
                        if (code1 != 0) {
                            result.setMessage((String) jsonObject.get("message"));
                            log.info((String) jsonObject.get("message"));
                            return;
                        }
                        if (transferData != null) {
                            List<Object> transferDataList = (List<Object>) transferData.get("list");
                            if (!transferDataList.isEmpty()) {
                                //转账类存在记录
                                //保存第一页数据
                                transferDataList.stream().forEach(ob -> {
                                    TransactionDetails transactionDetails = JSONObject.toJavaObject((JSON) ob, TransactionDetails.class);
                                    //订单号不存在
                                    if (transactionSeqList.isEmpty() || !transactionSeqList.contains(transactionDetails.getTransaction_seq())) {
                                        transactionDetailsList.add(transactionDetails);
                                    }
                                });
                                JSONObject transferPageInfo = (JSONObject) transferData.get("page_info");
                                int transferTotalPage = (int) transferPageInfo.get("total_page");
                                //查询其他页数据
                                if (transferTotalPage > 1) {
                                    for (int i = 2; i <= transferTotalPage; i++) {
                                        JSONObject jo = queryAccountTransactionDetails(str, TRANSFER, i, 1000, startDate, endDate);
                                        JSONObject accountData = (JSONObject) jo.get("data");
                                        List<Object> rechargeList = (List<Object>) accountData.get("list");
                                        rechargeList.stream().forEach(transactionDetails -> {
                                            TransactionDetails transactionDetailsOther = JSONObject.toJavaObject((JSON) transactionDetails, TransactionDetails.class);
                                            //订单号不存在
                                            if (transactionSeqList.isEmpty() || !transactionSeqList.contains(transactionDetailsOther.getTransaction_seq())) {
                                                transactionDetailsList.add(transactionDetailsOther);
                                            }
                                        });
                                    }
                                }
                            }
                        }

                    }
                });
            }
            //保存数据
            if (!transactionDetailsList.isEmpty()) {
                ctopAccountTransactionDetailsMapper.saveAccountTransactionDetails(transactionDetailsList, df.format(new Date()));
                log.info("新增交易记录：{}条", transactionDetailsList.size());
            }
            result.setSuccess(true);
            result.setMessage("success");
        } catch (Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setMessage("error");
            log.info("同步失败:{}", e.toString());
        }


        return result;
    }

    /**
     * 同步账户日流水
     *
     * @author zzy
     * @create: 2021-07-15
     */
    @Override
    public Result synchronousAccountTransactionDay(String startDate, String endDate) {
        log.info("开始同步账号日流水---日期{}---{}", startDate, endDate);
        Result result = new Result();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        Calendar ca = Calendar.getInstance();
        ca.setTime(new Date());
        ca.add(Calendar.DATE, -1);

        try {
            List<String> accountIdList = ctopAgentAccountMapper.getAllAccountId();
//            List<String> accountIdList = new ArrayList<>();
            //accountIdList.add("1744115510360071");
            if (!accountIdList.isEmpty()) {
                accountIdList.stream().forEach(str -> {
                    List<TransactionDay> transactionDetailsList = new ArrayList<>();
                    if (!str.isEmpty()) {
                        //查询账号下充值的交易流水
                        JSONObject jsonObject = queryAccountTransactionDay(str, 1, 1000, startDate, endDate);
                        JSONObject data = null;
                        int code = 1;
                        if (jsonObject != null) {
                            data = (JSONObject) jsonObject.get("data");
                            code = (int) jsonObject.get("code");
                        } else {
                            log.info("返回数据jsonObject为null:");
                        }
                        if (code != 0) {
                            result.setMessage((String) jsonObject.get("message"));
                            log.info("返回数据:" + jsonObject.toJSONString() + ":" + str);
                        }
                        if (data != null) {
                            List<Object> dataList = (List<Object>) data.get("list");
                            if (dataList != null && !dataList.isEmpty()) {
                                //充值类存在记录
                                //保存第一页数据
                                dataList.stream().forEach(ob -> {
                                    TransactionDay transactionDay = JSONObject.toJavaObject((JSON) ob, TransactionDay.class);
                                    List<String> advertiserIdList = ctopAccountTransactionDayMapper.getAdvertiserIdByDate(transactionDay.getDate(), transactionDay.getAdvertiserId());

                                    if (advertiserIdList.size() > 1) {
                                        ctopAccountTransactionDayMapper.deleteAccountTransactionById(advertiserIdList.get(0));
                                        log.info("----------->删除重复数据。accountId:{},date:{}", transactionDay.getAdvertiserId(), transactionDay.getDate());
                                    }
                                    //订单号不存在
                                    if (advertiserIdList.isEmpty() || advertiserIdList.size() <= 0) {
                                        transactionDetailsList.add(transactionDay);
                                    }

                                });
                                JSONObject page_info = (JSONObject) data.get("page_info");
                                int total_page = (int) page_info.get("total_page");
                                //查询其他页数据
                                if (total_page > 1) {
                                    for (int i = 2; i <= total_page; i++) {
                                        JSONObject jo = queryAccountTransactionDay(str, i, 1000, startDate, endDate);
                                        JSONObject accountData = (JSONObject) jo.get("data");
                                        List<Object> rechargeList = (List<Object>) accountData.get("list");
                                        rechargeList.stream().forEach(obj -> {
                                            TransactionDay transactionDay = JSONObject.toJavaObject((JSON) obj, TransactionDay.class);
                                            List<String> advertiserIdList = ctopAccountTransactionDayMapper.getAdvertiserIdByDate(transactionDay.getDate(), transactionDay.getAdvertiserId());

                                            if (advertiserIdList.size() > 1) {
                                                ctopAccountTransactionDayMapper.deleteAccountTransactionById(advertiserIdList.get(0));
                                            }

                                            //订单号不存在
                                            if (advertiserIdList.isEmpty() || advertiserIdList.size() <= 0) {
                                                transactionDetailsList.add(transactionDay);
                                            }
                                        });
                                    }
                                }
                            }
                        }
                    }
                    //保存数据
                    if (!transactionDetailsList.isEmpty()) {
                        ctopAccountTransactionDayMapper.saveAccountTransactionDay(transactionDetailsList, df.format(new Date()));
                        log.info("新增日流水记录：{}条", transactionDetailsList.size());
                    }
                });
            }

            result.setSuccess(true);
            result.setMessage("success");
        } catch (Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setMessage("error");
            log.info("同步失败:{}", e.toString());
        }


        return result;
    }


    @Override
    public void insertAccountTransactionDay(String startDate, String endDate) {
        List<String> accountIdList = ctopAgentAccountMapper.getAllAccountId2();
        if (!Check.isNull(accountIdList)) {
            accountIdList.forEach(accountId -> executorService.submit(() -> this.insertAccountTransactionDay(accountId, startDate, endDate, 1)));
        }
    }

    @Override
    public void insertAccountTransactionDayByProjectId(Long projectId, String startDate, String endDate) {
        List<String> accountIdList = ctopAgentAccountMapper.getAccountIdsByProjectId(projectId);
        if (!Check.isNull(accountIdList)) {
            accountIdList.forEach(accountId -> executorService.submit(() -> this.insertAccountTransactionDay(accountId, startDate, endDate, 1)));
        }
    }

    public void insertAccountTransactionDay(String accountId, String startDate, String endDate, Integer page) {
        try {
            JSONObject obj = queryAccountTransactionDay(accountId, page, 1000, startDate, endDate);
            if (!Check.isNull(obj) && obj.getInteger("code") == 0) {
                JSONObject data = obj.getJSONObject("data");
                JSONArray list = data.getJSONArray("list");
                List<TransactionDay> transactionDays = JSONArray.parseArray(list.toJSONString(), TransactionDay.class);
                if (!Check.isNull(transactionDays)) {
                    ctopAccountTransactionDayMapper.replaceAccountTransactionDay(transactionDays);
                }

                JSONObject pageInfo = data.getJSONObject("page_info");
                Integer totalPage = pageInfo.getInteger("total_page");
                if (totalPage > page) {
                    insertAccountTransactionDay(accountId, startDate, endDate, page + 1);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            log.info("同步失败:{}", e.toString());
        }


    }

    /**
     * 同步账户日流水
     *
     * @author zzy
     * @create: 2021-07-15
     */
    @Override
    public void synchronousAccountTransactionDayNew(String startDate, String endDate, int page, int pageSize) {

        List<TransactionDay> list = new ArrayList<>();
        List<String> accountIdList = ctopAgentAccountMapper.getAllAccountId();

//        List<String> accountIdList = new ArrayList<>();
//        accountIdList.add("1735775204994062");
//        accountIdList.add("1744114166675533");
//        accountIdList.add("1744114166069261");

        for (String accountId : accountIdList) {
            page = 1;
            log.info("同步头条账户流水信息{}:开始时间{},结束时间{},第{}页", accountId, startDate, endDate, page);

            JSONObject jsonObject = queryAccountTransactionDay(accountId, page, 1000, startDate, endDate);
            JSONObject data = null;
            int code = 1;
            if (jsonObject != null) {
                data = (JSONObject) jsonObject.get("data");
                code = (int) jsonObject.get("code");
            } else {
                log.info("头条账户流水信心为空，数据jsonObject为null");
                continue;
            }
            if (code != 0) {
                log.info("获取头条账户流水返回数据:" + jsonObject.toJSONString() + ":" + accountId);
                continue;
            }
            if (data != null) {
                List<Object> dataList = (List<Object>) data.get("list");
                if (dataList != null && !dataList.isEmpty()) {
                    dataList.stream().forEach(ob -> {
                        TransactionDay transactionDay = JSONObject.toJavaObject((JSON) ob, TransactionDay.class);
                        list.add(transactionDay);
                    });
                }
            }
            ctopAccountTransactionDayMapper.replaceAccountTransactionDay(list);
            log.info("获取头条账户:{}流水信息{}条", accountId, list.size());
            page++;
            int totalPage = jsonObject.getJSONObject("data").getJSONObject("page_info").getInteger("total_page");
            if (page <= totalPage) {
                synchronousAccountTransactionDayNew(startDate, endDate, page, 1000);
            }
        }

    }

    /**
     * 查询账号流水明细
     *
     * @return
     * @author zzy
     * @Param AccountId 账户id    transaction_type 流水类型  RECHARGE:充值  TRANSFER:转账     pageNum 当前页    pageSize 每页显示数量
     * @create: 2021-07-14
     */
    @Override
    public JSONObject queryAccountTransactionDetails(String AccountId, String transaction_type, int pageNum, int pageSize, String startDate, String endDate) {
        // 请求参数
        Map data = new HashMap() {
            {
                put("advertiser_id", AccountId);
                put("start_date", startDate);
                put("end_date", endDate);
                put("transaction_type", transaction_type);
                put("page", pageNum);
                put("page_size", pageSize);
            }
        };
        return sendHttpRequest(data, ACCOUNT_TRANSACTION_DETAILS_URL);
    }

    /**
     * 查询账号日流水
     *
     * @return
     * @author zzy
     * @Param AccountId 账户id       pageNum 当前页    pageSize 每页显示数量
     * @create: 2021-07-14
     */
    @Override
    public JSONObject queryAccountTransactionDay(String AccountId, int pageNum, int pageSize, String startDate, String endDate) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        Calendar ca = Calendar.getInstance();
        ca.setTime(new Date());
        ca.add(Calendar.DATE, -1);
        // 请求参数
        Map data = new HashMap() {
            {
                put("advertiser_id", AccountId);
                put("start_date", startDate);
                put("end_date", endDate);
                put("page", pageNum);
                put("page_size", pageSize);
            }
        };
        return sendHttpRequest(data, ACCOUNT_TRANSACTION_DAY_URL);


    }


    /**
     * 获取token
     *
     * @author zzy
     * @create: 2021-07-14
     */
    @Override
    public String getToken(long advertiserId) {
//        CtopOauthToken ctopOauthToken = ctopAgentAccountMapper.selectByAccountId(Long.parseLong(ADVERTISER_ID));
        CtopOauthToken ctopOauthToken = ctopAgentAccountMapper.selectByAccountId(advertiserId);
        if (ctopOauthToken != null) {
            return ctopOauthToken.getAccessToken();
        } else {
            log.info("未查询到Token");
            return null;
        }

    }

    /**
     * 获取账户列表
     *
     * @author zzy
     * @Param pageNum 当前页    pageSize 每页显示数量
     * @create: 2021-07-14
     */
    @Override
    public JSONObject selectAgentAdvertiser(int pageNum, int pageSize, String account) {
        // 请求参数
        Map data = new HashMap() {
            {
                put("advertiser_id", account);
                put("page", pageNum);
                put("page_size", pageSize);
            }
        };
        return sendHttpRequest(data, ACCOUNT_LIST_URL);
    }


    /**
     * 根据地址请求巨量殷勤，返回响应结果
     *
     * @author zzy
     * @Param data 请求参数    apiUrl请求路径
     * @create: 2021-07-14
     */
    public JSONObject sendHttpRequest(Map data, String apiUrl) {
        String access_token = getToken(Long.parseLong(data.get("advertiser_id").toString()));
        // 构造请求
        HttpEntityEnclosingRequestBase httpEntity = new HttpEntityEnclosingRequestBase() {
            @Override
            public String getMethod() {
                return "GET";
            }
        };

        httpEntity.setHeader("Access-Token", access_token);

        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;

        try {
            client = HttpClientBuilder.create().build();
            httpEntity.setURI(URI.create(OPEN_API_URL_PREFIX + apiUrl));
            httpEntity.setEntity(new StringEntity(JSONObject.toJSONString(data), ContentType.APPLICATION_JSON));

            response = client.execute(httpEntity);
            if (response != null && response.getStatusLine().getStatusCode() == 200) {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                StringBuffer result = new StringBuffer();
                String line = "";
                while ((line = bufferedReader.readLine()) != null) {
                    result.append(line);
                }
                bufferedReader.close();
                return JSONObject.parseObject(result.toString());
            }

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}
