package nckd.jxccl.swc.mas.plugin.form.structappr.change;

import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.IDataEntityProperty;
import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
import kd.bos.entity.datamodel.events.AfterAddRowEventArgs;
import kd.bos.entity.datamodel.events.ChangeData;
import kd.bos.entity.datamodel.events.PropertyChangedArgs;
import kd.bos.entity.report.CellStyle;
import kd.bos.form.control.EntryGrid;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.utils.ConvertUtil;
import nckd.jxccl.base.common.utils.DateUtil;
import nckd.jxccl.base.common.utils.QueryFieldBuilder;
import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
import nckd.jxccl.swc.constants.MasConstant;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 薪酬标准变更表单插件抽象基类
 *
 * @author W.Y.C
 * @date 2025/12/03
 */
public abstract class AbstractSalaryStdChgFormPlugin extends AbstractFormPlugin {

    @Override
    public void afterBindData(java.util.EventObject e) {
        DynamicObjectCollection entryCollection = this.getModel().getEntryEntity(FormConstant.NCKD_ENTRYENTITY);
        for (int rowIndex = 0; rowIndex < entryCollection.size(); rowIndex++) {
            DynamicObject entry = entryCollection.get(rowIndex);
            if(entry.get(MasConstant.NCKD_INSTALLMENTYEARS) != null) {
                int installmentYears = entry.getInt(MasConstant.NCKD_INSTALLMENTYEARS);
                initOperateOption(installmentYears, rowIndex);
            }
        }
        markChange();
    }

    @Override
    public void afterAddRow(AfterAddRowEventArgs e) {
        initOperateOption(0, e.getInsertRow());
    }

    @Override
    public void propertyChanged(PropertyChangedArgs e) {
        String fieldKey = e.getProperty().getName();
        ChangeData[] changeSet = e.getChangeSet();
        int rowIndex = changeSet[0].getRowIndex();
        Object oldValue = changeSet[0].getOldValue();
        Object newValue = changeSet[0].getNewValue();
        
        if (MasConstant.NCKD_INSTALLMENTYEARS.equalsIgnoreCase(fieldKey)) {
            if (!Objects.equals(oldValue, newValue)) {
                initOperateOption(ConvertUtil.toInt(newValue,0), rowIndex);
            }
        } else if (MasConstant.NCKD_APPRSTD.equalsIgnoreCase(fieldKey)) {
            handleApprStdChanged(oldValue, newValue, rowIndex);
        }
        markChange();
    }

