package com.awspaas.user.apps.bnbm.datalinkup.controller;

import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.bpmn.engine.model.run.delegate.ProcessInstance;
import com.actionsoft.bpms.commons.database.RowMap;
import com.actionsoft.bpms.commons.mvc.view.ResponseObject;
import com.actionsoft.bpms.server.UserContext;
import com.actionsoft.bpms.server.bind.annotation.Controller;
import com.actionsoft.bpms.server.bind.annotation.Mapping;
import com.actionsoft.bpms.util.DBSql;
import com.actionsoft.sdk.local.SDK;
import com.awspaas.user.apps.bnbm.datalinkup.entity.DateRange;
import com.awspaas.user.apps.bnbm.datalinkup.service.DataSummaryService;
import com.awspaas.user.apps.bnbm.datalinkup.service.DataSyncService;
import com.awspaas.user.apps.bnbm.datalinkup.service.impl.*;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @ClassName: DataLinkUpController
 * @Description:
 * @author: 李春洋
 * @date: 2025/8/8 10:38
 * @Blog: https://
 */
@Controller
public class DataLinkUpController {
    private static final Logger LOGGER = LoggerFactory.getLogger(DataLinkUpController.class);

    /**
     * 配置字段自动配置
     * @param sid
     * @param toTable
     * @param bindid
     * @param byTable
     * @return
     */
    @Mapping("com.awspaas.user.apps.bnbm.datalinkup.controller.DataLinkUpController_createTableFiled")
    public ResponseObject createTableFiled(String sid, String toTable, String bindid, String byTable) {
        ResponseObject ro = ResponseObject.newOkResponse();
        LOGGER.info("请求参数：sid:{},toTable:{},bindid:{},byTable{}", sid, toTable, bindid,byTable);

//        List<RowMap> maps = DBSql.getMaps("SHOW COLUMNS FROM " + toTable + " FROM aws7");
        List<RowMap> maps = DBSql.getMaps("SELECT COLUMN_NAME ,COLUMN_COMMENT \n" +
                "FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'aws7' \n" +
                "AND TABLE_NAME = '"+byTable+"'");

        if (maps == null) {
            ro.warn("表中没有字段");
            return ro;
        }
        ArrayList<BO> bos = new ArrayList<>();
        int i = 1;
        for (RowMap map : maps) {
            if (map.getString("COLUMN_NAME").equals("ID") || map.getString("COLUMN_NAME").equals("ORGID")
                    || map.getString("COLUMN_NAME").equals("BINDID")
                    || map.getString("COLUMN_NAME").equals("CREATEDATE") || map.getString("COLUMN_NAME").equals("CREATEUSER")
                    || map.getString("COLUMN_NAME").equals("UPDATEDATE")
                    || map.getString("COLUMN_NAME").equals("UPDATEUSER") || map.getString("COLUMN_NAME").equals("PROCESSDEFID")
                    || map.getString("COLUMN_NAME").equals("ISEND")) {
                continue;
            } else {
                BO bo = new BO();
                bo.set("XH", i++);
                bo.set("TBB", toTable);
                bo.set("TBBZD", map.getString("COLUMN_NAME"));
                bo.set("LDB", byTable);
                bo.set("LDBZD", map.getString("COLUMN_NAME"));
                bo.set("LDBZDM", map.getString("COLUMN_COMMENT"));
                bos.add(bo);
            }
        }
        ProcessInstance instanceById = SDK.getProcessAPI().getInstanceById(bindid);
        SDK.getBOAPI().create("BO_EU_BNBM_DATALINKUP_SJGTPZ_SUB", bos, instanceById, UserContext.fromSessionId(sid));
        ro.ok("创建子表数据完成");
        return ro;
    }

