package com.awspaas.user.apps.donenow_ivt.service;

import com.actionsoft.bpms.bo.engine.BO;
import com.actionsoft.bpms.bpmn.engine.model.run.delegate.ProcessInstance;
import com.actionsoft.bpms.server.UserContext;
import com.actionsoft.bpms.util.DBSql;
import com.actionsoft.bpms.util.TypeUtil;
import com.actionsoft.sdk.local.SDK;
import com.actionsoft.sdk.local.api.Logger;
import com.awspaas.user.apps.donenow_ivt.constant.IVTConstant;
import com.awspaas.user.apps.donenow_ivt.utils.PeriodCalculationUtil;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 付款计划服务
 */
public class PaymentPlanService {
    // 常量定义
    private static final Logger logger = SDK.getLogAPI().getLogger(PaymentPlanService.class);

    // 单例模式
    private static volatile PaymentPlanService instance;

    private PaymentPlanService() {
    }

    public static PaymentPlanService getInstance() {
        if (instance == null) {
            synchronized (PaymentPlanService.class) {
                if (instance == null) {
                    instance = new PaymentPlanService();
                }
            }
        }
        return instance;
    }


    /**
     * 创建付款计划
     * @param uc
     * @param orderId
     */
    public void createPaymentPlan(UserContext uc, String orderId) {
        BO purchaseOrder = SDK.getBOAPI().get("BO_EU_DNIVT_ORDER", orderId);
        List<BO> orderProducts = SDK.getBOAPI().query("BO_EU_DNIVT_ORDER_PRODUCT").bindId(purchaseOrder.getBindId()).list();
        String VENDOR_ACCOUNT_ID = purchaseOrder.getString("VENDOR_ACCOUNT_ID");//供应商账户ID

        int total = 0;
        boolean isOnlyOne = true;
        for (BO orderProduct : orderProducts) {
            if (StringUtils.isNotBlank(orderProduct.getString("CONTRACT_COST_ID"))) {
                String SERVICE_ID = DBSql.getString("select SERVICE_ID from BO_EU_DNCTT_CONTRACT_COST where ID=?", new Object[]{orderProduct.getString("CONTRACT_COST_ID")});
                //关联服务
                if (StringUtils.isNotBlank(SERVICE_ID)) {
                    isOnlyOne = false;
                    if (DBSql.getInt("select count(1) as cnt from  BO_EU_DNIVT_ORDER_PAYMENT_PLAN where ORDER_ID = ? and CONTRACT_COST_ID=? and CONTRACT_SERVICE_ID=?  AND PAY_AMOUNT is NOT null AND PAY_AMOUNT<>0", new Object[]{orderId, orderProduct.getString("CONTRACT_COST_ID"), SERVICE_ID}) > 0) {
                        continue;
                    }
                    String sql = "delete from BO_EU_DNIVT_ORDER_PAYMENT_PLAN where ORDER_ID = ? and CONTRACT_COST_ID=? and CONTRACT_SERVICE_ID=? and (PAY_AMOUNT is null or PAY_AMOUNT = 0)";
                    DBSql.update(sql, new Object[]{orderId, orderProduct.getString("CONTRACT_COST_ID"), SERVICE_ID});

                    logger.info("生成付款计划SERVICE_ID--" + SERVICE_ID);

                    BO service = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_SERVICE", SERVICE_ID);
                    String BILL_METHOD_ID = null;//计费方式  4601:自然月  4602:实际月
                    if (service.getString("OBJECT_TYPE").equals("2"))//服务包
                    {
                        BILL_METHOD_ID = DBSql.getString("select BILL_METHOD_ID from BO_EU_DNIVT_SERVICE_BUNDLE where ID=?", new Object[]{service.getString("OBJECT_ID")});
                    } else {
                        BILL_METHOD_ID = DBSql.getString("select BILL_METHOD_ID from BO_EU_DNIVT_SERVICE where ID=?", new Object[]{service.getString("OBJECT_ID")});
                    }

                    String RULE_CATE = service.getString("PURCHASE_PERIOD_TYPE");//采购周期
                    LocalDate PERIOD_BEGIN_DATE = service.get("PURCHASE_START_DATE", LocalDate.class);

                    LocalDate START_DATE = TypeUtil.convert(DBSql.getString("select START_DATE from BO_EU_DNCTT_CONTRACT where ID=?", new Object[]{service.getString("CONTRACT_ID")}).substring(0, 10), LocalDate.class);

                    LocalDate PERIOD_END_DATE = TypeUtil.convert(DBSql.getString("select END_DATE from BO_EU_DNCTT_CONTRACT where ID=?", new Object[]{service.getString("CONTRACT_ID")}).substring(0, 10), LocalDate.class);

                    //采购单开始日期
                    if (service.get("PURCHASE_START_DATE") != null) {
                        START_DATE = TypeUtil.convert(service.get("PURCHASE_START_DATE").toString().substring(0, 10), LocalDate.class);
                    }

                    //  List<PERIOD> periods = getPeriodList(RULE_CATE, PERIOD_BEGIN_DATE, START_DATE, PERIOD_END_DATE, StringUtils.isNotBlank(BILL_METHOD_ID) && BILL_METHOD_ID.equals("4601"));

                    //统一处理
                    // List<PeriodCalculationUtil.Period> periods = PeriodCalculationUtil.getPeriodList(RULE_CATE, PERIOD_BEGIN_DATE, START_DATE, PERIOD_END_DATE, true, true, -1);

                    List<PeriodCalculationUtil.Period> periods = PeriodCalculationUtil.getPeriodListByConfig(RULE_CATE, PERIOD_BEGIN_DATE, START_DATE, PERIOD_END_DATE, service.getString("PURCHASE_CALC_METHOD_1STPERIOD"), service.getString("CALC_METHOD_1STYEAR"), service.getString("MONTH_1STQUARTER"));

                    if (periods.isEmpty())
                        continue;

                    BigDecimal COST_TOTAL = orderProduct.get("COST_TOTAL", BigDecimal.class);//总金额

                    BigDecimal RATE_TOTAL = periods.stream().map(period -> period.getRate()).reduce(BigDecimal.ZERO, BigDecimal::add);


                    BigDecimal UNIT_COST_1STMONTH = BigDecimal.ZERO;
                    //首月总价需要单独计算   613	按年支付	4591	开通日期所在月
                    if (periods.size() > 0 && service.get("PURCHASE_CALC_METHOD_1STPERIOD").equals("4591")) {
                        PeriodCalculationUtil.Period period = periods.get(0);
                        if (period.getRate().compareTo(BigDecimal.ONE) < 0) {
                            UNIT_COST_1STMONTH = toBigDecimal(service.get("UNIT_COST_1STMONTH"));
                            UNIT_COST_1STMONTH = period.getRate().multiply(BigDecimal.valueOf(12)).multiply(UNIT_COST_1STMONTH);
                            RATE_TOTAL = RATE_TOTAL.subtract(period.getRate());//减去首月
                            COST_TOTAL = COST_TOTAL.subtract(UNIT_COST_1STMONTH);//减去首月
                        }
                    }


                    if (RATE_TOTAL.equals(BigDecimal.ZERO) || COST_TOTAL == null || COST_TOTAL.equals(BigDecimal.ZERO))
                        continue;

                    BigDecimal UNIT_COST = COST_TOTAL.divide(RATE_TOTAL, 10, RoundingMode.HALF_UP);
                    int i = 0;
                    for (PeriodCalculationUtil.Period period : periods) {
                        total++;
                        ProcessInstance processInstance = SDK.getProcessAPI().createProcessInstance("obj_5cb4ae4a42944fd0a9a284ff4c64c65d", uc.getUID(), "付款计划");

                        BO paymentPlan = new BO();
                        paymentPlan.setBindId(processInstance.getId());
                        paymentPlan.set("ORDER_ID", orderId);
                        paymentPlan.set("PLAN_DATE", period.getPeriodBeginDateStr());

                        //首月总价需要单独计算   613	按年支付	4591	开通日期所在月
                        if (i == 1 && service.get("PURCHASE_CALC_METHOD_1STPERIOD").equals("4591")) {
                            //firstRate<1
                            if (period.getRate().compareTo(BigDecimal.ONE) < 0) {
                                /*
                                BigDecimal UNIT_COST_1STMONTH = toBigDecimal(service.get("UNIT_COST_1STMONTH"));
                                UNIT_COST_1STMONTH = period.getRate().multiply(BigDecimal.valueOf(12)).multiply(UNIT_COST_1STMONTH);
                                paymentPlan.set("PLAN_AMOUNT", period.getRate().multiply(UNIT_COST_1STMONTH));
                                 */
                                if (periods.size() == 1) {
                                    paymentPlan.set("PLAN_AMOUNT", UNIT_COST_1STMONTH);
                                } else {
                                    continue;
                                }
                            } else {
                                paymentPlan.set("PLAN_AMOUNT", UNIT_COST.multiply(period.getRate()));
                            }
                        } else {
                            if (i == 2 && UNIT_COST_1STMONTH.compareTo(BigDecimal.ZERO) > 0) {
                                paymentPlan.set("PLAN_AMOUNT", UNIT_COST.multiply(period.getRate()).add(UNIT_COST_1STMONTH));
                            } else {
                                paymentPlan.set("PLAN_AMOUNT", UNIT_COST.multiply(period.getRate()));
                            }
                        }

                        paymentPlan.set("REMAIN_AMOUNT", paymentPlan.get("PLAN_AMOUNT"));
                        paymentPlan.set("CONTRACT_COST_ID", orderProduct.getString("CONTRACT_COST_ID"));
                        paymentPlan.set("CONTRACT_SERVICE_ID", service.getId());
                        paymentPlan.set("PAY_DESC", orderProduct.getString("NAME"));

                        paymentPlan.set("ACCOUNT_PAYEE", VENDOR_ACCOUNT_ID);//收款单位

                        paymentPlan.set("PERIOD_BEGIN_DATE", period.getPeriodBeginDateStr());
                        paymentPlan.set("PERIOD_END_DATE", period.getPeriodEndDateStr());

                        SDK.getBOAPI().create("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", paymentPlan, processInstance, uc);

                        System.out.println("==== 创建付款计划：" + paymentPlan.get("PLAN_DATE") + "，金额：" + paymentPlan.get("PLAN_AMOUNT") + " ====");
                    }
                }
            }
        }

        if (isOnlyOne) {
            total += 1;
            String sql = "delete from BO_EU_DNIVT_ORDER_PAYMENT_PLAN where ORDER_ID = ? and (PAY_AMOUNT is null or PAY_AMOUNT = 0)";
            DBSql.update(sql, new Object[]{orderId});

            //全部采购项 合并生成一条采购计划
            ProcessInstance processInstance = SDK.getProcessAPI().createProcessInstance("obj_5cb4ae4a42944fd0a9a284ff4c64c65d", uc.getUID(), "付款计划");

            String PLAN_DATE = null;
            if (purchaseOrder.get("EXPECTED_SHIP_DATE") != null)
                PLAN_DATE = purchaseOrder.get("EXPECTED_SHIP_DATE").toString().substring(0, 10);
            else PLAN_DATE = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

            BigDecimal PLAN_AMOUNT = orderProducts.stream().map(orderProduct -> orderProduct.get("COST_TOTAL", BigDecimal.class)).reduce(BigDecimal.ZERO, BigDecimal::add);

            String PAY_DESC = orderProducts.stream().map(orderProduct -> orderProduct.getString("NAME")).collect(Collectors.joining(","));

            if (StringUtils.isNotBlank(PAY_DESC) && PAY_DESC.length() > 300) PAY_DESC = PAY_DESC.substring(0, 300);

            BO paymentPlan = new BO();
            paymentPlan.setBindId(processInstance.getId());
            paymentPlan.set("ORDER_ID", orderId);
            paymentPlan.set("PLAN_DATE", PLAN_DATE);
            paymentPlan.set("PLAN_AMOUNT", PLAN_AMOUNT);
            paymentPlan.set("REMAIN_AMOUNT", PLAN_AMOUNT);
            paymentPlan.set("PAY_DESC", PAY_DESC);
            paymentPlan.set("ACCOUNT_PAYEE", VENDOR_ACCOUNT_ID);//收款单位
            SDK.getBOAPI().create("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", paymentPlan, processInstance, uc);
            System.out.println("==== 创建付款计划：" + paymentPlan.get("PLAN_DATE") + "，金额：" + paymentPlan.get("PLAN_AMOUNT") + " ====");

        }
        logger.info("付款计划生成完成，生成付款计划数量：" + total);
    }

