package com.mosty.bkzx.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mosty.base.enums.BKCSTypeEnum;
import com.mosty.base.enums.BKDbTypeEnum;
import com.mosty.base.enums.BkTypeEnum;
import com.mosty.base.model.dto.bkzx.TbBkDbBkDto;
import com.mosty.base.model.dto.bkzx.TbBkDbInsertDto;
import com.mosty.base.model.dto.bkzx.TbBkDbSearchDto;
import com.mosty.base.model.dto.bkzx.TbBkDbUpDto;
import com.mosty.base.model.entity.bkzx.TbBkDb;
import com.mosty.base.model.vo.base.DeptInfoVo;
import com.mosty.bkzx.mapper.TbBkDbMapper;
import com.mosty.bkzx.remote.TbBaseAdaptRemoteService;
import com.mosty.bkzx.service.TbBkDbService;
import com.mosty.bkzx.service.ThridBkService;
import com.mosty.bkzx.sjjs.client.AccountUtils;
import com.mosty.bkzx.sjjs.dto.ResponseStatusObject;
import com.mosty.common.base.exception.BusinessException;
import com.mosty.common.base.util.DateUtils;
import com.mosty.common.base.util.SpringIocContext;
import com.mosty.common.token.UserInfo;
import com.mosty.common.token.UserInfoManager;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

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

@AllArgsConstructor
@Service
public class TbBkDbServiceImpl extends ServiceImpl<TbBkDbMapper, TbBkDb> implements TbBkDbService {
    private final TbBaseAdaptRemoteService tbBaseAdaptRemoteService;
    private final AccountUtils accountUtils;


    @Override
    public boolean updateBatchById(Collection<TbBkDb> entityList, int batchSize) {
        return super.updateBatchById(entityList, batchSize);
    }

    @Override
    public void builderDb(TbBkDbInsertDto dto) throws BusinessException {
        UserInfo user = UserInfoManager.get();
        if (null == user) {
            throw new BusinessException("当前登陆用户信息无效！");
        }

        List<AccountUtils.Accounts> _accounts = this.accountUtils.findAccountsByArce(dto.getAreaCode());
        if (CollectionUtils.isEmpty(_accounts)) {
            throw new BusinessException("所要创建布控数据库区哉未找到，请重试！");
        }

//        this.builderDb(dto, user, _deptVo.getData(), _accounts);
    }

    /**
     * 布控数据库删除
     *
     * @param records
     * @throws BusinessException
     */
    @Override
    public void delDb(List<Long> records) throws BusinessException {
        if (CollectionUtils.isEmpty(records)) {
            throw new BusinessException("删除布控数据库记录集合无效！");
        }
        List<TbBkDb> _daoes = this.baseMapper.selectList(new LambdaQueryWrapper<TbBkDb>().in(TbBkDb::getId, records));
        if (CollectionUtils.isEmpty(_daoes)) {
            throw new BusinessException("删除的布控数据库信息不存在！");
        }
        this.baseMapper.deleteBatchIds(_daoes.stream().map(_tp -> _tp.getId()).collect(Collectors.toList()));
    }

    @Override
    public List<TbBkDb> selectList(Wrapper<TbBkDb> wrapper) throws BusinessException {
        return this.baseMapper.selectList(wrapper);
    }

    @Override
    public TbBkDb selectByOne(Wrapper<TbBkDb> wrapper) throws BusinessException {
        return this.baseMapper.selectOne(wrapper);
    }

    @Override
    public int updateEntity(TbBkDb entity) {
        if (null == entity) {
            return 0;
        }
        return this.baseMapper.updateById(entity);
    }

    /**
     * 布控数据库分页查询
     *
     * @param reqPar
     * @return
     */
    @Override
    public IPage<TbBkDb> getPageList(TbBkDbSearchDto reqPar) {
        if (null == reqPar) {
            throw new BusinessException("布控数据库分页查询请求参数无效！");
        }
        QueryWrapper<TbBkDb> qw = new QueryWrapper<>();
        IPage<TbBkDb> _pageData = this.baseMapper.selectPage(
                new Page<>(reqPar.getPageCurrent(), reqPar.getPageSize()),
                qw.lambda()
                        .like(StringUtils.isNotBlank(reqPar.getDbName()), TbBkDb::getDbName, reqPar.getDbName())
                        .eq(StringUtils.isNotBlank(reqPar.getDbCs()), TbBkDb::getDbCs, reqPar.getDbCs())
                        .eq(StringUtils.isNotBlank(reqPar.getDbType()), TbBkDb::getDbType, reqPar.getDbType())
                        .eq(StringUtils.isNotBlank(reqPar.getAreaCode()), TbBkDb::getAreaCode, reqPar.getAreaCode())
                        .eq(TbBkDb::getHidden, false)
                        .orderByDesc(TbBkDb::getXtCjsj)
        );
        return _pageData;
    }