    /**
     * 手动同步数据按钮（使用DataSyncService实现）
     *
     * @param dataStr       同步数据表配置(JSON数组)
     * @param sid           用户会话ID
     * @param formattedDate 同步时间（此实现中不使用该参数，由服务内部处理时间范围）
     * @return 响应结果
     */
    @Mapping("com.awspaas.user.apps.bnbm.datalinkup.controller.DataLinkUpController_manualSynchronization")
    public ResponseObject manualSynchronization(String dataStr, String sid, String formattedDate) {
        long methodStartTime = System.currentTimeMillis();
        LOGGER.info("【开始】数据同步操作，开始时间：{}", new Date(methodStartTime));

        ResponseObject ro = ResponseObject.newOkResponse();
        try {
            // 1. 解析JSON数据
            JSONArray configArray = new JSONArray(dataStr);
            List<BO> mainConfigs = new ArrayList<>();
            // 3. 创建数据同步服务实例
            DataSyncService syncService = null;
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DATE, -1); // 昨天
            Date endDate = cal.getTime();

            // 解析formattedDate为日期对象并计算时间范围
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate date = LocalDate.parse(formattedDate, dateFormatter);
            LocalDateTime startDateTime = date.atStartOfDay();  // 当天00:00:00
            Date startDate = Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant());

            // 2. 转换为BO对象列表
            for (int i = 0; i < configArray.length(); i++) {
                JSONObject config = configArray.getJSONObject(i);
                String ssyw = config.getString("SSYW");
                if ("销售".equals(ssyw)) {
                    syncService = new SaleDataSyncServiceImpl();
                    LOGGER.info("同步数据——销售的接口");
                }else if ("运营".equals(ssyw)) {
                    syncService = new ProductionDataSyncServiceImpl();
                    LOGGER.info("同步数据——生产运营的接口");
                } else {
                    syncService = new PurchaseDataSyncServiceImpl();
                    LOGGER.info("同步数据——采购的接口");
                }
                String timeField = config.getString("SJZD");
                String ccId = config.getString("CC_ID");
                String targetTable = config.getString("LDB");
                String partitionField = config.getString("FQBZD");
                String tableName = config.getString("TBB");
                String tablename = config.getString("TABLENAME");
                String bkgs = config.getString("SSBK");
                String jezd = config.getString("JEZD");// 金额字段

                List<BO> fieldMappings = SDK.getBOAPI()
                        .query("BO_EU_BNBM_DATALINKUP_SJGTPZ_SUB")
                        .addQuery("BINDID =", config.optString("_BINDID"))
                        .list();

                // 判断库存同步明细和汇总明细，如果是月初第一天就将上月最后一天数据存储到快照表
                if("库存".equals(tablename)){
                    if (LocalDate.now().getDayOfMonth() == 1) {
                        LOGGER.info("当天为1号，将前一天同步的全部数据存为快照，在删除同步新的全量库存数据");
                        // 执行同步逻辑
                        List<BO> list = SDK.getBOAPI().query(targetTable).list();
                        int pageSize = 1000;
                        int total = list.size();

                        // 分页处理并批量插入
                        for (int start = 0; start < total; start += pageSize) {
                            int end = Math.min(start + pageSize, total);
                            List<BO> subList = list.subList(start, end);

                            // 将子列表转换为目标BO的实例（如果需要字段映射，需在此处实现）
                            ArrayList<BO> boList = new ArrayList<>();
                            for (BO sourceBo : subList) {
                                // 这里应根据实际字段映射关系复制属性
                                // 例如：targetBo.set("fieldName", sourceBo.get("fieldName"));
                                boList.add(sourceBo);
                            }

                            // 批量插入当前分页数据
                            if (!boList.isEmpty()) {
                                SDK.getBOAPI().createDataBO("BO_EU_CG_KC_YDKBB", boList, UserContext.fromUID("admin"));
                            }
                        }
                    }
                }

                // 删除目标表数据（根据时间字段是否为空决定删除范围）
                if (timeField == null || timeField.isEmpty()) {
                    // 全量删除
                    syncService.deleteAllTargetData(targetTable);
                } else {
                    // 获取目标表时间字段名
                    String targetTimeField = syncService.getTargetTimeField(fieldMappings, timeField);
                    if (targetTimeField == null) {
                        LOGGER.error("无法找到源时间字段[{}]对应的目标表字段，跳过同步", timeField);
                        return ro.warn("无法找到源时间字段["+timeField+"]对应的目标表字段，跳过同步");
                    }
                    // 按时间范围删除
                    syncService.deleteTargetData(targetTable, targetTimeField, startDate, endDate);
                }
                if (tablename.equals("应收表")){
                    LOGGER.info("开始执行应收的明细汇总");
                    if ((!bkgs.equals("北新防水")) || (!bkgs.equals("北新涂料"))) {
                        syncService.querySourceDataYS(ccId, tableName, timeField, startDate, endDate, partitionField,
                                fieldMappings, targetTable, jezd);
                    }
                }else {
                    syncService.querySourceData(ccId, tableName, timeField, startDate, endDate, partitionField,
                            fieldMappings, targetTable, jezd);
                }

            }