    /**
     * 获取周期列表
     * @param RULE_CATE
     * @param CONTRACT_START_DATE
     * @param PERIOD_BEGIN_DATE
     * @param PERIOD_END_DATE
     * @param isNaturalMonth //自然月和实际月
     * @return
     */
    private List<PERIOD> getPeriodList(String RULE_CATE, LocalDate CONTRACT_START_DATE, LocalDate PERIOD_BEGIN_DATE, LocalDate PERIOD_END_DATE, boolean isNaturalMonth) {

        logger.info("获取周期列表");
        logger.info("RULE_CATE:" + RULE_CATE);
        logger.info("CONTRACT_START_DATE:" + CONTRACT_START_DATE);
        logger.info("PERIOD_BEGIN_DATE:" + PERIOD_BEGIN_DATE);
        logger.info("PERIOD_END_DATE:" + PERIOD_END_DATE);
        logger.info("isNaturalMonth:" + isNaturalMonth);

        if (RULE_CATE.equals(IVTConstant.PERIOD_TYPE_MONTH)) {
            isNaturalMonth = true;
        } else {
            isNaturalMonth = false;
        }

        if (CONTRACT_START_DATE.getDayOfMonth() != 1)// 不是1号开始，就从1号开始
            CONTRACT_START_DATE = CONTRACT_START_DATE.with(TemporalAdjusters.firstDayOfMonth());

        List<PERIOD> periodList = new ArrayList<>();
        //一次性收费
        if (RULE_CATE.equals(IVTConstant.PERIOD_TYPE_ONE_TIME)) {
            PERIOD period = new PERIOD();
            period.setPeriodBeginDate(PERIOD_BEGIN_DATE);
            period.setPeriodEndDate(PERIOD_END_DATE);
            period.setRate(BigDecimal.ONE);
            periodList.add(period);
        } else {
            LocalDate START_DATE = null;
            LocalDate currLastDay = null;//当前周期的结束日
            int periodDays = 0;//当前周期天数
            switch (RULE_CATE) {
                case IVTConstant.PERIOD_TYPE_MONTH://按月支付
                {
                    if (isNaturalMonth) {
                        //自然月
                        if (PERIOD_BEGIN_DATE.getDayOfMonth() != 1) {
                            currLastDay = PERIOD_BEGIN_DATE.with(TemporalAdjusters.lastDayOfMonth());
                            periodDays = PERIOD_BEGIN_DATE.lengthOfMonth();
                        }
                    } else {
                        //实际月
                        if (CONTRACT_START_DATE.isAfter(PERIOD_BEGIN_DATE))//合同开始日期在 服务开始日期之后
                        {
                            currLastDay = CONTRACT_START_DATE.minusDays(1);//获取合同开始日期的前一日
                            periodDays = GetPeriodDays(CONTRACT_START_DATE.minusMonths(1), currLastDay);

                        } else if (CONTRACT_START_DATE.isBefore(PERIOD_BEGIN_DATE)) {//合同开始日期在 服务开始日期之前
                            currLastDay = CONTRACT_START_DATE.plusMonths(1).minusDays(1);

                            periodDays = GetPeriodDays(CONTRACT_START_DATE, currLastDay);

                            if (currLastDay.isAfter(PERIOD_END_DATE))//如果当前周期结束日大于服务结束日
                            {
                                currLastDay = PERIOD_END_DATE;
                            }

                        } else {


                        }
                    }
                }
                break;
                case IVTConstant.PERIOD_TYPE_QUARTER://按季支付
                {
                    if (isNaturalMonth) {
                        //如果不是季度第一天
                        if (PERIOD_BEGIN_DATE.getDayOfMonth() != 1 || (PERIOD_BEGIN_DATE.getMonthValue() - 1) % 3 != 0) {
                            Month endMonth = getQuarterEndMonth(PERIOD_BEGIN_DATE.getMonth());
                            currLastDay = LocalDate.of(PERIOD_BEGIN_DATE.getYear(), endMonth, endMonth.length(PERIOD_BEGIN_DATE.isLeapYear()) // 考虑闰年2月的天数
                            );
                            periodDays = getDaysInCurrentQuarter(PERIOD_BEGIN_DATE);
                        }
                    } else {
                        //实际月
                        if (CONTRACT_START_DATE.isAfter(PERIOD_BEGIN_DATE))//合同开始日期在 服务开始日期之后
                        {
                            currLastDay = CONTRACT_START_DATE.minusDays(1);//获取合同开始日期的前一日
                            periodDays = GetPeriodDays(CONTRACT_START_DATE.minusMonths(3), currLastDay);

                        } else if (CONTRACT_START_DATE.isBefore(PERIOD_BEGIN_DATE)) {//合同开始日期在 服务开始日期之前
                            currLastDay = CONTRACT_START_DATE.plusMonths(3).minusDays(1);

                            periodDays = GetPeriodDays(CONTRACT_START_DATE, currLastDay);

                            if (currLastDay.isAfter(PERIOD_END_DATE))//如果当前周期结束日大于服务结束日
                            {
                                currLastDay = PERIOD_END_DATE;
                            }

                        } else {


                        }
                    }

                }
                break;
                case IVTConstant.PERIOD_TYPE_HALFYEAR://按半年支付
                    if (isNaturalMonth) {
                        // 若不是半年第一天，计算本半年剩余天数作为首个周期
                        if (PERIOD_BEGIN_DATE.getDayOfMonth() != 1 || (PERIOD_BEGIN_DATE.getMonthValue() - 1) % 6 != 0) {
                            Month endMonth = getHalfYearEndMonth(PERIOD_BEGIN_DATE.getMonth());
                            currLastDay = LocalDate.of(PERIOD_BEGIN_DATE.getYear(), endMonth, endMonth.length(PERIOD_BEGIN_DATE.isLeapYear()));
                            periodDays = getDaysInCurrentHalfYear(PERIOD_BEGIN_DATE);
                        }
                    } else {
                        //实际月
                        if (CONTRACT_START_DATE.isAfter(PERIOD_BEGIN_DATE))//合同开始日期在 服务开始日期之后
                        {
                            currLastDay = CONTRACT_START_DATE.minusDays(1);//获取合同开始日期的前一日
                            periodDays = GetPeriodDays(CONTRACT_START_DATE.minusMonths(6), currLastDay);

                        } else if (CONTRACT_START_DATE.isBefore(PERIOD_BEGIN_DATE)) {//合同开始日期在 服务开始日期之前
                            currLastDay = CONTRACT_START_DATE.plusMonths(6).minusDays(1);

                            periodDays = GetPeriodDays(CONTRACT_START_DATE, currLastDay);

                            if (currLastDay.isAfter(PERIOD_END_DATE))//如果当前周期结束日大于服务结束日
                            {
                                currLastDay = PERIOD_END_DATE;
                            }

                        } else {


                        }
                    }
                    break;
                case IVTConstant.PERIOD_TYPE_YEAR://按年支付
                {
                    if (isNaturalMonth) {
                        //如果不是年第一天
                        if (PERIOD_BEGIN_DATE.getDayOfMonth() != 1 || PERIOD_BEGIN_DATE.getMonthValue() != 1) {
                            //所在年最后一天
                            currLastDay = LocalDate.of(PERIOD_BEGIN_DATE.getYear(), 12, 31);
                            periodDays = PERIOD_BEGIN_DATE.lengthOfYear();
                        }

                    } else {
                        //实际月
                        if (CONTRACT_START_DATE.isAfter(PERIOD_BEGIN_DATE))//合同开始日期在 服务开始日期之后
                        {
                            currLastDay = CONTRACT_START_DATE.minusDays(1);//获取合同开始日期的前一日
                            periodDays = GetPeriodDays(CONTRACT_START_DATE.minusMonths(12), currLastDay);

                        } else if (CONTRACT_START_DATE.isBefore(PERIOD_BEGIN_DATE)) {//合同开始日期在 服务开始日期之前
                            currLastDay = CONTRACT_START_DATE.plusMonths(12).minusDays(1);

                            periodDays = GetPeriodDays(CONTRACT_START_DATE, currLastDay);

                            if (currLastDay.isAfter(PERIOD_END_DATE))//如果当前周期结束日大于服务结束日
                            {
                                currLastDay = PERIOD_END_DATE;
                            }
                        } else {


                        }
                    }
                }
                break;
                default: {
                    //报错，类型异常
                    return null;
                }
            }
            logger.info("currLastDay:" + currLastDay);
            logger.info("periodDays:" + periodDays);

            if (currLastDay != null) {
                if (currLastDay.isBefore(PERIOD_END_DATE)) {
                    PERIOD period = new PERIOD();
                    period.setPeriodBeginDate(PERIOD_BEGIN_DATE);
                    period.setPeriodEndDate(currLastDay);

                    BigDecimal periodRate = divideToBigDecimal(GetPeriodDays(PERIOD_BEGIN_DATE, currLastDay), periodDays);
                    period.setRate(periodRate);

                    periodList.add(period);

                    START_DATE = currLastDay.plusDays(1);//周期开始日期
                } else {
                    PERIOD period = new PERIOD();
                    period.setPeriodBeginDate(PERIOD_BEGIN_DATE);
                    period.setPeriodEndDate(PERIOD_END_DATE);

                    BigDecimal periodRate = divideToBigDecimal(GetPeriodDays(PERIOD_BEGIN_DATE, PERIOD_END_DATE), periodDays);
                    period.setRate(periodRate);

                    periodList.add(period);
                }
            } else {
                START_DATE = PERIOD_BEGIN_DATE;
            }

            logger.info("START_DATE:" + START_DATE);

            //循环
            if (START_DATE != null && START_DATE.isBefore(PERIOD_END_DATE)) {

                while (!START_DATE.isAfter(PERIOD_END_DATE)) {
                    LocalDate periodEnd = getNextPeriodStart(START_DATE, RULE_CATE).minusDays(1);//本周期结束时间

                    BigDecimal periodRate = BigDecimal.ONE;

                    if (periodEnd.isAfter(PERIOD_END_DATE)) {//如果结束日期大于合同结束日期，则计算结束日期和合同结束日期的差值，并计算该差值占整周期的比例
                        periodRate = divideToBigDecimal(GetPeriodDays(START_DATE, PERIOD_END_DATE), GetPeriodDays(START_DATE, periodEnd));
                        periodEnd = PERIOD_END_DATE;
                    }

                    PERIOD period = new PERIOD();
                    period.setPeriodBeginDate(START_DATE);
                    period.setPeriodEndDate(periodEnd);
                    period.setRate(periodRate);
                    periodList.add(period);

                    if (periodEnd != null) {
                        START_DATE = periodEnd.plusDays(1);
                    }
                }
            }
        }
        return periodList;
    }

