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

import kd.bos.coderule.api.CodeRuleInfo;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.entity.LocaleString;
import kd.bos.entity.operate.OperateOptionConst;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
import kd.bos.entity.plugin.PreparePropertysEventArgs;
import kd.bos.entity.plugin.args.AfterOperationArgs;
import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.ORM;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.DispatchServiceHelper;
import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
import kd.bos.servicehelper.operation.DeleteServiceHelper;
import kd.bos.servicehelper.operation.OperationServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import org.apache.commons.lang3.ObjectUtils;
import java.text.SimpleDateFormat;
import java.util.concurrent.TimeUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 出差申请单：操作插件，处理人人差旅出差申请单同步至HR的代他人出差申请
 * 表单标识：出差申请单(nckd_er_tripreqbill_ext)
 * @author wanghaiwu_kd
 * @date 2025/05/10
 */

public class BusinessTravelOpPlugin extends AbstractOperationServicePlugIn {

    private static Log logger = LogFactory.getLog(BusinessTravelOpPlugin.class);

    public void onPreparePropertys(PreparePropertysEventArgs e) {
        // 提前加载表单里的字段
        List<String> fieldKeys = e.getFieldKeys();
        fieldKeys.addAll(this.billEntityType.getAllFields().keySet());
    }

    @Override
    public void beginOperationTransaction(BeginOperationTransactionArgs args) {
        super.beginOperationTransaction(args);

    }

    @Override
    public void afterExecuteOperationTransaction(AfterOperationArgs args) {
        super.afterExecuteOperationTransaction(args);
        String operationKey = args.getOperationKey();
        DynamicObject[] regBillObjs = args.getDataEntities();
        logger.info("开始执行操作：{},实体:{}",operationKey, regBillObjs);

        switch (operationKey) {
            case "audit":
                for (DynamicObject regBillObj : regBillObjs) {
                    regBillObj.set("nckd_createhr", 1);

                    String currentUserId = RequestContext.get().getUserId();
                    String creatorId = regBillObj.getDynamicObject("creator").getString("id");

                    if(!creatorId.equals(currentUserId)) {
                        DynamicObject bosUser = BusinessDataServiceHelper.loadSingle(currentUserId, "bos_user");

                        regBillObj.set("nckd_lastauditor", bosUser);
                    }
                }
                SaveServiceHelper.save(regBillObjs);
                this.createDynamicObject(regBillObjs, operationKey);
                logger.info("生成为他人申请出差结果操作结束");
                break;
            case "triprevoke":
                for (DynamicObject regBillObj : regBillObjs) {
                    regBillObj.set("nckd_createhr", 1);
                }
                SaveServiceHelper.save(regBillObjs);
                this.createDynamicObject(regBillObjs, operationKey);
                logger.info("生成为他人申请出差结果操作结束");
                break;
            case "tripchange":
                for (DynamicObject regBillObj : regBillObjs) {
                    regBillObj.set("nckd_createhr", 0);
                }
                SaveServiceHelper.save(regBillObjs);
                this.deleteDynamicObject(regBillObjs, operationKey);
                logger.info("删除为他人申请出差结果操作结束");
            case "unaudit":
                for (DynamicObject regBillObj : regBillObjs) {
                    regBillObj.set("nckd_createhr", 0);
                }
                SaveServiceHelper.save(regBillObjs);
                this.deleteDynamicObject(regBillObjs, operationKey);
                logger.info("删除为他人申请出差结果操作结束");
                break;
            default:
                break;
        }

    }

    /**
     * 删除为下推的为他人申请出差
     * @param regBillObjs
     * @param key
     */
    private void deleteDynamicObject(DynamicObject[] regBillObjs,String key) {
        ArrayList<Long> longs = new ArrayList<>();
        ArrayList<String> billList = new ArrayList<>();
        logger.info("开始执行删除为他人申请出差操作");

        for (DynamicObject regBillObj : regBillObjs) {
            longs.add(regBillObj.getLong("id"));
            billList.add(regBillObj.getString("billno"));
        }

        DynamicObject travelLog = BusinessDataServiceHelper.newDynamicObject("nckd_travel_log");
        travelLog.set("nckd_er_tripreqbill",key);
        travelLog.set("name","出差申请单");
        travelLog.set("number","er_tripreqbill");
        travelLog.set("status","A");
        travelLog.set("enable",1);
        travelLog.set("nckd_billno",String.join(",", billList));

        try {
            String path = "nckd.jimin.jyyy.bd.servicehelper";
            //保存日志
            Map<String, Object> result = DispatchServiceHelper.invokeService(path,"bd","SaveTravleLogService","saveTravelLogData", travelLog);

            if(result != null){

            }
            //删除为他人申请出差
            result = DispatchServiceHelper.invokeService(path,"bd","SaveTravleLogService","deleteHRTripData", longs);
        } catch(Exception e1){
            logger.info(e1.getMessage());
        }
    }

