package cn.com.capcloud.api.action.service;

import cn.com.capcloud.ccui.core.common.json.JackJSON;
import cn.com.capcloud.ccui.core.common.json.JackJSONArray;
import cn.com.capcloud.ccui.core.common.json.JackJSONObject;
import cn.com.capcloud.core.noentitydb.JtPage;
import cn.com.capcloud.core.noentitydb.MongoTool;
import cn.com.capcloud.core.system.user.User;
import cn.com.capcloud.core.system.user.UserService;
import net.sf.json.JSONObject;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @Author LiaoJiaHui
 * @Create 2022/9/22 10:14
 */
@Service
public class MongoService {

    @Value("${rzth.mongodb.isCreateMongoDBConnect:N}")
    private  String isCreateMongoDBConnect;
    @Resource
    private ApiService apiService;
    @Resource
    private JdbcTemplate jdbcTemplate;
    @Resource
    private MongoTemplate mongoTemplate;
    @Resource
    private UserService userService;

    // mysql: apiController > apiAction > apiService
    // mongo: apiController > apiAction > 扩展类 > mongoService
    // 呜呜呜呜~ mongoService调用是在扩展类调的
    public JtPage showAll(String jsonStr, JackJSONObject retJson, HttpServletRequest request, JtPage jtPage) {
        if(!isCreateMongoDBConnect.equals("Y")){
            jtPage.setTotalElements( 0);
            jtPage.setNumber(0);
            jtPage.setNumberOfElements(0);
            jtPage.setSize(0);
            jtPage.setContent(new ArrayList<>());
            return jtPage;
        }
        User user=userService.getUser(request);
        Map<String,Object> queryMap=apiService.getQuery(jsonStr);
        String viewAllRoleId=String.valueOf(queryMap.get("view_all_data_role_id"));
        boolean isQueryAll=false;
        if(!"null".equals(viewAllRoleId)&&viewAllRoleId.length()>0) {
            String[] roleIdArray = viewAllRoleId.split(",");
            for(int i=0;i<roleIdArray.length;i++) {
                if(userService.isExistsRole(roleIdArray[i], user.getId())) {
                    isQueryAll=true;
                }
            }
        }
        if(!isQueryAll){//如果查询mongo校验用户是否有查询全部数据角色，没有则判断权限不足
            retJson.putAll(JSONObject.fromObject(apiService.getReturnDataByCode("4031")));
            return null;
        }
        JackJSONObject jsonObject = JackJSONObject.fromObject(jsonStr);
        Integer page =Integer.parseInt(String.valueOf(jsonObject.getJackJSONObject("queryParam").get("page")));
        Integer pageSize =Integer.parseInt(String.valueOf(jsonObject.getJackJSONObject("queryParam").get("pageSize")));
        Map<String, Object> dsMap=apiService.findDataSourceByJsonStr(jsonStr);
        String tableName=String.valueOf(dsMap.get("ds_table_name"));
        Query query;
        Query queryCount;
        List<Map> listMap;
        List<Map<String,Object>> fieldList=apiService.getQueryInfo(jsonStr);
        query=getMongoWhere(fieldList,jsonStr,jdbcTemplate,retJson);
        queryCount=getMongoWhere(fieldList,jsonStr,jdbcTemplate,retJson);
        query.limit(pageSize).skip(page*pageSize);//分页
        Sort sort=getMongoOrderBy(jsonStr);//排序
        query.with(sort);
        listMap=mongoTemplate.find(query, Map.class,tableName);
        long count=mongoTemplate.count(queryCount,tableName);
        List<Map<String,Object>> content=new ArrayList<>();
        for (int i = 0; i < listMap.size(); i++) {
            listMap.get(i).remove("_id");
            content.add(listMap.get(i));
        }
        content= JackJSON.parseObject(ApiDao.nullToStrFilter(content), ArrayList.class);
        jtPage.setTotalElements((int) count);
        if (count % pageSize == 0) {
            jtPage.setTotalPages((int) count/pageSize);
        } else {
            jtPage.setTotalPages((int) count/pageSize+1);
        }
        jtPage.setNumber(page);
        jtPage.setNumberOfElements((int) count);
        jtPage.setSize(pageSize);
        jtPage.setContent(content);
        return jtPage;
    }

