package com.kingdee.eas.custom.perfweb.handler;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kingdee.bos.Context;
import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
import com.kingdee.eas.base.permission.UserInfo;
import com.kingdee.eas.custom.perfweb.AssessmentResultDescriptionFactory;
import com.kingdee.eas.custom.perfweb.AssessmentResultDescriptionInfo;
import com.kingdee.eas.custom.perfweb.IAssessmentResultDescription;
import com.kingdee.eas.custom.perfweb.bizEnum.AutoStatusEnum;
import com.kingdee.eas.custom.perfweb.service.CenterPerfStatService;
import com.kingdee.eas.custom.perfweb.utils.FeishuMessageUtil;
import com.kingdee.eas.custom.perfweb.utils.UrlParamUtil;
import com.kingdee.eas.util.app.ContextUtil;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.shr.base.syssetting.context.SHRContext;
import com.kingdee.shr.base.syssetting.exception.SHRWebException;
import com.kingdee.shr.base.syssetting.exception.ShrWebBizException;
import com.kingdee.shr.base.syssetting.json.GridDataEntity;
import com.kingdee.shr.base.syssetting.web.handler.ListHandler;
import com.kingdee.shr.base.syssetting.web.json.JSONUtils;
import com.kingdee.shr.perfweb.app.base.evalplan.PerfPeriodFactory;
import com.kingdee.shr.perfweb.app.base.evalplan.PerfPeriodInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.ui.ModelMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 绩效考核结果报表 ListHandler：getGridRequestData 加载表格数据，approve 审批发飞书待办。
 */
public class CenterPerfStatReportHandlerEx extends ListHandler {

    private final Logger logger = Logger.getLogger(CenterPerfStatReportHandlerEx.class);
    private final Context ctx = SHRContext.getInstance().getContext();

