package com.kingdee.shr.compensation.app;

// 导入必要的类
import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.shr.base.syssetting.MSFServiceFacadeFactory;
import com.kingdee.shr.base.syssetting.app.osf.OSFAppUtil;
import com.kingdee.shr.compensation.util.CmpStrUtil;
import com.kingdee.util.DateTimeUtils;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.Period;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.*;

import org.apache.log4j.Logger;

public class RetMoneyFacadeControllerBean extends AbstractRetMoneyFacadeControllerBean {
    // 定义日志记录器
    private static Logger logger = Logger.getLogger("com.kingdee.shr.compensation.app.RetMoneyFacadeControllerBean");

    // 构造函数
    public RetMoneyFacadeControllerBean() {
    }
    protected void _retMoney(Context ctx) throws BOSException, EASBizException {
        MSFServiceFacadeFactory.getLocalInstance(ctx).processService("retMoneyService", new HashMap());
    }
    //todo 检查问题
    // 重写父类的_retMoney方法，用于回溯薪资
    protected void _retMoneyOld(Context ctx) throws BOSException, EASBizException {
        // 定义SQL查询语句，用于获取符合条件的薪资调整记录
        String sql = "/*dialect*/ SELECT FMONEY ,FID ,FPERSONID ,FCMPITEMID,FEFFECTDAY ,FLEFFECTDAY,CFTraceability,CFRetroactiveDate,foldfixadjustsalaryid   FROM T_HR_SFixAdjustSalary where  sysdate between   FEFFECTDAY  and FLEFFECTDAY and CFTraceability='Yes'   and (CFIsRet is null or CFIsRet=0)";
        HashSet<String> list = new HashSet<>(); // 用于存储处理过的薪资调整记录ID
        logger.error("sql" + sql); // 记录SQL查询语句到日志中
        IRowSet rs = DbUtil.executeQuery(ctx, sql); // 执行SQL查询，获取结果集

        try {
            BigDecimal money;
            // 遍历结果集中的每一行记录
            for (; rs.next(); logger.error("end mainid ==============" + money)) {
                BigDecimal sumMoney = BigDecimal.ZERO; // 初始化回溯薪资总额为0
                money = rs.getBigDecimal("FMONEY"); // 获取当前记录的薪资调整金额
                logger.error("statrt mainid ==============" + money); // 记录当前薪资调整金额到日志中
                Date cfretroactivedate = rs.getDate("cfretroactivedate"); // 获取回溯日期
                logger.error("cfretroactivedate " + DateTimeUtils.format(cfretroactivedate)); // 记录回溯日期到日志中
                String personid = rs.getString("FPERSONID"); // 获取员工ID
                logger.error("personid " + personid); // 记录员工ID到日志中
                String cmpitemid = rs.getString("FCMPITEMID"); // 获取薪资调整项目ID
                Date mainEffectday = rs.getDate("FEFFECTDAY"); // 获取薪资调整生效日期
                Date mainLeffectday = rs.getDate("FLEFFECTDAY"); // 获取薪资调整失效日期
                String mainleftdayYearMonth = DateTimeUtils.format(mainEffectday, "yyyy-MM"); // 格式化生效日期为“年-月”
                logger.error("mainleftdayYearMonth " + mainleftdayYearMonth); // 记录生效日期的“年-月”到日志中
                String oldfixadjustsalaryid = rs.getString("foldfixadjustsalaryid"); // 获取旧的薪资调整ID
                String id = rs.getString("fid"); // 获取当前薪资调整记录ID
                list.add(id); // 将当前记录ID添加到处理过的记录ID集合中

                // 定义子查询SQL语句，用于获取特定员工的薪资调整历史记录
                String detialSql = "/*dialect*/ select FEFFECTDAY ,FLEFFECTDAY,FMONEY,fid from T_HR_SFixAdjustSalary where FCMPITEMID='" + cmpitemid + "' " + " and fid ='" + oldfixadjustsalaryid + "' and  FPERSONID='" + personid + "' " + "   and (CFIsRet is null or CFIsRet=0) order by FEFFECTDAY asc ";
                logger.error("detial sql " + detialSql); // 记录子查询SQL语句到日志中
                IRowSet dettaiRs = DbUtil.executeQuery(ctx, detialSql); // 执行子查询，获取结果集

                // 如果子查询结果集不为空且包含记录
                if (dettaiRs != null && dettaiRs.size() > 0) {
                    String detialid;
                    // 遍历子查询结果集中的每一行记录
                    while (dettaiRs.next()) {
                        detialid = dettaiRs.getString("fid"); // 获取子查询记录的ID
                        logger.error("start detialid================================= " + dettaiRs.getString("fid")); // 记录子查询记录的ID到日志中
                        BigDecimal detailMony = dettaiRs.getBigDecimal("FMONEY"); // 获取子查询记录的薪资调整金额 10000
                        logger.error("dettaiRs：retMoney " + detailMony); // 记录子查询记录的薪资调整金额到日志中
                        BigDecimal retMoney = money.subtract(detailMony); // 计算回溯薪资
                        logger.error("retMoney " + retMoney); // 记录回溯薪资到日志中 2000
                        Date effectday = dettaiRs.getDate("FEFFECTDAY"); // 获取子查询记录的生效日期
                        Date leffectday = dettaiRs.getDate("FLEFFECTDAY"); // 获取子查询记录的失效日期
                        logger.error("detial_effectday " + DateTimeUtils.format(effectday)); // 记录子查询记录的生效日期到日志中
                        logger.error("detial_leffectday " + DateTimeUtils.format(leffectday)); // 记录子查询记录的失效日期到日志中
                        logger.error("detial_leffectday_before " + cfretroactivedate.before(effectday)); // 记录回溯日期是否在生效日期之前

                        // 初始化变量
                        HashSet<String> monthSet = null;
                        int months = 0;
                        String beginYearMonth;
                        String endYearMonth;
                        int detiailbeginday;
                        Date lastDate;
                        int days;
                        BigDecimal arrMoney;
                        long cntdays;

                        // 如果回溯日期在生效日期之前
                        if (cfretroactivedate.before(effectday)) {
                            beginYearMonth = DateTimeUtils.format(effectday, "yyyy-MM"); // 格式化生效日期为“年-月”
                            logger.error("beginYearMonth" + beginYearMonth); // 记录生效日期的“年-月”到日志中
                            endYearMonth = DateTimeUtils.format(leffectday, "yyyy-MM"); // 格式化失效日期为“年-月”
                            logger.error("endYearMonth" + endYearMonth); // 记录失效日期的“年-月”到日志中
                            monthSet = getMonthBetweenDate(effectday, leffectday); // 获取生效日期和失效日期之间的月份集合
                            logger.error("monthSet" + monthSet); // 记录月份集合到日志中
                            months = this.getAllMonth(effectday, leffectday); // 计算生效日期和失效日期之间的月份数
                            logger.error("detial_months " + months); // 记录月份数到日志中
                            detiailbeginday = DateTimeUtils.getDay(effectday); // 获取生效日期的天数
                            logger.error("detiailbeginday " + detiailbeginday); // 记录生效日期的天数到日志中
                            lastDate = this.getlengthOfMonth(effectday); // 获取生效日期所在月份的最后一天
                            if (detiailbeginday != 1) { // 如果生效日期不是该月的第一天
                                days = DateTimeUtils.getDay(lastDate); // 获取最后一天的天数
                                logger.error("detial_all_days " + days); // 记录最后一天的天数到日志中
                                arrMoney = retMoney.divide(new BigDecimal(days), 5).setScale(2); // 计算回溯薪资的平均分配金额
                                logger.error("detial_arrMoney " + arrMoney); // 记录平均分配金额到日志中
                                cntdays = this.getDaysBetweenDates(effectday, (Date) (lastDate.after(leffectday) ? leffectday : lastDate)) + 1L; // 计算回溯日期到最后一天的天数
                                logger.error("detial_cntdays " + cntdays); // 记录天数到日志中
                                sumMoney = sumMoney.add(arrMoney.multiply(new BigDecimal(cntdays))); // 计算回溯薪资总额
                                logger.error("detial_sumMoney " + sumMoney); // 记录回溯薪资总额到日志中
                                monthSet.remove(beginYearMonth); // 移除生效日期的“年-月”月份
                            }

                            // 如果生效日期所在月份等于失效日期所在月份
                            if (mainleftdayYearMonth.equals(endYearMonth)) {
                                monthSet.remove(endYearMonth); // 移除失效日期的“年-月”月份
                            }
                        } else {
                            // 如果回溯日期不在生效日期之前
                            months = this.getAllMonth(cfretroactivedate, leffectday); // 计算回溯日期和失效日期之间的月份数
                            beginYearMonth = DateTimeUtils.format(cfretroactivedate, "yyyy-MM"); // 格式化回溯日期为“年-月”
                            logger.error("beginYearMonth" + beginYearMonth); // 记录回溯日期的“年-月”到日志中
                            endYearMonth = DateTimeUtils.format(leffectday, "yyyy-MM"); // 格式化失效日期为“年-月”
                            logger.error("endYearMonth" + endYearMonth); // 记录失效日期的“年-月”到日志中
                            monthSet = getMonthBetweenDate(cfretroactivedate, leffectday); // 获取回溯日期和失效日期之间的月份集合
                            logger.error("monthSet" + monthSet); // 记录月份集合到日志中
                            logger.error("detial_months " + months); // 记录月份数到日志中
                            detiailbeginday = DateTimeUtils.getDay(cfretroactivedate); // 获取回溯日期的天数
                            logger.error("detiailbeginday " + detiailbeginday); // 记录回溯日期的天数到日志中
                            lastDate = this.getlengthOfMonth(cfretroactivedate); // 获取回溯日期所在月份的最后一天
                            if (detiailbeginday != 1) { // 如果回溯日期不是该月的第一天
                                days = DateTimeUtils.getDay(lastDate); // 获取最后一天的天数
                                logger.error("detial_all_days " + days); // 记录最后一天的天数到日志中
                                arrMoney = retMoney.divide(new BigDecimal(days), BigDecimal.ROUND_HALF_DOWN).setScale(2); // 计算回溯薪资的平均分配金额
                                logger.error("arrMoney " + arrMoney); // 记录平均分配金额到日志中
                                cntdays = this.getDaysBetweenDates(cfretroactivedate, (Date) (lastDate.after(leffectday) ? leffectday : lastDate)) + 1L; // 计算回溯日期到最后一天的天数
                                logger.error("detial_cntdays " + cntdays); // 记录天数到日志中
                                sumMoney = sumMoney.add(arrMoney.multiply(new BigDecimal(cntdays))); // 计算回溯薪资总额
                                logger.error("detial_sumMoney " + sumMoney); // 记录回溯薪资总额到日志中
                                monthSet.remove(endYearMonth); // 移除失效日期的“年-月”月份
                            }

                            // 如果回溯日期所在月份等于失效日期所在月份
                            if (mainleftdayYearMonth.equals(endYearMonth)) {
                                monthSet.remove(endYearMonth); // 移除失效日期的“年-月”月份
                            }
                        }

                        logger.error("monthSet ret " + monthSet); // 记录剩余月份集合到日志中
                        // 如果剩余月份集合不为空
                        if (monthSet.size() > 0) {
                            sumMoney = sumMoney.add(retMoney.multiply(new BigDecimal(monthSet.size()))); // 计算回溯薪资总额
                        }

                        logger.error("sumMoney " + sumMoney); // 记录回溯薪资总额到日志中
                        list.add(detialid); // 将子查询记录的ID添加到处理过的记录ID集合中
                        logger.error("end detialid================================= " + dettaiRs.getString("fid")); // 记录子查询记录的ID到日志中
                    }
                } else {
                    logger.error("没有调薪历史都是0"); // 记录没有调薪历史的情况
                    sumMoney = BigDecimal.ZERO; // 设置回溯薪资总额为0
                }

                // 定义SQL语句，用于检查是否存在特定的员工薪资支付表记录
                String exiSql = "select * from CT_CUS_PersonPayForm where CFPersonID ='" + personid + "' and CFAdjustSalary='" + id + "' ";
                logger.error("exiSql sql " + exiSql); // 记录SQL语句到日志中
                IRowSet extRs = DbUtil.executeQuery(ctx, exiSql); // 执行SQL查询，获取结果集

                String insertSql;
                // 如果结果集不为空且包含记录
                if (extRs != null && extRs.size() > 0) {
                    // 定义SQL语句，用于更新员工薪资支付表中的回溯薪资
                    insertSql = "update  CT_CUS_PersonPayForm set CFRetMoney=" + sumMoney.setScale(2, 5) + " where  CFAdjustSalary='" + id + "' ";
                    logger.error("updateSql " + insertSql); // 记录SQL语句到日志中
                    DbUtil.execute(ctx, insertSql); // 执行SQL更新操作
                } else {
                    // 如果结果集为空或不包含记录
                    // 定义SQL语句，用于向员工薪资支付表中插入新的回溯薪资记录
                    insertSql = " /*dialect*/ insert into CT_CUS_PersonPayForm(fid,CFPersonID,CFMonth,CFRetMoney,cfadjustsalary) values(newbosid('5FB9A7AC'),'" + personid + "',to_date('" + DateTimeUtils.format(mainEffectday) + "','yyyy-MM-dd')" + "," + sumMoney.setScale(2, 5) + ",'" + id + "')";
                    logger.error("insertSql " + insertSql); // 记录SQL语句到日志中
                    DbUtil.execute(ctx, insertSql); // 执行SQL插入操作
                }
            }

            String idStr = CmpStrUtil.convertListToString(list.toArray()); // 将处理过的记录ID集合转换为字符串
            logger.error("insqlInstance idStr " + CmpStrUtil.convertListToString(list.toArray())); // 记录处理过的记录ID字符串到日志中
            // 定义SQL语句，用于更新薪资调整表中的回溯标记
            String updateAdjustSalarySql = "update T_HR_SFixAdjustSalary set cfisret=1 where fid in ( " + idStr + ") ";
            logger.error("updateAdjustSalarySql" + updateAdjustSalarySql); // 记录SQL语句到日志中
            DbUtil.execute(ctx, updateAdjustSalarySql); // 执行SQL更新操作
        } catch (SQLException var32) {
            var32.printStackTrace(); // 打印SQL异常堆栈信息
            throw new BOSException("回算出错"); // 抛出自定义的BOSException异常
        } catch (ParseException var33) {
            var33.printStackTrace(); // 打印日期解析异常堆栈信息
            throw new BOSException("回算出错"); // 抛出自定义的BOSException异常
        }
    }

