package com.yeejoin.amos.boot.module.tzs.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.utils.DateUtils;
import com.yeejoin.amos.boot.biz.common.utils.JsonValueUtils;
import com.yeejoin.amos.boot.module.tzs.api.mapper.IdxUjerMapper;
import com.yeejoin.amos.boot.module.tzs.biz.utils.StringUtils;
import com.yeejoin.amos.boot.module.tzs.flc.api.dto.BizRecordCount;
import com.yeejoin.amos.boot.module.tzs.flc.api.dto.IdxUjerDto;
import com.yeejoin.amos.boot.module.tzs.flc.api.feign.IdxFeignService;
import com.yeejoin.amos.boot.module.tzs.flc.api.service.InspectionService;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.RegionModel;
import org.apache.commons.lang.text.StrSubstitutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;

import java.util.*;

import static java.util.regex.Pattern.compile;

@Service
public class InspectionServiceImpl implements InspectionService {

    private final Logger log = LoggerFactory.getLogger(InspectionServiceImpl.class);

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    IdxFeignService idxFeignService;

    @Autowired
    IdxUjerMapper idxUjerMapper;

    @Autowired
    JdbcTemplate bizJdbcTemplate;

    @Override
    public IPage<IdxUjerDto> bizDetailList(
            String dimensionTableId,
            String selectValue,
            String bizType, int current, int size
    ) {
        List<String> companyIds = idxFeignService.getTreeChildIds(dimensionTableId, selectValue).getResult();
        Collection<CompanyModel> companyModels = Privilege.companyClient.companyTreeWithoutAuth().getResult();
        Map<String, String> companyMap = new HashMap<>();
        convertCompanyTreeToMap(companyModels, null, companyMap);
        IPage<IdxUjerDto> idxUjerPage = new Page<>(current, size);
        IPage<IdxUjerDto> page = idxUjerMapper.getPage(idxUjerPage, companyIds, bizType);
        List<IdxUjerDto> records = page.getRecords();
        if (!CollectionUtils.isEmpty(records)) {
            for (IdxUjerDto record : records) {
                record.setBusinessAddressStr(record.getBusinessAddress() != null ? new String(record.getBusinessAddress()) : "");
                record.setCompanyName(companyMap.get(record.getCompanyId()));
            }
        }
        return page;
    }

    private void convertCompanyTreeToMap(Collection<CompanyModel> companyModels, Collection<Map<String, Object>> children, Map<String, String> companyMap) {
        if (!CollectionUtils.isEmpty(companyModels)) {
            for (CompanyModel companyModel : companyModels) {
                if (!ObjectUtils.isEmpty(companyModel)) {
                    companyMap.put(String.valueOf(companyModel.getSequenceNbr()), companyModel.getCompanyName());
                    convertCompanyTreeToMap(null, (Collection<Map<String, Object>>) companyModel.getChildren(), companyMap);
                }
            }
        }
        if (!CollectionUtils.isEmpty(children)) {
            for (Map<String, Object> child : children) {
                if (!ObjectUtils.isEmpty(child)) {
                    companyMap.put(String.valueOf(child.get("sequenceNbr")), String.valueOf(child.get("companyName")));
                    convertCompanyTreeToMap(null, (Collection<Map<String, Object>>) child.get("children"), companyMap);
                }
            }
        }
    }

    @Override
    public List<Map<String, Object>> bizRecordCountByField(List<BizRecordCount> bizRecordCountList) {
        List<Map<String, Object>> result = new ArrayList<>();
        for (BizRecordCount requestData : bizRecordCountList) {
            Map<String, Object> item = bizRecordCountByField(requestData);
            result.add(item);
        }
        return result;
    }

