package nccloud.api.uapbd.stordocmanage.storedoc;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import nc.bs.dao.BaseDAO;
import nc.jdbc.framework.processor.ColumnListProcessor;
import nc.jdbc.framework.processor.MapListProcessor;
import nccloud.api.rest.utils.OpenApiPageInfo;
import nccloud.api.rest.utils.ResultMessageUtil;
import nccloud.api.uapbd.common.utils.OpenApiPagenationUtils;
import nccloud.commons.lang.StringUtils;
import nccloud.ws.rest.resource.AbstractNCCRestResource;
import org.json.JSONString;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import java.util.*;

/**
 * 仓库接口
 */
@Path("uapbd/stordoc/stordoc")
public class StordocManageResource extends AbstractNCCRestResource {

    public static final BaseDAO BASE_DAO = new BaseDAO();

    @Override
    public String getModule() {
        return "uapbd";
    }

    /**
     * 手动构建SQL条件
     *
     * @param paramMap 参数Map
     * @return SQL条件字符串
     */
    private String buildCondition(Map<String, Object> paramMap) {
        List<String> conditions = new ArrayList<>();

        // 处理code数组 - 使用IN条件
        if (paramMap.containsKey("code")) {
            String[] codes = (String[]) paramMap.get("code");
            if (codes != null && codes.length > 0) {
                StringBuilder codeCondition = new StringBuilder("code in (");
                for (int i = 0; i < codes.length; i++) {
                    if (i > 0) {
                        codeCondition.append(",");
                    }
                    codeCondition.append("'").append(escapeSql(codes[i])).append("'");
                }
                codeCondition.append(")");
                conditions.add(codeCondition.toString());
            }
        }
        // 处理pk_group数组 - 使用IN条件
        if (paramMap.containsKey("pk_group")) {
            String[] pk_groups = (String[]) paramMap.get("pk_group");
            if (pk_groups != null && pk_groups.length > 0) {
                StringBuilder codeCondition = new StringBuilder("pk_group in (");
                for (int i = 0; i < pk_groups.length; i++) {
                    if (i > 0) {
                        codeCondition.append(",");
                    }
                    codeCondition.append("'").append(escapeSql(pk_groups[i])).append("'");
                }
                codeCondition.append(")");
                conditions.add(codeCondition.toString());
            }
        }
        // 处理pk_org数组 - 使用IN条件
        if (paramMap.containsKey("pk_org")) {
            String[] pk_orgs = (String[]) paramMap.get("pk_org");
            if (pk_orgs != null && pk_orgs.length > 0) {
                StringBuilder codeCondition = new StringBuilder("pk_org in (");
                for (int i = 0; i < pk_orgs.length; i++) {
                    if (i > 0) {
                        codeCondition.append(",");
                    }
                    codeCondition.append("'").append(escapeSql(pk_orgs[i])).append("'");
                }
                codeCondition.append(")");
                conditions.add(codeCondition.toString());
            }
        }

        // 处理name数组 - 使IN条件
        if (paramMap.containsKey("name")) {
            String[] names = (String[]) paramMap.get("name");
            if (names != null && names.length > 0) {
                StringBuilder nameCondition = new StringBuilder("name in (");
                for (int i = 0; i < names.length; i++) {
                    if (i > 0) {
                        nameCondition.append(",");
                    }
                    nameCondition.append("'").append(escapeSql(names[i])).append("'");
                }
                nameCondition.append(")");
                conditions.add(nameCondition.toString());
            }
        }

        return conditions.isEmpty() ? "" : String.join(" and ", conditions);
    }

    /**
     * SQL注入防护 - 转义单引号
     *
     * @param input 输入字符串
     * @return 转义后的字符串
     */
    private String escapeSql(String input) {
        return input == null ? null : input.replace("'", "''");
    }