    // 获取特定年份和月份的天数
    public int getALlDays(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, 1);
        int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        return daysInMonth;
    }

    // 计算两个日期之间的月份数
    public int getAllMonth(Date beginDate, Date endDate) {
        LocalDate startDatetmp = LocalDate.of(DateTimeUtils.getYear(beginDate), DateTimeUtils.getMonth(beginDate), DateTimeUtils.getDay(beginDate));
        LocalDate endDatetmp = LocalDate.of(DateTimeUtils.getYear(endDate), DateTimeUtils.getMonth(endDate), DateTimeUtils.getDay(endDate));
        logger.error("startDatetmp" + startDatetmp);
        logger.error("endDatetmp" + endDatetmp);
        Period period = Period.between(startDatetmp, endDatetmp);
        logger.error("period" + period);
        int months = period.getMonths();
        logger.error("months" + months);
        return months;
    }

    // 获取特定日期所在月份的最后一天
    public Date getlengthOfMonth(Date date) throws ParseException {
        logger.error("getlengthOfMonth—date" + date);
        LocalDate currentDate = LocalDate.of(DateTimeUtils.getYear(date), DateTimeUtils.getMonth(date), DateTimeUtils.getDay(date));
        logger.error("getlengthOfMonth—date" + currentDate);
        int lastDay = currentDate.lengthOfMonth();
        logger.error("getlengthOfMonth—lastDay" + lastDay);
        String tempDate = DateTimeUtils.getYear(date) + "-" + DateTimeUtils.getMonth(date) + "-" + lastDay;
        logger.error("getlengthOfMonth—tempDate" + tempDate);
        return DateTimeUtils.parseDate(tempDate);
    }

    // 计算两个日期之间的天数
    public long getDaysBetweenDates(Date start, Date end) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(start);
        long startTime = cal.getTimeInMillis();
        cal.setTime(end);
        long endTime = cal.getTimeInMillis();
        long diff = Math.abs(endTime - startTime);
        return diff / 86400000L;
    }

    // 获取两个日期之间的月份集合
    public static HashSet<String> getMonthBetweenDate(Date startTime, Date endTime) {
        HashSet<String> list = new HashSet<>();

        // 遍历两个日期之间的月份
        for (Calendar calendar = Calendar.getInstance(); startTime.getTime() <= endTime.getTime(); startTime = calendar.getTime()) {
            logger.error("getMonthBetweenDate—tempDate" + DateTimeUtils.format(startTime, "yyyy-MM"));
            list.add(DateTimeUtils.format(startTime, "yyyy-MM"));
            calendar.setTime(startTime);
            calendar.add(Calendar.MONTH, 1);
        }

        return list;
    }

    // 获取两个日期之间的月份集合
    public static List<String> getMonthBetweenDate_V1(Date startTime, Date endTime) {
        List<String> list = new ArrayList<>();
        LocalDate startDate = startTime.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate();
        LocalDate endDate = endTime.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate();

        // 计算年份和月份差值
        int startYear = startDate.getYear();
        int startMonth = startDate.getMonthValue();
        int endYear = endDate.getYear();
        int endMonth = endDate.getMonthValue();

        int yearDifference = endYear - startYear;
        int monthDifference = yearDifference * 12 + (endMonth - startMonth);

        // 如果 endDate 小于 startLocalDate 的下个月的第一天，则减去 1
        LocalDate nextMonthFirstDay = startDate.plusMonths(1).withDayOfMonth(1);
        if (endDate.isBefore(nextMonthFirstDay)) {
            monthDifference--;
        }
        int month=0;
        do{
            month++;
            String monthStr =startMonth+"";
            if(startMonth<10){
                monthStr="0"+monthStr;
            }
            String yearMonth = startYear + "-" + monthStr;
            if(12==startMonth){
                startMonth=1;
                startYear=startYear+1;
            }else {
                startMonth++;
            }
            list.add(yearMonth);
        }while (month<monthDifference);
        return list;
    }

    public static void main(String[] args) throws ParseException {
        long s = System.currentTimeMillis();
        System.out.println(DateTimeUtils.format(DateTimeUtils.parseDate("2024-07-17"))+"--"+DateTimeUtils.format(DateTimeUtils.parseDate("2024-11-01")));
        System.out.println(getMonthBetweenDate_V1(DateTimeUtils.parseDate("2024-07-17"),DateTimeUtils.parseDate("2024-11-01")));
        System.out.println("time:"+(System.currentTimeMillis()-s));
        s = System.currentTimeMillis();
//        List list = new ArrayList<>(getMonthBetweenDate(new Date(123,1,1),new Date()));
//        Collections.sort(list);
//        System.out.println(list);
        System.out.println("time:"+(System.currentTimeMillis()-s));
        //[2023-02, 2023-03, 2023-04, 2023-05, 2023-06, 2023-07, 2023-08, 2023-09, 2023-10, 2023-11, 2023-12, 2024-01, 2024-02, 2024-03, 2024-04, 2024-05, 2024-06, 2024-07, 2024-08, 2024-09, 2024-10, 2024-11, 2024-12, 2025-01, 2025-02, 2025-03, 2025-04]
        //[2023-02, 2023-03, 2023-04, 2023-05, 2023-06, 2023-07, 2023-08, 2023-09, 2023-10, 2023-11, 2023-12, 2024-01, 2024-02, 2024-03, 2024-04, 2024-05, 2024-06, 2024-07, 2024-08, 2024-09, 2024-10, 2024-11, 2024-12, 2025-01, 2025-02, 2025-03, 2025-04]

    }
}