    /**
     * 获取下一周期开始时间
     * @param start 当前周期开始时间
     * @param periodType 周期类型
     * @return 下一周期开始时间
     */
    public static LocalDate getNextPeriodStart(LocalDate start, String periodType) {
        // 根据不同的周期类型计算下一周期的开始时间
        switch (periodType) {
            case IVTConstant.PERIOD_TYPE_MONTH:
                // 如果是月周期，则在当前时间基础上增加1个月
                return start.plus(1, ChronoUnit.MONTHS);
            case IVTConstant.PERIOD_TYPE_QUARTER:
                // 如果是季度周期，则在当前时间基础上增加3个月
                return start.plus(3, ChronoUnit.MONTHS);
            case IVTConstant.PERIOD_TYPE_HALFYEAR:
                // 如果是半年周期，则在当前时间基础上增加6个月
                return start.plus(6, ChronoUnit.MONTHS);
            case IVTConstant.PERIOD_TYPE_YEAR:
                // 如果是年周期，则在当前时间基础上增加1年
                return start.plus(1, ChronoUnit.YEARS);
            default:
                // 如果周期类型不匹配任何已知类型，则返回原始开始时间
                return start;
        }
    }

    /**
     * 获取当前季度的结束月份
     */
    private static Month getQuarterEndMonth(Month month) {
        int monthValue = month.getValue();
        if (monthValue <= 3) {
            return Month.MARCH;   // 第一季度结束月
        } else if (monthValue <= 6) {
            return Month.JUNE;    // 第二季度结束月
        } else if (monthValue <= 9) {
            return Month.SEPTEMBER; // 第三季度结束月
        } else {
            return Month.DECEMBER;  // 第四季度结束月
        }
    }

