package com.kingdee.eas.custom.szpgm.osf.service;

import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.bsf.service.app.IHRMsfService;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;
import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 获取组织信息接口。
 * <p>
 * 根据组织类型、最后修改日期、组织名称、组织编号等条件分页查询组织基础信息，
 * 包含组织名称、编号、上下级关系、状态等字段。
 * 数据来源于 t_org_admin（组织管理表），左连 T_Org_admin（取上级组织信息）、
 * T_Org_LayerType（组织类型表），按修改时间降序排列。
 * </p>
 *
 * <h3>入参说明</h3>
 * <table>
 *   <tr><th>参数名</th><th>类型</th><th>必填</th><th>说明</th></tr>
 *   <tr><td>layerType</td>  <td>String</td><td>否</td><td>组织类型，支持逗号分隔多个值（如：公司、部门、集团、中心、子中心、公司（新）），精确匹配</td></tr>
 *   <tr><td>modifyDate</td> <td>String</td><td>否</td><td>最后修改日期（yyyy-MM-dd），查询该日期及之后修改的组织</td></tr>
 *   <tr><td>name</td>       <td>String</td><td>否</td><td>组织名称，左模糊匹配</td></tr>
 *   <tr><td>code</td>       <td>String</td><td>否</td><td>组织编号，精确匹配</td></tr>
 *   <tr><td>size</td>       <td>int</td>   <td>否</td><td>每页条数，默认100，最大1000</td></tr>
 *   <tr><td>page</td>       <td>int</td>   <td>否</td><td>页码，默认1</td></tr>
 * </table>
 *
 * <h3>返回值说明</h3>
 * <table>
 *   <tr><th>字段</th><th>类型</th><th>说明</th></tr>
 *   <tr><td>code</td>   <td>String</td><td>状态码（200:成功，500:异常）</td></tr>
 *   <tr><td>msg</td>    <td>String</td><td>提示信息</td></tr>
 *   <tr><td>page</td>   <td>int</td>   <td>当前页码</td></tr>
 *   <tr><td>size</td>   <td>int</td>   <td>每页条数</td></tr>
 *   <tr><td>data</td>   <td>List</td>  <td>组织列表，每项字段见下方</td></tr>
 * </table>
 * <p>data 列表中每项包含以下字段：</p>
 * <table>
 *   <tr><th>字段</th><th>类型</th><th>说明</th></tr>
 *   <tr><td>id</td>          <td>String</td><td>主键ID</td></tr>
 *   <tr><td>name</td>        <td>String</td><td>组织名称</td></tr>
 *   <tr><td>fullname</td>    <td>String</td><td>组织全称（显示名）</td></tr>
 *   <tr><td>code</td>        <td>String</td><td>组织编号</td></tr>
 *   <tr><td>parent</td>      <td>String</td><td>上级组织编号</td></tr>
 *   <tr><td>fullnumber</td>  <td>String</td><td>组织全编码（长编码层级路径）</td></tr>
 *   <tr><td>disporder</td>   <td>String</td><td>显示排序号</td></tr>
 *   <tr><td>status</td>      <td>String</td><td>是否启用（"1":有效，"0":封存，与数据库 fissealup 字段取反）</td></tr>
 *   <tr><td>description</td> <td>String</td><td>备注说明</td></tr>
 *   <tr><td>modifyDate</td>  <td>String</td><td>修改日期（yyyy-MM-dd，当前版本不返回此字段，如需返回请取消注释）</td></tr>
 *   <tr><td>layerType</td>   <td>String</td><td>组织类型名称</td></tr>
 * </table>
 *
 * @author szpgm
 * @since 1.0.0
 */
public class GetOrgInfoOsfService implements IHRMsfService {

