package com.steering.pss.plnsaleord.planStove;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.ibatis.io.ResolverUtil.IsA;

import CoreFS.SA08.CoreXmlSqlParsersFactory;

import com.steering.comm.db.DBCommon;
import com.steering.comm.tools.EntityTool;
import com.steering.pss.judge.comm.ChemJudgeHelper;
import com.steering.pss.judge.comm.JudgeHelper;
import com.steering.pss.judge.model.CraftOrdDesignStdCicEntity;
import com.steering.pss.judge.model.QcmJhyElementsEntity;

public class GaiPanOptimizer  extends DBCommon {
    
    // 线程池大小 - 可根据实际服务器配置调整
	private static final int THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors(); // 按CPU核数设置
	private static final int BATCH_SIZE = 5; // 增大批次减少任务数（但需平衡内存）
    
	/**
	 * 优化后的改判异步处理方法（分批写入版）
	 * @param proessCode 工序代码
	 */
	public void optimizedGaiPan(final String proessCode, Connection conn) throws Exception {
	    conn.setAutoCommit(false);
	    
	    // 1. 预加载所有必要数据
	    final List<QcmJhyElementsEntity> allStoveNos = loadAllStoveNos(conn,proessCode);
	    final List<Map<String, Object>> orderData = loadOrderData(proessCode, conn);
	    if(proessCode.equals("F")){
	    	List<Map<String, Object>> orderDataD = loadOrderData("D", conn);
	    	orderData.addAll(orderDataD);
	    }
	    final Map<String, List<CraftOrdDesignStdCicEntity>> stdCicCache = loadStdCicCache(orderData, conn);
	    
	    // 2. 创建线程池
	    int coreCount = Runtime.getRuntime().availableProcessors();
	    ExecutorService executor = Executors.newFixedThreadPool(Math.min(coreCount, THREAD_POOL_SIZE));
	    
	    // 3. 先清空目标表
	    try (PreparedStatement delStmt = conn.prepareStatement(
	            "DELETE FROM zg_ord_std_cic WHERE proess_code = ?")) {
	        delStmt.setString(1, proessCode);
	        delStmt.executeUpdate();
	    }
	    
	    // 4. 分批处理炉号并立即写入
	    try (PreparedStatement insertStmt = conn.prepareStatement(
	            "INSERT INTO zg_ord_std_cic(stove_no, pro_order_no, proess_code,cic) VALUES (?, ?, ?,?)")) {
	        
	        // 计数器跟踪进度
	        AtomicInteger processedCount = new AtomicInteger(0);
	        int totalStoves = allStoveNos.size();
	        
	        for (int i = 0; i < totalStoves; i += BATCH_SIZE) {
	            int endIndex = Math.min(i + BATCH_SIZE, totalStoves);
	            List<QcmJhyElementsEntity> batchStoveNos = allStoveNos.subList(i, endIndex);
	            
	            // 提交批次任务
	            Future<List<Object[]>> future = executor.submit(new BatchProcessor(
	                batchStoveNos, orderData, stdCicCache
	            ));
	            
	            // 等待本批次完成并立即写入
	            List<Object[]> batchResults = future.get();
	            for (Object[] result : batchResults) {
	                insertStmt.setString(1, (String) result[0]);
	                insertStmt.setString(2, (String) result[1]);
	                insertStmt.setString(3, proessCode);
	                insertStmt.setString(4, (String) result[2]);
	                insertStmt.addBatch();
	            }
	            
	            // 执行本批次插入
	            insertStmt.executeBatch();
	            conn.commit(); // 每批提交一次（可选）
	            
	            // 清空批处理缓存
	            insertStmt.clearBatch();
	            
	            // 打印进度
	            processedCount.addAndGet(batchResults.size());
	            System.out.println(
	            	    "已新增 " + processedCount.get() + " 总炉号：" + totalStoves + "" 
	            	);
	        }
	    } finally {
	        // 确保关闭线程池
	        if (executor != null) {
	            executor.shutdown();
	            if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
	                executor.shutdownNow();
	            }
	        }
	    }
	}
    
    /**
     * 加载所有炉号列表
     */
    private List<QcmJhyElementsEntity> loadAllStoveNos(Connection conn,String proessCode) throws SQLException {
        List<String> stoveNos = new ArrayList<>();
        List<QcmJhyElementsEntity> stoveNosEntity = new ArrayList<>();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
        	String sql = CoreXmlSqlParsersFactory.getSql("FrmEndLibrary.queryMaterial");
        	if (!proessCode.equals("")) {
    			sql += "  AND T.PROCESS_CDOE='" + proessCode + "'";
    		}
			//sql += "  AND T.judge_stove_no='A24080849'";
        	sql+="GROUP BY T.MATERIAL_NO, T.MATERIAL_NAME, T.JUDGE_STOVE_NO, T.BATCH_NO,T.GRADECODE,T.JUDGE_ID," +
                    "T.BATCH_GROUD_NO, T.STOVE_NO, T.PRO_ORDER_ID, T.GX_PLAN_NO, T.HEAT_PLAN_NO, " +
                    "T.PRO_PLAN_ID_NEXT, T.GX_PLAN_NO_NEXT, T.PRODUCNAME, T.GRADENAME, T.STEELNAME, T.PLINE_CODE," +
                    "T.SPEC_NAME, T.MODEL_DESC, T.STD_NAME, T.STD_STYLE_DESC, T.NEXT_PROCESS_CDOE, " +
                    "T.PLINE_NAME, T.ACT_DIMATER, T.ACT_HEIGHT, T.ACT_LEN_MIN, " +
                    "T.ACT_LEN_MAX, T.PRODUCT_FLAG, T.MAT_STATUS, T.BELONG_NAME, T.ORDER_NO, " +
                    "T.ORDER_SEQ, T.PRO_ORDER_NO,T.ORD_LN_DLY_PK, T.CIC, T.PROCESS_CDOE, T.JUGDE_APPLY_CODE, " +
                    "T.JUDGE_RESULT_CODE, T.BELONG_NAME,T.HEAT_PLAN_NO_NEXT,T.HEAT_PLAN_NO_OLD,t.ORDER_SEQ_NO ";
            
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            
            while (rs.next()) {
                stoveNos.add(rs.getString("STOVE_NO"));
            }
            String queryElments = CoreXmlSqlParsersFactory.getSql("FrmEndLibrary.queryelments");
            for (int i = 0; i < stoveNos.size(); i++) {
            	ps = conn.prepareStatement(queryElments);
                ps.setString(1, stoveNos.get(i));
                rs = ps.executeQuery();
                QcmJhyElementsEntity elementsEntity = null;
                elementsEntity = EntityTool.getEntityByRs(rs, QcmJhyElementsEntity.class);
                if(!elementsEntity.equals(null)&&elementsEntity!=null)stoveNosEntity.add(elementsEntity);
			}
        } finally {
            //closeResources(conn, ps, rs);
        }
        return stoveNosEntity;
    }
    
    /**
     * 加载订单数据
     */
    private List<Map<String, Object>> loadOrderData(String proessCode,Connection conn) throws SQLException {
        List<Map<String, Object>> orders = new ArrayList<>();
        PreparedStatement ps = null;
        ResultSet rs = null;
        
        try {
            String dSql = "";
            switch (proessCode) {
                case "D":
                    dSql = CoreXmlSqlParsersFactory.getSql("FrmEndLibrary.queryPlanOrderD") + ")";
                    break;
                case "E":
                    dSql = CoreXmlSqlParsersFactory.getSql("FrmEndLibrary.queryPlanOrderE")+ ") DBK";
                    break;
                case "F":
                    dSql = CoreXmlSqlParsersFactory.getSql("FrmEndLibrary.queryPlanOrderF")+ ") RCL";
                    break;
                case "G":
                    dSql = CoreXmlSqlParsersFactory.getSql("FrmEndLibrary.queryPlanOrderG")+ ") JGX";
                    break;
            }
            //dSql+=" where ORDER_NO like '%250254E%' ";
            
            ps = conn.prepareStatement(dSql);
            rs = ps.executeQuery();
            
            while (rs.next()) {
                Map<String, Object> order = new HashMap<>();
                order.put("PRO_ORDER_NO", rs.getString("PRO_ORDER_NO"));
                order.put("ORD_LN_DLY_PK", rs.getString("ORD_LN_DLY_PK"));
                orders.add(order);
            }
        } finally {
            //closeResources(conn, ps, rs);
        }
        return orders;
    }
    
    /**
     * 加载标准成分缓存
     */
    private Map<String, List<CraftOrdDesignStdCicEntity>> loadStdCicCache(
            List<Map<String, Object>> orderList,Connection conn) throws SQLException {
        
        Map<String, List<CraftOrdDesignStdCicEntity>> cache = new HashMap<>();
        String queryStdCic = CoreXmlSqlParsersFactory.getSql("FrmEndLibrary.queryeStdCic");
        
        for (Map<String, Object> order : orderList) {
            PreparedStatement ps = null;
            ResultSet rs = null;
            
            try {
                String ordLnDlyPk = order.get("ORD_LN_DLY_PK").toString();
                String ordLnPk = ordLnDlyPk.substring(0, ordLnDlyPk.length() - 3);
                
                ps = conn.prepareStatement(queryStdCic);
                ps.setString(1, ordLnPk);
                rs = ps.executeQuery();
                
                List<CraftOrdDesignStdCicEntity> entities = 
                    EntityTool.getEntitysByRs(rs, CraftOrdDesignStdCicEntity.class);
                
                if(entities.size()>0)cache.put(ordLnPk, entities);
            } finally {
                //closeResources(conn, ps, rs);
            }
        }
        return cache;
    }
    
    /**
     * 批量处理器 - 内部类
     */
    private class BatchProcessor implements java.util.concurrent.Callable<List<Object[]>> {
        
        private final List<QcmJhyElementsEntity> stoveNos;
        private final List<Map<String, Object>> orderData;
        private final Map<String, List<CraftOrdDesignStdCicEntity>> stdCicCache;
        
        public BatchProcessor(List<QcmJhyElementsEntity> stoveNos, 
                              List<Map<String, Object>> orderData,
                              Map<String, List<CraftOrdDesignStdCicEntity>> stdCicCache) {
            this.stoveNos = stoveNos;
            this.orderData = orderData;
            this.stdCicCache = stdCicCache;
        }
        
        @Override
        public List<Object[]> call() throws Exception {
            List<Object[]> results = new ArrayList<>();
            
            // 每个批次只处理一个炉号（减少锁竞争）
            for (QcmJhyElementsEntity stoveNo : stoveNos) {
                if (stoveNo != null && stoveNo.getAssayno() != null) {
                    processSingleStove(stoveNo.getStoveNo(), stoveNo, results);
                }
            }
            return results;
        }
        
        private void processSingleStove(String stoveNo, 
                                          QcmJhyElementsEntity elementsEntity,
                                          List<Object[]> results) {
        	long start = System.currentTimeMillis();
        	Runtime rt = Runtime.getRuntime();
        	long startMem = rt.totalMemory() - rt.freeMemory(); // 初始内存占用
        	// 对每个炉号的处理加锁（确保顺序执行）
            synchronized (JudgeHelper.class) {
	            for (Map<String, Object> order : orderData) {
	                String ordLnDlyPk = order.get("ORD_LN_DLY_PK").toString();
	                String ordLnPk = ordLnDlyPk.substring(0, ordLnDlyPk.length() - 3);
	                List<CraftOrdDesignStdCicEntity> stdCicList = stdCicCache.get(ordLnPk);
	                if (stdCicList == null) continue;
	                Map<String, List<CraftOrdDesignStdCicEntity>> stdCicByCic = new HashMap<>();

	                for (CraftOrdDesignStdCicEntity item : stdCicList) {
	                    String cic = item.getCic(); 
	                    if (!stdCicByCic.containsKey(cic)) {
	                        stdCicByCic.put(cic, new ArrayList<CraftOrdDesignStdCicEntity>());
	                    }
	                    stdCicByCic.get(cic).add(item);
	                }

	                // 遍历分组执行判定
	                for (Map.Entry<String, List<CraftOrdDesignStdCicEntity>> entry : stdCicByCic.entrySet()) {
	                    String cic = entry.getKey();
	                    ArrayList<CraftOrdDesignStdCicEntity> cicItems = new ArrayList<>(entry.getValue());
	                    
	                    Object[] judgeResults = ChemJudgeHelper.JudgeNew(
	                        elementsEntity, 
	                        cicItems, 
	                        null, 
	                        true
	                    );
	                    
	                    if (judgeResults != null && judgeResults.length > 0 && 
	                        judgeResults[0].toString().isEmpty()) {
	                        results.add(new Object[]{
	                            stoveNo, 
	                            order.get("PRO_ORDER_NO"),
	                            cic 
	                        });
	                    }
	                }
	            }
            }

            long cost = (System.currentTimeMillis() - start)/1000;//秒
            long currentMem = rt.totalMemory() - rt.freeMemory();
            long memUsedM = currentMem / 1024/1024; // 当前内存占用（M）
            System.out.println("炉号"+stoveNo+"处理耗时:"+cost+"S, 内存:"+memUsedM+"M");
        }
    }
        
}