    /**
     * 计算当前季度的总天数
     */
    private static int getDaysInCurrentQuarter(LocalDate date) {
        // 获取当前月份
        Month currentMonth = date.getMonth();
        // 确定当前季度的起始月份和结束月份
        Month startMonth = getQuarterStartMonth(currentMonth);
        Month endMonth = getQuarterEndMonth(currentMonth);

        // 构建季度的第一天（当月第一天）
        LocalDate quarterStart = LocalDate.of(date.getYear(), startMonth, 1);

        // 构建季度的最后一天（当月最后一天）
        LocalDate quarterEnd = LocalDate.of(date.getYear(), endMonth, endMonth.length(date.isLeapYear()) // 考虑闰年2月的天数
        );

        // 计算两个日期之间的天数（包含首尾两天）
        return (int) ChronoUnit.DAYS.between(quarterStart, quarterEnd) + 1;
    }

    /**
     * 获取当前季度的起始月份
     */
    private static Month getQuarterStartMonth(Month month) {
        int monthValue = month.getValue();
        if (monthValue <= 3) {
            return Month.JANUARY; // 第一季度：1-3月
        } else if (monthValue <= 6) {
            return Month.APRIL;   // 第二季度：4-6月
        } else if (monthValue <= 9) {
            return Month.JULY;    // 第三季度：7-9月
        } else {
            return Month.OCTOBER; // 第四季度：10-12月
        }
    }