    /**
     * 报表列表数据：调 getCenterPerfStatService（CenterPerfStatService.queryReport）后封装 GridDataEntity。
     * periodId 未选时由 Service 取考核中最新周期；组织未选时按系统行政组织范围过滤。
     */
    @Override
    protected GridDataEntity getGridRequestData(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException {
        try {
            ListFilterParams filterParams = parseListFilterParams(request);
            Map<String, Object> queryResult = CenterPerfStatService.queryReport(ctx, filterParams.periodId, filterParams.orgId, filterParams.adminOrgRangeIds);
            if (!"200".equals(String.valueOf(queryResult.get("code")))) {
                throw new ShrWebBizException(String.valueOf(queryResult.get("msg")));
            }

            Map<String, Object> data = (Map<String, Object>) queryResult.get("data");
            List<Map<String, Object>> allRows = data != null && data.get("rows") != null ? (List<Map<String, Object>>) data.get("rows") : new ArrayList<>();

            int rows = Integer.parseInt(request.getParameter("rows"));
            int page = Integer.parseInt(request.getParameter("page"));
            int records = allRows.size();
            int from = Math.max((page - 1) * rows, 0);
            int to = Math.min(from + rows, records);
            List<Map<String, Object>> pageRows = from < to ? allRows.subList(from, to) : new ArrayList<>();

            GridDataEntity grid = new GridDataEntity();
            grid.setRecords(records);
            grid.setPage(page);
            grid.setTotal(records == 0 ? 0 : (records % rows == 0 ? records / rows : records / rows + 1));
            grid.setRows(pageRows);

            Map<String, Object> userdata = new HashMap<>();
            if (data != null) {
                userdata.put("periodId", data.get("periodId"));
                userdata.put("periodName", data.get("periodName"));
                userdata.put("gradePercents", data.get("gradePercents"));
            }
            grid.setUserdata(userdata);
            return grid;
        } catch (ShrWebBizException e) {
            throw e;
        } catch (Exception e) {
            logger.error("绩效考核结果报表加载失败", e);
            throw new ShrWebBizException(e.getMessage());
        }
    }

    /**
     * 从高级过滤 JSON 取 F7 选中项 id（dataItem）
     */
    private String getFilterId(JSONObject filterJson, String key) {
        if (filterJson == null || !filterJson.containsKey(key)) {
            return null;
        }
        JSONObject item = filterJson.getJSONObject(key);
        if (item == null) {
            return null;
        }
        JSONArray dataItem = item.getJSONArray("dataItem");
        if (dataItem == null || dataItem.isEmpty()) {
            return null;
        }
        return dataItem.getJSONObject(0).getString("id");
    }

    /**
     * 从高级过滤 JSON 取 values 字段（与前端 getFastFilterItems().period.values 一致）
     */
    private String getFilterValues(JSONObject filterJson, String key) {
        if (filterJson == null || !filterJson.containsKey(key)) {
            return null;
        }
        JSONObject item = filterJson.getJSONObject(key);
        if (item == null) {
            return null;
        }
        return StringUtils.trimToNull(item.getString("values"));
    }

    private String resolvePeriodId(JSONObject filterJson, HttpServletRequest request) {
        String periodId = getFilterId(filterJson, "period");
        if (StringUtils.isBlank(periodId)) {
            periodId = getFilterId(filterJson, "periodId");
        }
        if (StringUtils.isBlank(periodId)) {
            periodId = getFilterValues(filterJson, "period");
        }
        if (StringUtils.isBlank(periodId)) {
            periodId = getFilterValues(filterJson, "periodId");
        }
        if (StringUtils.isBlank(periodId)) {
            periodId = StringUtils.trimToNull(request.getParameter("periodId"));
        }
        return periodId;
    }

    private String resolveOrgId(JSONObject filterJson) {
        String orgId = getFilterId(filterJson, "orgId");
        if (StringUtils.isBlank(orgId)) {
            orgId = getFilterId(filterJson, "adminOrg");
        }
        if (StringUtils.isBlank(orgId)) {
            orgId = getFilterValues(filterJson, "orgId");
        }
        if (StringUtils.isBlank(orgId)) {
            orgId = getFilterValues(filterJson, "adminOrg");
        }
        return orgId;
    }

    /**
     * 审批：action=hrStart|directorApprove|gmApprove（与前端 remoteCall method=approve 对应）。
     * billIds 由 fastFilterItems 查询条件及单据状态自动解析，无需勾选行。
     */
    public void approveAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException {
        Map<String, Object> res = new LinkedHashMap<>();
        String action = request.getParameter("action");
        ListFilterParams filterParams = parseListFilterParams(request);
        String periodId = filterParams.periodId;

        UserInfo user = ContextUtil.getCurrentUserInfo(ctx);
        String creatorId = user != null && user.getPerson() != null ? user.getPerson().getNumber() : null;
        if (StringUtils.isBlank(creatorId)) {
            res.put("code", "500");
            res.put("msg", "无法获取当前登录人工号");
            JSONUtils.writeJson(response, res);
            return;
        }

        AutoStatusEnum expect;
        AutoStatusEnum target;
        String nextCode;
        String doneCode;
        String emptyMsg;
        String successMsgPrefix;
        if ("hrStart".equals(action)) {
            expect = AutoStatusEnum.WFQ;
            target = AutoStatusEnum.ZJSPZ;
            nextCode = "JXJG02";
            doneCode = null;
            emptyMsg = "当前查询条件下没有可发起的单据";
            successMsgPrefix = "发起审批成功";
        } else if ("directorApprove".equals(action)) {
            expect = AutoStatusEnum.ZJSPZ;
            target = AutoStatusEnum.ZJLSPZ;
            nextCode = "JXJG03";
            doneCode = "JXJG02";
            emptyMsg = "当前查询条件下没有总监审批中的单据";
            successMsgPrefix = "总监审批通过";
        } else if ("gmApprove".equals(action)) {
            expect = AutoStatusEnum.ZJLSPZ;
            target = AutoStatusEnum.SPTG;
            nextCode = null;
            doneCode = "JXJG03";
            emptyMsg = "当前查询条件下没有总经理审批中的单据";
            successMsgPrefix = "总经理审批通过";
        } else {
            res.put("code", "500");
            res.put("msg", "不支持的 action：" + action);
            JSONUtils.writeJson(response, res);
            return;
        }

        String billIds;
        try {
            billIds = resolveApproveBillIds(periodId, filterParams.orgId, filterParams.adminOrgRangeIds, expect.getValue());
        } catch (ShrWebBizException e) {
            res.put("code", "500");
            res.put("msg", e.getMessage());
            JSONUtils.writeJson(response, res);
            return;
        }
        if (StringUtils.isBlank(billIds)) {
            res.put("code", "500");
            res.put("msg", emptyMsg);
            JSONUtils.writeJson(response, res);
            return;
        }

        if ("hrStart".equals(action)) {
            String gradeCheckMsg = CenterPerfStatService.validateGradeActualEqualsTotalForHrStart(
                    ctx, periodId, filterParams.orgId, filterParams.adminOrgRangeIds, expect.getValue());
            if (gradeCheckMsg != null) {
                res.put("code", "500");
                res.put("msg", gradeCheckMsg);
                JSONUtils.writeJson(response, res);
                return;
            }
        }

        try {
            String periodName = "";
            if (StringUtils.isBlank(periodId)) {
                periodId = CenterPerfStatService.resolveDefaultPeriodId(ctx);
            }
            if (StringUtils.isNotBlank(periodId)) {
                PerfPeriodInfo period = PerfPeriodFactory.getLocalInstance(ctx).getPerfPeriodInfo("where id = '" + periodId + "'");
                if (period != null) {
                    periodName = period.getName();
                }
            }
            String title = "绩效考核结果待审批【" + periodName + "】，请及时处理";
            String pcurl = UrlParamUtil.buildCenterPerfStatReportListOaUrl(periodId);
            String appurl = pcurl;
            String nextReceiver = nextCode != null ? getHrBaseNumber(ctx, nextCode) : null;
            if (nextCode != null && StringUtils.isBlank(nextReceiver)) {
                res.put("code", "500");
                res.put("msg", "未配置审批人工号：" + nextCode);
                JSONUtils.writeJson(response, res);
                return;
            }   

            IAssessmentResultDescription iBill = AssessmentResultDescriptionFactory.getLocalInstance(ctx);
            List<String> validBillIds = new ArrayList<>();
            for (String billId : billIds.split(",")) {
                billId = billId.trim();
                if (StringUtils.isBlank(billId)) {
                    continue;
                }
                AssessmentResultDescriptionInfo bill = iBill.getAssessmentResultDescriptionInfo(new ObjectUuidPK(billId));
                if (bill == null) {
                    res.put("code", "500");
                    res.put("msg", "未找到单据：" + billId);
                    JSONUtils.writeJson(response, res);
                    return;
                }
                if (bill.getAutoStatus() != expect) {
                    res.put("code", "500");
                    res.put("msg", "单据[" + bill.getNumber() + "]状态不正确，无法执行该操作");
                    JSONUtils.writeJson(response, res);
                    return;
                }
                validBillIds.add(billId);
            }

            // 办结上一节点待办：flowId 与推送时一致（周期 + 接收人 + 待办时状态）
            if (doneCode != null) {
                String doneReceiver = getHrBaseNumber(ctx, doneCode);
                if (StringUtils.isBlank(doneReceiver)) {
                    res.put("code", "500");
                    res.put("msg", "未配置审批人工号：" + doneCode);
                    JSONUtils.writeJson(response, res);
                    return;
                }
                String doneFlowId = buildCenterPerfFlowId(periodId, doneReceiver, expect.getValue());
                if (target == AutoStatusEnum.SPTG) {
                    FeishuMessageUtil.sendFeishuCall(doneReceiver, title, pcurl, "绩效考核结果审批", appurl, doneFlowId,
                            FeishuMessageUtil.VIEWTYPE_READ, FeishuMessageUtil.ISREMARK_COMPLETE, creatorId);
                } else {
                    FeishuMessageUtil.sendFeishuCall(doneReceiver, title, pcurl, "绩效考核结果审批", appurl, doneFlowId,
                            FeishuMessageUtil.VIEWTYPE_READ, FeishuMessageUtil.ISREMARK_DONE, creatorId);
                }
            }

            for (String billId : validBillIds) {
                AssessmentResultDescriptionInfo bill = iBill.getAssessmentResultDescriptionInfo(new ObjectUuidPK(billId));
                bill.setAutoStatus(target);
                iBill.update(new ObjectUuidPK(billId), bill);
            }

            // 推送下一节点待办（每个周期每个接收人一条，总监审批后 HR 推给总监的那条 flowId 已被置为已办）
            if (nextReceiver != null && !validBillIds.isEmpty()) {
                String nextFlowId = buildCenterPerfFlowId(periodId, nextReceiver, target.getValue());
                FeishuMessageUtil.sendFeishuTodo(nextReceiver, title, pcurl, "绩效考核结果审批", appurl, nextFlowId, creatorId);
            }

            int processedCount = validBillIds.size();

            res.put("code", "200");
            res.put("msg", buildSuccessMsg(successMsgPrefix, periodName, processedCount, action));
        } catch (Exception e) {
            logger.error("绩效考核结果审批失败", e);
            res.put("code", "500");
            res.put("msg", "审批失败：" + e.getMessage());
        }
        JSONUtils.writeJson(response, res);
    }

    /**
     * 解析列表快速过滤：考核周期、组织及行政组织范围（与前端 getFastFilterItems 同源）。
     */
    private ListFilterParams parseListFilterParams(HttpServletRequest request) throws SHRWebException {
        ListFilterParams params = new ListFilterParams();
        String fastFilterItems = request.getParameter("fastFilterItems");
        JSONObject filterJson = StringUtils.isNotBlank(fastFilterItems) ? JSONObject.parseObject(fastFilterItems) : null;
        params.periodId = resolvePeriodId(filterJson, request);
        params.orgId = resolveOrgId(filterJson);
        if (StringUtils.isBlank(params.orgId)) {
            params.adminOrgRangeIds = getCurrentRequestAdminOrgRangeIdSet(request);
        }
        return params;
    }

    /**
     * 按查询条件及目标状态解析待处理单据 id。
     */
    private String resolveApproveBillIds(String periodId, String orgId, Set<String> adminOrgRangeIds,
            String expectStatusValue) throws ShrWebBizException {
        Map<String, Object> queryResult = CenterPerfStatService.queryReport(ctx, periodId, orgId, adminOrgRangeIds);
        if (!"200".equals(String.valueOf(queryResult.get("code")))) {
            throw new ShrWebBizException(String.valueOf(queryResult.get("msg")));
        }
        Map<String, Object> data = (Map<String, Object>) queryResult.get("data");
        List<Map<String, Object>> rows = data != null && data.get("rows") != null ? (List<Map<String, Object>>) data.get("rows") : new ArrayList<>();
        List<String> billIds = new ArrayList<>();
        for (Map<String, Object> row : rows) {
            if (!expectStatusValue.equals(String.valueOf(row.get("autoStatus")))) {
                continue;
            }
            Object id = row.get("id");
            if (id != null && StringUtils.isNotBlank(String.valueOf(id))) {
                billIds.add(String.valueOf(id));
            }
        }
        return StringUtils.join(billIds, ",");
    }

    private static class ListFilterParams {
        private String periodId;
        private String orgId;
        private Set<String> adminOrgRangeIds;
    }

    private String buildSuccessMsg(String prefix, String periodName, int count, String action) {
        String periodPart = StringUtils.isNotBlank(periodName) ? "【" + periodName + "】" : "";
        String countPart = "，共处理 " + count + " 条绩效考核结果";
        if ("hrStart".equals(action)) {
            return prefix + periodPart + countPart + "，已推送总监审批待办";
        }
        if ("directorApprove".equals(action)) {
            return prefix + periodPart + countPart + "，总监待办已办结，已推送总经理审批待办";
        }
        if ("gmApprove".equals(action)) {
            return prefix + periodPart + countPart + "，审批流程已全部完成";
        }
        return prefix + periodPart + countPart;
    }

    private String getHrBaseNumber(Context ctx, String code) throws Exception {
        if (StringUtils.isBlank(code)) {
            return null;
        }
        String sql = "select FSimpleName from T_HR_ZDY0HRBase where FNumber=? and FState=1";
        IRowSet rowSet = DbUtil.executeQuery(ctx, sql, new Object[]{code});
        if (rowSet != null && rowSet.next()) {
            return StringUtils.trimToNull(rowSet.getString("FSimpleName"));
        }
        return null;
    }

    /**
     * 飞书待办 flowId：{考核周期短码}_{接收人工号}_{状态}
     * <p>
     * 周期 ID 形如 LJiKDANrQyeBpHqSZW/o/UUaiOU=，仅取 / 前一段，避免 flowId 过长。
     * 推送待办与办结须使用相同 flowId。例如 HR 发起推总监时状态为 ZJSPZ，总监审批办结时也用 ZJSPZ。
     */
    private String buildCenterPerfFlowId(String periodId, String receiverNumber, String statusValue) {
        return toShortPeriodId(periodId) + "_" + toFlowIdPart(receiverNumber)
                + "_" + toFlowIdPart(statusValue);
    }

    /** BOS 主键含 /、=，flowId 只保留第一段（/ 之前）。 */
    private String toShortPeriodId(String periodId) {
        if (StringUtils.isBlank(periodId)) {
            return "";
        }
        String trimmed = periodId.trim();
        int slash = trimmed.indexOf('/');
        if (slash > 0) {
            return trimmed.substring(0, slash);
        }
        return trimmed.replace("=", "_");
    }

    private String toFlowIdPart(String value) {
        if (StringUtils.isBlank(value)) {
            return "";
        }
        return value.trim().replace("/", "_").replace("=", "_");
    }
}