    /**
     * 创建为他人申请出差
     * @param regBillObjs
     * @param operationKey
     */
    public void createDynamicObject(DynamicObject[] regBillObjs, String operationKey) {
        ORM orm = ORM.create();
        logger.info("开始执行创建为他人申请出差操作");

        for (DynamicObject regBillObj : regBillObjs) {
            // 获取行程信息
            DynamicObjectCollection tripentry = regBillObj.getDynamicObjectCollection("tripentry");

            for (DynamicObject dynamicObject : tripentry) {
                // 日志信息
                DynamicObject travelLog = BusinessDataServiceHelper.newDynamicObject("nckd_travel_log");
                travelLog.set("nckd_er_tripreqbill", operationKey);
                travelLog.set("name","出差申请单");
                travelLog.set("number","er_tripreqbill");
                travelLog.set("status","A");
                travelLog.set("enable",1);
                travelLog.set("nckd_billno", regBillObj.getString("billno"));

                List<String> nameList = new ArrayList<>();
                List<String> numberList = new ArrayList<>();
                // 获取出差人
                DynamicObjectCollection travelers1 = dynamicObject.getDynamicObjectCollection("travelers");
                for (DynamicObject object : travelers1) {
                    DynamicObject user = object.getDynamicObject("fbasedataid");
                    nameList.add(user.getString("name"));
                    numberList.add(user.getString("number"));
                }
                travelLog.set("nckd_travels",String.join(",", nameList)); // 出差人
                List<String> travelerno = new ArrayList<>();
                // 获取工号，去查询考勤人员
                QFilter qFilter2 = new QFilter("number", QCP.in, numberList);
                QFilter qFilter1 = new QFilter("laborrelstatus.number", QCP.not_equals, "1080_S");// 排除离职
                DynamicObject[] wtpAttendpeople = BusinessDataServiceHelper.load("wtp_attendperson", "id,name,number", new QFilter[]{qFilter1, qFilter2});
                DynamicObject[] wtpAttfilebases = new DynamicObject[0];
                if(wtpAttendpeople.length > 0){
                    List<Long> idList = Arrays.stream(wtpAttendpeople)
                            .map(order ->  order.getLong("id"))
                            .collect(Collectors.toList());

                    List<String> nameList2 = Arrays.stream(wtpAttendpeople)
                            .map(order ->  order.getString("name"))
                            .collect(Collectors.toList());

                    travelerno = nameList.stream()
                            .filter(name -> !nameList2.contains(name))
                            .collect(Collectors.toList());


                    // 查询考勤档案
                    QFilter qFilter3 = new QFilter("attperson.id", QCP.in, idList);
                    QFilter status = new QFilter("iscurrentversion", QCP.equals, "1")
                            .and("status", QCP.equals, "C")
                            .and("enable", QCP.equals, "1");

                    wtpAttfilebases = BusinessDataServiceHelper.load("wtp_attfilebase", "id,name,number,attperson,org," +
                            "affiliateadminorg,dependencytype,adminorg,textname,managingscope,agreedlocation,job," +
                            "position,company,workplace,dependency,empgroup,hrperson,personnum,textname,usablestatus"
                            , new QFilter[]{qFilter3, status});
                    if(wtpAttfilebases.length > 0){
                        Map<Long, DynamicObject> map2 =
                                Arrays.stream(wtpAttfilebases)
                                        .collect(Collectors.toMap(
                                                detail -> detail.getLong("attperson.id"), // 获取 useorg.id 作为 key
                                                detail -> detail, // 整个 DynamicObject 作为 value
                                                (existing, replacement) -> existing // 保留前面的值
                                        ));
                        QFilter qFilter4 = new QFilter("attperson.id", QCP.in, idList);
                        QFilter status2 = new QFilter("iscurrentversion", QCP.equals, "0")
                                .and("status", QCP.equals, "C")
                                .and("enable", QCP.equals, "1");
                        DynamicObject[] load = BusinessDataServiceHelper.load("wtp_attfilebase", "id,name,number,attperson,org," +
                                "affiliateadminorg,dependencytype,adminorg,textname,managingscope,agreedlocation,job," +
                                "position,company,workplace,dependency,empgroup,hrperson,personnum,textname,usablestatus", new QFilter[]{qFilter4, status2}, "hisversion desc");
                        Map<Long, DynamicObject> map3 =
                                Arrays.stream(load)
                                        .collect(Collectors.toMap(
                                                detail -> detail.getLong("attperson.id"), // 获取 useorg.id 作为 key
                                                detail -> detail, // 整个 DynamicObject 作为 value
                                                (existing, replacement) -> existing // 保留前面的值
                                        ));

                        initDate(regBillObj, dynamicObject, wtpAttendpeople, map2, travelLog, travelerno, map3, operationKey);
                    }

                }
                if(wtpAttendpeople.length == 0 || wtpAttfilebases.length == 0){
                    travelLog.set("nckd_travelsno",String.join(",", numberList));
                    travelLog.set("nckd_returnparameter","未找到对应考勤人员及档案");

                    try {
                        String path = "nckd.jimin.jyyy.bd.servicehelper";
                        Map<String, Object> result = DispatchServiceHelper.invokeService(path,"bd","SaveTravleLogService","saveTravelLogData", travelLog);

                        if(result != null){

                        }
                    } catch(Exception e1){
                        logger.info(e1.getMessage());
                    }
                }
            }
        }
    }

