package nccloud.openapi.ic.onhand;

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

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.uapbd.util.MyHelper;
import nc.impl.pubapp.pattern.database.SqlBuilderUtil;
import nc.jdbc.framework.processor.MapProcessor;
import nc.vo.bd.material.MaterialVO;
import nc.vo.bd.stordoc.StordocVO;
import nc.vo.cmp.util.StringUtils;
import nc.vo.pub.BusinessException;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import org.json.JSONString;

import nc.bs.framework.common.NCLocator;
import nc.vo.ic.onhand.entity.OnhandVO;
import nc.vo.pub.lang.UFDouble;
import nc.ws.opm.pub.utils.result.APIErrCodeEnum;
import nccloud.api.ic.onhand.IAPIOnhandQuery;
import nccloud.api.rest.utils.ResultMessageUtil;

/**
 * 现存量信息查询资源类
 *
 * @version NCC1909
 * @Description:
 * @author: shijkb
 * @date: 2019年11月8日 下午2:42:47
 */
@Path("ic/onhand")
public class OnhandResource {


    /**
     * 现存量查询
     */
    @POST
    @Path("onhandQuery")
    @Consumes("application/json")
    @Produces("application/json")
    public JSONString onhandQuery(Map<String, Object> paramMap) {
        if (paramMap == null) {
            return ResultMessageUtil.exceptionToJSON("传入参数错误,组织、单据日期条件必输", APIErrCodeEnum.BUSINESSEXCCODE.getCode());
        }
        try {
            OnhandVO[] onhandVOs = NCLocator.getInstance().lookup(IAPIOnhandQuery.class)
                    .queryOnhandVOByDims(paramMap);
            // 对数据进行整合组装,返回数量
            UFDouble onhandNum = UFDouble.ZERO_DBL;
            if (null != onhandVOs && onhandVOs.length > 0) {
                for (OnhandVO onhandVO : onhandVOs) {
                    onhandNum = onhandNum.add(onhandVO.getNonhandnum());
                }
            }
            return ResultMessageUtil.toJSON(onhandNum, "现存量查询成功!");
        } catch (Exception e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
    }

    /**
     * 现存量查询
     */
    @POST
    @Path("onhandsQuery")
    @Consumes("application/json")
    @Produces("application/json")
    public JSONString onhandsQuery(List<Map<String, Object>> paramMapList) {
        if (paramMapList == null) {
            return ResultMessageUtil.exceptionToJSON("传入参数错误,组织、单据日期条件必输", APIErrCodeEnum.BUSINESSEXCCODE.getCode());
        }
        try {
            OnhandVO[] onhandVOs = NCLocator.getInstance().lookup(IAPIOnhandQuery.class)
                    .queryOnhandVOByDims(paramMapList);
            // 对数据进行整合组装,返回物料+仓库+数量

            if (null != onhandVOs && onhandVOs.length > 0) {
                // 提炼出onhandVOs里的物料和仓库
                Set<String> materialPkSet = Arrays.stream(onhandVOs)
                        .map(onhandVO -> onhandVO.getCmaterialvid())
                        .collect(Collectors.toSet());
                Set<String> warehousePkSet = Arrays.stream(onhandVOs)
                        .map(onhandVO -> onhandVO.getCwarehouseid())
                        .collect(Collectors.toSet());
                Map<String, String> materialPKCodeMap = queryPK2CodeMap("pk_material", materialPkSet, "bd_material");
                Map<String, String> warehousePKCodeMap = queryPK2CodeMap("pk_stordoc", warehousePkSet, "bd_stordoc");
                if (materialPKCodeMap == null || materialPKCodeMap.isEmpty()) {
                    throw new BusinessException("queryOnhand end : materialPKCodeMap is null");
                }
                if (warehousePKCodeMap == null || warehousePKCodeMap.isEmpty()) {
                    throw new BusinessException("queryOnhand end : warehousePKCodeMap is null");
                }
                // 根据物料和仓库分组
                Map<String, List<OnhandVO>> groupedOnhand = Arrays.stream(onhandVOs)
                        .collect(Collectors.groupingBy(onhandVO -> onhandVO.getPk_org() + "_" + onhandVO.getCmaterialvid() + "_" + onhandVO.getCwarehouseid()));
                Set<String> keys = groupedOnhand.keySet();
                JSONArray reArray = new JSONArray();
                for (String dimkey : keys) {
                    List<OnhandVO> onhandVOList = groupedOnhand.get(dimkey);
                    JSONObject jsonObject = new JSONObject();
                    UFDouble onhandNum = UFDouble.ZERO_DBL;

                    jsonObject.put("materialpk", onhandVOList.get(0).getCmaterialvid());
                    jsonObject.put("materialCode", materialPKCodeMap.getOrDefault(onhandVOList.get(0).getCmaterialvid(), ""));
                    jsonObject.put("warehousepk", onhandVOList.get(0).getCwarehouseid());
                    jsonObject.put("warehouseCOde", warehousePKCodeMap.getOrDefault(onhandVOList.get(0).getCwarehouseid(), ""));
                    for (OnhandVO onhandVO : onhandVOList) {
                        onhandNum = onhandNum.add(onhandVO.getNonhandnum());
                    }
                    jsonObject.put("onhandnum", onhandNum);
                    reArray.add(jsonObject);
                }
                return ResultMessageUtil.toJSON(reArray, "现存量查询成功!");

            } else {
                return ResultMessageUtil.toJSON(null, "现存量查询成功,无数据!");
            }
        } catch (Exception e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
    }

    /**
     * 根据条件批量查询现存量
     *
     * @author mzr
     * @date 2025/7/16
     */
    @POST
    @Path("onhandQueryByCondition")
    @Consumes("application/json")
    @Produces("application/json")
    public JSONString onhandQueryByCondition(Map<String, Object> paramMap) {
        if (paramMap == null) {
            return ResultMessageUtil.exceptionToJSON("传入参数错误,组织条件必输", APIErrCodeEnum.BUSINESSEXCCODE.getCode());
        }
        try {
            OnhandVO[] onhandVOs = NCLocator.getInstance().lookup(IAPIOnhandQuery.class)
                    .queryOnhandVOByCondition(paramMap);
            // 对数据进行整合组装
            if (null != onhandVOs && onhandVOs.length > 0) {
                JSONArray resArr = new JSONArray();
                for (OnhandVO onhandVO : onhandVOs) {
                    String cmaterialvid = onhandVO.getCmaterialvid();
                    String cwarehouseid = onhandVO.getCwarehouseid();
                    Map<String, Object> goodsMap = this.getMaterialInfo(cmaterialvid);
                    String selectFields = StordocVO.CODE + "," + StordocVO.NAME;
                    Map<String, Object> stordocMap = this.transferFields(StordocVO.getDefaultTableName(), selectFields, StordocVO.PK_STORDOC, cwarehouseid);
                    JSONObject oneJson = new JSONObject();
                    oneJson.put("pk_material", cmaterialvid);
                    oneJson.put("materialCode", goodsMap.getOrDefault(MaterialVO.CODE, ""));// 物料编码
                    oneJson.put("materialName", goodsMap.getOrDefault(MaterialVO.NAME, ""));// 物料名称
                    oneJson.put("materialtype", goodsMap.getOrDefault(MaterialVO.MATERIALTYPE, "")); // 型号
                    oneJson.put("materialspec", goodsMap.getOrDefault(MaterialVO.MATERIALSPEC, "")); // // 规格
                    oneJson.put("unitcode", goodsMap.getOrDefault("unitcode", "")); // // 计量单位编码
                    oneJson.put("unitname", goodsMap.getOrDefault("unitname", "")); // // 计量单位名称
                    oneJson.put("warehousePk", onhandVO.getCwarehouseid());
                    oneJson.put("warehouseCode", stordocMap.getOrDefault(StordocVO.CODE, ""));// 仓库编码
                    oneJson.put("warehouseName", stordocMap.getOrDefault(StordocVO.NAME, ""));// 仓库名称
                    oneJson.put("vbatchcode", onhandVO.getVbatchcode());// 批次号
                    oneJson.put("onhandnum", onhandVO.getNonhandnum());
                    resArr.add(oneJson);
                }
                return ResultMessageUtil.toJSON(resArr, "现存量查询成功!");

            } else {
                return ResultMessageUtil.toJSON(null, "现存量查询成功,无数据!");
            }
        } catch (Exception e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
    }


    private Map<String, String> queryPK2CodeMap(String pkname, Set<String> pks, String tablename) throws DAOException {
        SqlBuilderUtil SqlBuilderUtil = new SqlBuilderUtil();
        SqlBuilder sql = new SqlBuilder();
        sql.append(" select code," + pkname + " from " + tablename + " where ");
        sql.append(pkname, pks.toArray(new String[0]));
        List<Map<String, Object>> remain = (List<Map<String, Object>>) new BaseDAO().executeQuery(sql.toString(), new nc.jdbc.framework.processor.MapListProcessor());
        if (remain == null || remain.isEmpty()) {
            return null;
        }
        // 转换为 pk和 code 的映射
        Map<String, String> pkCodeMap = new HashMap<>();
        for (Map<String, Object> row : remain) {
            if (row != null) {
                String pk = row.get(pkname) != null ? row.get(pkname).toString() : null;
                String code = row.get("code") != null ? row.get("code").toString() : null;
                if (pk != null && code != null) {
                    pkCodeMap.put(pk, code);
                }
            }
        }
        return pkCodeMap;
    }

    public Map<String, Object> transferFields(String tableName, String selectFields, String pkField, String pk) throws Exception {
        if (StringUtils.isEmpty(pk)) {
            return null;
        }
        SqlBuilder sqlBuilder = new SqlBuilder();
        sqlBuilder.append(" select " + selectFields);
        sqlBuilder.append(" from " + tableName);
        sqlBuilder.append(" where dr = 0 ");
        sqlBuilder.append(" and ");
        sqlBuilder.append(pkField, pk);

        Map<String, Object> result = (Map<String, Object>) new BaseDAO().executeQuery(sqlBuilder.toString(), new MapProcessor());

        if (result == null || result.isEmpty()) {
            result = new HashMap<>();
        }

        return result;
    }

    private Map getMaterialInfo(String pkMaterial) throws BusinessException {
        String sql = " select a.code, a.name, a.materialtype, a.materialspec, a.pk_measdoc, c.code unitcode, c.name unitname " +
                "from bd_material a " +
                "left join bd_materialconvert b on a.pk_material = b.pk_material " +
                "left join bd_measdoc c on a.pk_measdoc = c.pk_measdoc " +
                "where a.pk_material = '" + pkMaterial + "' ";
        Map map = (Map) new BaseDAO().executeQuery(sql, new MapProcessor());
        return map;
    }
}
