package nckd.jimin.jyyy.fi.plugin.form;

import kd.bos.context.RequestContext;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.resource.ResManager;
import kd.bos.form.events.BeforeDoOperationEventArgs;
import kd.bos.form.operate.AbstractOperate;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.fi.er.business.utils.ErCommonUtils;
import kd.fi.er.business.utils.ReimburseUpAppQfilterUtil;
import kd.fi.er.formplugin.botp.up.PublicReimburseBotpUpPlugin;
import kd.fi.er.formplugin.botp.up.service.BotpDrawServiceStdImpl;
import kd.fi.er.formplugin.botp.up.service.IBotpDrawService;
import kd.fi.er.formplugin.botp.up.service.ValidBillArg;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 对公报销单（nckd_er_publicreimbur_ext），处理上拉费用申请过滤问题
 * @author wanghaiwu_kd
 * @date 2025/06/19
 */
public class ErDailyReimburseExtBotpUpPlugin extends PublicReimburseBotpUpPlugin {
    private static final Log log = LogFactory.getLog(ErDailyReimburseExtBotpUpPlugin.class);

    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
        Object source = args.getSource();
        String opKey = ((AbstractOperate)source).getOperateKey();

        if("addapplycheck".equals(opKey)) {
            DynamicObject item = (DynamicObject) this.getModel().getValue("nckd_expenseitem");
            String fieldKey = "";
            String fieldName = "";

            if (item == null) {
                this.getView().showTipNotification(ResManager.loadKDString("请先选择费用类型。", "PublicReimburseBotpUpPlugin_0", "fi-er-formplugin", new Object[0]));
                args.setCancel(true);
            } else if (checkProject(item)) {
                //item = BusinessDataServiceHelper.loadSingle(item.getPkValue(), item.getDynamicObjectType().getName());
                String pjtype = item.getString("nckd_pjtype");

                //标准项目
                if ("project".equals(pjtype)) {
                    fieldKey = "nckd_project";
                    fieldName = "项目";
                }
                //核算项目
                else if ("acctitem".equals(pjtype)) {
                    fieldKey = "nckd_acctitem";
                    fieldName = "核算项目";
                }

                if (this.getModel().getValue(fieldKey) == null) {
                    this.getView().showTipNotification(ResManager.loadKDString("请先选择" +  fieldName + "。", "PublicReimburseBotpUpPlugin_0", "fi-er-formplugin", new Object[0]));
                    args.setCancel(true);
                } else {
                    super.beforeDoOperation(args);
                }
            } else {
                super.beforeDoOperation(args);
            }
        } else {
            super.beforeDoOperation(args);
        }
    }

    /**
     * 判断是否需要校验项目/核算项目必填
     * @return
     */
    private boolean checkProject(DynamicObject item){
        boolean needCheck = false;
        DynamicObject company = null;
        if (this.getControl("company") != null) {
            company = (DynamicObject) this.getModel().getValue("company");
        } else if (this.getView().getParentView().getControl("company") != null) {
            company = (DynamicObject) this.getView().getParentView().getModel().getValue("company");
        }
        Long companyId = company == null ? null : (Long) company.getPkValue();
        companyId = companyId != null ? companyId : RequestContext.get().getOrgId();
        String controlproject = (String) ErCommonUtils.getEMParameter(companyId, "nckd_controlproject");

        if("1".equals(controlproject)) {
            item = BusinessDataServiceHelper.loadSingle(item.getPkValue(), item.getDynamicObjectType().getName());

            String isrelapjtype = item.getString("nckd_isrelapjtype");
            String isrelapj = (String) this.getModel().getValue("nckd_isrelapj");

            //必选
            if ("1".equals(isrelapjtype) || ("2".equals(isrelapjtype) && "1".equals(isrelapj))) {
                needCheck = true;
            }
        }

        log.info("needCheck:" + needCheck);

        return needCheck;
    }

    /**
     * 增加扩展过滤条件
     * @param sFilter
     */
    private void addExtendFilter(QFilter sFilter){
        DynamicObjectCollection collection = (DynamicObjectCollection)this.getModel().getValue("nckd_payviewtypemul");
        List<Long> idList = (List)collection.stream().mapToLong((x) -> {
            return x.getLong("fbasedataid_id");
        }).boxed().collect(Collectors.toList());

        QFilter viewTypeFilter = new QFilter("nckd_payviewtype.id", QCP.in, idList);

        DynamicObject[] items = BusinessDataServiceHelper.load("er_expenseitemedit", "id", viewTypeFilter.toArray());

        List<Long> itemIds = (List) Arrays.stream(items).map((o) -> {
            return o.getLong("id");
        }).collect(Collectors.toList());

        //费用类型过滤
        sFilter.and(new QFilter("nckd_expenseitem.id", QCP.in, itemIds));

        DynamicObject item = (DynamicObject) this.getModel().getValue("nckd_expenseitem");
        boolean checkProject = checkProject(item);

        if(checkProject) {
            String pjtype = item.getString("nckd_pjtype");

            String fieldKey = "";
            //标准项目
            if ("project".equals(pjtype)) {
                fieldKey = "nckd_project";
            }
            //核算项目
            else if ("acctitem".equals(pjtype)) {
                fieldKey = "nckd_acctitem";
            }

            Long curProjectId = ((DynamicObject) this.getModel().getValue(fieldKey)).getLong("id");
            //项目/核算项目过滤
            sFilter.and(new QFilter(fieldKey + ".id", QCP.equals, curProjectId));
        }
    }

    /**
     *
     * @param includeApplierAndProjectOwer
     * @return
     */
    @Override
    protected Object getBillList(boolean includeApplierAndProjectOwer) {
        IBotpDrawService drawService = new BotpDrawServiceStdImpl(this.getModel(), this.getView());
        String selectFieds = "id as billid,billno,applier,org,company,description,bizdate,expenseentryentity.expenseitem as expenseitem,expenseentryentity.entrycurrency as entrycurrency,expenseentryentity.exchangerate as exchangerate,expenseentryentity.orgiexpebalanceamount as orgiexpebalanceamount,expenseentryentity.expebalanceamount as expebalanceamount,expenseentryentity.id as entryid,expenseentryentity.entrycostdept as costdept,expenseentryentity.std_entrycostcenter as costcenter,expenseentryentity.entrycostcompany as costcompany";

        //增加扩展字段
        selectFieds += ", nckd_project, nckd_acctitem";

        QFilter qFilter = new QFilter("billstatus", "=", "E");
        qFilter.and(new QFilter("expenseentryentity.orgiexpebalanceamount", ">", BigDecimal.ZERO));
        switch (ErCommonUtils.getEMParameter(this.getCompany(), "relatapplybillfilterrange").toString()) {
            case "0":
                if (includeApplierAndProjectOwer) {
                    qFilter.and((new QFilter("applier", "=", this.getApplier())).or("projectower.FBASEDATAID_id", "in", Collections.singletonList(this.getApplier())));
                } else {
                    qFilter.and(new QFilter("applier", "=", this.getApplier()));
                }

                qFilter.and(new QFilter("company", "=", this.getCompany()));
                break;
            case "1":
                qFilter.and(new QFilter("org", "=", this.getDept()));
                break;
            case "2":
                qFilter.and(new QFilter("company", "=", this.getCompany()));
                break;
            case "4":
                if (includeApplierAndProjectOwer) {
                    qFilter.and((new QFilter("applier", "=", this.getApplier())).or("projectower.FBASEDATAID_id", "in", Collections.singletonList(this.getApplier())));
                } else {
                    qFilter.and(new QFilter("applier", "=", this.getApplier()));
                }
        }

        qFilter.and(new QFilter("currency", "=", ErCommonUtils.getPk(this.getModel().getValue("currency"))));
        Long currency;
        if (this.getModel().getDataEntity().getDynamicObjectType().getProperties().containsKey("currency")) {
            currency = ErCommonUtils.getPk(this.getView().getModel().getValue("currency"));
            if (currency != null) {
                qFilter.and(new QFilter("currency", "=", currency));
            }
        }

        currency = null;
        if (this.getView().getModel().getProperty("reimbursetype") != null) {
            String reimbursetype = (String)this.getModel().getValue("reimbursetype");
            QFilter reimbursetypeQfilter;
            if (!"expense".equals(reimbursetype) && !" ".equals(reimbursetype) && !"asset".equals(reimbursetype) && reimbursetype != null) {
                reimbursetypeQfilter = new QFilter("reimbursetype", "=", this.getModel().getValue("reimbursetype"));
            } else {
                reimbursetypeQfilter = (new QFilter("reimbursetype", "=", "expense")).or("reimbursetype", "=", " ").or("reimbursetype", "=", "otherexpenses").or("reimbursetype", "=", (Object)null);
            }

            qFilter = ReimburseUpAppQfilterUtil.setBizitemFilter(this.getModel(), qFilter, reimbursetypeQfilter);
            qFilter.and(reimbursetypeQfilter);
        }

        //增加扩展过滤
        addExtendFilter(qFilter);

        ValidBillArg arg = new ValidBillArg("er_dailyapplybill", selectFieds, new QFilter[]{qFilter});
        return drawService.getValidBills(this.getExistPks(), new ValidBillArg[]{arg});


    }

    private Map<Long, List<Long>> getExistPks() {
        Map<Long, List<Long>> result = new HashMap<Long, List<Long>>();
        DynamicObjectCollection entryEntity = this.getModel().getEntryEntity("writeoffapply");
        if (entryEntity == null || entryEntity.size() < 1) {
            return result;
        }
        for (DynamicObject row : entryEntity) {
            long sourcebillid = row.getLong("sourceapplybillid");
            List<Long> entryIds = result.get(sourcebillid);
            if (entryIds == null) {
                entryIds = new ArrayList<Long>();
                result.put(sourcebillid, entryIds);
            }
            entryIds.add(row.getLong("sourceapplyentryid"));
        }
        return result;
    }
}
