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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yeejoin.amos.boot.biz.common.constants.BizConstant;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.biz.common.entity.DataDictionary;
import com.yeejoin.amos.boot.biz.common.service.impl.DataDictionaryServiceImpl;
import com.yeejoin.amos.boot.biz.common.utils.Menu;
import com.yeejoin.amos.boot.biz.common.utils.MenuFrom;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.biz.common.utils.TreeParser;
import com.yeejoin.amos.boot.module.common.api.dto.*;
import com.yeejoin.amos.boot.module.common.api.entity.FireTeam;
import com.yeejoin.amos.boot.module.common.api.entity.OrgUsr;
import com.yeejoin.amos.boot.module.common.api.feign.EquipFeignClient;
import com.yeejoin.amos.boot.module.common.api.mapper.FireTeamMapper;
import com.yeejoin.amos.boot.module.common.api.service.IFireTeamService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.typroject.tyboot.core.foundation.exception.BaseException;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 消防队伍 服务实现类
 *
 * @author tb
 * @date 2021-06-07
 */
@Service
public class FireTeamServiceImpl extends BaseService<FireTeamDto, FireTeam, FireTeamMapper>
        implements IFireTeamService {

    @Resource
    FireTeamMapper fireTeamMapper;

    @Autowired
    EquipFeignClient equipFeignClient;

    @Autowired
    OrgUsrServiceImpl orgUsrService;

    @Autowired
    DataDictionaryServiceImpl iDataDictionaryService;

    @Autowired
    private RedisUtils redisUtils;

    @Value("${fire-rescue}")
    private String fireRescueId;
    private static final String GETPARENT ="getParent";
    private static final String GETNAME="getName";
    private static final String GETSEQUENCENBR="getSequenceNbr";
    private static final String TEAMID ="teamId";
    private static final String IS_DELETE="is_delete";
    /**
     * 获取监控大队列表
     *
     * @return
     */
    public List<FireBrigadeResourceDto> listMonitorFireBrigade(String code) {
        return fireTeamMapper.listMonitorFireBrigade(code);
    }

    /**
     * 消防队伍分页查询
     *
     * @param page 分页对象
     * @param team 查询参数
     * @return
     */
    public IPage<FireTeamCardDto> listFireTeamByPage(Page<FireTeamCardDto> page, FireTeamListDto team) {
        // 获取消防车辆列表
        ResponseModel<Object> result = equipFeignClient.getFireCarListAll();
        Map<Object, Long> teamCarCountMap = Maps.newConcurrentMap();
        if (!ValidationUtil.isEmpty(result)) {
            List<Map<String, Object>> fireCarListMapList = (List<Map<String, Object>>) result.getResult();
            if (!ValidationUtil.isEmpty(fireCarListMapList)) {
                teamCarCountMap = fireCarListMapList.stream().filter(car -> !ValidationUtil.isEmpty(car.get(TEAMID)))
                        .collect(Collectors.groupingBy(car -> car.get(TEAMID), Collectors.counting()));
            }
        }

        // 查询单位
        if (Objects.equals("1", team.getNodeType())) {
            List<OrgUsr> companyDeptList = orgUsrService.listOrgUserById(team.getNodeId());
            team.setNodeIds(
                    companyDeptList.stream().map(e -> e.getSequenceNbr().toString()).collect(Collectors.toList()));
        }
        // 查询队伍
        if (Objects.equals("0", team.getNodeType())) {
            List<FireTeam> teamList = listFireTeamById(team.getNodeId());
            team.setNodeIds(teamList.stream().map(e -> e.getSequenceNbr().toString()).collect(Collectors.toList()));
        }

        if(!ValidationUtil.isEmpty(team.getTypeCode())) {
            team.setTypeCodes(Arrays.asList(team.getTypeCode().split(",")));
        }

        IPage<FireTeamCardDto> fireTeamListPage = this.baseMapper.getFireTeamForPage(page, team);
        List<FireTeamCardDto> fireTeamList = fireTeamListPage.getRecords();
        Map<Object, Long> finalTeamCarCountMap = teamCarCountMap;
        fireTeamList.forEach(t -> {
            // 递归返回teamId bug2684 bykongfm
            List<Long> teamIds = new ArrayList<>();
            getAllTeamId(teamIds, t.getSequenceNbr());
            int carNum = 0;
            int fighterNum = 0;
            for (Long tempId : teamIds) {
                if (finalTeamCarCountMap.get(tempId.toString()) != null) {
                    carNum += finalTeamCarCountMap.get(tempId.toString()).intValue();
                }
                fighterNum += fireTeamMapper.getFighterNumByTeamId(tempId);
            }
            t.setCarNum(carNum);
            t.setFighterNum(fighterNum);

        });
        fireTeamListPage.setRecords(fireTeamList);
        return fireTeamListPage;
    }

    public List<FireTeam> listFireTeamById(Long teamId) {
        return this.baseMapper.listFireTeamById(teamId);
    }

    public List<FireTeamDto> queryFireTeamForListTree(Boolean isDelete) {
        return fireTeamMapper.listFireTeamDtoTree(isDelete);
    }

    public List<FireTeamDto> queryFireTeamForList(Boolean isDelete, Map<String,Object> map) {
        if (map == null || map.size() < 1) {
            return fireTeamMapper.listFireTeamDto(isDelete, null, null, null, null, null,null);
        }
        // 权限处理
        String bizOrgCode = map.containsKey("bizOrgCode") ? map.get("bizOrgCode").toString() : null;

        String nodeId = map.containsKey("nodeId") ? map.get("nodeId").toString() : null;
        String nodeType = map.containsKey("nodeType") ? map.get("nodeType").toString() : null;
        String name = map.containsKey("name") ? map.get("name").toString() : null;
        String typeCode = map.containsKey("typeCode") ? map.get("typeCode").toString() : null;

        List<String> nodeIdsList = null;
        // 查询单位
        if (Objects.equals("1", nodeType)) {
            List<OrgUsr> companyDeptList = orgUsrService.listOrgUserById(Long.parseLong(nodeId));
            nodeIdsList = companyDeptList.stream().map(e -> e.getSequenceNbr().toString()).collect(Collectors.toList());
        }
        // 查询队伍
        if (Objects.equals("0", nodeType)) {
            List<FireTeam> teamList = listFireTeamById(Long.parseLong(nodeId));
            nodeIdsList = teamList.stream().map(e -> e.getSequenceNbr().toString()).collect(Collectors.toList());
        }
        return fireTeamMapper.listFireTeamDto(isDelete, nodeId, nodeType, name, typeCode, nodeIdsList,bizOrgCode);
    }

    /**
     * 根据列表构造队伍树
     *
     * @param columnMap 查询列表条件
     * @return 队伍树
     * @throws Exception
     */
    public List<Menu> getTeamTree(Map<String, Object> columnMap) throws Exception {
        Collection<FireTeam> list = this.listByMap(columnMap);
        return TreeParser.getTree(null, list, FireTeam.class.getName(), GETSEQUENCENBR, 2, GETNAME, GETPARENT,
                null,null);
    }

    public List<Menu> getTeamTreeLikeCode(QueryWrapper<FireTeam> columnMap) throws Exception {
        Collection<FireTeam> list = this.list(columnMap);
        return TreeParser.getTree(null, list, FireTeam.class.getName(), GETSEQUENCENBR, 2, GETNAME, GETPARENT,
                null,null);
    }
    /**
     * 获取机场单位-队伍树
     *
     * @return
     */
    public List<MenuFrom> getCompanyTeamTree() throws Exception {
        MenuFrom root = new MenuFrom("-1", "消防队伍", null, null);
        // 机场单位
        // bug:2457需求要求不显示部门，因此更换方法 by 陈浩 2021-08-18
        List<OrgUsr> companyDeptList = orgUsrService.selectCompanyList();
        List<MenuFrom> companyDeptMenuList = Lists.newArrayList();
        companyDeptList.forEach(o -> {
            if (ValidationUtil.isEmpty(o.getParentId())) {
                o.setParentId("-1");
            }
            companyDeptMenuList
                    .add(new MenuFrom(o.getSequenceNbr().toString(), o.getBizOrgName(), o.getParentId(), "1"));
        });
        // 消防队伍
        List<MenuFrom> teamMenuList = Lists.newArrayList();
        List<FireTeamDto> teamList = this.queryFireTeamForList(false, null);
        teamList.forEach(team -> {
            if (ValidationUtil.isEmpty(team.getParent())) {
                // 将单位下没有上级队伍的队伍直接挂在单位下（方便组成树结构）
                team.setParent(team.getCompany());
            }
            teamMenuList.add(
                    new MenuFrom(team.getSequenceNbr().toString(), team.getName(), team.getParent().toString(), "0"));
        });
        companyDeptMenuList.addAll(teamMenuList);
        List<MenuFrom> menuList = TreeParser.getTreexin("-1", companyDeptMenuList, MenuFrom.class.getName(), "getKey",
                1, GETNAME, "getParentId", "getNodeType");
        root.setChildren(menuList);
        return Lists.newArrayList(root);
    }

    /**
     * 根据队伍id查询队伍下人员列表
     *
     * @param teamIds
     * @return
     */
    public List<FirefightersDto> getFighterByTeamId(List<String> teamIds) {
        return this.baseMapper.queryFighterByTeamId(teamIds);
    }

    public FireTeam saveFireTeam(FireTeam fireTeam) {

//    	/*修改bug 4547 名称在前端没有完成修改的问题  by 陈浩 on 2022-01-26 end  */
        if (fireTeam.getAddress() != null) {
            JSONObject address = WaterResourceServiceImpl.getLongLatFromAddress(fireTeam.getAddress());
            fireTeam.setAddress(address.getString(BizConstant.ADDRESS));
            fireTeam.setLongitude(Double.valueOf(address.getString(BizConstant.LONGITUDE)));
            fireTeam.setLatitude(Double.valueOf(address.getString(BizConstant.LATITUDE)));
        }
        if (ValidationUtil.isEmpty(fireTeam.getParent())) {
            fireTeam.setTreeCode(TreeParser.genTreeCode());
        } else {
            FireTeam parentTeam = getById(fireTeam.getParent());
            fireTeam.setTreeCode(parentTeam.getTreeCode() + TreeParser.genTreeCode());
        }

        DataDictionary dataDictionary = iDataDictionaryService.getById(fireTeam.getTypeCode());
        if (null != dataDictionary) {
            fireTeam.setType(dataDictionary.getName());
        }
        if (ValidationUtil.isEmpty(fireTeam.getSequenceNbr())) {
            save(fireTeam);
        } else {
            /*如果修改的队伍有下级队伍，所属单位一起修改 2021-10-18 陈召 开始*/
            LambdaQueryWrapper<FireTeam> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FireTeam::getParent, fireTeam.getSequenceNbr());
            wrapper.eq(BaseEntity::getIsDelete, false);
            List<FireTeam> fireTeams = baseMapper.selectList(wrapper);
            if (!fireTeams.isEmpty()) {
                fireTeams.forEach(i -> {
                    i.setCompany(fireTeam.getCompany());
                    i.setCompanyName(fireTeam.getCompanyName());
                    i.setCompanyCode(fireTeam.getCompanyCode());
                    i.setIsDelete(false);
                    this.updateById(i);
                });
            }
            /*如果修改的队伍有下级队伍，所属单位一起修改 2021-10-18 陈召 结束*/
            fireTeam.setIsDelete(false);
            this.updateById(fireTeam);
        }
        return fireTeam;
    }

    public static JSONObject getLongLatFromAddress(String address) {
        JSONObject result = new JSONObject();
        result.put(BizConstant.ADDRESS, "");
        result.put(BizConstant.LONGITUDE, "0");
        result.put(BizConstant.LATITUDE, "0");
        if (StringUtils.isNotEmpty(address)) {
            String[] addressData = address.split("@address@");
            if (addressData.length > 1) {
                result.put(BizConstant.ADDRESS, addressData[0]);
                JSONObject langLatObj = JSON.parseObject(addressData[1]);
                if (StringUtils.isNotEmpty(langLatObj.getString(BizConstant.LONGITUDE))) {
                    result.put(BizConstant.LONGITUDE, langLatObj.getString(BizConstant.LONGITUDE));
                } else {
                    result.put(BizConstant.LONGITUDE, "0");
                }
                if (StringUtils.isNotEmpty(langLatObj.getString(BizConstant.LATITUDE))) {
                    result.put(BizConstant.LATITUDE, langLatObj.getString(BizConstant.LATITUDE));
                } else {
                    result.put(BizConstant.LATITUDE, "0");
                }
            } else {
                result.put(BizConstant.ADDRESS, addressData[0]);
            }
        }
        return result;
    }

    /**
     * 根据id删除队伍
     *
     * @param parent
     */
    public void deleteById(Long parent) throws Exception {
        // 查询是否有下属队伍
        /* 3026 【web】日常管理>机场单位，删除有级联数据的部门时，应无法直接删除 chenzhao 2021-09-28 start */
        LambdaQueryWrapper<FireTeam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FireTeam::getParent, parent);
        wrapper.eq(BaseEntity::getIsDelete, 0);
        List<FireTeam> fireTeams = baseMapper.selectList(wrapper);
        /* 3026 【web】日常管理>机场单位，删除有级联数据的部门时，应无法直接删除 chenzhao 2021-09-28 end */
        if (!ValidationUtil.isEmpty(fireTeams) && fireTeams.size() > 0) {
            // 有下属队伍不能删除
            throw new BaseException("该队伍下有下级队伍，不能删除", null, "该队伍下有下级队伍，不能删除");
        }
        update(new UpdateWrapper<FireTeam>().eq("sequence_nbr", parent).set(IS_DELETE, 1));
    }

    @Override
    public List<FireTeamZhDto> getFireTeamList(Integer pageNum, Integer pageSize, RequestData par) {

        if (null == pageNum || null == pageSize) {
            pageNum = 1;
            pageSize = Integer.MAX_VALUE;
        } else {
            pageNum = (pageNum - 1) * pageSize;
        }

        List<FireTeamZhDto> list = fireTeamMapper.getFireTeamList(pageNum, pageSize, par);

        // 获取消防车辆列表
        ResponseModel<List<Map<String, Object>>> result = equipFeignClient.getFireCarListAllcount();

        List<Map<String, Object>> result1 = result.getResult();
        if (result1 != null && result1.size() > 0) {
            list.forEach(fireTeamZhDto -> {
                Long sequenceNbr = fireTeamZhDto.getSequenceNbr();
                result1.forEach(map -> {
                    String mapId = String.valueOf(map.get(TEAMID));
                    if (String.valueOf(sequenceNbr).equals(mapId)) {
                        Integer carNum = Integer.valueOf(map.get("carNum").toString());
                        fireTeamZhDto.setCarNum(carNum);
                    }
                });
            });
        }




        return list;
    }

    @Override
    public Integer getFireTeamListCount(RequestData par) {

        return fireTeamMapper.getFireTeamListCount(par);
    }

    @Override
    public FireTeam getFireTeamBySequenceNbr(Long id) {
        return this.getById(id);
    }

    @Override
    public List<FireTeamZhDto> getFireTeamCountList() {
        List<FireTeamZhDto> list = fireTeamMapper.getFireTeamCountList();

        // 获取消防车辆列表
        ResponseModel<List<Map<String, Object>>> result = equipFeignClient.getFireCarListAllcount();

        List<Map<String, Object>> result1 = result.getResult();
        if (result1 != null && result1.size() > 0) {
            Map<String, Object> combineResultMap = new HashMap<String, Object>();
            result1.stream().forEach(obj -> {
                combineResultMap.put(obj.get(TEAMID).toString(), obj.get("carNum"));
            });
            list.stream().forEach(obj -> {
                if (combineResultMap.containsKey(obj.getSequenceNbr().toString())) {
                    obj.setCarNum(Integer.valueOf(combineResultMap.get(obj.getSequenceNbr().toString()).toString()));
                }
            });
        }

        return list;

    }

    public Integer getFightNumByTeamId(Long teamId) {
        Integer count = 0;
        // 获取自己的数据
        count += fireTeamMapper.getFighterNumByTeamId(teamId);
        // 获取下部分数据
        LambdaQueryWrapper<FireTeam> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FireTeam::getParent, teamId).eq(FireTeam::getIsDelete, false);
        List<FireTeam> fireTeamList = this.list(queryWrapper);
        if (fireTeamList.size() == 0) {
            return count;
        } else {
            for (FireTeam t : fireTeamList) {
                count += getFightNumByTeamId(t.getSequenceNbr());
            }
        }
        // 获取子集数据
        return count;
    }

    public void getAllTeamId(List<Long> teamIds, Long teamId) {
        teamIds.add(teamId);
        LambdaQueryWrapper<FireTeam> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FireTeam::getParent, teamId).eq(FireTeam::getIsDelete, false);
        List<FireTeam> fireTeamList = this.list(queryWrapper);
        if (fireTeamList.size() == 0) {
            // 没有下级单位
        } else {
            for (FireTeam t : fireTeamList) {
                getAllTeamId(teamIds, t.getSequenceNbr());
            }
        }
    }

    /**
     * 加载系统中本单位消防队伍中类型为【企（事）业单位医疗救援队（站）】的队伍  --->急救站
     *
     * @param typeCode
     */
    public List<FireTeam> getFirstAidForTypeCodeAndCompanyId(String dicCode, String typeCode, Long companyId) {
        List<FireTeam> da=null;
        DataDictionary dataDictionary = iDataDictionaryService.getByCode(dicCode, typeCode);
        if (ObjectUtils.isEmpty(dataDictionary)) {
            return da;
        }
        String code = dataDictionary.getCode();
        LambdaQueryWrapper<FireTeam> queryWrapper = new LambdaQueryWrapper<FireTeam>();
        queryWrapper.eq(FireTeam::getTypeCode, code);
        queryWrapper.eq(FireTeam::getIsDelete, false);
        queryWrapper.eq(FireTeam::getCompany, companyId);
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<FireTeam> getFireTeamList() {

        QueryWrapper<FireTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(IS_DELETE, false);
        return fireTeamMapper.selectList(queryWrapper);
    }

    @Override
    public List<FireTeam> getExcelFireTeamList(String bizOrgCode) {

        QueryWrapper<FireTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(IS_DELETE, false);
        queryWrapper.like("biz_org_code",bizOrgCode);
        return fireTeamMapper.selectList(queryWrapper);
    }


    public List<Menu> getFirstTeamToDesignatedDepartment() throws Exception {
        LambdaQueryWrapper<FireTeam> queryWrapper = new LambdaQueryWrapper<FireTeam>();
        queryWrapper.eq(FireTeam::getTypeCode, "116");
        queryWrapper.eq(FireTeam::getIsDelete, false);

        return TreeParser.getTree(null, this.baseMapper.selectList(queryWrapper), FireTeam.class.getName(), GETSEQUENCENBR, 2, GETNAME, GETPARENT,
                null,null);
    }

    /**
     * @param
     * @return
     * @throws Exception
     */

    public List<Menu> getFirstTeamToDesignatedDepartment(String dicCode, String typeCode) throws Exception {
        List<Menu> da=null;

        DataDictionary dataDictionary = iDataDictionaryService.getByCode(dicCode, typeCode);
        if (ObjectUtils.isEmpty(dataDictionary)) {
            return da;
        }
        String code = dataDictionary.getCode();
        LambdaQueryWrapper<FireTeam> queryWrapper = new LambdaQueryWrapper<FireTeam>();
        queryWrapper.eq(FireTeam::getTypeCode, code);
        queryWrapper.eq(FireTeam::getIsDelete, false);
        // 消防救援保障部为保证灵活性以及防止名字变更 通过id查询  ID在配置文件中配置
      queryWrapper.eq(FireTeam::getCompany,fireRescueId);
        LambdaQueryWrapper<FireTeam> queryWrapper1 = new LambdaQueryWrapper<FireTeam>();
        queryWrapper1.eq(FireTeam::getIsDelete, false);
       queryWrapper1.eq(FireTeam::getCompany,fireRescueId);
        queryWrapper1.isNull(FireTeam::getParent);
     queryWrapper1.eq(FireTeam::getTypeCode,code);
        FireTeam parentFireTeam = this.baseMapper.selectOne(queryWrapper1);
        if (parentFireTeam == null) {
            return da;
        }
        return TreeParser.getTreeTeam(parentFireTeam.getSequenceNbr(), this.baseMapper.selectList(queryWrapper), FireTeam.class.getName(), GETSEQUENCENBR, 2, GETNAME, GETPARENT,
                null,null);
        // TODO Auto-generated method stub
    }

    public List<Menu> getFireTeamTypeTree(String bizOrgCode) throws Exception {
        return iDataDictionaryService.getFireTeamTypeTree(bizOrgCode);
    }

}