    /**
     * 获取当前半年的结束月份
     */
    private static Month getHalfYearEndMonth(Month month) {
        int monthValue = month.getValue();
        return monthValue <= 6 ? Month.JUNE : Month.DECEMBER;
    }

    /**
     * 获取当前半年的起始月份
     */
    private static Month getHalfYearStartMonth(Month month) {
        int monthValue = month.getValue();
        return monthValue <= 6 ? Month.JANUARY : Month.JULY;
    }

    /**
     * 计算当前半年的总天数
     */
    private static int getDaysInCurrentHalfYear(LocalDate date) {
        Month currentMonth = date.getMonth();
        Month startMonth = getHalfYearStartMonth(currentMonth);
        Month endMonth = getHalfYearEndMonth(currentMonth);

        LocalDate halfYearStart = LocalDate.of(date.getYear(), startMonth, 1);
        LocalDate halfYearEnd = LocalDate.of(date.getYear(), endMonth, endMonth.length(date.isLeapYear()));

        return GetPeriodDays(halfYearStart, halfYearEnd);
    }

    private static int GetPeriodDays(LocalDate start, LocalDate end) {
        return (int) ChronoUnit.DAYS.between(start, end) + 1;
    }

    // 定义一个方法，将两个 int 相除并返回 BigDecimal
    public static BigDecimal divideToBigDecimal(int numerator, int denominator) {
        if (denominator == 0) {
            throw new ArithmeticException("分母不能为零");
        }

        // 使用 BigDecimal 进行精确计算
        BigDecimal num = new BigDecimal(numerator);
        BigDecimal den = new BigDecimal(denominator);

        // 设置小数点后的位数和舍入模式
        return num.divide(den, 10, RoundingMode.HALF_UP); // 保留 10 位小数
    }


