package com.liquidnet.service.platform.service.impl.adam.dm.processor;

import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.adam.dto.vo.AdamTagVo;
import com.liquidnet.service.adam.dto.vo.AdamUserInfoVo;
import com.liquidnet.service.adam.entity.AdamUser;
import com.liquidnet.service.adam.entity.AdamUserInfo;
import com.liquidnet.service.platform.service.impl.adam.dm.DMUserInfoService;
import com.liquidnet.service.platform.service.impl.adam.dm.DMUserService;
import com.liquidnet.service.platform.service.impl.adam.dm.DataMigrationProcessorService;
import com.mysql.cj.jdbc.result.ResultSetImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class DMUserInformationProcessor extends DataMigrationProcessorService {
    @Autowired
    DMUserService dmUserService;
    @Autowired
    DMUserInfoService dmUserInfoService;

    public static Map<String, AdamTagVo> sexMap = new HashMap<>();

    static {
        sexMap.put("SECRET", AdamTagVo.getNew().setVal("MS00").setDesc("保密"));
        sexMap.put("MALE", AdamTagVo.getNew().setVal("MS01").setDesc("男性"));
        sexMap.put("FEMALE", AdamTagVo.getNew().setVal("MS02").setDesc("女性"));
    }

    @SneakyThrows
    @Override
    public void dataProcessing(Integer dg, Integer dG, String incrDt, String flg, String flu) {
        if (StringUtils.isNotEmpty(flu)) {
            log.info("DM.flush.user:{}", userMapper.executeForDM("adam_user"));
            log.info("DM.flush.user_info:{}", userMapper.executeForDM("adam_user_info"));

//            log.info("DM.flush.AdamUserInfoVo:{}", mongoTemplate.remove(Query.query(Criteria.where("_id").exists(true)), AdamUserInfoVo.class.getSimpleName()).getDeletedCount());
        }

//        String sqlCount = "select count(1) from users where delete_tag in (0,1) and length(mobile)=11 and created_at" + (StringUtils.isBlank(incrDt) ? "<" : ">=") + "curdate()";
        String sqlCount = "select count(1) from users where delete_tag in (0,1) and created_at" + (StringUtils.isBlank(incrDt) ? "<curdate()" : (">=curdate()-" + incrDt));
        if (null != dg) {
            sqlCount = sqlCount + " and uid%" + dG + "=" + dg;
        }
        String field = "uid,mobile,username,sex,birthday,area,sign,face_url,back_url,created_at,updated_at,is_complete,rong_cloud_token,rong_cloud_tag";
//                     1-uid,2-mobile,3-username,4-sex,5-birthday,6-area,7-sign,8-face_url,9-back_url,10-created_at,11-updated_at,12-is_complete,13-rong_cloud_token,14-rong_cloud_tag
        String sql = sqlCount.replace("count(1)", field);
        boolean smFlg = "1".equals(flg);
        if (smFlg) {
            sqlCount += "and mobile in (" + DG_MBL + ")";
            sql += " and mobile in (" + DG_MBL + ")";
        }
        sql += " order by uid limit ?,?";

        LocalDateTime currentYear = DateUtil.Formatter.yyyyMMddHHmmss.parse("2021-01-01 00:00:00");
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSetImpl row = null;
        try {
            Class.forName(DB_DRIVER);
            connection = DriverManager.getConnection(DB_URL + DB_NAME_PASSPORT, DB_USER, DB_PWD);
            statement = connection.prepareStatement(sqlCount);
            row = (ResultSetImpl) statement.executeQuery();
            row.first();
            int ct = row.getInt(1), pSize = 1000, num = 0, tl = 0, pl = ct;
            log.info("DM.execute.counts:{}/{},{} ~ {} ----------------------------> start.sql:{}", pl, num, pSize, tl, sql);

            row.close();
            statement.close();
            while (ct > 0) {
                statement = connection.prepareStatement(sql);
                int ls = pSize * num;
                statement.setInt(1, ls);
                statement.setInt(2, pSize);
                row = (ResultSetImpl) statement.executeQuery();
                log.info("DM.execute.limit {},{} - begin", ls, pSize);

                List<AdamUser> userList = new ArrayList<>();
                List<AdamUserInfo> userInfoList = new ArrayList<>();
                List<AdamUserInfoVo> vos = new ArrayList<>();
                while (row.next()) {
                    AdamTagVo sex = sexMap.get(row.getString(4));
                    String uid = row.getString(1);
                    if (!reUidList.contains(uid)) {
                        AdamUser user = new AdamUser();
                        user.setUid(uid);
                        String mobile = row.getString(2);
                        user.setMobile(mobile);
                        LocalDateTime createdAt = row.getLocalDateTime(10), updatedAt = row.getLocalDateTime(11);
                        user.setCreatedAt(createdAt);
                        user.setUpdatedAt(updatedAt);
                        user.setState(1);

                        AdamUserInfo userInfo = new AdamUserInfo();
                        userInfo.setUid(user.getUid());
                        userInfo.setNickname(row.getString(3));
                        userInfo.setSex(JsonUtils.toJson(sex));
                        userInfo.setBirthday(row.getLocalDate(5));
                        userInfo.setArea(row.getString(6));
                        userInfo.setSignature(row.getString(7));
                        userInfo.setAvatar(row.getString(8));
                        userInfo.setBackground(row.getString(9));
                        userInfo.setQrCode("lN".concat(userInfo.getUid()).concat(RandomStringUtils.randomAlphanumeric(5).toUpperCase()));
                        userInfo.setRongCloudToken(row.getString(13));
                        userInfo.setRongCloudTag(row.getInt(14));

                        AdamUserInfoVo vo = AdamUserInfoVo.getNew();
                        vo.setUid(user.getUid());
                        vo.setMobile(user.getMobile());
                        vo.setNickname(userInfo.getNickname());
                        vo.setState(user.getState());
                        vo.setSex(sex);
                        vo.setBirthday(DateUtil.Formatter.yyyy_MM_dd.format(userInfo.getBirthday()));
                        vo.setArea(userInfo.getArea());
                        vo.setSignature(userInfo.getSignature());
                        vo.setAvatar(userInfo.getAvatar());
                        vo.setBackground(userInfo.getBackground());
                        vo.setCreateAt(user.getCreatedAt());
                        vo.setUpdatedAt(user.getUpdatedAt());
                        vo.setIsComplete(row.getInt(12));
                        vo.setQrCode(userInfo.getQrCode());

                        userList.add(user);
                        userInfoList.add(userInfo);
                        vos.add(vo);

                        if (StringUtils.length(mobile) == 11) {
                            dmRdmService.setUidByMobile(mobile, uid);
                            dmRdmService.setUserInfoVoByUid(uid, vo);
                        }
                    }
                    if (userList.size() == 500 || (userList.size() > 0 && smFlg)) {
                        tl += userList.size();
//                        mongoTemplate.insert(vos, AdamUserInfoVo.class.getSimpleName());
                        log.info("DM.execute.result:{} - {}", dmUserService.saveBatch(userList), dmUserInfoService.saveBatch(userInfoList));
                        vos.clear();
                        userList.clear();
                        userInfoList.clear();
                    }
                }
                row.close();
                statement.close();

                num++;
                ct -= pSize;

                log.info("DM.execute.limit {},{} - handle.counts:{}", ls, pSize, tl);
            }
            log.info("DM.execute.counts:{}/{},{} ~ {} ----------------------------> end", pl, num, pSize, tl);
        } catch (Exception e) {
            log.error("ex:getConnection,dG/dg:{}/{},msg:{}", dG, dg, e.getMessage());
        }
        try {
            if (null != row) row.close();
        } catch (SQLException ignored) {
        }
        try {
            if (null != statement) statement.close();
        } catch (SQLException ignored) {
        }
        try {
            if (null != connection) connection.close();
        } catch (SQLException ignored) {
        }
    }
}