    /**
     * 查询组织基础信息（分页接口）。
     * <p>
     * 根据组织类型、修改日期、名称、编号等条件组合查询，支持分页返回。
     * 组织类型支持逗号分隔的多个值，名称按左模糊匹配，编号精确匹配。
     * </p>
     *
     * @param context EAS 平台上下文对象
     * @param map     入参，支持以下 key（均为可选）：
     *                <ul>
     *                  <li><b>layerType</b>  — 组织类型，逗号分隔多个值，精确匹配</li>
     *                  <li><b>modifyDate</b> — 最后修改日期（yyyy-MM-dd），查询该日期及之后的数据</li>
     *                  <li><b>name</b>       — 组织名称，左模糊匹配</li>
     *                  <li><b>code</b>       — 组织编号，精确匹配</li>
     *                  <li><b>page</b>       — 页码，默认1</li>
     *                  <li><b>size</b>       — 每页条数，默认100，上限1000</li>
     *                </ul>
     * @return {@code Map<String, Object>}，包含以下 key：
     *         <ul>
     *           <li><b>code</b> — 状态码（"200" 成功，"500" 异常）</li>
     *           <li><b>msg</b>  — 提示信息</li>
     *           <li><b>page</b> — 当前页码</li>
     *           <li><b>size</b> — 每页条数</li>
     *           <li><b>data</b> — 组织信息列表（{@code List<Map<String, Object>>}）</li>
     *         </ul>
     * @throws EASBizException 业务异常
     * @throws BOSException    平台异常
     */
    @Override
    public Object process(Context context, Map map) throws EASBizException, BOSException {
        Map<String, Object> result = new HashMap<String, Object>();
        List<Map<String, Object>> list = new ArrayList<>();

        // ==================== 入参解析 ====================
        String layerType = (String) map.get("layerType");
        String modifyDate = (String) map.get("modifyDate");
        String name = (String) map.get("name");
        String code = (String) map.get("code");

        // 每页条数：默认100，上限1000，兼容 Integer 和 String 类型
        int maxSize = 1000;
        int size = 100;
        if (map.get("size") != null) {
            if (map.get("size") instanceof Integer) {
                size = (int) map.get("size");
            } else if (map.get("size") instanceof String) {
                size = Integer.parseInt((String) map.get("size"));
            }
            size = Math.min(maxSize, size);
        }

        // 页码：默认1，兼容 Integer 和 String 类型
        int page = 1;
        if (map.get("page") != null) {
            if (map.get("page") instanceof Integer) {
                page = (int) map.get("page");
            } else if (map.get("page") instanceof String) {
                page = Integer.parseInt((String) map.get("page"));
            }
        }

        // ==================== 构建查询并执行 ====================
        try {
            result.put("msg", "成功");
            result.put("code", "200");
            result.put("page", page);
            result.put("size", size);
            result.put("data", list);

            // 获取基础SQL（where 1=1），动态追加过滤条件和分页参数
            StringBuilder sql = getSql();
            List<Object> paramArr = new ArrayList<>();

            // 修改日期过滤：组织最后修改时间 >= 指定日期
            if (StringUtils.isNotBlank(modifyDate)) {
                sql.append(" and org.flastupdatetime >= ? ");
                paramArr.add(modifyDate);
            }

            // 组织类型精确匹配，支持逗号分隔多个值（IN 查询）
            if (StringUtils.isNotBlank(layerType)) {
                sql.append(" and lt.fname_l2 in('' ");

                    String[] layerTypeArr = layerType.split(",");
                    for (int i = 0; i < layerTypeArr.length; i++) {
                        sql.append(" ,?");
                        paramArr.add(layerTypeArr[i]);
                    }

                sql.append(" ) ");
            }

            // 组织名称左模糊匹配
            if (StringUtils.isNotBlank(name)) {
                sql.append(" and org.fname_l2 like ? ");
                paramArr.add(name + "%");
            }

            // 组织编号精确匹配
            if (StringUtils.isNotBlank(code)) {
                sql.append(" and org.fnumber = ? ");
                paramArr.add(code);
            }

            // 分页：LIMIT 条数 OFFSET 偏移量
            sql.append(" order by org.fid desc LIMIT ? OFFSET ? ");
            paramArr.add(size);
            paramArr.add(((page - 1) * size));

            // 执行SQL查询
            IRowSet rs = DbUtil.executeQuery(context, sql.toString(), paramArr.toArray());

            // 遍历结果集，逐行转换为 Map 放入返回列表
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            while (rs.next()) {
                Map<String, Object> params = new HashMap<String, Object>();

                params.put("name", rs.getString("name"));           // 组织名称
                params.put("fullname", rs.getString("fullname"));   // 组织全称（显示名）
                params.put("code", rs.getString("code"));           // 组织编号
                params.put("parent", rs.getString("parent"));       // 上级组织编号
                params.put("fullnumber", rs.getString("fullnumber")); // 组织全编码（长编码路径）
                params.put("disporder", rs.getString("disporder")); // 显示排序号
                // 状态取反：DB中 fissealup=1(封存)→接口返回 "0"，fissealup=0(有效)→接口返回 "1"
                int statusVal = rs.getInt("status");
                params.put("status", statusVal == 1 ? "0" : "1");
                params.put("id", rs.getString("id"));               // 主键ID
                params.put("description", rs.getString("description")); // 备注说明
                // 修改日期（当前版本不返回，如需返回请取消下行注释）
                //Date modifyDateVal = rs.getTimestamp("modifyDate");
                //params.put("modifyDate", modifyDateVal != null ? sdf.format(modifyDateVal) : "");
                params.put("layerType", rs.getString("layerType")); // 组织类型名称

                list.add(params);
            }
        } catch (Exception e) {
            // 捕获所有异常，返回错误码和异常信息
            e.printStackTrace();
            result.put("msg", e.getMessage());
            result.put("code", "500");
        }
        return result;
    }