    /**
     * 将Object转换为BigDecimal
     * @param obj 待转换的对象（支持Number、String等可转换为数字的类型）
     * @return 转换后的BigDecimal
     * @throws IllegalArgumentException 若对象无法转换为BigDecimal
     */
    public static BigDecimal toBigDecimal(Object obj) {
        if (obj == null) {
            throw new IllegalArgumentException("对象不能为null");
        }

        if (obj instanceof BigDecimal) {
            return (BigDecimal) obj;
        } else if (obj instanceof Number) {
            // 处理数字类型（Integer、Double、Long等）
            return new BigDecimal(obj.toString());
        } else if (obj instanceof String) {
            // 处理字符串类型（需符合数字格式）
            try {
                return new BigDecimal((String) obj);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("字符串无法转换为BigDecimal: " + obj, e);
            }
        } else {
            throw new IllegalArgumentException("不支持的类型转换: " + obj.getClass().getName());
        }
    }

    /**
     * 周期
     */
    private class PERIOD {
        private LocalDate PERIOD_BEGIN_DATE;
        private LocalDate PERIOD_END_DATE;
        private BigDecimal RATE;

        public void setPeriodBeginDate(LocalDate periodBeginDate) {
            this.PERIOD_BEGIN_DATE = periodBeginDate;
        }

        public void setPeriodEndDate(LocalDate periodEndDate) {
            this.PERIOD_END_DATE = periodEndDate;
        }

        public void setRate(BigDecimal rate) {
            this.RATE = rate;
        }

        public LocalDate getPeriodBeginDate() {
            return PERIOD_BEGIN_DATE;
        }

        public LocalDate getPeriodEndDate() {
            return PERIOD_END_DATE;
        }

        public String getPeriodBeginDateStr() {
            return PERIOD_BEGIN_DATE.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }

        public String getPeriodMonthStr() {
            return PERIOD_BEGIN_DATE.format(DateTimeFormatter.ofPattern("yyyyMM"));
        }

        public String getPeriodEndDateStr() {
            return PERIOD_END_DATE.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }

        public BigDecimal getRate() {
            return RATE;
        }

    }
}
