package com.kingdee.shr.customer.gtiit.osf;

import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.bsf.service.app.IHRMsfService;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.util.DateTimeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import java.math.BigDecimal;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * description: RetMoneyService <br>
 * date: 2025/4/21 10:37 <br>
 * author: lhbj <br>
 * version: 1.0 <br>
 */
public class RetMoneyService implements IHRMsfService {
    // 定义日志记录器
    private static Logger logger = Logger.getLogger("com.kingdee.shr.customer.gtiit.osf.RetMoneyService");

    @Override
    public Object process(Context ctx, Map<String, Object> map) throws EASBizException, BOSException {
        try {
            String sql = "\n" +
                    " /*dialect*/SELECT FMONEY ,FID ,FPERSONID ,FCMPITEMID,FEFFECTDAY ,FLEFFECTDAY,CFTraceability,CFRetroactiveDate,foldfixadjustsalaryid \n" +
                    " FROM T_HR_SFixAdjustSalary where sysdate between  FEFFECTDAY and FLEFFECTDAY \n" +
                    " and CFTraceability='Yes' and FEFFECTDAY < cfretroactivedate ";
            HashSet<String> list = new HashSet<>(); // 用于存储处理过的薪资调整记录ID
            logger.error("sql" + sql); // 记录SQL查询语句到日志中
            IRowSet rs = DbUtil.executeQuery(ctx, sql); // 执行SQL查询，获取结果集
            while (rs.next()) {
                BigDecimal sumMoney = BigDecimal.ZERO; // 初始化回溯薪资总额为0
                BigDecimal money = rs.getBigDecimal("FMONEY"); // 获取当前记录的薪资调整金额
                Date cfretroactivedate = new Date(rs.getDate("cfretroactivedate").getTime()); // 获取回溯日期
                String personid = rs.getString("FPERSONID"); // 获取员工ID
                String cmpitemid = rs.getString("FCMPITEMID"); // 获取薪资调整项目ID
                Date mainEffectday = new Date(rs.getDate("FEFFECTDAY").getTime()); // 获取薪资调整生效日期
                Date mainLeffectday = rs.getDate("FLEFFECTDAY"); // 获取薪资调整失效日期
                logger.error("dettaiRs-mainEffectday:"+mainEffectday+",leffectday:"+mainLeffectday); //每工作日工资
                String mainleftdayYearMonth = DateTimeUtils.format(mainEffectday, "yyyy-MM"); // 格式化生效日期为“年-月”
                String oldfixadjustsalaryid = rs.getString("foldfixadjustsalaryid"); // 获取旧的薪资调整ID
                String id = rs.getString("fid"); // 获取当前薪资调整记录ID
                if (StringUtils.isNotBlank(oldfixadjustsalaryid)) {
                    String sqlOld = "\n" +
                            " SELECT FMONEY ,FID ,FPERSONID ,FCMPITEMID,FEFFECTDAY ,FLEFFECTDAY,CFTraceability,CFRetroactiveDate,foldfixadjustsalaryid \n" +
                            " FROM T_HR_SFixAdjustSalary where fid ='" + oldfixadjustsalaryid + "' ";
                    logger.error("sqlOld================================= " + sqlOld);
                    IRowSet dettaiRs = DbUtil.executeQuery(ctx, sqlOld); // 执行SQL查询，获取结果集
                    String detialid;
                    if (dettaiRs.next()) {
                        detialid = dettaiRs.getString("fid"); // 获取子查询记录的ID
                        logger.error("start detialid================================= " + detialid); // 记录子查询记录的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("dettaiRs-effectday:"+effectday+",leffectday:"+leffectday); //每工作日工资
                        //获取月份差
                        List<String> stringList = this.getMonthBetweenDate_V1(mainEffectday,cfretroactivedate);
                        //获取开始日期
                        Calendar cal = Calendar.getInstance();
                        cal.setTime(mainEffectday);
                        cal.set(Calendar.DAY_OF_MONTH, 1);
                        String startDate = DateTimeUtils.format(cal.getTime(), "yyyy-MM-dd");
                        //结束日期
                        boolean endBool=false;
                        Calendar cal2 = Calendar.getInstance();
                        cal2.setTime(cfretroactivedate);
                        if(cal2.get(Calendar.DAY_OF_MONTH)>1){
                            cal2.add(Calendar.MONTH, 1);
                            endBool=true;
                        }
                        cal2.set(Calendar.DAY_OF_MONTH, 1);
                        cal2.add(Calendar.DAY_OF_MONTH, -1);

                        String endDate = DateTimeUtils.format(cal2.getTime(), "yyyy-MM-dd");
                        //有效结束日期
                        String leffectDate = endDate;
                        if(endBool){
                            leffectDate = DateTimeUtils.format(cfretroactivedate, "yyyy-MM-dd");
                        }
                        //有效日期
                        String effectDate = DateTimeUtils.format(mainEffectday, "yyyy-MM-dd");

                        StringBuilder sqlDay = new StringBuilder();
                        sqlDay.append(" select to_char(wItem.fdate,'yyyy-MM-dd') from T_HR_ATS_WORKCALENDARITEM wItem ");
                        sqlDay.append(" left join T_HR_ATS_WORKCALENDAR w on w.fid=wItem.fcalendargroupid ");
                        sqlDay.append(" left join ( ");
                        sqlDay.append("     select fcalendarid from T_HR_ATS_ATTENDANCEFILE ");
                        sqlDay.append("     where fproposerid = ? ");
                        sqlDay.append("     order by fleffdt desc ");
                        sqlDay.append(" ) cal on cal.fcalendarid=w.fid ");
                        sqlDay.append(" where wItem.fweek not in(0,6) ");
                        sqlDay.append(" and to_char(wItem.fdate,'yyyy-MM-dd') >= ? ");
                        sqlDay.append(" and to_char(wItem.fdate,'yyyy-MM-dd') <= ? ");
                        sqlDay.append(" order by wItem.fdate desc ");
                        logger.error("sqlDay:" + sqlDay.toString()); //每工作日工资

                        //由于每月的天数不一致所以需要每月分开这算
                        for(String yearMonth : stringList) {
                            startDate=yearMonth+"-01";
                            Calendar endCal = Calendar.getInstance();
                            endCal.setTime(DateTimeUtils.parseDate(startDate));
                            endCal.add(Calendar.MONTH, 1);
                            endCal.add(Calendar.DAY_OF_MONTH, -1);
                            endDate=DateTimeUtils.format(endCal.getTime(), "yyyy-MM-dd");;

                            logger.error("sqlDay-param:personid:" + personid+",startDate:"+startDate+",endDate:"+endDate); //每工作日工资
                            IRowSet dayRs1 = DbUtil.executeQuery(ctx, sqlDay.toString(), new String[]{personid, startDate, endDate}); // 执行SQL查询，获取结果集

                            BigDecimal days1 = BigDecimal.ZERO;
                            if (dayRs1.next()) {
                                days1 = new BigDecimal(dayRs1.size());
                            }
                            BigDecimal days2 = BigDecimal.ZERO;
                            String startDate2=startDate.compareTo(effectDate)>0?startDate:effectDate;
                            String endDate2=endDate.compareTo(leffectDate)>0?leffectDate:endDate;
                            logger.error("折算sqlDay-param:personid:" + personid+",effectDate:"+effectDate+",endDate:"+endDate); //每工作日工资
                            logger.error("折算sqlDay-param:personid:" + personid+",startDate2:"+startDate2+",endDate2:"+endDate2); //每工作日工资
                            IRowSet dayRs2 = DbUtil.executeQuery(ctx, sqlDay.toString(),new String[]{personid,startDate2,endDate2}); // 执行SQL查询，获取结果集
                            if (dayRs2.next()){
                                days2= new BigDecimal(dayRs2.size());
                            }
                            logger.error("sumMoney-days1:" + days1); //每工作日工资
                            logger.error("sumMoney-days2:" + days2); //每工作日工资
                            logger.error("sumMoney:" + sumMoney); //每工作日工资
                            if(days1.compareTo(BigDecimal.ZERO) > 0) {
                                BigDecimal dayMoney = retMoney.divide(days1,BigDecimal.ROUND_HALF_UP,BigDecimal.ROUND_HALF_UP);
                                logger.error("sumMoney-day:" + dayMoney); //每工作日工资
                                sumMoney = sumMoney.add(dayMoney.multiply(days2));
                                logger.error("sumMoney-days:" + sumMoney); //折算工资
                            }else {
                                sumMoney= sumMoney.add(BigDecimal.ZERO);
                            }
                        }

                        // 定义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 = "/*dialect*/ update  CT_CUS_PersonPayForm set CFRetMoney=" + sumMoney.setScale(2, 4) +",CFMonth=to_date('" + DateTimeUtils.format(cfretroactivedate) + "','yyyy-MM-dd')"+ " 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(cfretroactivedate) + "','yyyy-MM-dd')" + "," + sumMoney.setScale(2, 5) + ",'" + id + "')";
                            logger.error("insertSql " + insertSql); // 记录SQL语句到日志中
                            DbUtil.execute(ctx, insertSql); // 执行SQL插入操作
                        }
                    }
                }
            }
            String sft = "update CT_CUS_PersonPayForm set CFRetMoney=0 where CFAdjustSalary in(select fid from T_HR_SFixAdjustSalary where CFTraceability='No')";
            DbUtil.execute(ctx, sft); // 执行SQL插入操作
        } catch (Exception e) {
            e.printStackTrace();
            throw new BOSException(e);
        }
        return null;
    }
    // 获取两个日期之间的月份集合
    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(monthDifference).withDayOfMonth(1);
        if (endDate.isBefore(nextMonthFirstDay)) {
            monthDifference--;
        }
        if (endDate.isAfter(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;
    }

}
