package nckd.jxccl.hr.psms.plugin.form.contribution;

import kd.bos.bill.BillShowParameter;
import kd.bos.bill.OperationStatus;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.entity.ILocaleString;
import kd.bos.dataentity.metadata.IDataEntityProperty;
import kd.bos.entity.BasedataEntityType;
import kd.bos.entity.datamodel.events.ChangeData;
import kd.bos.entity.datamodel.events.IDataModelChangeListener;
import kd.bos.entity.datamodel.events.PropertyChangedArgs;
import kd.bos.entity.property.BasedataProp;
import kd.bos.form.FormShowParameter;
import kd.bos.form.field.BasedataEdit;
import kd.bos.form.field.events.AfterBindingDataEvent;
import kd.bos.form.field.events.BasedataEditListener;
import kd.bos.form.field.events.BeforeF7SelectEvent;
import kd.bos.form.field.events.BeforeF7SelectListener;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.list.ListShowParameter;
import kd.bos.mvc.bill.BillView;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.sdk.plugin.Plugin;
import nckd.jxccl.base.common.constant.FormConstant;
import nckd.jxccl.base.common.enums.psms.ScoreItemEnum;
import nckd.jxccl.base.common.utils.ConvertUtil;
import nckd.jxccl.base.entity.helper.EntityHelper;
import nckd.jxccl.hr.psms.common.ContributionConstant;
import nckd.jxccl.hr.psms.helper.ContributionHelper;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.EventObject;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
* 年度贡献积分单据-表单插件
* 实体标识：nckd_contribbill
* @author W.Y.C
* @date 2025/10/25 22:57
* @version 1.0
*/
public class ContribBillFormPlugin extends AbstractFormPlugin implements Plugin, BeforeF7SelectListener, BasedataEditListener, IDataModelChangeListener {

    @Override
    public void initialize() {
        this.getModel().addDataModelChangeListener(this);
        BasedataEdit mulEdit = this.getControl("nckd_scoreitemsub");
        mulEdit.addBasedataEditListener(this);
    }

    @Override
    public void afterBindingData(AfterBindingDataEvent evt) {
        BillShowParameter showParameter = (BillShowParameter) this.getView().getFormShowParameter();
        String formId = showParameter.getFormId();
        if(formId.equalsIgnoreCase("nckd_contribbill_i") || formId.equalsIgnoreCase("nckd_contribbill_g")){
            BasedataEdit edit = (BasedataEdit) evt.getSource();
            Object v = evt.getDataEntity();
            Object editSearchProp = null;
            Object displayProp = "";
            if (v == null) {
                return;
            }

            BasedataEntityType dt;
            if (((DynamicObject) v).getDataEntityType() instanceof BasedataEntityType) {
                dt = (BasedataEntityType) ((DynamicObject) v).getDataEntityType();
            } else {
                dt = (BasedataEntityType) ((BasedataProp) edit.getProperty()).getComplexType();
            }

            //获取数据包中的名称字段值
            String nameKey = dt.getNameProperty();
            IDataEntityProperty p2 = dt.findProperty(nameKey);
            if (p2 != null) {
                displayProp = p2.getValueFast(v);
                if (displayProp instanceof ILocaleString) {
                    displayProp = displayProp.toString();
                }
            }

            //动态修改多选基础资料的显示属性为名称(部门)
            if ("nckd_scoreitemsub".equals(edit.getKey())) {
                nameKey = "nckd_scoreitemlevel";
            }
            IDataEntityProperty p4 = dt.findProperty(nameKey);
            if (p4 != null) {
                Object valueFast = p4.getValueFast(v);
                if(valueFast instanceof DynamicObject){
                    displayProp = ConvertUtil.toDynamicObjectOrNull(valueFast).getString(FormConstant.NAME_KEY);
                    editSearchProp = ConvertUtil.toDynamicObjectOrNull(valueFast).getString(FormConstant.NUMBER_KEY);

                }
            }

            //设置显示属性
            evt.setDisplayProp(displayProp.toString());
            //设置编辑显示属性
            evt.setEditSearchProp(editSearchProp == null ? "" : editSearchProp.toString());
        }

       /* //修改"单项奖项目"，F7显示字段
        */
    }