            LOGGER.info("开始使用DataSyncService处理数据同步 ({}条配置)", mainConfigs.size());

            ro.put("success", true);
            ro.put("message", "数据同步操作已完成");
            LOGGER.info("数据同步成功完成");
        } catch (Exception e) {
            LOGGER.error("手动同步异常", e);
            ro.put("success", false);
            ro.put("message", "数据同步失败: " + e.getMessage());
        }

        long methodEndTime = System.currentTimeMillis();
        LOGGER.info("【完成】数据同步操作，总耗时：{}ms", methodEndTime - methodStartTime);
        return ro;
    }

    /**
     * 执行数据汇总计算（使用DataSummaryService实现）
     * @return 响应结果
     */
    @Mapping("com.awspaas.user.apps.bnbm.datalinkup.controller.DataLinkUpController_calculateSummary")
    public ResponseObject calculateSummary(String dataStr, String sid, String formattedDate) {
        long methodStartTime = System.currentTimeMillis();
        LOGGER.info("【开始】数据计算汇总操作，开始时间：{}", new Date(methodStartTime));
        ResponseObject ro = ResponseObject.newOkResponse();
        JSONArray configArray = new JSONArray(dataStr);

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1); // 昨天
        Date endDate = cal.getTime();

        // 解析formattedDate为日期对象并计算时间范围
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate date = LocalDate.parse(formattedDate, dateFormatter);
        LocalDateTime startDateTime = date.atStartOfDay();  // 当天00:00:00
        Date startDate = Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant());
        DataSummaryService summaryService = null;
        SaleCountDimensionImpl saleCountDimension = null;

        try {
            LOGGER.info("开始执行销售数据多维度汇总计算");

            DateRange dateRange = new DateRange();
            dateRange.setStartDate(startDate);
            dateRange.setEndDate(endDate);
            LOGGER.info("汇总计算开始时间为：{}，结束时间为：{}",startDate,endDate);
            // 2. 执行汇总计算
            for (int i = 0; i < configArray.length(); i++) {
                JSONObject config = configArray.getJSONObject(i);
                String timeField = config.getString("SJZD");
                String ccId = config.getString("CC_ID");
                String targetTable = config.getString("LDB");
                String partitionField = config.getString("FQBZD");
                String tableName = config.getString("TBB");
                String bkgs = config.getString("SSBK");
                String ssyw = config.getString("SSYW");

                // 1. 创建数据汇总服务实例
                if ("销售".equals(ssyw)) {
                    summaryService = new SaleDataSummaryServiceImpl();
                    saleCountDimension = new SaleCountDimensionImpl();
                }else if ("采购".equals(ssyw)){
                    summaryService = new PurchaseDataSummaryServiceImpl();
                    LOGGER.info("采购业务检测到，创建summaryService实例");
                } else if ("运营".equals(ssyw)) {
//                    summaryService = new ProductionDataSyncServiceImpl();
                    LOGGER.info("运营业务检测到，创建summaryService实例");
                } else {
                    LOGGER.error("{}没有汇总类",ssyw);
                }

                List<RowMap> bkgsMaps = DBSql.getMaps("SELECT BKGS FROM " + targetTable + " GROUP BY BKGS");
                if (bkgsMaps != null) {
                    for (RowMap map : bkgsMaps) {
                        BO bo = new BO();
                        bo.set("BKGS", map.getString("BKGS"));

                        if ("销售".equals(ssyw)) {
                            LOGGER.info("======== 开始并行执行销售数据汇总计算，BKGS: {} ========", bo.get("BKGS"));

                            LOGGER.info("开始执行一体化-销售数据汇总计算，BKGS: {}", bo.get("BKGS"));
                            summaryService.calculateSummary(dateRange, bo);
                            LOGGER.info("完成一体化-销售数据汇总计算，BKGS: {}", bo.get("BKGS"));

//                            saleCountDimension = new SaleCountDimensionImpl();
                            LOGGER.info("开始执行销售数据多维度汇总计算，BKGS: {}", bo.get("BKGS"));
                            saleCountDimension.calculateSummary(dateRange, bo);
                            LOGGER.info("完成销售数据多维度汇总计算，BKGS: {}", bo.get("BKGS"));

                        } else {
                            // 非销售业务，单线程执行
                            LOGGER.info("======== 开始执行采购数据汇总计算，BKGS: {} ========", bo.get("BKGS"));
                            try {
                                summaryService.calculateSummary(dateRange, bo);
                                LOGGER.info("======== 采购数据汇总计算完成，BKGS: {} ========", bo.get("BKGS"));
                            } catch (Exception e) {
                                LOGGER.error("采购数据汇总计算异常，BKGS: {}", bo.get("BKGS"), e);
                                throw new RuntimeException("采购数据汇总计算失败: " + e.getMessage(), e);
                            }
                        }
                    }
                }
            }

            ro.put("success", true);
            ro.put("message", "数据汇总计算完成");
            LOGGER.info("销售数据多维度汇总计算完成");
        } catch (Exception e) {
            String errorMsg = "数据汇总计算失败: " + e.getMessage();
            LOGGER.error(errorMsg, e);
            ro.put("success", false);
            ro.put("message", errorMsg);

        }
        long methodEndTime = System.currentTimeMillis();
        LOGGER.info("【完成】数据计算汇总操作，总耗时：{}ms", methodEndTime - methodStartTime);
        return ro;
    }

    /**
     * 各板块数据汇总
     * @param dataStr       同步数据表配置(JSON数组)
     * @param sid           用户会话ID
     * @param formattedDate 同步时间（此实现中不使用该参数，由服务内部处理时间范围）
     * @return 响应结果
     */
    @Mapping("com.awspaas.user.apps.bnbm.datalinkup.controller.DataLinkUpController_summaryData")
    public ResponseObject summaryData(String dataStr, String sid, String formattedDate){
        long methodStartTime = System.currentTimeMillis();
        LOGGER.info("【开始】数据汇总操作，开始时间：{}", new Date(methodStartTime));

        ResponseObject ro = ResponseObject.newOkResponse();

        DataSyncService dataSyncService = null;

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1); // 昨天
        Date endDate = cal.getTime();

        // 解析formattedDate为日期对象并计算时间范围
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate date = LocalDate.parse(formattedDate, dateFormatter);
        LocalDateTime startDateTime = date.atStartOfDay();  // 当天00:00:00
        Date startDate = Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String startDateStr = simpleDateFormat.format(startDate)+" 00:00:00";
        String endDateStr = simpleDateFormat.format(endDate)+" 23:59:59";
        LOGGER.info("时间范围：{}-{}",startDateStr,endDateStr);

        JSONArray configArray = new JSONArray(dataStr);
        // 2. 转换为BO对象列表
        for (int i = 0; i < configArray.length(); i++) {
            long configStartTime = System.currentTimeMillis();

            JSONObject mainConfig = configArray.getJSONObject(i);
            String targetTable = mainConfig.getString("LDB");//落地表
            String timeField = mainConfig.getString("SJZD");//时间字段
            String bindId = mainConfig.getString("_BINDID");//bindid
            String plate = mainConfig.getString("SSBK");// 所属板块
            String tablename = mainConfig.getString("TABLENAME");//表名
            String ssyw = mainConfig.getString("SSYW");
            String hzb = "";//汇总表

            LOGGER.info("【开始处理】配置项[{}]，板块：{}，BindID：{}，开始时间：{}",
                    i+1, plate, bindId, new Date(configStartTime));

            if ("销售".equals(ssyw)) {
                dataSyncService = new SaleDataSyncServiceImpl();
                if ("销售表".equals(tablename)){
                    hzb = "BO_EU_BNBM_DATALINKUP_XS_XSL_HZ";
                }else {
                    hzb = "BO_EU_BNBM_DATALINKUP_XS_YSL";
                }
                LOGGER.info("汇总板块数据——销售的接口");
            } else if ("采购".equals(ssyw)){
                dataSyncService = new PurchaseDataSyncServiceImpl();
                if ("采购单".equals(tablename)){
                    hzb = "BO_EU_DWD_ORDER_CGDD_HZ";
                } else if ("应付单".equals(tablename)){
                    hzb = "BO_EU_DWD_ORDER_YFD_HZ";
                } else if ("库存".equals(tablename)) {
                    hzb = "BO_EU_DWD_ORDER_KC_HZ";
                } else if ("物流表".equals(tablename)) {
                    hzb = "BO_EU_CG_WLD_HZ";
                } else if ("入库单".equals(tablename)){
                    hzb = "BO_EU_DWD_ORDER_RKD_HZ";
                } else {
                    LOGGER.error("当前表没有汇总表");
                    continue;
                }
                LOGGER.info("汇总板块数据——采购的接口");
            } else if ("运营".equals(ssyw)) {
                dataSyncService = new ProductionDataSyncServiceImpl();
                if ("生产入库".equals(tablename)) {
                    hzb = "BO_EU_BNBM_SCRK_HZ";
                } else if ("生产出库".equals(tablename)) {
                    hzb = "BO_EU_BNBM_SCCK_HZ";
                }else {
                    LOGGER.error("当前表没有汇总表");
                    continue;
                }
                LOGGER.info("汇总板块数据——运营的接口");
            } else {
                LOGGER.error("{}当前表没有汇总表",ssyw);
                return ro.err(ssyw+"当前表没有汇总表");
            }

            LOGGER.info("即将同步的数据：{}",plate);
            try {
                // 查询子表字段映射配置
                long queryStartTime = System.currentTimeMillis();
                List<BO> fieldMappings = SDK.getBOAPI()
                        .query("BO_EU_BNBM_DATALINKUP_SJGTPZ_SUB")
                        .addQuery("BINDID =", bindId)
                        .list();
                //获取板块公司
                List<RowMap> maps = DBSql.getMaps("SELECT BKGS FROM " + targetTable + " GROUP BY BKGS");
                String bkgss = maps.stream().map(o -> o.getString("BKGS")).collect(Collectors.joining(","));
                String[] bkgsArr = bkgss.split(",");

                LOGGER.info("字段映射配置查询完成，耗时：{}ms", System.currentTimeMillis() - queryStartTime);

                // 删除目标表数据（根据时间字段是否为空决定删除范围）
                long deleteStartTime = System.currentTimeMillis();
                if (timeField == null || timeField.isEmpty()) {
                    // 全量删除
                    for (String bkgs : bkgsArr) {
                        String deleteSql = "DELETE FROM "+hzb+" WHERE BKGS = '"+bkgs+"'";
                        int deletedCount = DBSql.update(deleteSql);
                        LOGGER.info("已删除目标表["+hzb+"]中{}条数据（时间范围: {} - {})，耗时：{}ms",
                                deletedCount, startDateStr, endDateStr, System.currentTimeMillis() - deleteStartTime);
                    }
                    // 根据时间范围增加数据分页查询数据存储到BO_EU_BNBM_DATALINKUP_XS_XSL_HZ
                    // 全量分页迁移数据到汇总表
                    long summarizeStartTime = System.currentTimeMillis();
                    if (tablename.equals("应收表")){
                        dataSyncService.summarizeScopeDataYs(targetTable, null, null, null, hzb);
                    }else {
                        dataSyncService.summarizeScopeData(targetTable, null, null, null, hzb);
                    }
                    LOGGER.info("全量数据汇总完成，耗时：{}ms", System.currentTimeMillis() - summarizeStartTime);
                } else {
                    // 获取目标表时间字段名
                    String targetTimeField = dataSyncService.getTargetTimeField(fieldMappings, timeField);
                    if (targetTimeField == null) {
                        LOGGER.error("无法找到源时间字段[{}]对应的目标表字段，跳过同步", timeField);
                    }
                    // 按时间范围删除
                    for (String bkgs : bkgsArr) {
                        String deleteSql = "DELETE FROM " + hzb +
                                " WHERE BKGS = '"+bkgs+"' AND " + targetTimeField + " >= ? ";
                        LOGGER.info("deleteSql:{}",deleteSql);
                        int deletedCount = DBSql.update(deleteSql, new Object[]{startDateStr});
                        LOGGER.info("已删除目标表["+hzb+"]中{}条数据（时间范围: {} - {})",
                                deletedCount, startDateStr, endDateStr);
                    }
                    // 根据时间范围增加数据分页查询数据存储到BO_EU_BNBM_DATALINKUP_XS_XSL_HZ
                    // 按时间范围分页迁移数据到汇总表
                    long summarizeStartTime = System.currentTimeMillis();
                    if (tablename.equals("应收表")){
                        dataSyncService.summarizeScopeDataYs(targetTable, startDate, endDate, targetTimeField, hzb);
                    }else {
                        dataSyncService.summarizeScopeData(targetTable, startDate, endDate, targetTimeField, hzb);
                        if (hzb.equals("BO_EU_DWD_ORDER_RKD_HZ")){
                            int update = DBSql.update("UPDATE BO_EU_DWD_ORDER_RKD_HZ rkd " +
                                    " JOIN BO_EU_ZZDYQY zzd ON rkd.BKGS = zzd.BKGS AND rkd.KCZZ = zzd.XSZZ " +
                                    " SET rkd.QYGS = zzd.QYGS " +
                                    " WHERE rkd.QYGS IS NULL");
                            LOGGER.info("更新入库单区域公司条数：{}",update);
                        }
                    }
                    LOGGER.info("范围数据汇总完成，耗时：{}ms", System.currentTimeMillis() - summarizeStartTime);
                }
                LOGGER.info("【完成处理】配置项[{}]，板块：{}，总耗时：{}ms",
                        i+1, plate, System.currentTimeMillis() - configStartTime);
            } catch (Exception e) {
                LOGGER.error("处理配置失败 [板块={}, BindID={}]: {}",
                        plate, mainConfig.getString("_BINDID"), e.getMessage(), e);
                return ro.err("处理配置失败 [板块='"+plate+"', BindID='"+mainConfig.getString("BINDID")+"']: '"+e.getMessage()+"'");
            }
        }
        long methodEndTime = System.currentTimeMillis();
        LOGGER.info("【完成】数据汇总操作，总耗时：{}ms", methodEndTime - methodStartTime);
        return ro.ok("汇总数据完成");
    }


}