    @Override
    public Map<String, Object> bizRecordCountByField(BizRecordCount bizRecordCount) {
        Map map = JSONObject.parseObject(JSONObject.toJSONString(bizRecordCount), Map.class);
        StrSubstitutor ss = new StrSubstitutor(map);

        String selectSql = "SELECT ";
        if (!ValidationUtil.isEmpty(bizRecordCount.getBizRecordItems())) {
            bizRecordCount.setExpression(buildBizRecordItems(bizRecordCount.getBizRecordItems()));
        }
        if (!ValidationUtil.isEmpty(bizRecordCount.getExpression())) {
            selectSql += bizRecordCount.getExpression() + " as count";
        } else {
            selectSql += "COUNT(*) count";
        }
        if (!ValidationUtil.isEmpty(bizRecordCount.getTableName())) {
            selectSql = selectSql + " FROM ${tableName}";
        }
        if (!ValidationUtil.isEmpty(bizRecordCount.getFieldKey())) {
            selectSql = selectSql + (selectSql.contains("WHERE") ? " AND" : " WHERE") + " ${fieldKey}='${fieldValue}'";
        }
        selectSql = ss.replace(selectSql);

        Map<String, Object> queryResult = bizJdbcTemplate.queryForMap(selectSql);
        log.info("查询sql：" + selectSql);
        HashMap<String, Object> item = new HashMap<>();
        item.put("key", bizRecordCount.getTitle());
        item.put("value", queryResult.get("count"));
        return item;
    }

    @Override
    public JSONObject getSafetySupervisionCode(String bizTable) {
        String safetySupervisionCode = "（%s）市监特令中[%s]第  %s 号";
        AgencyUserModel agencyUserModel = Privilege.agencyUserClient.getme().getResult();
        Object reginSeq = JsonValueUtils.getValueByKey(JSONObject.parse(JSON.toJSONString(agencyUserModel)), "companys", "companys.0.regionSeq");
        String region = "";
        if (!ValidationUtil.isEmpty(reginSeq)) {
            List<RegionModel> result = Systemctl.regionClient.queryDeptByIds(reginSeq.toString()).getResult();
            for (int i = 0; i < result.size(); i++) {
                RegionModel regionModel = result.get(i);
                String regionName = regionModel.getRegionName();
                if (regionName.contains("市") || regionName.contains("区") || regionName.contains("县")) {
                    region = region + regionName.substring(0, 1);
                }
            }
        }

        String countSql = "SELECT count(1) FROM " + bizTable;
        Long count = bizJdbcTemplate.queryForObject(countSql, Long.class);
        int year = DateUtils.getYear(DateUtils.getDateNow());

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", String.format(safetySupervisionCode, region, year, count + 1));
        return jsonObject;
    }

    @Override
    public JSONObject getSafetySupervisionCodeMap(String bizTable, String mapKey, String mapValue) {
        JSONObject jsonObject = new JSONObject();
        String sql = String.format("SELECT `%s`, `%s` FROM %s", mapKey, mapValue, bizTable);
        List<Map<String, Object>> list = bizJdbcTemplate.queryForList(sql);
        list.forEach(x -> {
            jsonObject.put(x.get(mapKey).toString(), x.get(mapValue));
        });
        return jsonObject;
    }

    @Override
    public JSONObject getSafetySupervisionInfo() {
        AgencyUserModel agencyUserModel = Privilege.agencyUserClient.getme().getResult();
        Object companyId = JsonValueUtils.getValueByKey(JSONObject.parse(JSON.toJSONString(agencyUserModel)), "companys", "companys.0.sequenceNbr");
        Collection<CompanyModel> result = Privilege.companyClient.queryAgencyTree(null).getResult();


        JSONObject jsonObject = findParentCompanyById(JSONArray.parseArray(JSONArray.toJSONString(result)), companyId);
        String parentCompanyName = null;
        String regionName = null;

        if (!ValidationUtil.isEmpty(jsonObject)) { // 有上级单位
            parentCompanyName = jsonObject.getString("companyName");
            String selfCompanyName = JsonValueUtils.getValueByKey(JSONObject.parse(JSON.toJSONString(agencyUserModel)), "companys", "companys.0.companyName").toString();
            regionName = StringUtils.getStrByPattern(selfCompanyName, compile("(.*?)省|(.*?)市|(.*?)区"));
        } else {
            jsonObject = findCompanyById(JSONArray.parseArray(JSONArray.toJSONString(result)), companyId);
            parentCompanyName = jsonObject.getString("companyName");
            regionName = StringUtils.getStrByPattern(parentCompanyName, compile("(.*?)省"));
        }
        jsonObject.clear();
        jsonObject.put("reconsiderOrgName", parentCompanyName + "/" + regionName + "人民政府");
        jsonObject.put("lawsuitOrgName", regionName + "人员法院");
        return jsonObject;
    }