    private void initDate(DynamicObject dynamicObject, DynamicObject tripentry, DynamicObject[] travelers
            , Map<Long, DynamicObject> map, DynamicObject log, List<String> travelerno,Map<Long, DynamicObject> map3, String operationKey){
        // 出差申请单id
        long id = dynamicObject.getLong("id");
        List<String> travelerList = new ArrayList<>();
        List<String> travelerListNo = new ArrayList<>();
        StringBuilder errstr = new StringBuilder();


        DynamicObject bosUser = dynamicObject.getDynamicObject("nckd_lastauditor");

        Date startdate = tripentry.getDate("startdate");
        Date enddate = tripentry.getDate("enddate");
        // 计算合计申请时长
        long diffInMillies = Math.abs(enddate.getTime() - startdate.getTime());
        long diffInDays = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS) +1;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        //出差类型-出差
        QFilter qFilter = new QFilter("number", QCP.equals, "JY1010_S");
        DynamicObject object = BusinessDataServiceHelper.loadSingle("wtbd_traveltype", qFilter.toArray());

        // 交通工具
        QFilter qFilter2 = new QFilter("number", QCP.equals, "1040_S");
        DynamicObject object2 = BusinessDataServiceHelper.loadSingle("wtbd_traveltool", qFilter2.toArray());

