package com.mobvista.apptag.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonArray;
import org.apache.commons.lang3.StringUtils;

import java.sql.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.*;

/**
 * @package: com.mobvista.apptag.utils
 * @author: wangjf
 * @date: 2019-08-12
 * @time: 15:18
 * @email: jinfeng.wang@mobvista.com
 * @phone: 152-1062-7698
 */
public class StorageTag {
    //  private static final String CONNECTION_URL = "jdbc:mysql://localhost:3306/app_tag?useUnicode=true&characterEncoding=utf8&useSSL=false";
    private static final String CONNECTION_URL = "jdbc:mysql://dataplatform-app-tag.c5yzcdreb1xr.us-east-1.rds.amazonaws.com:3306/app_tag?useSSL=false";
    private static final String DRIVER = "com.mysql.jdbc.Driver";
    //  private static final String USER = "root";
    private static final String USER = "apptag_rw";
    //  private static final String PASSWORD = "19920627";
    private static final String PASSWORD = "7gyLEVtkER3u8c9";
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static ObjectMapper mapper = new ObjectMapper();
    private static Connection connection = null;
    private static PreparedStatement preparedStatement = null;
    private static PreparedStatement preparedStatement_admin = null;

    public static void main(String[] args) {

        String sql = String.format("SELECT a.package_name,a.app_name,a.platform,JSON_KEYS(feat_id) tag_arr,t.tag FROM app_tag.tag_result a " +
                "LEFT JOIN (SELECT package_name,tag FROM app_tag.tag_list WHERE tag > 1) t " +
                "ON a.package_name = t.package_name WHERE t.package_name IS NOT NULL AND t.package_name NOT IN (SELECT DISTINCT package_name FROM app_tag.storage)");
        String sqlAdmin = String.format("SELECT a.package_name,a.app_name,a.platform,feat_id tag FROM app_tag.tag_result a " +
                "LEFT JOIN app_tag.user u ON a.user_id = u.user_id WHERE u.role = 1 AND a.package_name NOT IN (SELECT DISTINCT package_name FROM app_tag.storage)");

        try {
            Class.forName(DRIVER);
            connection = DriverManager.getConnection(CONNECTION_URL, USER, PASSWORD);
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement_admin = connection.prepareStatement(sqlAdmin);
            ResultSet resultSetAdmin = preparedStatement_admin.executeQuery();
            ResultSet resultSet = preparedStatement.executeQuery();
            Map<String, Integer> map = new HashMap<>();
            while (resultSet.next()) {
                String packageName = resultSet.getString("package_name");
                String appName = resultSet.getString("app_name");
                String platform = resultSet.getString("platform");
                String userCount = resultSet.getString("tag");
                String tag_arr = resultSet.getString("tag_arr");
                JsonArray jsonArray = GsonUtil.String2JsonArray(tag_arr);
                for (int i = 0; i < jsonArray.size(); i++) {
                    //  jsonArray.get(i).getAsString() tagId
                    String key = packageName + "#@#" + appName + "#@#" + platform + "#@#" + jsonArray.get(i).getAsString() + "#@#" + userCount;
                    if (map.containsKey(key)) {
                        map.put(key, map.get(key) + 1);
                    } else {
                        map.put(key, 1);
                    }
                    if (map.size() == 1000) {
                        insert(map);
                        map = new HashMap<>();
                    }
                }
            }
            insert(map);

            resultSet.close();
            preparedStatement.close();
            if (resultSetAdmin.next()) {
                insertAdmin(resultSetAdmin);
            }
            resultSetAdmin.close();
            preparedStatement_admin.close();
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
                if (preparedStatement_admin != null) {
                    preparedStatement_admin.close();
                }
            } catch (SQLException se) {
            }
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
    }

    //  更新已经入库的标签
    private static void delete(Set<String> set) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection con = DriverManager.getConnection(CONNECTION_URL, USER, PASSWORD);
            Statement stmt1 = con.createStatement();
            //  Statement stmt2 = con.createStatement();
            String deleteSql1 = "DELETE FROM storage_result WHERE package_name IN ";
            //  String deleteSql2 = "DELETE FROM storage WHERE package_name IN ";
            Iterator<String> iterator = set.iterator();
            StringBuffer sql = new StringBuffer();
            while (iterator.hasNext()) {
                String packageName = iterator.next();
                sql.append("'").append(packageName).append("',");
            }
            stmt1.execute(deleteSql1 + "(" + sql.substring(0, sql.length() - 1) + ")");
            stmt1.close();
            //  stmt2.execute(deleteSql2 + "(" + sql.substring(0, sql.length() - 1) + ")");
            //  stmt2.close();
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void update(Set<String> set) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection con = DriverManager.getConnection(CONNECTION_URL, USER, PASSWORD);
            Statement stmt1 = con.createStatement();
            Statement stmt2 = con.createStatement();
            String updateSql1 = "UPDATE app_tag.tag_result SET flag = 1 WHERE package_name IN ";
            String updateSql2 = "UPDATE app_tag.tag_list SET flag = 1 WHERE package_name IN ";
            Iterator<String> iterator = set.iterator();
            StringBuffer sql = new StringBuffer();
            while (iterator.hasNext()) {
                String packageName = iterator.next();
                sql.append("'").append(packageName).append("',");
            }
            stmt1.execute(updateSql1 + "(" + sql.substring(0, sql.length() - 1) + ")");
            stmt1.close();
            stmt2.execute(updateSql2 + "(" + sql.substring(0, sql.length() - 1) + ")");
            stmt2.close();
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param resultSet
     * @throws SQLException
     * @desc 插入超级管理员标注的标签
     */
    private static void insertAdmin(ResultSet resultSet) throws SQLException {

        StringBuffer insertSql = new StringBuffer();
        Set<String> packageSet = new HashSet<>();
        while (resultSet.next()) {
            String packageName = resultSet.getString("package_name");
            String appName = resultSet.getString("app_name");
            if (StringUtils.isNotBlank(appName)) {
                appName = appName.replace("\'", "\\'");
            }
            String platform = resultSet.getString("platform");
            String tag = resultSet.getString("tag");

            insertSql.append("('").append(packageName).append("','").append(appName).append("','").append(platform).append("','").append(tag)
                    .append("','").append(sdf.format(new Date())).append("'),");
            packageSet.add(packageName);
        }
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection con = DriverManager.getConnection(CONNECTION_URL, USER, PASSWORD);
            Statement stmt = con.createStatement();
            String insert_sql = "REPLACE INTO storage(package_name, app_name, platform, tag, update_time) " +
                    "VALUES";
            //  System.out.println(insert_sql + insertSql.substring(0, insertSql.length() - 1));
            if (insertSql.length() > 0) {
                stmt.executeQuery(insert_sql + insertSql.substring(0, insertSql.length() - 1));
            }
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (packageSet.size() > 0) {
            update(packageSet);
        }
    }