    @Override
    public void afterCreateNewData(EventObject e) {
        FormShowParameter formShowParameter = this.getView().getFormShowParameter();
        if (formShowParameter.getStatus() == OperationStatus.ADDNEW) {
            Object value = this.getModel().getValue(ContributionConstant.NCKD_SCOREITEM);
            if (value != null) {
                DynamicObject scoreItem = ConvertUtil.toDynamicObjectOrNull(value);
                if (scoreItem != null) {
                    String scoreItemNumber = scoreItem.getString(FormConstant.NUMBER_KEY);
                    if (ScoreItemEnum.SKILL_CONTEST_SCORE.getCode().equalsIgnoreCase(scoreItemNumber)) {
                        //技能竞赛积分默认三行分录
                        DynamicObjectCollection dynamicObjectCollection = this.getModel().getDataEntity(true).getDynamicObjectCollection(ContributionConstant.NCKD_ENTRYENTITY);
                        DynamicObjectCollection scoreItemRankColl = QueryServiceHelper.query(ContributionConstant.NCKD_SCOREITEMRANK,
                                FormConstant.ID_KEY+","+FormConstant.NAME_KEY+","+FormConstant.NUMBER_KEY,
                                new QFilter[]{new QFilter(ContributionConstant.NCKD_SCOREITEM, QCP.equals, scoreItem.getLong(FormConstant.ID_KEY))},
                                ContributionConstant.INDEX_KEY
                        );
                        for (DynamicObject scoreItemRank : scoreItemRankColl) {
                            DynamicObject dynamicObject = dynamicObjectCollection.addNew();
                            DynamicObject newScoreItemRank = EntityHelper.newEntity(ContributionConstant.NCKD_SCOREITEMRANK, scoreItemRank.getLong(FormConstant.ID_KEY));
                            newScoreItemRank.set(ContributionConstant.NAME_KEY, scoreItemRank.getString(FormConstant.NAME_KEY));
                            newScoreItemRank.set(ContributionConstant.NUMBER_KEY, scoreItemRank.getString(FormConstant.NUMBER_KEY));

                            dynamicObject.set(ContributionConstant.NCKD_SCOREITEMRANKEN,newScoreItemRank);
                        }
                        this.getView().updateView(ContributionConstant.NCKD_ENTRYENTITY);
                    }
                }
            }
        }
    }

    @Override
    public void registerListener(EventObject e) {
        super.registerListener(e);
        // 积分具体项目字段添加值变化监听
        BasedataEdit scoreItemSubField = this.getView().getControl(ContributionConstant.NCKD_SCOREITEMSUB);
        if (scoreItemSubField != null) {
            scoreItemSubField.addBeforeF7SelectListener(this);
        }

        BasedataEdit scoreItemRankField = this.getView().getControl(ContributionConstant.NCKD_SCOREITEMRANK);
        if (scoreItemRankField != null) {
            scoreItemRankField.addBeforeF7SelectListener(this);
        }
    }