    /**
     * 处理核定标准字段变化
     * @param oldValue 旧值
     * @param newValue 新值
     * @param rowIndex 行索引
     */
    private void handleApprStdChanged(Object oldValue, Object newValue, int rowIndex) {
        DynamicObject payUnit = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(MasConstant.NCKD_PAYUNIT));
        DynamicObject lawEntity = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(MasConstant.NCKD_LAWENTITY));
        DynamicObject projectCategory = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(MasConstant.NCKD_PROJECTCATEGORY));
        Date year = ConvertUtil.toDate(this.getModel().getValue(MasConstant.NCKD_YEAR));
        //判断"核定标准"是否大于0
        BigDecimal apprStd = ConvertUtil.toBigDecimal(newValue);
        if (apprStd != null && apprStd.compareTo(BigDecimal.ZERO) > 0) {
            if (payUnit != null && lawEntity != null && year != null && projectCategory != null) {
                if (!Objects.equals(oldValue, newValue)) {
                    //计算：延期支付总金额、支付年份1、支付年份1....
                    //====================================== 获取延期支付比例 begin ======================================
                    LocalDateTime localDateTime = DateUtil.toLocalDateTime(year);
                    LocalDateTime beginOfYear = DateUtil.beginOfYear(localDateTime);
                    LocalDateTime endOfYear = DateUtil.endOfYear(localDateTime);

                    QueryFieldBuilder deferPayRatoConfQueryFieldBuilder = QueryFieldBuilder.create()
                            .add(MasConstant.NCKD_PROJECTCATEGORY)
                            .addIdNumberName(MasConstant.NCKD_PAYUNIT)
                            .addIdNumberName(MasConstant.NCKD_DEFERPAYMONEY)
                            .add(MasConstant.NCKD_DEFERPAYRATIO)
                            .add(MasConstant.NCKD_DEFERPAYRATIO)
                            .add(MasConstant.NCKD_PAYOUTTIMES)
                            .add(MasConstant.NCKD_YEAR)
                            .add(FormConstant.NCKD_ENTRYENTITY)
                            .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_TIMES)
                            .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_PAYOUTRATIO)
                            .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_PAYOUTMONEY)
                            .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_DEFERREDPAYITEM)
                            .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_DEFERREDPAYDESC)
                            .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_TERMPAYDESC)
                            .orderDesc(MasConstant.CREATE_TIME_KEY)
                            .orderAsc(String.join(".", FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_TIMES));
                    QFilter deferPayRatoConfFilter = new QFilter(MasConstant.NCKD_PAYUNIT, QCP.equals, payUnit.getLong(FormConstant.ID_KEY))
                            .and(MasConstant.NCKD_LAWENTITY, QCP.equals, lawEntity.getLong(FormConstant.ID_KEY))
                            .and(MasConstant.NCKD_YEAR, QCP.large_equals, DateUtil.toDate(beginOfYear))
                            .and(MasConstant.NCKD_YEAR, QCP.less_equals, DateUtil.toDate(endOfYear))
                            .and(QFilterCommonHelper.getEnableFilter());
                    DynamicObject[] dbDeferPayRatoConfArray = BusinessDataServiceHelper.load(MasConstant.DEFERPAYRATOCONF_ENTITYID, deferPayRatoConfQueryFieldBuilder.buildSelect(), new QFilter[]{deferPayRatoConfFilter});
                    Map<String, List<DynamicObject>> dbDeferPayRatoConfMap = Arrays.stream(dbDeferPayRatoConfArray)
                            .collect(Collectors.groupingBy(obj -> {
                                DynamicObject dbProjectCategory = obj.getDynamicObject(MasConstant.NCKD_PROJECTCATEGORY);
                                if (dbProjectCategory != null) {
                                    return dbProjectCategory.getString(FormConstant.NUMBER_KEY);
                                }
                                return ""; // 处理无项目分类的情况
                            }));
                    List<DynamicObject> dbDeferPayRatoConfList = dbDeferPayRatoConfMap.get(projectCategory.getString(FormConstant.NUMBER_KEY));

                    if (dbDeferPayRatoConfList != null && !dbDeferPayRatoConfList.isEmpty()) {
                        DynamicObject deferPayRatoConf = dbDeferPayRatoConfList.get(0);
                        //延期支付比例（%）
                        BigDecimal deferPayRatio = deferPayRatoConf.getBigDecimal(MasConstant.NCKD_DEFERPAYRATIO);
                        //延期支付金额
                        BigDecimal deferPayMoney = deferPayRatoConf.getBigDecimal(MasConstant.NCKD_DEFERPAYMONEY);
                        LocalDateTime beginYear = DateUtil.toLocalDateTime(deferPayRatoConf.getDate(MasConstant.NCKD_YEAR));
                        BigDecimal deferPayTotalAmt;
                        if (deferPayMoney != null && deferPayMoney.compareTo(BigDecimal.ZERO) > 0) {
                            //优先使用【延期支付金额】
                            deferPayTotalAmt = deferPayMoney;
                        } else {
                            //核算标准*延期支付比例/100
                            deferPayTotalAmt = apprStd.multiply(deferPayRatio.divide(new BigDecimal(100), 2, RoundingMode.DOWN));
                        }
                        this.getModel().setValue(MasConstant.NCKD_DEFERPAYTOTALAMT, deferPayTotalAmt, rowIndex);
                        DynamicObjectCollection entryColl = deferPayRatoConf.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
                        int i = 0;
                        for (DynamicObject entry : entryColl) {
                            int times = entry.getInt(MasConstant.NCKD_TIMES);
                            //兑现比例（%）
                            BigDecimal payoutRatio = entry.getBigDecimal(MasConstant.NCKD_PAYOUTRATIO);
                            //兑现金额
                            BigDecimal payoutMoney = entry.getBigDecimal(MasConstant.NCKD_PAYOUTMONEY);
                            BigDecimal payaMount;
                            if (payoutMoney != null && payoutMoney.compareTo(BigDecimal.ZERO) > 0) {
                                //优先使用【兑现金额】
                                payaMount = payoutMoney;
                            } else {
                                //延期支付总金额*兑现比例
                                payaMount = deferPayTotalAmt.multiply(payoutRatio.divide(new BigDecimal(100), 2, RoundingMode.DOWN));
                            }
                            if (i != 0) {
                                beginYear = DateUtil.addYears(beginYear, 1);
                            }
                            this.getModel().setValue(MasConstant.NCKD_PAYYEAR + (i + 1), DateUtil.toDate(beginYear), rowIndex);
                            this.getModel().setValue(MasConstant.NCKD_PAYAMOUNT + (i + 1), payaMount, rowIndex);
                            i++;
                        }

                    }
                    //====================================== 获取延期支付比例 end ======================================

                }
            }
        } else {
            this.getModel().setValue(MasConstant.NCKD_DEFERPAYTOTALAMT, null);
        }
    }

    /**
     * 设置支付N锁定或解锁
     * @param installmentYears 分期支付年
     * @param rowIndex 行索引
     */
    private void initOperateOption(int installmentYears, int rowIndex) {
        if (rowIndex > -1) {
            for (int i = 1; i <= 10; i++) {
                this.getView().setEnable(false, rowIndex, MasConstant.NCKD_PAYYEAR + i);
                this.getView().setEnable(false, rowIndex, MasConstant.NCKD_PAYAMOUNT + i);
            }
            for (int i = 1; i <= installmentYears; i++) {
                this.getView().setEnable(true, rowIndex, MasConstant.NCKD_PAYYEAR + i);
                this.getView().setEnable(true, rowIndex, MasConstant.NCKD_PAYAMOUNT + i);
            }
            for (int i = installmentYears+1; i <= 10; i++) {
                this.getModel().setValue( MasConstant.NCKD_PAYYEAR + i,null,rowIndex);
                this.getModel().setValue( MasConstant.NCKD_PAYAMOUNT + i,null,rowIndex);
            }
        }
    }

    //标记变更
    private void markChange() {
        DynamicObjectCollection entryColl = this.getModel().getDataEntity(true).getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
        DynamicObjectCollection oldEntryColl = this.getModel().getDataEntity(true).getDynamicObjectCollection("nckd_oldentryentity");

        List<CellStyle> cellStyles = new ArrayList<>();
        int i = 0;
        for (DynamicObject entry : entryColl) {
            long originId = entry.getLong("nckd_originid");
            for (DynamicObject oldEntry : oldEntryColl) {
                long oldOriginId = oldEntry.getLong("nckd_originidold");
                if (originId == oldOriginId) {
                    DataEntityPropertyCollection properties = oldEntry.getDynamicObjectType().getProperties();
                    for (IDataEntityProperty property : properties) {
                        String oldName = property.getName();
                        String name = oldName.replace("old", "");
                        Object value = entry.get(name);
                        Object oldValue = oldEntry.get(oldName);
                        if (!Objects.equals(value, oldValue)) {
                            CellStyle cellStyle = new CellStyle();
                            cellStyle.setFieldKey(name);
                            cellStyle.setRow(i);
                            cellStyle.setForeColor("#fb2323");
                            cellStyles.add(cellStyle);
                        }

                    }
                }
            }
            i++;
        }
        EntryGrid entryGrid = this.getControl(FormConstant.NCKD_ENTRYENTITY);
        entryGrid.setCellStyle(cellStyles);
    }
}