    private static void insert(Map<String, Integer> map) throws JsonProcessingException {
        Iterator<String> iterator = map.keySet().iterator();
        Map<String, Map<String, String>> tagMap = new HashMap<>();
        StringBuffer insertSql_1 = new StringBuffer();
        StringBuffer insertSql_2 = new StringBuffer();

        Set<String> packageSet = new HashSet<>();
        Map<String, String> featMap = getMap();

        while (iterator.hasNext()) {
            String key = iterator.next();
            String[] strs = key.split("#@#");
            String packageName = strs[0];
            String appName = strs[1];
            if (StringUtils.isNotBlank(appName)) {
                appName = appName.replace("'", "\\'");
            } else {
                appName = "";
            }
            String platform = strs[2];
            String tagId = strs[3];
            Integer userCount = Integer.parseInt(strs[4]);
            Integer tagCount = map.get(key);
            String key1 = packageName + "#@#" + appName + "#@#" + platform;
            DecimalFormat df = new DecimalFormat("#.###");
            Double tagRate = Double.parseDouble(df.format(tagCount / Double.valueOf(userCount)));
            if (tagRate > 0.5) {
                packageSet.add(packageName);
                insertSql_1.append("('").append(packageName).append("','").append(appName).append("','").append(platform).append("','").append(tagId)
                        .append("','").append(sdf.format(new Date())).append("',").append(userCount).append(",").append(tagCount).append(",").append(tagRate).append("),");
                Map<String, String> tmap = new HashMap<>();
                if (tagMap.containsKey(key1)) {
                    tmap = tagMap.get(key1);
                    tmap.put(tagId, featMap.getOrDefault(tagId, ""));
                } else {
                    tmap.put(tagId, featMap.getOrDefault(tagId, ""));
                }
                tagMap.put(key1, tmap);
            }
        }

        if (packageSet.size() > 0) {
            delete(packageSet);
        }

        Iterator<String> iters = tagMap.keySet().iterator();
        while (iters.hasNext()) {
            String key = iters.next();
            String[] arr = key.split("#@#");
            insertSql_2.append("('").append(arr[0]).append("','").append(arr[1]).append("','").append(arr[2]).append("','").append(mapper.writeValueAsString(tagMap.get(key))).append("','")
                    .append(sdf.format(new Date())).append("'),");
        }

        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection con = DriverManager.getConnection(CONNECTION_URL, USER, PASSWORD);
            Statement stmt = con.createStatement();
            Statement stmt1 = con.createStatement();
            String insert_sql1 = "REPLACE INTO storage_result(package_name, app_name, platform, feat_id, update_time, user_count, tag_count, tag_rate) " +
                    "VALUES";


            String insert_sql2 = "REPLACE INTO storage(package_name, app_name, platform, tag, update_time) " +
                    "VALUES";
            //  System.out.println(insert_sql1 + insertSql_1.substring(0, insertSql_1.length() - 1));
            //  System.out.println(insert_sql2 + insertSql_2.substring(0, insertSql_2.length() - 1));
            if (insertSql_1.length() > 0) {
                System.out.println("insertSql ==>> " + insertSql_1);
                System.out.println("insertSql ====>>> " + insert_sql1 + insertSql_1.substring(0, insertSql_1.length() - 1));
                stmt.executeQuery(insert_sql1 + insertSql_1.substring(0, insertSql_1.length() - 1));
            }
            if (insertSql_2.length() > 0) {
                stmt1.executeQuery(insert_sql2 + insertSql_2.substring(0, insertSql_2.length() - 1));
            }
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (packageSet.size() > 0) {
            update(packageSet);
        }
    }

    private static Map<String, String> getMap() {
        Map<String, String> map = new HashMap<>();
        try {
            Class.forName(DRIVER);
            connection = DriverManager.getConnection(CONNECTION_URL, USER, PASSWORD);
            String sql = "SELECT DISTINCT second_id,second_tag FROM tag_feat";
            preparedStatement = connection.prepareStatement(sql);
            ResultSet resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                String secondId = resultSet.getString("second_id");
                String secondTag = resultSet.getString("second_tag");
                map.put(secondId, secondTag);
            }
            resultSet.close();
            preparedStatement.close();
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
            } catch (SQLException se) {
            }
            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
        return map;
    }
}