        for (DynamicObject traveler : travelers) {
            // 考情档案
            DynamicObject wtpAttfilebase = map.get(traveler.getLong("id"));
            if(ObjectUtils.isEmpty(wtpAttfilebase)){
                travelerListNo.add(traveler.getString("name"));
                errstr.append(traveler.getString("name")+",");
                continue;
            }
            travelerList.add(traveler.getString("name"));
            //  traveler  考勤人员信息
            // 构建 为他人加班申请 ,直接为审核状态
            DynamicObject wtamBusitripbill = BusinessDataServiceHelper.newDynamicObject("wtam_busitripbill");
            wtamBusitripbill.set("billstatus","A");
            CodeRuleInfo codeRule = CodeRuleServiceHelper.getCodeRule(wtamBusitripbill.getDataEntityType().getName(), wtamBusitripbill, null);
            String number = CodeRuleServiceHelper.getNumber(codeRule, wtamBusitripbill);
            wtamBusitripbill.set("billno",number);

            wtamBusitripbill.set("creator", bosUser);

            wtamBusitripbill.set("nckd_tripreqbillid", id);
            // 考勤人员
            wtamBusitripbill.set("personid", traveler);
            // 考勤管理组织
            wtamBusitripbill.set("org",wtpAttfilebase.get("org"));
            // 考勤档案
            wtamBusitripbill.set("attfile",wtpAttfilebase);
            DynamicObject wtpAttfilebase2 = map3.get(traveler.getLong("id"));
            wtamBusitripbill.set("attfilebasef7",wtpAttfilebase2);
            // 样式类型
            wtamBusitripbill.set("billstyle","1");
            // 申请类型
            wtamBusitripbill.set("applytyperadio","1");
            // 是否档案废弃
            wtamBusitripbill.set("isattfilediscard",0);
            // 是否存在工作流
            wtamBusitripbill.set("isattfilediscard",0);
            // 审批状态
            wtamBusitripbill.set("auditstatus","A");

            // 申请时长合计
            wtamBusitripbill.set("sumtriptime",diffInDays);

            // 出差结束日期
            wtamBusitripbill.set("edate",enddate);

            // 出差开始日期
            wtamBusitripbill.set("sdate",startdate);

            // 合计单位 A:天
            wtamBusitripbill.set("sumunit","A");
            // 是否变更单
            wtamBusitripbill.set("ischange",0);
            // 未出差（销差）
            wtamBusitripbill.set("isnottrip",0);
            // 是否最新单据
            wtamBusitripbill.set("isnewbill",1);
            // 出差日期
            wtamBusitripbill.set("btdate",1);
            // 原单id
            wtamBusitripbill.set("originalid",0);


            // 行程单据体
            DynamicObjectCollection entryentity = wtamBusitripbill.getDynamicObjectCollection("entryentity");
            DynamicObject dynamicObject1 = entryentity.addNew();

            dynamicObject1.set("busitriptype",object); // 出差类型
            dynamicObject1.set("startdatestr",sdf.format(tripentry.getDate("startdate"))); // 开始日期
            dynamicObject1.set("startdate",tripentry.getDate("startdate")); // 开始日期
            dynamicObject1.set("enddatestr",sdf.format(tripentry.getDate("enddate"))); // 结束日期
            dynamicObject1.set("enddate",tripentry.getDate("enddate")); // 结束日期
            dynamicObject1.set("traveltool",object2); // 交通工具 todo

            dynamicObject1.set("from",tripentry.get("from")); // 出发地
            dynamicObject1.set("to",tripentry.get("to")); // 目的地
            dynamicObject1.set("triptimestr",diffInDays+"天"); // 申请时长
            dynamicObject1.set("triptime",diffInDays); // 申请时长
            dynamicObject1.set("efftctime",diffInDays); // 有效时长
            dynamicObject1.set("unit","A"); // 单位
            dynamicObject1.set("tripresontex",dynamicObject.get("description")); // 出差原因
            dynamicObject1.set("strapplytime",new LocaleString(diffInDays+"天")); // 申请时长显示 多语言文本
            dynamicObject1.set("owndate",startdate); // 班次归属日期
            dynamicObject1.set("startmethod","3"); // 出差方式（开始） 默认全天
            dynamicObject1.set("endmethod","3"); // 出差方式（结束） 默认全天
            dynamicObject1.set("enclosuremode","A"); // 附件信息 下拉列表

            try {

                String path = "nckd.jimin.jyyy.bd.servicehelper";
                boolean isWorkFlow = Boolean.parseBoolean(operateOption.getVariableValue("WF", Boolean.FALSE.toString()));
                if(!isWorkFlow){
                    operationKey = "triprevoke";
                }

                Map<String, Object> result = DispatchServiceHelper.invokeService(path,"bd","SaveTravleLogService","saveHRTripData", wtamBusitripbill, "submiteffect", operationKey);

                if(result != null){

                }
            } catch(Exception e1){
                logger.info(e1.getMessage());
            }

        }
        if(errstr.length() > 0){
            errstr.append("未找到对应考勤人员档案");
        }

        log.set("nckd_travelsalready",String.join(",", travelerList));
        log.set("nckd_travelsno",String.join(",", travelerno)+String.join(",", travelerListNo));
        String str = "";
        if(travelerno.size() > 0){
            str = String.join(",", travelerno)+ "未找到对应考勤人员。";
        }
        str = str + errstr.toString();
        log.set("nckd_returnparameter",str);

        try {
            String path = "nckd.jimin.jyyy.bd.servicehelper";
            Map<String, Object> result = DispatchServiceHelper.invokeService(path,"bd","SaveTravleLogService","saveTravelLogData", log);

            if(result != null){

            }
        } catch(Exception e1){
            logger.info(e1.getMessage());
        }
    }
}
