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

import com.liquidnet.service.adam.dto.vo.AdamMemberOrderVo;
import com.liquidnet.service.adam.entity.AdamMemberOrder;
import com.liquidnet.service.platform.service.impl.adam.dm.DMMemberOrderService;
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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class DMMemberOrderProcessor extends DataMigrationProcessorService {
    @Autowired
    DMMemberOrderService dmMemberOrderService;

    // APPWEPAY|APPALIPAY|WAPWEPAY|WAPALIPAY|JSWEPAY|GIFT_CODE|VIP_CODE|APPLETWEPAY
    public static final Map<String, String> dfMap = new HashMap<>();
    public static final Map<String, String> ptMap = new HashMap<>();

    static {
        dfMap.put("APPWEPAY", "app");
        dfMap.put("APPALIPAY", "app");
        dfMap.put("WAPWEPAY", "wap");
        dfMap.put("WAPALIPAY", "wap");
        dfMap.put("JSWEPAY", "js");
        dfMap.put("APPLETWEPAY", "applet");
        dfMap.put("APPLETALIPAY", "applet");

        ptMap.put("APPWEPAY", "wepay");
        ptMap.put("APPALIPAY", "alipay");
        ptMap.put("WAPWEPAY", "wepay");
        ptMap.put("WAPALIPAY", "alipay");
        ptMap.put("JSWEPAY", "wepay");
        ptMap.put("APPLETWEPAY", "wepay");
        ptMap.put("APPLETALIPAY", "alipay");
    }

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

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

        String sqlCount = "select count(1) from user_vip_card_orders where status in (1,5) and created_at" + (StringUtils.isBlank(incrDt) ? "<" : ">=") + "curdate()";
        if (null != dg) {
            sqlCount = sqlCount + " and id%" + dG + "=" + dg;
        }
        String field = "order_code,uid,order_sub_type,vip_card_price,price,status,card_number,birthday,pay_type,pay_code,pay_at,created_at,updated_at,client_ip,source,version";
//      1-order_code,2-uid,3-order_sub_type,4-vip_card_price,5-price,6-status,7-card_number,8-birthday,
//      9-pay_type,10-pay_code,11-pay_at,12-created_at,13-updated_at,14-client_ip,15-source,16-version
        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 ?,?";

        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<AdamMemberOrder> memberOrderList = new ArrayList<>();
                List<AdamMemberOrderVo> vos = new ArrayList<>();
                while (row.next()) {
                    String uid = row.getString(2);
                    if (!reUidList.contains(uid)) {
                        AdamMemberOrder memberOrder = new AdamMemberOrder();
                        memberOrder.setOrderNo(row.getString(1));
                        memberOrder.setUid(uid);
                        memberOrder.setMode(row.getInt(3));
                        memberOrder.setPrice(row.getBigDecimal(4));
                        memberOrder.setPricePaid(row.getBigDecimal(5));
                        memberOrder.setMemberName(MEMBER_NAME);
                        memberOrder.setMemberId(MEMBER_ID);
                        memberOrder.setMemberPriceId(MEMBER_ID);
                        memberOrder.setDays(365);
                        memberOrder.setState(row.getInt(6));
                        memberOrder.setMemberNo(row.getString(7));
                        memberOrder.setBirthday(row.getString(8));
                        String payType = row.getString(9);
                        memberOrder.setDeviceFrom(dfMap.get(payType));
                        memberOrder.setPayType(ptMap.get(payType));
                        memberOrder.setPayNo(row.getString(10));
                        memberOrder.setPaymentAt(row.getLocalDateTime(11));
                        memberOrder.setCreatedAt(row.getLocalDateTime(12));
                        memberOrder.setUpdatedAt(row.getLocalDateTime(13));
                        memberOrder.setClientIp(row.getString(14));
                        memberOrder.setSource(row.getString(15));
                        memberOrder.setVersion(row.getString(16));

                        AdamMemberOrderVo vo = AdamMemberOrderVo.getNew().copy(memberOrder);

                        memberOrderList.add(memberOrder);
                        vos.add(vo);
                    }
                    if (memberOrderList.size() == 500 || (memberOrderList.size() > 0 && smFlg)) {
                        tl += memberOrderList.size();
                        mongoTemplate.insert(vos, AdamMemberOrderVo.class.getSimpleName());
                        log.info("DM.execute.limit.result:{}", dmMemberOrderService.saveBatch(memberOrderList));
                        vos.clear();
                        memberOrderList.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) {
        }
    }
}