    /**
     * 查询仓库信息
     * 示例:
     * JSON输入示例:
     * {
     * "ufinterface": {
     * "data": {
     * "code": ["仓库code", "ST002"],
     * "name": ["仓库name", "仓库B"],
     * "org_code": ["ORG01", "ORG02"],
     * "group_codes": ["GROUP001", "GROUP002"]
     * },
     * "pageInfo": {
     * "pageNo": 1,
     * "pageSize": 10
     * }
     * }
     * }
     *
     * @param json 输入的JSON字符串
     * @return JSONString 包含查询结果或错误信息
     */
    @POST
    @Path("queryStordoc")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public JSONString queryStordoc(JSONString json) {
        JSONObject jObject = JSON.parseObject(json.toJSONString());
        if (jObject == null) {
            return ResultMessageUtil.exceptionToJSON(new NullPointerException("请求JSON对象为null"));
        }
        JSONObject ufinterfaceObj = jObject.getJSONObject("ufinterface");
        if (ufinterfaceObj == null) {
            return ResultMessageUtil.exceptionToJSON(new NullPointerException("ufinterface节点为null"));
        }
        JSONObject data = ufinterfaceObj.getJSONObject("data"); // 查询条件
        JSONObject pageInfoJson = ufinterfaceObj.getJSONObject("pageInfo"); // 分页信息
        if (data == null) {
            data = new JSONObject();
        }
        Map<String, Object> paramMap = new HashMap<>();
        JSONArray code_json = data.getJSONArray("code");
        JSONArray name_json = data.getJSONArray("name");
        JSONArray orgCodeArr = data.getJSONArray("org_code");
        JSONArray groupCodeArr = data.getJSONArray("group_codes");

        // 处理数组类型的参数
        if (code_json != null && !code_json.isEmpty()) {
            paramMap.put("code", code_json.toArray(new String[0]));
        }
        if (name_json != null && !name_json.isEmpty()) {
            paramMap.put("name", name_json.toArray(new String[0]));
        }

        try {
            // 将 org_code 转换为主键保存到 paramMap
            if (orgCodeArr != null && !orgCodeArr.isEmpty()) {
                List<String> pkOrgList = new ArrayList<>();
                StringBuilder cond = new StringBuilder("code in (");
                for (int i = 0; i < orgCodeArr.size(); i++) {
                    if (i > 0) {
                        cond.append(",");
                    }
                    cond.append("'").append(escapeSql(orgCodeArr.getString(i))).append("'");
                }
                cond.append(")");
                Collection stockOrgs = BASE_DAO.retrieveByClause(nc.vo.org.StockOrgVO.class, cond.toString(), new String[]{"pk_stockorg"});
                if (stockOrgs != null) {
                    for (Object obj : stockOrgs) {
                        nc.vo.org.StockOrgVO vo = (nc.vo.org.StockOrgVO) obj;
                        pkOrgList.add(vo.getPk_stockorg());
                    }
                }
                if (!pkOrgList.isEmpty()) {
                    paramMap.put("pk_org", pkOrgList.toArray(new String[0]));
                }
            }

            // 将 group_codes 转换为主键保存到 paramMap
            if (groupCodeArr != null && !groupCodeArr.isEmpty()) {
                List<String> pkGroupList = new ArrayList<>();
                StringBuilder cond = new StringBuilder("code in (");
                for (int i = 0; i < groupCodeArr.size(); i++) {
                    if (i > 0) {
                        cond.append(",");
                    }
                    cond.append("'").append(escapeSql(groupCodeArr.getString(i))).append("'");
                }
                cond.append(")");
                Collection groups = BASE_DAO.retrieveByClause(nc.vo.org.GroupVO.class, cond.toString(), new String[]{"pk_group"});
                if (groups != null) {
                    for (Object obj : groups) {
                        nc.vo.org.GroupVO vo = (nc.vo.org.GroupVO) obj;
                        pkGroupList.add(vo.getPk_group());
                    }
                }
                if (!pkGroupList.isEmpty()) {
                    paramMap.put("pk_group", pkGroupList.toArray(new String[0]));
                }
            }

            String condition = buildCondition(paramMap);
            if (StringUtils.isNotBlank(condition)) {
                condition = "dr = 0 and " + condition;
            } else {
                condition = "dr=0";
            }

            String sql = "SELECT pk_stordoc FROM bd_stordoc WHERE " + condition;
            List<String> allPks = (List<String>) BASE_DAO.executeQuery(sql, new ColumnListProcessor());
            OpenApiPageInfo openApiPageInfo = new OpenApiPageInfo();
            String[] currPks = OpenApiPagenationUtils.getCurrentPagePksAndPageInfo(allPks, pageInfoJson, openApiPageInfo);

            if (currPks == null || currPks.length == 0) {
                return ResultMessageUtil.toJSONByPage(new JSONObject[0], openApiPageInfo, false);
            }
            StringJoiner stringJoiner = new StringJoiner(",");
            for (String pk : currPks) {
                stringJoiner.add("'" + pk + "'");
            }
            String pks = stringJoiner.toString();

            String mainSql = "SELECT sd.*, " +
                    "so.code AS org_code, so.name AS org_name, " +
                    "og.code AS group_code, og.name AS group_name, " +
                    "ad.code AS address_code, ad.name AS address_name, " +
                    "ba.code AS storaddr_code " +
                    "FROM bd_stordoc sd " +
                    "LEFT JOIN org_stockorg so ON sd.pk_org = so.pk_stockorg " +
                    "LEFT JOIN org_group og ON sd.pk_group = og.pk_group " +
                    "LEFT JOIN bd_addressdoc ad ON sd.pk_address = ad.pk_addressdoc " +
                    "LEFT JOIN bd_address ba ON sd.storaddr = ba.pk_address " +
                    "WHERE sd.pk_stordoc IN (" + pks + ")";

            @SuppressWarnings("unchecked")
            List<Map<String, Object>> rows = (List<Map<String, Object>>) BASE_DAO.executeQuery(mainSql, new MapListProcessor());

            List<JSONObject> resultList = new ArrayList<>();
            for (Map<String, Object> row : rows) {
                JSONObject stordocJson = new JSONObject(true); // 使用有序Map

                for (Map.Entry<String, Object> entry : row.entrySet()) {
                    String key = entry.getKey().toLowerCase();
                    if ("org_code".equals(key) || "org_name".equals(key) ||
                            "group_code".equals(key) || "group_name".equals(key) ||
                            "address_code".equals(key) || "address_name".equals(key) ||
                            "storaddr_code".equals(key)) {
                        continue;
                    }
                    stordocJson.put(entry.getKey(), entry.getValue());
                }

                JSONObject pkOrgDetailsJson = new JSONObject(true);
                pkOrgDetailsJson.put("pk_org", row.get("pk_org"));
                pkOrgDetailsJson.put("code", row.get("org_code"));
                pkOrgDetailsJson.put("name", row.get("org_name"));
                stordocJson.put("pk_org", pkOrgDetailsJson);

                JSONObject pkGroupDetailsJson = new JSONObject(true);
                pkGroupDetailsJson.put("pk_group", row.get("pk_group"));
                pkGroupDetailsJson.put("code", row.get("group_code"));
                pkGroupDetailsJson.put("name", row.get("group_name"));
                stordocJson.put("pk_group", pkGroupDetailsJson);

                JSONObject pkAddressDetailsJson = new JSONObject(true);
                pkAddressDetailsJson.put("pk_address", row.get("pk_address"));
                pkAddressDetailsJson.put("code", row.get("address_code"));
                pkAddressDetailsJson.put("name", row.get("address_name"));
                stordocJson.put("pk_address", pkAddressDetailsJson);

                JSONObject storaddrDetailsJson = new JSONObject(true);
                storaddrDetailsJson.put("pk_address", row.get("storaddr"));
                storaddrDetailsJson.put("code", row.get("storaddr_code"));
                stordocJson.put("storaddr", storaddrDetailsJson);

                resultList.add(stordocJson);
            }

            return ResultMessageUtil.toJSONByPage(resultList.toArray(new JSONObject[0]), openApiPageInfo, false);

        } catch (Exception e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
    }

}
