package org.jeecg.ctop.finance.agent.service.impl;

import cn.com.ctop.common.module.entity.CtopOauthToken;
import com.alibaba.fastjson.JSON;
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.jeecg.ctop.finance.agent.entity.TransactionDay;
import org.jeecg.ctop.finance.agent.entity.TransactionDetails;
import org.jeecg.ctop.finance.agent.mapper.CtopAccountTransactionDayMapper;
import org.jeecg.ctop.finance.agent.mapper.CtopAccountTransactionDetailsMapper;
import org.jeecg.ctop.finance.agent.mapper.CtopAgentAccountMapper;
import org.jeecg.ctop.finance.agent.service.AgentManagementService;
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.*;

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";

    @Resource
    CtopAgentAccountMapper ctopAgentAccountMapper;
    @Resource
    CtopAccountTransactionDetailsMapper ctopAccountTransactionDetailsMapper;

    @Resource
    CtopAccountTransactionDayMapper ctopAccountTransactionDayMapper;

    /**
     * 同步代理商下账号
     *
     * @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 {
            //分页查询第一页数据
            JSONObject agentAccountList = selectAgentAdvertiser(1, 2000);
            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);
                    JSONObject agentData = (JSONObject) agenttList.get("data");
                    List<Long> list = (List<Long>) agentData.get("list");
                    list.stream().forEach(str -> {
                        dataList.add(str.toString());
                    });

                }
                //查询数据库已存在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("开始同步账号日流水");
        Result result = new Result();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        Calendar ca = Calendar.getInstance();
        ca.setTime(new Date());
        ca.add(Calendar.DATE, -1);
        List<TransactionDay> transactionDetailsList = new ArrayList<>();
        try {
            List<String> accountIdList = ctopAgentAccountMapper.getAllAccountId();
            if (!accountIdList.isEmpty()) {
                accountIdList.stream().forEach(str -> {
                    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.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.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;
    }

    /**
     * 查询账号流水明细
     *
     * @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() {
        CtopOauthToken ctopOauthToken = ctopAgentAccountMapper.selectByAccountId(Long.parseLong(ADVERTISER_ID));
        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) {
        // 请求参数
        Map data = new HashMap() {
            {
                put("advertiser_id", ADVERTISER_ID);
                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();
        // 构造请求
        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;
    }

}