    @Override
    public Page<JSONObject> getMapByRegion(Long regionSeq, String tableId, String type) {
        Page<JSONObject> page = new Page<>(1, 10);
        Collection<RegionModel> result = Systemctl.regionClient.queryByParentId(regionSeq).getResult();
        JSONObject tableMap = idxFeignService.queryByTableId(tableId).getResult();
        String tableName = tableMap.getString("tableName");
        JSONArray tableCols = tableMap.getJSONArray("tableCols");
        Map<String, String> columMap = new HashMap<>();
        tableCols.forEach(x -> {
            Map<String, String> obj = (Map) x;
            if (!"type".equals(obj.get("columnName"))) {
                columMap.put(obj.get("name"), obj.get("columnName"));
            }
        });
        JSONObject jsonObject = new JSONObject();
        String selectSql = "SELECT * FROM " + tableName + " WHERE type=" + StringUtils.str2sqlValue(type);
        Map<String, Object> objectMap = bizJdbcTemplate.queryForMap(selectSql);
        result.forEach(x -> {
            String regionName = columMap.get(x.getRegionName());
            jsonObject.put(regionName, objectMap.get(regionName));
        });

        if (!ValidationUtil.isEmpty(jsonObject)) {
            page.setTotal(1);
            List<JSONObject> list = new ArrayList();
            list.add(jsonObject);
            page.setRecords(list);
        }
        return page;
    }

    private String buildBizRecordItems(List<BizRecordCount.BizRecordItem> bizRecordItems) {
        String sql = "";
        for (BizRecordCount.BizRecordItem item : bizRecordItems) {
            StringJoiner whereSql = new StringJoiner(" OR ");
            for (int i = 1; i <= item.getColumnIndex(); i++) {
                whereSql.add(String.format("%s%s='%s'", item.getColumnPrefix(), i, item.getColumnValue()));
            }
            sql = sql + ((ValidationUtil.isEmpty(sql) ? "" : "+") + String.format("(SELECT count(*) FROM %s WHERE %s)", item.getTableName(), whereSql));
        }
        return sql;
    }

    private static JSONObject findParentCompanyById(JSONArray companyModels, Object companyId) {
        for (int i = 0; i < companyModels.size(); i++) {
            JSONObject jsonObject = findCompanyById(companyModels.getJSONObject(i), companyId);
            if (!ValidationUtil.isEmpty(jsonObject)) {
                return findCompanyById(companyModels.getJSONObject(i), jsonObject.getString("parentId"));
            }
        }
        return null;
    }

    private static JSONObject findCompanyById(JSONArray companyModels, Object companyId) {
        for (int i = 0; i < companyModels.size(); i++) {
            JSONObject jsonObject = findCompanyById(companyModels.getJSONObject(i), companyId);
            if (!ValidationUtil.isEmpty(jsonObject)) {
                return findCompanyById(companyModels.getJSONObject(i), jsonObject.getString("sequenceNbr"));
            }
        }
        return null;
    }

    private static JSONObject findCompanyById(JSONObject treeNode, Object companyId) {
        if (treeNode.getString("sequenceNbr").equals(String.valueOf(companyId))) {
            return treeNode;
        } else {
            JSONArray children = treeNode.getJSONArray("children");
            if (!ValidationUtil.isEmpty(children)) {
                for (int i = 0; i < children.size(); i++) {
                    JSONObject result = findCompanyById(children.getJSONObject(i), companyId);
                    if (!ValidationUtil.isEmpty(result)) {
                        return result;
                    }
                }
            }
            return null;
        }
    }
}