    /**
     * 构建组织信息查询的基础 SQL。
     * <p>
     * 从 t_org_admin（组织管理表）左连 T_Org_admin（取上级组织信息）、
     * T_Org_LayerType（组织类型表），查询组织名称、编号、全编码、上级组织编号、
     * 显示顺序、封存状态、备注、修改时间、类型等字段。
     * 返回的 SQL 以 {@code where 1=1} 结尾，过滤条件和分页参数由调用方通过
     * {@link StringBuilder#append} 动态拼接。
     * </p>
     * <p>
     * 涉及表：
     * <ul>
     *   <li><b>t_org_admin</b>（org）—— 组织管理表，主表</li>
     *   <li><b>T_Org_admin</b>（porg）—— 组织管理表（二次关联，通过 fparentid 取上级组织信息）</li>
     *   <li><b>T_Org_LayerType</b>（lt）—— 组织类型表</li>
     * </ul>
     * </p>
     *
     * @return 包含占位符的基础 SQL（以 {@code where 1=1} 结尾），
     *         后续可动态追加 AND 条件和分页参数
     */
    private static StringBuilder getSql() {
        StringBuilder sql = new StringBuilder();
        sql.append(" /*dialect*/ select ");
        sql.append(" org.fname_l2 \"name\", ");              // 组织名称
        sql.append(" org.fdisplayname_l2 fullname, ");      // 组织全称（显示名）
        sql.append(" org.fnumber code, ");                  // 组织编号
        sql.append(" porg.fnumber parent, ");              // 上级组织编号
        sql.append(" org.flongNumber fullnumber, ");        // 组织长编码（层级路径）
        sql.append(" org.fsortcode disporder, ");           // 显示排序号
        sql.append(" org.fissealup status, ");              // 封存状态（1=封存，0=有效，接口层取反）
        sql.append(" org.fid id, ");                        // 主键ID
        sql.append(" org.fdescription_l2 description, ");   // 备注说明
        sql.append(" org.flastupdatetime modifyDate, ");    // 最后修改时间
        sql.append(" lt.fname_l2 layerType ");              // 组织类型名称
        sql.append(" from t_org_admin org ");               // 组织管理表
        sql.append(" left join T_Org_admin porg on porg.fid = org.fparentid ");  // 左连组织管理表（取上级组织信息）
        sql.append(" left join T_Org_LayerType lt on lt.fid = org.flayertypeid "); // 左连组织类型表
        sql.append(" where 1=1 ");                          // 占位，便于后续动态拼接 AND 条件

        return sql;
    }
}
