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

import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.adam.dto.vo.AdamThirdPartInfoVo;
import com.liquidnet.service.adam.entity.AdamThirdParty;
import com.liquidnet.service.platform.service.impl.adam.dm.DMThirdPartyService;
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.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.List;

@Slf4j
@Service
public class DMThirdPartsProcessor extends DataMigrationProcessorService {
    @Autowired
    DMThirdPartyService dmThirdPartyService;

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

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

        String sqlCount = "select count(1) from (" +
                "                         select row_number() over (partition by uid,type order by created_at desc) rn,id,uid,open_id,avatar,nickname,type,created_at,updated_at from user_third_parts where `status`=1 and delete_tag in (0,1) and open_id<>'' and uid>0 and created_at" + (StringUtils.isBlank(incrDt) ? "<curdate()" : (">=curdate()-" + incrDt)) +
                "                     ) t where t.rn=1";
        if (null != dg) {
            sqlCount = sqlCount + " and id%" + dG + "=" + dg;
        }
        String field = "uid,open_id,avatar,nickname,type,created_at,updated_at";
//                     1-uid,2-open_id,3-avatar,4-nickname,5-type,6-created_at,7-updated_at
        String sql = sqlCount.replace("count(1)", field);
        boolean smFlg = "1".equals(flg);
        if (smFlg) {
            sqlCount += " and uid in (" + DG_UID + ")";
            sql += " and uid in (" + DG_UID + ")";
        }
        sql += " order by id 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 = 2000, 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<AdamThirdParty> thirdPartyList = new ArrayList<>();
                List<AdamThirdPartInfoVo> vos = new ArrayList<>();
                while (row.next()) {
                    String uid = row.getString(1);
                    if (!reUidList.contains(uid)) {
                        AdamThirdParty thirdParty = new AdamThirdParty();
                        thirdParty.setUid(uid);
                        thirdParty.setOpenId(row.getString(2));
                        thirdParty.setAvatar(row.getString(3));
                        thirdParty.setNickname(row.getString(4));
                        thirdParty.setPlatform(row.getString(5));
                        thirdParty.setState(1);
                        LocalDateTime createdAt = row.getLocalDateTime(6);
                        thirdParty.setCreatedAt(createdAt);
                        thirdParty.setUpdatedAt(row.getLocalDateTime(7));

                        AdamThirdPartInfoVo vo = AdamThirdPartInfoVo.getNew();
                        vo.setUid(thirdParty.getUid());
                        vo.setOpenId(thirdParty.getOpenId());
                        vo.setNickname(thirdParty.getNickname());
                        vo.setAvatar(thirdParty.getAvatar());
                        vo.setPlatform(thirdParty.getPlatform());
                        vo.setState(thirdParty.getState());
                        vo.setCreatedAt(thirdParty.getCreatedAt());
                        vo.setUpdatedAt(thirdParty.getUpdatedAt());

                        thirdPartyList.add(thirdParty);
                        vos.add(vo);

                        dmRdmService.setUidByPlatformOpenId(thirdParty.getPlatform(), thirdParty.getOpenId(), uid);
                        dmRdmService.addThirdPartVoListByUid(uid, dmRdmService.getThirdPartVoListByUid(uid), vo);
                    }
                    if (thirdPartyList.size() == 1000 || (thirdPartyList.size() > 0 && smFlg) || ct <= 1000) {
                        tl += thirdPartyList.size();
//                        mongoTemplate.insert(vos, AdamThirdPartInfoVo.class.getSimpleName());
                        log.info("DM.execute.limit.result:{}", dmThirdPartyService.saveBatch(thirdPartyList));
                        vos.clear();
                        thirdPartyList.clear();
                    }
                }
                if (thirdPartyList.size() > 0) {
                    tl += thirdPartyList.size();
                    log.info("DM.execute.limit.result:{}", dmThirdPartyService.saveBatch(thirdPartyList));
                }
                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:{}/{}", dG, dg, e);
        }
        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) {
//        }
    }
}