    public JackJSONArray save(String jsonStr, JackJSONObject retJson, HttpServletRequest request, JackJSONArray array) {
        if(!isCreateMongoDBConnect.equals("Y")){
            return new JackJSONArray();
        }
        Map<String, Object> dsMap=apiService.findDataSourceByJsonStr(jsonStr);
        String tableName=String.valueOf(dsMap.get("ds_table_name"));
        for (int i = 0; i < array.size(); i++) {
            Map<String, Object> map = array.getJackJSONObject(i);
            save(tableName,map);
        }
        retJson.putAll(JackJSONObject.fromObject(apiService.getReturnDataByCode("ok")));
        Map<String,Object> map=new HashMap<>();
        map.put("saveData",array);
        retJson.put("data",map);
        return new JackJSONArray();
    }

    public void save(String tableName, Map<String,Object> map){
        if(!isCreateMongoDBConnect.equals("Y")){
            return ;
        }
        setDefaultValue(map);
        MongoTool.save(tableName,map,mongoTemplate);
    }

    //set一些默认值
    public void setDefaultValue(Map<String,Object> objMap){
        String status=String.valueOf(objMap.get("status"));
        if("null".equals(status)||status.length()==0){
            objMap.put("status","0");
        }
        String createTime=String.valueOf(objMap.get("create_time"));
        if("null".equals(createTime)||createTime.length()==0){
            DateTime d = new DateTime();
            objMap.put("create_time", d.toString("yyyy-MM-dd HH:mm:ss"));
        }
        if("null".equals(createTime)||createTime.length()==0){
            DateTime d = new DateTime();
            objMap.put("update_time", d.toString("yyyy-MM-dd HH:mm:ss"));
        }
        String uuid=String.valueOf(objMap.get("uuid"));
        if("null".equals(uuid)||uuid.length()==0){
            objMap.put("uuid", UUID.randomUUID().toString().replaceAll("-",""));
        }
    }

    public Sort getMongoOrderBy(String jsonStr){
        JackJSONObject jsonObject = JackJSONObject.fromObject(jsonStr).getJackJSONObject("queryParam");
        try {
            jsonObject.size();
        } catch (Exception e) {
            jsonObject=new JackJSONObject();
        }
        Map<String,Object> dsMap=apiService.findDataSourceByJsonStr(jsonStr);
        Map<String,Object> queryMap=apiService.getQuery(jsonStr);
        String dsPkId = String.valueOf(dsMap.get("ds_pk_id"));
        String defaultSortType = "desc";
        String sortField = String.valueOf(jsonObject.get("sortField"));
        String sortType = String.valueOf(jsonObject.get("sortType"));
        if ("null".equals(sortField)|| sortField.length() == 0) {
            sortField=String.valueOf(queryMap.get("default_sort_field"));
            if("null".equals(sortField)|| sortField.length() == 0){
                sortField = dsPkId;
            }
        }
        if ("null".equals(sortType)|| sortType.length() == 0) {
            sortType=String.valueOf(queryMap.get("default_sort_type"));
            if("null".equals(sortType)|| sortType.length() == 0){
                sortType = defaultSortType;
            }
        }
        Sort sort;
        if(sortType.equals("desc")){
            sort = Sort.by(
                    Sort.Order.desc(sortField)
                    //,Sort.Order.desc("create_time") //支持多字段排序
            );
        }else{
            sort = Sort.by(
                    Sort.Order.asc(sortField)
            );
        }
        return sort;
    }

    public Query getMongoWhere(List<Map<String,Object>> fieldList, String jsonStr, JdbcTemplate jdbcTemplate, JackJSONObject retJson){
        JackJSONObject queryParamJson=JackJSONObject.fromObject(jsonStr).getJackJSONObject("queryParam");
        try {
            queryParamJson.size();
        } catch (Exception e) {
            return new Query();
        }
        return getMongoWhereByFieldInfo(fieldList,jsonStr,jdbcTemplate,retJson);
    }