    @Override
    public void beforeF7Select(BeforeF7SelectEvent beforeF7SelectEvent) {
        String fieldKey = beforeF7SelectEvent.getProperty().getName();
        if (ContributionConstant.NCKD_SCOREITEMSUB.equalsIgnoreCase(fieldKey) || ContributionConstant.NCKD_SCOREITEMRANK.equalsIgnoreCase(fieldKey)) {
            DynamicObject scoreItem = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEM));
            if(scoreItem == null){
                this.getView().showTipNotification("请先选择“积分项目”");
                beforeF7SelectEvent.setCancel( true);
                return;
            }
            // 构建过滤条件：假设B字段的F7列表关联实体中有一个字段与A字段值关联（例如"relatedField"）
            QFilter filter = new QFilter(ContributionConstant.NCKD_SCOREITEM, QCP.equals, scoreItem.getLong(FormConstant.ID_KEY));
            // 获取F7列表的显示参数并设置过滤条件
            ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
            showParameter.getListFilterParameter().setFilter(filter);
        }
    }

    @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(isScoreCalculationTriggerField(fieldKey) && !Objects.equals(oldValue, newValue)) {
            if(rowIndex > -1) {
                //分录内容变更
                handleEntryRowChange(rowIndex);
            } else {
                //表头字段变更
                handleHeadFieldChange();
            }
        }
    }

    /**
     * 判断是否为触发积分计算的字段
     * @param fieldKey 变更字段
     * @return: boolean
     * @author W.Y.C
     * @date: 2025/10/26 19:46
     */
    private boolean isScoreCalculationTriggerField(String fieldKey) {
        return ContributionConstant.NCKD_YEAR.equalsIgnoreCase(fieldKey)
                || ContributionConstant.NCKD_PERSON.equalsIgnoreCase(fieldKey)
                || ContributionConstant.NCKD_SCOREITEMSUB.equalsIgnoreCase(fieldKey)
                || ContributionConstant.NCKD_SCOREITEM.equalsIgnoreCase(fieldKey)
                || ContributionConstant.NCKD_SCOREITEMRANK.equalsIgnoreCase(fieldKey)
                || ContributionConstant.NCKD_ORISCORE.equalsIgnoreCase(fieldKey);
    }

    /**
     * 处理分录行变更
     * 分录变更则针对当前分录计算积分
     * @param rowIndex 行索引
     * @return: void
     * @author W.Y.C
     * @date: 2025/10/26 19:47
     */
    private void handleEntryRowChange(int rowIndex) {
        Long id = ConvertUtil.toLong(this.getModel().getValue(FormConstant.ID_KEY));
        Date date = ConvertUtil.toDate(this.getModel().getValue(ContributionConstant.NCKD_YEAR));
        DynamicObject scoreItem = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEM));
        DynamicObject scoreItemSub = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMSUB));
        DynamicObject scoreItemRank = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMRANK));
        DynamicObject person = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_PERSON, rowIndex));
        BigDecimal oriScore = ConvertUtil.toBigDecimal(this.getModel().getValue(ContributionConstant.NCKD_ORISCORE, rowIndex));
        if (date != null && scoreItem != null && scoreItemSub != null && scoreItemRank != null) {
            if (person != null  && oriScore != null && oriScore.compareTo(BigDecimal.ZERO) > 0) {
                //科研与创新需要需要匹配积分规则
                QFilter filter = new QFilter(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEM), QCP.equals, scoreItem.getLong(FormConstant.ID_KEY))
                        .and(new QFilter(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMSUB), QCP.equals, scoreItemSub.getLong(FormConstant.ID_KEY)))
                        .and(new QFilter(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMRANK), QCP.equals, scoreItemRank.getLong(FormConstant.ID_KEY)));
                Map<String, BigDecimal> scoreConf = ContributionHelper.getScoreConfByPersonMaxScore(filter);
                String key = scoreItem.getLong(FormConstant.ID_KEY) + "-" + scoreItemSub.getLong(FormConstant.ID_KEY) + "-" + scoreItemRank.getLong(FormConstant.ID_KEY);
                BigDecimal validScore = oriScore;
                if (!scoreConf.isEmpty() && scoreConf.containsKey(key) &&  scoreConf.get(key) != null && scoreConf.get(key).compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal maxScore = scoreConf.get(key);
                    if (maxScore != null) {
                        validScore = oriScore.compareTo(maxScore) > 0 ? maxScore : oriScore;
                    }
                }
                this.getModel().setValue(ContributionConstant.NCKD_SCORE, validScore, rowIndex);
                this.getView().updateView(ContributionConstant.NCKD_SCORE, rowIndex);
            }
        }else{
            this.getModel().setValue(ContributionConstant.NCKD_SCORE, oriScore, rowIndex);
            this.getView().updateView(ContributionConstant.NCKD_SCORE, rowIndex);
        }
    }

    /**
     * 处理分录行变更
     * 分录变更则针对当前分录计算积分
     * @param rowIndex 行索引
     * @return: void
     * @author W.Y.C
     * @date: 2025/10/26 19:47
     */
    private void handleEntryRowChange1(int rowIndex) {
        Long id = ConvertUtil.toLong(this.getModel().getValue(FormConstant.ID_KEY));
        Date date = ConvertUtil.toDate(this.getModel().getValue(ContributionConstant.NCKD_YEAR));
        DynamicObject scoreItem = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEM));
        DynamicObject scoreItemSub = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMSUB));
        DynamicObject scoreItemRank = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMRANK));
        DynamicObject person = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_PERSON, rowIndex));
        BigDecimal oriScore = ConvertUtil.toBigDecimal(this.getModel().getValue(ContributionConstant.NCKD_ORISCORE, rowIndex));

        if (date != null && scoreItem != null && scoreItemSub != null && person != null
                && oriScore != null && oriScore.compareTo(BigDecimal.ZERO) > 0) {
            //计算本次可用积分
            ContributionHelper.ScoreItemValidScore scoreItemValidScore = new ContributionHelper.ScoreItemValidScore(
                    person.getLong(FormConstant.ID_KEY),
                    scoreItem.getLong(FormConstant.ID_KEY),
                    scoreItemSub.getLong(FormConstant.ID_KEY),
                    scoreItemRank != null ? scoreItemRank.getLong(FormConstant.ID_KEY) : null);
            scoreItemValidScore.setCurrentScore(oriScore);
            ContributionHelper.getScoreItemValidScore(scoreItemValidScore, date, id);
            this.getModel().setValue(ContributionConstant.NCKD_SCORE, scoreItemValidScore.getValidScore(), rowIndex);
            this.getView().updateView(ContributionConstant.NCKD_SCORE, rowIndex);
        }
    }

    /**
     * 处理表头字段变更
     * 表头变更则重新计算所有分录（已维护人员和原积分的数据）的积分
     * @param
     * @return: void
     * @author W.Y.C
     * @date: 2025/10/26 19:47
     */
    private void handleHeadFieldChange() {
        Long id = ConvertUtil.toLong(this.getModel().getValue(FormConstant.ID_KEY));
        Date date = ConvertUtil.toDate(this.getModel().getValue(ContributionConstant.NCKD_YEAR));
        DynamicObject scoreItem = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEM));
        DynamicObject scoreItemSub = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMSUB));
        DynamicObject scoreItemRank = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMRANK));


        if (date != null && scoreItem != null && scoreItemSub != null && scoreItemRank != null) {

            DynamicObjectCollection entryEntity = this.getModel().getEntryEntity(FormConstant.NCKD_ENTRYENTITY);

            //科研与创新需要需要匹配积分规则
            QFilter filter = new QFilter(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEM), QCP.equals, scoreItem.getLong(FormConstant.ID_KEY))
                    .and(new QFilter(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMSUB), QCP.equals, scoreItemSub.getLong(FormConstant.ID_KEY)))
                    .and(new QFilter(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMRANK), QCP.equals, scoreItemRank.getLong(FormConstant.ID_KEY)));
            Map<String, BigDecimal> scoreConf = ContributionHelper.getScoreConfByPersonMaxScore(filter);
            String key = scoreItem.getLong(FormConstant.ID_KEY)+"-"+scoreItemSub.getLong(FormConstant.ID_KEY)+"-"+scoreItemRank.getLong(FormConstant.ID_KEY);
            for (int i = 0; i < entryEntity.size(); i++) {
                DynamicObject entry = entryEntity.get(i);
                BigDecimal oriScore = entry.getBigDecimal(ContributionConstant.NCKD_ORISCORE);
                BigDecimal validScore = oriScore;
                if(!scoreConf.isEmpty() && scoreConf.containsKey(key) &&  scoreConf.get(key) != null && scoreConf.get(key).compareTo(BigDecimal.ZERO) > 0){
                    BigDecimal maxScore = scoreConf.get(key);
                    if (maxScore != null && oriScore != null) {
                        validScore = oriScore.compareTo(maxScore) > 0 ? maxScore : oriScore;
                    } else {
                        // 根据业务需求处理 null 值情况
                        validScore = oriScore != null ? oriScore : BigDecimal.ZERO;
                    }
                }
                this.getModel().setValue(ContributionConstant.NCKD_SCORE, validScore, i);
            }

        }else{
            DynamicObjectCollection entryEntity = this.getModel().getEntryEntity(FormConstant.NCKD_ENTRYENTITY);
            for (int i = 0; i < entryEntity.size(); i++) {
                DynamicObject entry = entryEntity.get(i);
                BigDecimal oriScore = entry.getBigDecimal(ContributionConstant.NCKD_ORISCORE);
                this.getModel().setValue(ContributionConstant.NCKD_SCORE, oriScore, i);
            }
        }
    }


    /**
     * 处理表头字段变更
     * 表头变更则重新计算所有分录（已维护人员和原积分的数据）的积分
     * @param
     * @return: void
     * @author W.Y.C
     * @date: 2025/10/26 19:47
     */
    private void handleHeadFieldChange1() {
        Long id = ConvertUtil.toLong(this.getModel().getValue(FormConstant.ID_KEY));
        Date date = ConvertUtil.toDate(this.getModel().getValue(ContributionConstant.NCKD_YEAR));
        DynamicObject scoreItem = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEM));
        DynamicObject scoreItemSub = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMSUB));
        DynamicObject scoreItemRank = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMRANK));

        if (date != null && scoreItem != null && scoreItemSub != null) {
            //重置分录所有分录的"录用积分"字段
            DynamicObjectCollection entryEntity = this.getModel().getEntryEntity(FormConstant.NCKD_ENTRYENTITY);
            List<ContributionHelper.ScoreItemValidScore> scoreItemValidScoreList = new ArrayList<>(entryEntity.size());

            for (int i = 0; i < entryEntity.size(); i++) {
                DynamicObject person = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_PERSON, i));
                BigDecimal oriScore = ConvertUtil.toBigDecimal(this.getModel().getValue(ContributionConstant.NCKD_ORISCORE, i));

                if(person != null && oriScore != null && oriScore.compareTo(BigDecimal.ZERO) > 0){
                    ContributionHelper.ScoreItemValidScore scoreItemValidScore = new ContributionHelper.ScoreItemValidScore(
                            person.getLong(FormConstant.ID_KEY),
                            scoreItem.getLong(FormConstant.ID_KEY),
                            scoreItemSub.getLong(FormConstant.ID_KEY),
                            scoreItemRank != null ? scoreItemRank.getLong(FormConstant.ID_KEY) : null);
                    scoreItemValidScore.setCurrentScore(oriScore);
                    scoreItemValidScore.setRowIndex(i);
                    scoreItemValidScoreList.add(scoreItemValidScore);
                }
            }

            if (!scoreItemValidScoreList.isEmpty()) {
                ContributionHelper.getScoreItemValidScore(scoreItemValidScoreList, date, id);
                for (ContributionHelper.ScoreItemValidScore scoreItemValidScore : scoreItemValidScoreList) {
                    this.getModel().setValue(ContributionConstant.NCKD_SCORE, scoreItemValidScore.getValidScore(), scoreItemValidScore.getRowIndex());
                }
                this.getView().updateView(FormConstant.NCKD_ENTRYENTITY);
            }
        }
    }

}