    @Override
    public Object bKDb(TbBkDbBkDto reqPar) {
        if (null == reqPar || null == reqPar.getId() || null == reqPar.getBkJssj() || null == reqPar.getBkJssj()) {
            throw new BusinessException("布控数据参数异常，请核查！");
        }
        List<TbBkDb> _dbs = this.baseMapper.selectList(new LambdaQueryWrapper<TbBkDb>()
                .eq(TbBkDb::getId, reqPar.getId())
        );
        if (CollectionUtils.isEmpty(_dbs)) {
            return "未找到需要进行布控的数据库！";
        }

        _dbs = this.baseMapper.selectList(new LambdaQueryWrapper<TbBkDb>()
                .eq(TbBkDb::getDbCs, _dbs.get(0).getDbCs())
                .eq(TbBkDb::getSssgajid, _dbs.get(0).getSssgajid())
        );
        if (CollectionUtils.isEmpty(_dbs)) {
            return "未找到需要进行布控的数据库！";
        }

        List<TbBkDb> _bkdbitems = new ArrayList<TbBkDb>();
        List<TbBkDb> _bkdbs = _dbs.stream().filter(_tp -> (StringUtils.isEmpty(_tp.getDbBkzt()) || _tp.getDbBkzt().equals("0"))).collect(Collectors.toList());
        List<TbBkDb> _expritDbs = _dbs.stream().filter(_tp -> StringUtils.isNotBlank(_tp.getDbBkzt()) && _tp.getDbBkzt().equals("1")
                && (_tp.getBkJssj().getTime() < DateUtils.getNowDate().getTime())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(_bkdbs)) {
            _bkdbitems.addAll(_bkdbs);
        }
        if (!CollectionUtils.isEmpty(_expritDbs)) {
            _bkdbitems.addAll(_expritDbs);
        }
        _bkdbitems.forEach(_tp -> {
            _tp.setBkJssj(reqPar.getBkJssj());
            _tp.setBkKassj(reqPar.getBkKssj());
            _tp.setJgxxjssjhm(reqPar.getJgxxjssjhm());
        });
        UserInfo user = UserInfoManager.get();

        Map<BKCSTypeEnum, List<TbBkDb>> _dbItems = new HashMap<>();
        for (TbBkDb _db : _bkdbitems) {
            BKCSTypeEnum _cs = BKCSTypeEnum.toValue(_db.getDbCs());
            if (null == _cs) {
                continue;
            }
            if (_dbItems.containsKey(_cs)) {
                _dbItems.get(_cs).add(_db);
            } else {
                List<TbBkDb> _dbes = new ArrayList<>();
                _dbes.add(_db);
                _dbItems.put(_cs, _dbes);
            }
        }
        if (CollectionUtils.isEmpty(_dbItems)) {
            throw new BusinessException("未找到需进行布控的数据！");
        }

        List<ResponseStatusObject> _statusObjects = new ArrayList<>();
        Iterator<Map.Entry<BKCSTypeEnum, List<TbBkDb>>> _iter = _dbItems.entrySet().iterator();
        while (_iter.hasNext()) {
            Map.Entry<BKCSTypeEnum, List<TbBkDb>> _node = _iter.next();
            ThridBkService _service = (ThridBkService) SpringIocContext.getBean(_node.getKey().getBeanName());
            if (null != _service) {
                List<ResponseStatusObject> _tmpresult = _service.startBkDb(_node.getValue(), user);
                if (null != _tmpresult) {
                    _statusObjects.addAll(_tmpresult);
                }
            }
        }
        if (CollectionUtils.isEmpty(_statusObjects)) {

            return MessageFormat.format("布控{0}{1}数据库成功！", _dbs.get(0).getSssgaj(), (_dbs.get(0).getDbType().equals(BKDbTypeEnum.Personnel.getCode()) ? "人像" : "车辆"));
        }
        List<TbBkDb> _upDbs = new ArrayList<TbBkDb>();
        for (ResponseStatusObject _tp : _statusObjects) {
            TbBkDb _tmpDb = _bkdbitems.stream().filter(_tmp -> StringUtils.isNotBlank(_tmp.getDispositionID()) && _tmp.getDispositionID().equals(_tp.getId())).findAny().orElse(null);
            if (_tmpDb != null) {
                _tmpDb.setDbBkzt("1");
                _tmpDb.setBkKassj(_tmpDb.getBkKassj());
                _tmpDb.setBkJssj(_tmpDb.getBkJssj());
                _tmpDb.setJgxxjssjhm(_tmpDb.getJgxxjssjhm());
                _upDbs.add(_tmpDb);
            }
        }
        if (!CollectionUtils.isEmpty(_upDbs)) {
            this.updateBatchById(_upDbs);
        } else {
            throw new BusinessException(MessageFormat.format("布控{0}{1}数据库失败！", _dbs.get(0).getSssgaj(), (_dbs.get(0).getDbType().equals(BKDbTypeEnum.Personnel.getCode()) ? "人像" : "车辆")));
        }
        return MessageFormat.format("布控{0}{1}数据库成功！", _dbs.get(0).getSssgaj(), (_dbs.get(0).getDbType().equals(BKDbTypeEnum.Personnel.getCode()) ? "人像" : "车辆"));
    }