    /*
    现在只有模糊查询和精确查询
     */
    public Query getMongoWhereByFieldInfo(List<Map<String,Object>> fieldList, String jsonStr, JdbcTemplate jdbcTemplate, JackJSONObject retJson){
        JackJSONObject requestJson=JackJSONObject.fromObject(jsonStr);
        JackJSONObject queryParamJson=requestJson.getJackJSONObject("queryParam");
        Map<String,Object> map=new HashMap<>();
        String whereSql="";
        Criteria criteria=new Criteria();
        for (int i = 0; i < fieldList.size(); i++) {
            map.put(String.valueOf(fieldList.get(i).get("name")),fieldList.get(i));//map里存一份用field做key
            // 点查询
            if (!"null".equals(String.valueOf(fieldList.get(i).get("is_query"))) && fieldList.get(i).get("is_query").equals("Y")
                    && !"null".equals(String.valueOf(fieldList.get(i).get("query_type"))) && fieldList.get(i).get("query_type").equals("0")
                    && !"null".equals(String.valueOf(queryParamJson.get(fieldList.get(i).get("name"))))) {
                if (!(fieldList.get(i).get("name").equals("starttime") || fieldList.get(i).get("name").equals("endtime"))) {
                    if (fieldList.get(i).get("type").equals("String")) {
                        if (fieldList.get(i).get("show_type").equals("checkbox")){
                            String checkStr=String.valueOf(queryParamJson.get(fieldList.get(i).get("name")));
                            if(!"".equals(checkStr)){
                                String[] checkboxArray = String.valueOf(queryParamJson.get(fieldList.get(i).get("name"))).split(",");
                                for (int j = 0; j < checkboxArray.length; j++) {
                                    //whereSql += " and FIND_IN_SET('" +checkboxArray[j]+"',"+ fieldList.get(i).get("name") + ")";
                                    //todo 啊这，得研究一下mongo怎么写
                                }
                            }
                        }else if (String.valueOf(fieldList.get(i).get("show_type")).equals("tree")){
                            String treeValue=String.valueOf(queryParamJson.get(fieldList.get(i).get("name")));
                            String isRecursion=String.valueOf(queryParamJson.get("isRecursion"));
                            if(!"".equals(treeValue)&&("null".equals(isRecursion)||isRecursion.equals("Y"))){
                                whereSql += " and FIND_IN_SET(" +fieldList.get(i).get("name")+","+fieldList.get(i).get("dict_code")+"('"+ treeValue + "'))";
                                whereSql += " and " + fieldList.get(i).get("name") + " != ''";
                            }else if(!"".equals(treeValue)&&isRecursion.equals("N")){
                                whereSql += " and " + fieldList.get(i).get("name") + " = '"+queryParamJson.get(fieldList.get(i).get("name"))+"'";
                            }
                        }else if (!"null".equals(String.valueOf(fieldList.get(i).get("is_fuzzy_search")))&&fieldList.get(i).get("is_fuzzy_search").equals("0")) {
                            if (!"null".equals(String.valueOf(queryParamJson.get(fieldList.get(i).get("name"))))
                                    && String.valueOf(queryParamJson.get(fieldList.get(i).get("name"))).length() > 0) {
                                // 模糊查询下
                                criteria.and(fieldList.get(i).get("name")+"").regex(queryParamJson.get(fieldList.get(i).get("name"))+"");
                            }
                        }else if (!"null".equals(String.valueOf(fieldList.get(i).get("is_fuzzy_search")))&&fieldList.get(i).get("is_fuzzy_search").equals("2")) {
                            if (!"null".equals(String.valueOf(queryParamJson.get(fieldList.get(i).get("name"))))
                                    && String.valueOf(queryParamJson.get(fieldList.get(i).get("name"))).length() > 0) {
                                // 精确查询
                                criteria.and(fieldList.get(i).get("name")+"").is(queryParamJson.get(fieldList.get(i).get("name")));
                            }
                        }
                    } else if (!"null".equals(String.valueOf(queryParamJson.get(fieldList.get(i).get("name"))))
                            && String.valueOf(queryParamJson.get(fieldList.get(i).get("name"))).length() > 0) {
                        if(fieldList.get(i).get("name").equals("create_org_id")) {
                            whereSql += " and " + fieldList.get(i).get("name") + " in ("
                                    + queryParamJson.get(fieldList.get(i).get("name"))+")";
                        }
                    }
                }
            }
        }
        return new Query(criteria);
    }
}