    /**
     * 撤销对已经布控的数据撤销布控
     *
     * @param idKeys
     * @return
     */
    @Override
    public Object unBkDb(List<Long> idKeys) {
        if (CollectionUtils.isEmpty(idKeys)) {
            throw new BusinessException("撤销布控数据库信息无效！");
        }
        List<TbBkDb> _tbBkDbItems = this.selectList(new LambdaQueryWrapper<TbBkDb>().in(TbBkDb::getId, idKeys));
        if (CollectionUtils.isEmpty(_tbBkDbItems)) {
            throw new BusinessException("撤销布控数据库信息无效！");
        }
        _tbBkDbItems = _tbBkDbItems.stream().filter(_tmp -> StringUtils.isNotBlank(_tmp.getDbBkzt()) && _tmp.getDbBkzt().equals("1")).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(_tbBkDbItems)) {
            throw new BusinessException("当前所选择的数据均未进行下发布控，无法进行撤销布控操作！");
        }
        Map<BKCSTypeEnum, List<TbBkDb>> _dbItems = new HashMap<>();
        for (TbBkDb _temp : _tbBkDbItems) {
            BKCSTypeEnum _cs = BKCSTypeEnum.toValue(_temp.getDbCs());
            if (null == _cs) {
                continue;
            }
            if (_dbItems.containsKey(_cs)) {
                _dbItems.get(_cs).add(_temp);
            } else {
                List<TbBkDb> _items = new ArrayList<>();
                _items.add(_temp);
                _dbItems.put(_cs, _items);
            }
        }
        if (CollectionUtils.isEmpty(_dbItems)) {
            throw new BusinessException("撤销布控数据库信息无效！");
        }
        List<String> _dbKeys = new ArrayList<>();
        Iterator<Map.Entry<BKCSTypeEnum, List<TbBkDb>>> _iter = _dbItems.entrySet().iterator();
        while (_iter.hasNext()) {
            Map.Entry<BKCSTypeEnum, List<TbBkDb>> _node = _iter.next();
            List<String> _tmpKeys = ((ThridBkService) SpringIocContext.getBean(_node.getKey().getBeanName())).cancleDbBuKong(_node.getValue());
            if (!CollectionUtils.isEmpty(_tmpKeys)) {
                _dbKeys.addAll(_tmpKeys);
            }
        }
        if (CollectionUtils.isEmpty(_dbKeys)) {
            throw new BusinessException("撤销数据布控操作失败，请重试！");
        }
        _tbBkDbItems = _tbBkDbItems.stream().filter(_tp -> _dbKeys.contains(_tp.getDbId())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(_tbBkDbItems)) {
            throw new BusinessException("撤销数据布控操作失败，请重试！");
        }
        _tbBkDbItems.forEach(_tp -> {
            _tp.setDbBkzt("0");
            _tp.setDbId(StringUtils.EMPTY);
        });
        this.updateBatchById(_tbBkDbItems);
        return MessageFormat.format("成功撤销数据库布控总数：{0}，失败数：{1}", _tbBkDbItems.size(), idKeys.size() - _tbBkDbItems.size());
    }

    /**
     * 编辑布控数据库信息
     *
     * @param upDto
     * @return
     */
    @Override
    public Object modify(TbBkDbUpDto upDto) {
        TbBkDb _dbinfo = this.baseMapper.selectById(upDto.getId());
        if (null == _dbinfo) {
            throw new BusinessException("布控数据库未找到！");
        }
        List<TbBkDb> _dbitems = this.baseMapper.selectList(new LambdaQueryWrapper<TbBkDb>().eq(TbBkDb::getAreaCode, _dbinfo.getAreaCode()));
        if (CollectionUtils.isEmpty(_dbitems)) {
            throw new BusinessException("编辑的布控数据未找到！");
        }
        _dbitems.forEach(_tp -> {
            _tp.setDbName(upDto.getDbName());
            _tp.setDescription(upDto.getDescription());
            _tp.setBkKassj(upDto.getBkKassj());
            _tp.setBkJssj(upDto.getBkJssj());
        });
        Boolean _succes = this.updateBatchById(_dbitems);
        if (!_succes) {
            return "更新布控数据基础信息成功！";
        }
        return "更新布控数据库基础信息失败，请重试！";
    }

    @Override
    public TbBkDb getDetail(String id) {
        return this.baseMapper.selectById(id);
    }

    @Override
    public List<Map> getAreList() {
        return accountUtils.getAccountList();
    }

    /**
     * 创建布控车库
     *
     * @param dto
     * @param user
     */
    private void builderDb(TbBkDbInsertDto dto, UserInfo user, DeptInfoVo detpVo, List<AccountUtils.Accounts> accounts) {
        List<TbBkDb> _dbitems = this.baseMapper.selectList(
                new LambdaQueryWrapper<TbBkDb>()
                        .eq(TbBkDb::getSssgajdm, dto.getAreaCode()));

        if (!CollectionUtils.isEmpty(_dbitems)) {
            long _counts = 0;
            if (dto.getDbType() == BKDbTypeEnum.All) {
                _counts = _dbitems.stream().filter(_temp -> {
                    return _temp.getDbType().equals(BKDbTypeEnum.Personnel.getCode()) ||
                            _temp.getDbType().equals(BKDbTypeEnum.Car.getCode());
                }).count();
            } else {
                _counts = _dbitems.stream().filter(_temp -> {
                    return _temp.getDbType().equals(dto.getDbType().getCode());
                }).count();
            }
            if (_counts > 0) {
                throw new BusinessException("你当前所选择市的布控数据库已经存在，请不要重复创建布控数据库！");
            }
        }
        List<TbBkDb> _dbs = new ArrayList<>();
        for (AccountUtils.Accounts _account : accounts) {
            if (_account.isPeopleLibrary()) {
                TbBkDb _tempA = new TbBkDb();
                _tempA.setHidden(_account.isHidden());
                _tempA.setDescription(dto.getDescription());
                _tempA.setSssgajid(detpVo.getDeptcode());
                _tempA.setDbName(dto.getDbName());
                _tempA.setDbType(BKDbTypeEnum.Personnel.getCode());
                _tempA.setDbCs(BKCSTypeEnum.DAHUA.getValue());
                _tempA.setAreaCode(_account.getAreaCode());
                _tempA.setAreaName(_account.getName());
                _tempA.setBkKassj(dto.getBkKassj());
                _tempA.setBkJssj(dto.getBkJssj());
                _tempA.setAccount(_account);
                _dbs.add(_tempA);
            }

            if (_account.isCarLibrary()) {
                TbBkDb _tempb = new TbBkDb();
                _tempb.setDescription(dto.getDescription());
                _tempb.setSssgajid(detpVo.getDeptcode());
                _tempb.setDbName(dto.getDbName());
                _tempb.setDbType(BKDbTypeEnum.Car.getCode());
                _tempb.setDbCs(BKCSTypeEnum.DAHUA.getValue());
                if (!_account.isPeopleLibrary()) {
                    _tempb.setHidden(true);
                } else {
                    _tempb.setHidden(BKDbTypeEnum.Car.isHidden());
                }
                _tempb.setAreaName(_account.getName());
                _tempb.setBkJssj(dto.getBkJssj());
                _tempb.setBkKassj(dto.getBkKassj());
                _tempb.setAreaCode(_account.getAreaCode());
                _tempb.setAccount(_account);
                _dbs.add(_tempb);
            }
        }
        for (BKCSTypeEnum _tmp : BKCSTypeEnum.values()) {
            if (_tmp.isEnable()) {
                ThridBkService dbService = (ThridBkService) SpringIocContext.getBean(_tmp.getBeanName());
                if (null != dbService) {
                    dbService.createDb(_dbs, user, detpVo);
                }
            }
        }
        this.saveOrUpdateBatch(_dbs);
    }

    private List<TbBkDb> convertDaHuaByPrimKey(List<ThridBkService.DbInfo> dbInfo, TbBkDbInsertDto dto, DeptInfoVo detpVo) {
        List<TbBkDb> _resdata = new ArrayList<TbBkDb>();
        if (CollectionUtils.isEmpty(dbInfo)) {
            return null;
        }
        for (int _index = 0; _index < dbInfo.size(); _index++) {
            TbBkDb _tpDb = new TbBkDb();
            _tpDb.setDbName(dto.getDbName());
            _tpDb.setDbId(dbInfo.get(_index).getDbKey());
            _tpDb.setDbCs(BKCSTypeEnum.DAHUA.getValue());
            _tpDb.setDescription(dto.getDescription());
            _tpDb.setHidden(dbInfo.get(_index).isHidden());
            _tpDb.setDbType(this.getBkDbType(_tpDb.getDbId()));
            _tpDb.setSssgajid(detpVo.getDeptid());
            _tpDb.setSssgaj(detpVo.getDeptname());
            _tpDb.setSssgajdm(detpVo.getDeptcode());
            BKDbTypeEnum _dbType = BKDbTypeEnum.toCode(_tpDb.getDbType());
            if (null != _dbType) {
                if (_dbType == BKDbTypeEnum.Car && !_tpDb.getHidden()) {
                    _tpDb.setHidden(true);
                }
            }
            if (_tpDb.getDbType().equals(BKDbTypeEnum.Personnel.getCode())) {
                _tpDb.setBkType(BkTypeEnum.BKRL.getValue());
            }
            _resdata.add(_tpDb);
        }
        return _resdata;
    }

    /**
     * 大华数据转换
     *
     * @param object
     * @return
     */
    private List<TbBkDb> convertDaHua(JSONObject object, TbBkDbInsertDto dto, DeptInfoVo detpVo) {
        List<TbBkDb> _resdata = new ArrayList<TbBkDb>();
        if (object == null) {
            return _resdata;
        }
        JSONArray _jsArray = object.getJSONObject("ResponseStatusListObject").getJSONArray("ResponseStatusObject");
        for (int _index = 0; _index < _jsArray.size(); _index++) {
            TbBkDb _tpDb = new TbBkDb();
            _tpDb.setDbName(dto.getDbName());
            _tpDb.setDbId(_jsArray.getJSONObject(_index).getString("Id"));
            _tpDb.setDbCs(BKCSTypeEnum.DAHUA.getValue());
            _tpDb.setDescription(dto.getDescription());
            _tpDb.setDbType(this.getBkDbType(_tpDb.getDbId()));
            _tpDb.setSssgajid(detpVo.getDeptid());
            _tpDb.setSssgaj(detpVo.getDeptname());
            _tpDb.setSssgajdm(detpVo.getDeptcode());
            if (_tpDb.getDbType().equals(BKDbTypeEnum.Personnel.getCode())) {
                _tpDb.setBkType(BkTypeEnum.BKRL.getValue());
            }
            _resdata.add(_tpDb);
        }
        return _resdata;
    }

    /**
     * 获取布控库类型
     *
     * @param dbId
     * @return
     */
    private String getBkDbType(String dbId) {
        String _typeCode = dbId.substring(20, 22);
        if ("05".equals(_typeCode)) {
            return BKDbTypeEnum.Personnel.getCode();
        } else {
            return BKDbTypeEnum.Car.getCode();
        }
    }
}
